From 89aed71bed6fba09e7a81cbe02c530d2670fea6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20A=C5=9F=C4=B1c=C4=B1?= Date: Tue, 27 Oct 2009 10:13:00 +0000 Subject: [PATCH] Move pisi-1.0_beta2 tag --- tags/pisi-1.0_beta2/CODING | 126 -- tags/pisi-1.0_beta2/COPYING | 346 ---- tags/pisi-1.0_beta2/MANIFEST.in | 7 - tags/pisi-1.0_beta2/NEWS | 15 - tags/pisi-1.0_beta2/README | 12 - tags/pisi-1.0_beta2/TODO | 220 -- tags/pisi-1.0_beta2/doc/algorithm.sty | 79 - tags/pisi-1.0_beta2/doc/algorithmic.sty | 158 -- tags/pisi-1.0_beta2/doc/dependency.pdf | Bin 119423 -> 0 bytes tags/pisi-1.0_beta2/doc/dependency.tex | 381 ---- .../Dandik Fedora'nin component treesi.txt | 249 --- .../doc/notes/component-notes.txt | 167 -- .../notes/mandrake component _ group tree.txt | 879 -------- .../doc/notes/release hikayesi.txt | 110 - ...rce release ve binary build numaralari.txt | 125 -- tags/pisi-1.0_beta2/doc/package_versions.pdf | Bin 102463 -> 0 bytes tags/pisi-1.0_beta2/doc/package_versions.tex | 186 -- tags/pisi-1.0_beta2/doc/prettyref.sty | 37 - tags/pisi-1.0_beta2/pisi-cli | 65 - tags/pisi-1.0_beta2/pisi-spec.dtd | 117 -- tags/pisi-1.0_beta2/pisi.e3p | 484 ----- tags/pisi-1.0_beta2/pisi/__init__.py | 34 - .../pisi/actionsapi/__init__.py | 27 - .../pisi/actionsapi/autotools.py | 154 -- .../pisi/actionsapi/coreutils.py | 81 - tags/pisi-1.0_beta2/pisi/actionsapi/get.py | 192 -- tags/pisi-1.0_beta2/pisi/actionsapi/kde.py | 82 - .../pisi/actionsapi/libtools.py | 73 - .../pisi/actionsapi/perlmodules.py | 76 - .../pisi/actionsapi/pisitools.py | 240 --- .../pisi/actionsapi/pisitoolsfunctions.py | 81 - .../pisi/actionsapi/pythonmodules.py | 67 - tags/pisi-1.0_beta2/pisi/actionsapi/scons.py | 44 - .../pisi/actionsapi/shelltools.py | 212 -- .../pisi/actionsapi/variables.py | 83 - tags/pisi-1.0_beta2/pisi/api.py | 347 ---- tags/pisi-1.0_beta2/pisi/archive.py | 242 --- tags/pisi-1.0_beta2/pisi/atomicoperations.py | 468 ----- tags/pisi-1.0_beta2/pisi/build.py | 594 ------ tags/pisi-1.0_beta2/pisi/cli/README | 23 - tags/pisi-1.0_beta2/pisi/cli/__init__.py | 137 -- tags/pisi-1.0_beta2/pisi/cli/colors.py | 64 - tags/pisi-1.0_beta2/pisi/cli/commands.py | 1183 ----------- tags/pisi-1.0_beta2/pisi/cli/pisicli.py | 110 - tags/pisi-1.0_beta2/pisi/comariface.py | 99 - tags/pisi-1.0_beta2/pisi/component.py | 127 -- tags/pisi-1.0_beta2/pisi/config.py | 100 - tags/pisi-1.0_beta2/pisi/configfile.py | 139 -- tags/pisi-1.0_beta2/pisi/constants.py | 87 - tags/pisi-1.0_beta2/pisi/context.py | 41 - tags/pisi-1.0_beta2/pisi/dependency.py | 116 -- tags/pisi-1.0_beta2/pisi/fetcher.py | 304 --- tags/pisi-1.0_beta2/pisi/files.py | 80 - tags/pisi-1.0_beta2/pisi/graph.py | 161 -- tags/pisi-1.0_beta2/pisi/index.py | 130 -- tags/pisi-1.0_beta2/pisi/installdb.py | 190 -- tags/pisi-1.0_beta2/pisi/lockeddbshelve.py | 91 - tags/pisi-1.0_beta2/pisi/metadata.py | 102 - tags/pisi-1.0_beta2/pisi/oo.py | 39 - tags/pisi-1.0_beta2/pisi/operations.py | 441 ---- tags/pisi-1.0_beta2/pisi/package.py | 121 -- tags/pisi-1.0_beta2/pisi/packagedb.py | 172 -- tags/pisi-1.0_beta2/pisi/pgraph.py | 81 - tags/pisi-1.0_beta2/pisi/pxml/__init__.py | 23 - tags/pisi-1.0_beta2/pisi/pxml/autoxml.py | 814 -------- tags/pisi-1.0_beta2/pisi/pxml/xmlext.py | 27 - tags/pisi-1.0_beta2/pisi/pxml/xmlextcdom.py | 203 -- tags/pisi-1.0_beta2/pisi/pxml/xmlextmdom.py | 198 -- tags/pisi-1.0_beta2/pisi/pxml/xmlextpiks.py | 175 -- tags/pisi-1.0_beta2/pisi/pxml/xmlfile.py | 22 - tags/pisi-1.0_beta2/pisi/pxml/xmlfilecdom.py | 168 -- tags/pisi-1.0_beta2/pisi/pxml/xmlfilemdom.py | 159 -- tags/pisi-1.0_beta2/pisi/pxml/xmlfilepiks.py | 140 -- tags/pisi-1.0_beta2/pisi/repodb.py | 122 -- tags/pisi-1.0_beta2/pisi/sourcearchive.py | 71 - tags/pisi-1.0_beta2/pisi/sourcedb.py | 74 - tags/pisi-1.0_beta2/pisi/sourcefetcher.py | 90 - tags/pisi-1.0_beta2/pisi/specfile.py | 270 --- tags/pisi-1.0_beta2/pisi/ui.py | 98 - tags/pisi-1.0_beta2/pisi/uri.py | 108 - tags/pisi-1.0_beta2/pisi/util.py | 559 ----- tags/pisi-1.0_beta2/pisi/version.py | 193 -- tags/pisi-1.0_beta2/po/pisi.pot | 1673 --------------- tags/pisi-1.0_beta2/po/tr.po | 1827 ----------------- tags/pisi-1.0_beta2/setup.py | 101 - tags/pisi-1.0_beta2/tests/README | 10 - tags/pisi-1.0_beta2/tests/a.xml | 22 - tags/pisi-1.0_beta2/tests/actionsapitests.py | 58 - tags/pisi-1.0_beta2/tests/archivetests.py | 114 - tags/pisi-1.0_beta2/tests/autoxmltests.py | 102 - tags/pisi-1.0_beta2/tests/beta-build.sh | 41 - tags/pisi-1.0_beta2/tests/beta-light.sh | 23 - tags/pisi-1.0_beta2/tests/beta-remoterepo.sh | 25 - tags/pisi-1.0_beta2/tests/beta-upgrade.sh | 24 - tags/pisi-1.0_beta2/tests/configfiletests.py | 61 - tags/pisi-1.0_beta2/tests/constantstests.py | 67 - tags/pisi-1.0_beta2/tests/dependencytests.py | 28 - tags/pisi-1.0_beta2/tests/fetchertests.py | 51 - tags/pisi-1.0_beta2/tests/filestests.py | 31 - tags/pisi-1.0_beta2/tests/graphtests.py | 33 - .../tests/helloworld/actions.py | 102 - .../tests/helloworld/hello-1.3.tar.gz.part | Bin 11520 -> 0 bytes .../pisi-1.0_beta2/tests/helloworld/pspec.xml | 35 - tags/pisi-1.0_beta2/tests/installdbtests.py | 38 - tags/pisi-1.0_beta2/tests/metadatatests.py | 40 - tags/pisi-1.0_beta2/tests/ootests.py | 39 - tags/pisi-1.0_beta2/tests/packagedbtests.py | 41 - tags/pisi-1.0_beta2/tests/packagetests.py | 50 - tags/pisi-1.0_beta2/tests/pccts/actions.py | 53 - .../pccts/files/pccts-1.33.33-gentoo.diff | 69 - tags/pisi-1.0_beta2/tests/pccts/pspec.xml | 42 - tags/pisi-1.0_beta2/tests/pisi.conf | 6 - tags/pisi-1.0_beta2/tests/popt/actions.py | 25 - tags/pisi-1.0_beta2/tests/popt/files.xml | 507 ----- .../tests/popt/files/popt-1.7-uclibc.patch.gz | Bin 891 -> 0 bytes tags/pisi-1.0_beta2/tests/popt/metadata.xml | 87 - tags/pisi-1.0_beta2/tests/popt/pspec.xml | 75 - tags/pisi-1.0_beta2/tests/run.py | 52 - tags/pisi-1.0_beta2/tests/sourcedbtests.py | 39 - tags/pisi-1.0_beta2/tests/specfiletests.py | 78 - tags/pisi-1.0_beta2/tests/testcase.py | 27 - tags/pisi-1.0_beta2/tests/unzip/actions.py | 35 - .../tests/unzip/files/unzip-5.50-dotdot.patch | 85 - tags/pisi-1.0_beta2/tests/unzip/pspec.xml | 48 - tags/pisi-1.0_beta2/tests/unzip2/actions.py | 37 - .../unzip2/files/unzip-5.50-dotdot.patch | 85 - tags/pisi-1.0_beta2/tests/unzip2/pspec.xml | 48 - tags/pisi-1.0_beta2/tests/utiltests.py | 35 - tags/pisi-1.0_beta2/tests/versiontests.py | 71 - tags/pisi-1.0_beta2/tests/xmlexttests.py | 45 - tags/pisi-1.0_beta2/tests/zip/actions.py | 32 - .../tests/zip/files/zcrypt.patch | 752 ------- .../files/zip-2.3-unix_configure-pic.patch | 12 - .../tests/zip/files/zip-CAN-2004-1010.patch | 25 - tags/pisi-1.0_beta2/tests/zip/pspec.xml | 48 - tags/pisi-1.0_beta2/tests/zip2/actions.py | 34 - .../tests/zip2/files/zcrypt.patch | 752 ------- .../files/zip-2.3-unix_configure-pic.patch | 12 - .../tests/zip2/files/zip-CAN-2004-1010.patch | 25 - tags/pisi-1.0_beta2/tests/zip2/pspec.xml | 50 - tags/pisi-1.0_beta2/tools/cat-db.py | 26 - .../pisi-1.0_beta2/tools/check-source-repo.py | 32 - tags/pisi-1.0_beta2/tools/convert_history.py | 84 - tags/pisi-1.0_beta2/tools/ebuild2pisi.py | 194 -- tags/pisi-1.0_beta2/tools/fetchAll.py | 56 - tags/pisi-1.0_beta2/tools/find-lib-deps.py | 64 - .../tools/fix_old_metadata_files.py | 61 - .../tools/installAllAvailable.sh | 8 - tags/pisi-1.0_beta2/tools/lspisi | 57 - tags/pisi-1.0_beta2/tools/repostats.py | 695 ------- .../tools/rmcomp-source-repo.py | 46 - tags/pisi-1.0_beta2/tools/svndist.py | 31 - tags/pisi-1.0_beta2/tools/update-environ.py | 14 - tags/pisi-1.0_beta2/tools/update-po.sh | 4 - 154 files changed, 23811 deletions(-) delete mode 100644 tags/pisi-1.0_beta2/CODING delete mode 100644 tags/pisi-1.0_beta2/COPYING delete mode 100644 tags/pisi-1.0_beta2/MANIFEST.in delete mode 100644 tags/pisi-1.0_beta2/NEWS delete mode 100644 tags/pisi-1.0_beta2/README delete mode 100644 tags/pisi-1.0_beta2/TODO delete mode 100644 tags/pisi-1.0_beta2/doc/algorithm.sty delete mode 100644 tags/pisi-1.0_beta2/doc/algorithmic.sty delete mode 100644 tags/pisi-1.0_beta2/doc/dependency.pdf delete mode 100644 tags/pisi-1.0_beta2/doc/dependency.tex delete mode 100644 tags/pisi-1.0_beta2/doc/notes/Dandik Fedora'nin component treesi.txt delete mode 100644 tags/pisi-1.0_beta2/doc/notes/component-notes.txt delete mode 100644 tags/pisi-1.0_beta2/doc/notes/mandrake component _ group tree.txt delete mode 100644 tags/pisi-1.0_beta2/doc/notes/release hikayesi.txt delete mode 100644 tags/pisi-1.0_beta2/doc/notes/source release ve binary build numaralari.txt delete mode 100644 tags/pisi-1.0_beta2/doc/package_versions.pdf delete mode 100644 tags/pisi-1.0_beta2/doc/package_versions.tex delete mode 100644 tags/pisi-1.0_beta2/doc/prettyref.sty delete mode 100755 tags/pisi-1.0_beta2/pisi-cli delete mode 100644 tags/pisi-1.0_beta2/pisi-spec.dtd delete mode 100644 tags/pisi-1.0_beta2/pisi.e3p delete mode 100644 tags/pisi-1.0_beta2/pisi/__init__.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/__init__.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/autotools.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/coreutils.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/get.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/kde.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/libtools.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/perlmodules.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/pisitools.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/pisitoolsfunctions.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/pythonmodules.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/scons.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/shelltools.py delete mode 100644 tags/pisi-1.0_beta2/pisi/actionsapi/variables.py delete mode 100644 tags/pisi-1.0_beta2/pisi/api.py delete mode 100644 tags/pisi-1.0_beta2/pisi/archive.py delete mode 100644 tags/pisi-1.0_beta2/pisi/atomicoperations.py delete mode 100644 tags/pisi-1.0_beta2/pisi/build.py delete mode 100644 tags/pisi-1.0_beta2/pisi/cli/README delete mode 100644 tags/pisi-1.0_beta2/pisi/cli/__init__.py delete mode 100644 tags/pisi-1.0_beta2/pisi/cli/colors.py delete mode 100644 tags/pisi-1.0_beta2/pisi/cli/commands.py delete mode 100644 tags/pisi-1.0_beta2/pisi/cli/pisicli.py delete mode 100644 tags/pisi-1.0_beta2/pisi/comariface.py delete mode 100644 tags/pisi-1.0_beta2/pisi/component.py delete mode 100644 tags/pisi-1.0_beta2/pisi/config.py delete mode 100644 tags/pisi-1.0_beta2/pisi/configfile.py delete mode 100644 tags/pisi-1.0_beta2/pisi/constants.py delete mode 100644 tags/pisi-1.0_beta2/pisi/context.py delete mode 100644 tags/pisi-1.0_beta2/pisi/dependency.py delete mode 100644 tags/pisi-1.0_beta2/pisi/fetcher.py delete mode 100644 tags/pisi-1.0_beta2/pisi/files.py delete mode 100644 tags/pisi-1.0_beta2/pisi/graph.py delete mode 100644 tags/pisi-1.0_beta2/pisi/index.py delete mode 100644 tags/pisi-1.0_beta2/pisi/installdb.py delete mode 100644 tags/pisi-1.0_beta2/pisi/lockeddbshelve.py delete mode 100644 tags/pisi-1.0_beta2/pisi/metadata.py delete mode 100644 tags/pisi-1.0_beta2/pisi/oo.py delete mode 100644 tags/pisi-1.0_beta2/pisi/operations.py delete mode 100644 tags/pisi-1.0_beta2/pisi/package.py delete mode 100644 tags/pisi-1.0_beta2/pisi/packagedb.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pgraph.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/__init__.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/autoxml.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlext.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlextcdom.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlextmdom.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlextpiks.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlfile.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlfilecdom.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlfilemdom.py delete mode 100644 tags/pisi-1.0_beta2/pisi/pxml/xmlfilepiks.py delete mode 100644 tags/pisi-1.0_beta2/pisi/repodb.py delete mode 100644 tags/pisi-1.0_beta2/pisi/sourcearchive.py delete mode 100644 tags/pisi-1.0_beta2/pisi/sourcedb.py delete mode 100644 tags/pisi-1.0_beta2/pisi/sourcefetcher.py delete mode 100644 tags/pisi-1.0_beta2/pisi/specfile.py delete mode 100644 tags/pisi-1.0_beta2/pisi/ui.py delete mode 100644 tags/pisi-1.0_beta2/pisi/uri.py delete mode 100644 tags/pisi-1.0_beta2/pisi/util.py delete mode 100644 tags/pisi-1.0_beta2/pisi/version.py delete mode 100644 tags/pisi-1.0_beta2/po/pisi.pot delete mode 100644 tags/pisi-1.0_beta2/po/tr.po delete mode 100755 tags/pisi-1.0_beta2/setup.py delete mode 100644 tags/pisi-1.0_beta2/tests/README delete mode 100644 tags/pisi-1.0_beta2/tests/a.xml delete mode 100644 tags/pisi-1.0_beta2/tests/actionsapitests.py delete mode 100644 tags/pisi-1.0_beta2/tests/archivetests.py delete mode 100644 tags/pisi-1.0_beta2/tests/autoxmltests.py delete mode 100755 tags/pisi-1.0_beta2/tests/beta-build.sh delete mode 100755 tags/pisi-1.0_beta2/tests/beta-light.sh delete mode 100755 tags/pisi-1.0_beta2/tests/beta-remoterepo.sh delete mode 100755 tags/pisi-1.0_beta2/tests/beta-upgrade.sh delete mode 100644 tags/pisi-1.0_beta2/tests/configfiletests.py delete mode 100644 tags/pisi-1.0_beta2/tests/constantstests.py delete mode 100644 tags/pisi-1.0_beta2/tests/dependencytests.py delete mode 100644 tags/pisi-1.0_beta2/tests/fetchertests.py delete mode 100644 tags/pisi-1.0_beta2/tests/filestests.py delete mode 100644 tags/pisi-1.0_beta2/tests/graphtests.py delete mode 100644 tags/pisi-1.0_beta2/tests/helloworld/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/helloworld/hello-1.3.tar.gz.part delete mode 100644 tags/pisi-1.0_beta2/tests/helloworld/pspec.xml delete mode 100644 tags/pisi-1.0_beta2/tests/installdbtests.py delete mode 100644 tags/pisi-1.0_beta2/tests/metadatatests.py delete mode 100644 tags/pisi-1.0_beta2/tests/ootests.py delete mode 100644 tags/pisi-1.0_beta2/tests/packagedbtests.py delete mode 100644 tags/pisi-1.0_beta2/tests/packagetests.py delete mode 100644 tags/pisi-1.0_beta2/tests/pccts/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/pccts/files/pccts-1.33.33-gentoo.diff delete mode 100644 tags/pisi-1.0_beta2/tests/pccts/pspec.xml delete mode 100644 tags/pisi-1.0_beta2/tests/pisi.conf delete mode 100644 tags/pisi-1.0_beta2/tests/popt/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/popt/files.xml delete mode 100644 tags/pisi-1.0_beta2/tests/popt/files/popt-1.7-uclibc.patch.gz delete mode 100644 tags/pisi-1.0_beta2/tests/popt/metadata.xml delete mode 100644 tags/pisi-1.0_beta2/tests/popt/pspec.xml delete mode 100755 tags/pisi-1.0_beta2/tests/run.py delete mode 100644 tags/pisi-1.0_beta2/tests/sourcedbtests.py delete mode 100644 tags/pisi-1.0_beta2/tests/specfiletests.py delete mode 100644 tags/pisi-1.0_beta2/tests/testcase.py delete mode 100644 tags/pisi-1.0_beta2/tests/unzip/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/unzip/files/unzip-5.50-dotdot.patch delete mode 100644 tags/pisi-1.0_beta2/tests/unzip/pspec.xml delete mode 100644 tags/pisi-1.0_beta2/tests/unzip2/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/unzip2/files/unzip-5.50-dotdot.patch delete mode 100644 tags/pisi-1.0_beta2/tests/unzip2/pspec.xml delete mode 100644 tags/pisi-1.0_beta2/tests/utiltests.py delete mode 100644 tags/pisi-1.0_beta2/tests/versiontests.py delete mode 100644 tags/pisi-1.0_beta2/tests/xmlexttests.py delete mode 100644 tags/pisi-1.0_beta2/tests/zip/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/zip/files/zcrypt.patch delete mode 100644 tags/pisi-1.0_beta2/tests/zip/files/zip-2.3-unix_configure-pic.patch delete mode 100644 tags/pisi-1.0_beta2/tests/zip/files/zip-CAN-2004-1010.patch delete mode 100644 tags/pisi-1.0_beta2/tests/zip/pspec.xml delete mode 100644 tags/pisi-1.0_beta2/tests/zip2/actions.py delete mode 100644 tags/pisi-1.0_beta2/tests/zip2/files/zcrypt.patch delete mode 100644 tags/pisi-1.0_beta2/tests/zip2/files/zip-2.3-unix_configure-pic.patch delete mode 100644 tags/pisi-1.0_beta2/tests/zip2/files/zip-CAN-2004-1010.patch delete mode 100644 tags/pisi-1.0_beta2/tests/zip2/pspec.xml delete mode 100755 tags/pisi-1.0_beta2/tools/cat-db.py delete mode 100755 tags/pisi-1.0_beta2/tools/check-source-repo.py delete mode 100755 tags/pisi-1.0_beta2/tools/convert_history.py delete mode 100755 tags/pisi-1.0_beta2/tools/ebuild2pisi.py delete mode 100755 tags/pisi-1.0_beta2/tools/fetchAll.py delete mode 100755 tags/pisi-1.0_beta2/tools/find-lib-deps.py delete mode 100755 tags/pisi-1.0_beta2/tools/fix_old_metadata_files.py delete mode 100755 tags/pisi-1.0_beta2/tools/installAllAvailable.sh delete mode 100755 tags/pisi-1.0_beta2/tools/lspisi delete mode 100755 tags/pisi-1.0_beta2/tools/repostats.py delete mode 100755 tags/pisi-1.0_beta2/tools/rmcomp-source-repo.py delete mode 100755 tags/pisi-1.0_beta2/tools/svndist.py delete mode 100755 tags/pisi-1.0_beta2/tools/update-environ.py delete mode 100755 tags/pisi-1.0_beta2/tools/update-po.sh diff --git a/tags/pisi-1.0_beta2/CODING b/tags/pisi-1.0_beta2/CODING deleted file mode 100644 index 3002d1e0..00000000 --- a/tags/pisi-1.0_beta2/CODING +++ /dev/null @@ -1,126 +0,0 @@ -Like every serious project, there are guidelines. -Oooooo. "Coding Standards". - -Guidelines ----------- - -0. Before reading any further please observe - PEP 8: Style Guide for Python Code - http://www.python.org/peps/pep-0008.html -1. When using dirnames, don't expect the dir to end - with a trailing slash, and please use the dirnames - in pisiconfig. Use util.join_path instead of os.path.join -2. Python indentation is usually 4 spaces. -3. Follow python philosophy of 'batteries included' -4. Use exceptions, don't return error codes -5. Don't make the PISI code have runtime dependencies on - a particular distribution (as much as possible). -6. Don't assume narrow use cases. Allow for a mediocre - amount of generalization in your code, for pieces that - will be required later. -7. If you are changing something, check if that change - breaks anything and fix breakage. For instance a - name. Running the tests is not always enough! -8. A good design ensures separation of concerns. Every module - has a specific documented responsibility. Don't make the - horse clean your windows. -9. To ensure readability avoid nesting python constructs - more than 3 levels deep. Python is a good language (unlike C), - so you can define inner functions in a convenient way, use - such decomposition techniques to break down your code into - manageable chunks. The worst code you can write is one huge - procedure that goes on for 1000 (or more) lines. -10. Use a particular abstraction like a class or function only - if it makes sense. Don't just define things because they can - be defined. Define only things that will/may be used. -11. If you are doing an expensive task like searching through - 10000 text chunks, please use an efficient data structure - and algorithm. We are not MS engineers who know no data - structure beyond doubly linked lists and no algorithm beyond - quicksort. -12. Resist the temptation to develop kludges and workarounds in - response to pressure. Take your time to solve the problems by - the book. The payoff comes later. -13. Same thing goes for premature optimizations. Knuth and Dijkstra - are watching over your shoulder. :) - - -Unit testing ------------- - -Unit tests are located in unittests directory. Running the tests is -trivial. But you must synchronize your code and data with the test -code, which can be a tedious work if you lose discipline. - -Sample data files are located in the same directory with test modules. - -For running the entire test suite, use the following command: - -$ ./tests/run.py - -The following command will run tests in specfiletests and archivetests -in unittests dir: - -$ ./tests/run.py specfile archive - -Do not depend on the output of unittests. Instead of producing an -output message/data in your tests, check the data internally. By -definition, unittest should just report succeeding and failing cases. - -If you didn't, take a look at the links below for having an idea of -unit testing. -http://www.extremeprogramming.org/rules/unittests.html -http://www.extremeprogramming.org/rules/unittests2.html - - -Misc. Suggestions ------------------ - -1. Demeter's Law - -In OO programming, try to invoke Demeter's law. -One of the "rules" there is not directly accessing any -objects that are further than, 2/3 refs, away. So the -following code is OK. - destroy_system(a.system().name()) -but the following isn't as robust - destroy_system(object_store.root().a.system.name()) -As you can tell, this introduces too many implementation -dependencies. The rule of thumb is that, in these cases -this statement must have been elsewhere.... It may be a -good idea to not count the object scope in this case, -so in Python self.a means only one level of reference, -not two. - -One quibble with this: it may be preferable not to insist -on this where it would be inefficient. So if everything -is neatly packed into one object contained in another -object, why replicate everything in the upper level? If -the semantics prevents dependency changes, then chains -of 3 or even 4 could be acceptable. - -OTOH, in Python and C++, it's not always good to implement -accessor/modifier pairs for every property of an object. -It would be much simpler if you are not doing any special -processing on the property (e.g. if what the type system -does is sufficient). - -The main rule of thumb in Demeter's Law is avoiding -putting more than, say, 10 methods in a class. That works -really well in practice, forcing refactoring every now -and then. - -2. We all know, you're using LISP but didn't want to tell -us. Don't be scared, as a success story and for your encouragment -there are tens of people somewhere with LISP releated jobs. - -3. If you are studying Data structures and Algorithms, and if -your first assignment is to implement a basic FIFO queue, -don't implement it. Just show your teacher the syntax of LISP, -tell him how beautiful it is, and show how an autistic person -can count lots of parenthesis with a "one second" look, you'll -probably get A+. - -4. If you are interested in "Playstation 2 Linux Games Programming" -or "How to extend C programs with Guile", please don't exercise -your valuable skills in this project. diff --git a/tags/pisi-1.0_beta2/COPYING b/tags/pisi-1.0_beta2/COPYING deleted file mode 100644 index 5ff207a8..00000000 --- a/tags/pisi-1.0_beta2/COPYING +++ /dev/null @@ -1,346 +0,0 @@ -NOTE! The GPL below is copyrighted by the Free Software Foundation, but -the instance of code that it refers to (the kde programs) are copyrighted -by the authors who actually wrote it. - ---------------------------------------------------------------------------- - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/tags/pisi-1.0_beta2/MANIFEST.in b/tags/pisi-1.0_beta2/MANIFEST.in deleted file mode 100644 index e423d286..00000000 --- a/tags/pisi-1.0_beta2/MANIFEST.in +++ /dev/null @@ -1,7 +0,0 @@ -recursive-include po * -recursive-include tests *.py -recursive-include tools * -recursive-include doc * -include . *.dtd -include . README NEWS CODING COPYING - diff --git a/tags/pisi-1.0_beta2/NEWS b/tags/pisi-1.0_beta2/NEWS deleted file mode 100644 index 047b8974..00000000 --- a/tags/pisi-1.0_beta2/NEWS +++ /dev/null @@ -1,15 +0,0 @@ -PISI Beta 1/2 release 17/18 November 2005: - - * support for components, see the completed items in TODO - * a tool to find library dependencies - * various improvements and bugfixes - -PISI Alpha 9 release 13 November 2005: - - * new package: pisi.pxml - * first release of autoxml, a metaclass for high-level xml processing - * uses 4suite.org for fast xml processing - * supports multiple parsers: minidom, 4suite and in the future: piksemel - * all xml structures in PISI have been updated to use autoxml - * improvements in the ui interface - * significant fixes for Turkish translations diff --git a/tags/pisi-1.0_beta2/README b/tags/pisi-1.0_beta2/README deleted file mode 100644 index 810c526f..00000000 --- a/tags/pisi-1.0_beta2/README +++ /dev/null @@ -1,12 +0,0 @@ -PISI - Packages Installed Succesfully as Intended - -PISI is a new package manager implemented in python for the PARDUS -distribution. - -Main features - - - Implemented in python. - - All specification and intermediate data is in an XML format. - - Fast database access implemented with berkeley DB. - - Integrates both low-level and high-level package operations. - diff --git a/tags/pisi-1.0_beta2/TODO b/tags/pisi-1.0_beta2/TODO deleted file mode 100644 index 1796fdf9..00000000 --- a/tags/pisi-1.0_beta2/TODO +++ /dev/null @@ -1,220 +0,0 @@ - - -PiSi TODO List -============== - -A list of tasks to accomplish, organized into priority sections - -Legend: - -- Todo -? Not determined if/how we have to do -/ In progress -+ Accomplished - -1. Pre-Alpha - - + reading spec file - + writing - + files - + metadata - + Actions API framework - + sample api modules (autotools) - + unit test - + source building - + package module - + extraction - + add file / compression - + package creation - + install database - + package database - + command line interface - + pisi-build - + pisi-install - + pisi-index - + pisi-updatedb - + single repository index - + simple dependency checking - + Package/Files - -2. Alpha - - + multi-package dependency analysis (eray) - + design a package operation planner - + install/remove operations (eray) - + command line interface: - + pisi remove - + svn-like CLI - + configuration file - + define the format of the configuration file - + extend Config module (config.py) accordingly - + define configuration keys (baris - meren) - + query - + list of installed packages (eray) - + refactor actionsAPI (caglar) - + fix xml indentation (meren) - + define file types (doc, executable, conf, etc...) (baris - meren) - + write specfile (eray) - + file locking for database access [not tested!] (eray) - + implement file uri - + extend the modules dealing with files accordingly - + ui module improvements - + methods for interaction (yes, no questions, etc.) - + implement source database (eray) - + easy package preparation - + convert ebuild to pisi - + COMAR interface - + what do we need to specify in a package. - + package install: register config script - + package remove: unregister config script - + internet installation - + support URI's whereever a filename is supported - + http server - + pisi updatedb over internet - -3. Beta - - + info cmd: reverse dependencies of a package - + a helper script for finding dependencies (eray) - + autoxml: automated xml processing (eray) - + design - + basic types - + list type - + class type - + localtext/text types - + revised interface - + improved error handling, check routines, hooks, format/print routines - + xmlfile support (read/write) - + string member, in addition to tag/attribute members - + replace specfile with new specfile using autoxml - + autoxmlize: metadata, index, dependency and related code paths - + inheritance support - + revise writing, error reporting, tests - + components (eray) - + requirements - + xml format, add to PSPEC - + index component.xml's and make use of them in build - + a database of components: - + query components by name - + query list of packages in a component - + index: update component database(s) - + bug fixing - + install/remove/upgrade components - + safety switch: preserve system.base, install system.devel for build, etc. - + info - + started documentation - + component dependencies - + multiple package repository (eray) - + decide how to implement - + support repo order - + refactor xml support and implement multiple backends - + 4suite support (initial patch by faik, completed by eray) - + piksemel support (eray) - + fix autoxml implementation to use 4suite by default - + partial caching and automatic resume for file download (meren) - + use a '.part' extension - + search-file command (eray) - + exception handling (eray) - + uniform exception hierarchy - + proper handling - + API: we even have application users (eray) - + a facade module pisi.api (eray) - + a library init command (eray) - + high-level package ops, index (eray) - + info/util commands (eray) - + build commands (baris) - + documentation - + actionsAPI documentation, unittests (caglar - meren) - + versioning information document (eray - baris) - + UI - + PISIMAT - + pykde GUI (cartman) - + improve interface (eray) - + refactor UI, reintroduce base class - + add an ack interface, start cleaning up a bit - + cli (eray) - + ask alternatives to choose from - + eliminate \n's from infos, what's the point? - + metaclass coolness for CLI command framework (eray) - + i18n support - + translations and correct language for summary, description (packagers) - + make pisi messages translatable (eray) - + .pot support for dist script (gurer) - + translate messages mesajların çevirisinin yapılması (pisi tr.po) (eray) - + proper unicode handling in code - tons of fixes (eray - baris) - + configure-pending (eray) - + proper commar connection (baris - gurer) - + ignore-deps (eray) - + more robust upgrade (eray) - + query (eray) - + comar OM information (Provides) - + find package by name, display summary/description - + info --files option (like rpm -ql, but better of course) - + implement missing unit tests - + sourcedb - + package (baris) - + configuration file (baris) - + upgrade (eray) - + upgrade operation - + test upgrade op - + system-wide upgrade (upgrade-all) komutu - + incremental build (eray) - + generate binary release number by comparing MD5s (eray) - + keep track of successfully completed configure, make, install - steps (necessary for large-scale builds?) (meren) - + database locking bugs (eray) - -4. Release - - * medium priority - - - component improvements (optional) - - if comp a has comp b, then it must have all packages in b - - maintain a list if components each component has - - * low priority - - - improve url support, it's a little dumb at the moment - - devise a File class that works with URLs - - consider adding "other" protocols - - removable media: media:// - - search command: (eray) - - implement an inverted index (if there's a good one, just use it) - - search in either summary, or description - - english stemming - - turkish stemming - - phonetic/syntactic fault tolerance (whichever works!) - - in particular evaluate soundex and metaphone - - research if there are language independent phonetic encodings - - implement as an option (or make it possible to turn it off if it works well :)) - - fault tolerant search in package names (somehow) - / overhaul installdb (try to merge its use with packagedb) (eray) - / verify metodlari - + SpecFile - + MetaData - + Files - - Index (somebody should write one :} ) - - autoxml: - - revise error checking, printing and tests - - make autoxml dependent on only xmlext and xmlfile interfaces - ? non-interactive use - -5. Post Release - - - high-level build commands - - install build dependencies - - build-all (or build-distro) command - - an emerge command, just for fun - - more support for categories: - - put categories into a database - - fast search for categories - / make a package and sourcedb for each repo - + packagedb - - sourceb - - transaction stuff for database (eray) - - multi-architecture support (baris, caglar) - / design decisions - / extend XML specs to support that - - cross-platform building support - - incremental build/fetch for repository index (pisi-index.xml) - - diffsets (caglar) diff --git a/tags/pisi-1.0_beta2/doc/algorithm.sty b/tags/pisi-1.0_beta2/doc/algorithm.sty deleted file mode 100644 index 843e3d5b..00000000 --- a/tags/pisi-1.0_beta2/doc/algorithm.sty +++ /dev/null @@ -1,79 +0,0 @@ -% ALGORITHM STYLE -- Released 8 April 1996 -% for LaTeX-2e -% Copyright -- 1994 Peter Williams -% E-mail Peter.Williams@dsto.defence.gov.au -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{algorithm} -\typeout{Document Style `algorithm' - floating environment} - -\RequirePackage{float} -\RequirePackage{ifthen} -\newcommand{\ALG@within}{nothing} -\newboolean{ALG@within} -\setboolean{ALG@within}{false} -\newcommand{\ALG@floatstyle}{ruled} -\newcommand{\ALG@name}{Algorithm} -\newcommand{\listalgorithmname}{List of \ALG@name s} - -% Declare Options -% first appearance -\DeclareOption{plain}{ - \renewcommand{\ALG@floatstyle}{plain} -} -\DeclareOption{ruled}{ - \renewcommand{\ALG@floatstyle}{ruled} -} -\DeclareOption{boxed}{ - \renewcommand{\ALG@floatstyle}{boxed} -} -% then numbering convention -\DeclareOption{part}{ - \renewcommand{\ALG@within}{part} - \setboolean{ALG@within}{true} -} -\DeclareOption{chapter}{ - \renewcommand{\ALG@within}{chapter} - \setboolean{ALG@within}{true} -} -\DeclareOption{section}{ - \renewcommand{\ALG@within}{section} - \setboolean{ALG@within}{true} -} -\DeclareOption{subsection}{ - \renewcommand{\ALG@within}{subsection} - \setboolean{ALG@within}{true} -} -\DeclareOption{subsubsection}{ - \renewcommand{\ALG@within}{subsubsection} - \setboolean{ALG@within}{true} -} -\DeclareOption{nothing}{ - \renewcommand{\ALG@within}{nothing} - \setboolean{ALG@within}{true} -} -\DeclareOption*{\edef\ALG@name{\CurrentOption}} - -% ALGORITHM -% -\ProcessOptions -\floatstyle{\ALG@floatstyle} -\ifthenelse{\boolean{ALG@within}}{ - \ifthenelse{\equal{\ALG@within}{part}} - {\newfloat{algorithm}{htbp}{loa}[part]}{} - \ifthenelse{\equal{\ALG@within}{chapter}} - {\newfloat{algorithm}{htbp}{loa}[chapter]}{} - \ifthenelse{\equal{\ALG@within}{section}} - {\newfloat{algorithm}{htbp}{loa}[section]}{} - \ifthenelse{\equal{\ALG@within}{subsection}} - {\newfloat{algorithm}{htbp}{loa}[subsection]}{} - \ifthenelse{\equal{\ALG@within}{subsubsection}} - {\newfloat{algorithm}{htbp}{loa}[subsubsection]}{} - \ifthenelse{\equal{\ALG@within}{nothing}} - {\newfloat{algorithm}{htbp}{loa}}{} -}{ - \newfloat{algorithm}{htbp}{loa} -} -\floatname{algorithm}{\ALG@name} - -\newcommand{\listofalgorithms}{\listof{algorithm}{\listalgorithmname}} - diff --git a/tags/pisi-1.0_beta2/doc/algorithmic.sty b/tags/pisi-1.0_beta2/doc/algorithmic.sty deleted file mode 100644 index 68f18aa0..00000000 --- a/tags/pisi-1.0_beta2/doc/algorithmic.sty +++ /dev/null @@ -1,158 +0,0 @@ -% ALGORITHMIC STYLE -- Released 8 APRIL 1996 -% for LaTeX version 2e -% Copyright -- 1994 Peter Williams -% E-mail PeterWilliams@dsto.defence.gov.au -\NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{algorithmic} -\typeout{Document Style `algorithmic' - environment} -% -\RequirePackage{ifthen} -\RequirePackage{calc} -\newboolean{ALC@noend} -\setboolean{ALC@noend}{false} -\newcounter{ALC@line} -\newcounter{ALC@rem} -\newlength{\ALC@tlm} -% -\DeclareOption{noend}{\setboolean{ALC@noend}{true}} -% -\ProcessOptions -% -% ALGORITHMIC -\newcommand{\algorithmicrequire}{\textbf{Require:}} -\newcommand{\algorithmicensure}{\textbf{Ensure:}} -\newcommand{\algorithmiccomment}[1]{\{#1\}} -\newcommand{\algorithmicend}{\textbf{end}} -\newcommand{\algorithmicif}{\textbf{if}} -\newcommand{\algorithmicthen}{\textbf{then}} -\newcommand{\algorithmicelse}{\textbf{else}} -\newcommand{\algorithmicelsif}{\algorithmicelse\ \algorithmicif} -\newcommand{\algorithmicendif}{\algorithmicend\ \algorithmicif} -\newcommand{\algorithmicfor}{\textbf{for}} -\newcommand{\algorithmicforall}{\textbf{for all}} -\newcommand{\algorithmicdo}{\textbf{do}} -\newcommand{\algorithmicendfor}{\algorithmicend\ \algorithmicfor} -\newcommand{\algorithmicwhile}{\textbf{while}} -\newcommand{\algorithmicendwhile}{\algorithmicend\ \algorithmicwhile} -\newcommand{\algorithmicloop}{\textbf{loop}} -\newcommand{\algorithmicendloop}{\algorithmicend\ \algorithmicloop} -\newcommand{\algorithmicrepeat}{\textbf{repeat}} -\newcommand{\algorithmicuntil}{\textbf{until}} -\def\ALC@item[#1]{% -\if@noparitem \@donoparitem - \else \if@inlabel \indent \par \fi - \ifhmode \unskip\unskip \par \fi - \if@newlist \if@nobreak \@nbitem \else - \addpenalty\@beginparpenalty - \addvspace\@topsep \addvspace{-\parskip}\fi - \else \addpenalty\@itempenalty \addvspace\itemsep - \fi - \global\@inlabeltrue -\fi -\everypar{\global\@minipagefalse\global\@newlistfalse - \if@inlabel\global\@inlabelfalse \hskip -\parindent \box\@labels - \penalty\z@ \fi - \everypar{}}\global\@nobreakfalse -\if@noitemarg \@noitemargfalse \if@nmbrlist \refstepcounter{\@listctr}\fi \fi -\sbox\@tempboxa{\makelabel{#1}}% -\global\setbox\@labels - \hbox{\unhbox\@labels \hskip \itemindent - \hskip -\labelwidth \hskip -\ALC@tlm - \ifdim \wd\@tempboxa >\labelwidth - \box\@tempboxa - \else \hbox to\labelwidth {\unhbox\@tempboxa}\fi - \hskip \ALC@tlm}\ignorespaces} -% -\newenvironment{algorithmic}[1][0]{ -\let\@item\ALC@item - \newcommand{\ALC@lno}{% -\ifthenelse{\equal{\arabic{ALC@rem}}{0}} -{{\footnotesize \arabic{ALC@line}:}}{}% -} -\let\@listii\@listi -\let\@listiii\@listi -\let\@listiv\@listi -\let\@listv\@listi -\let\@listvi\@listi -\let\@listvii\@listi - \newenvironment{ALC@g}{ - \begin{list}{\ALC@lno}{ \itemsep\z@ \itemindent\z@ - \listparindent\z@ \rightmargin\z@ - \topsep\z@ \partopsep\z@ \parskip\z@\parsep\z@ - \leftmargin 1em - \addtolength{\ALC@tlm}{\leftmargin} - } - } - {\end{list}} - \newcommand{\ALC@it}{\addtocounter{ALC@line}{1}\addtocounter{ALC@rem}{1}\ifthenelse{\equal{\arabic{ALC@rem}}{#1}}{\setcounter{ALC@rem}{0}}{}\item} - \newcommand{\ALC@com}[1]{\ifthenelse{\equal{##1}{default}}% -{}{\ \algorithmiccomment{##1}}} - \newcommand{\REQUIRE}{\item[\algorithmicrequire]} - \newcommand{\ENSURE}{\item[\algorithmicensure]} - \newcommand{\STATE}{\ALC@it} - \newcommand{\COMMENT}[1]{\algorithmiccomment{##1}} - \newenvironment{ALC@if}{\begin{ALC@g}}{\end{ALC@g}} - \newenvironment{ALC@for}{\begin{ALC@g}}{\end{ALC@g}} - \newenvironment{ALC@whl}{\begin{ALC@g}}{\end{ALC@g}} - \newenvironment{ALC@loop}{\begin{ALC@g}}{\end{ALC@g}} - \newenvironment{ALC@rpt}{\begin{ALC@g}}{\end{ALC@g}} - \renewcommand{\\}{\@centercr} - \newcommand{\IF}[2][default]{\ALC@it\algorithmicif\ ##2\ \algorithmicthen% -\ALC@com{##1}\begin{ALC@if}} - \newcommand{\ELSE}[1][default]{\end{ALC@if}\ALC@it\algorithmicelse% -\ALC@com{##1}\begin{ALC@if}} - \newcommand{\ELSIF}[2][default]% -{\end{ALC@if}\ALC@it\algorithmicelsif\ ##2\ \algorithmicthen% -\ALC@com{##1}\begin{ALC@if}} - \newcommand{\FOR}[2][default]{\ALC@it\algorithmicfor\ ##2\ \algorithmicdo% -\ALC@com{##1}\begin{ALC@for}} - \newcommand{\FORALL}[2][default]{\ALC@it\algorithmicforall\ ##2\ % -\algorithmicdo% -\ALC@com{##1}\begin{ALC@for}} - \newcommand{\WHILE}[2][default]{\ALC@it\algorithmicwhile\ ##2\ % -\algorithmicdo% -\ALC@com{##1}\begin{ALC@whl}} - \newcommand{\LOOP}[1][default]{\ALC@it\algorithmicloop% -\ALC@com{##1}\begin{ALC@loop}} - \newcommand{\REPEAT}[1][default]{\ALC@it\algorithmicrepeat% -\ALC@com{##1}\begin{ALC@rpt}} - \newcommand{\UNTIL}[1]{\end{ALC@rpt}\ALC@it\algorithmicuntil\ ##1} - \ifthenelse{\boolean{ALC@noend}}{ - \newcommand{\ENDIF}{\end{ALC@if}} - \newcommand{\ENDFOR}{\end{ALC@for}} - \newcommand{\ENDWHILE}{\end{ALC@whl}} - \newcommand{\ENDLOOP}{\end{ALC@loop}} - }{ - \newcommand{\ENDIF}{\end{ALC@if}\ALC@it\algorithmicendif} - \newcommand{\ENDFOR}{\end{ALC@for}\ALC@it\algorithmicendfor} - \newcommand{\ENDWHILE}{\end{ALC@whl}\ALC@it\algorithmicendwhile} - \newcommand{\ENDLOOP}{\end{ALC@loop}\ALC@it\algorithmicendloop} - } - \renewcommand{\@toodeep}{} - \begin{list}{\ALC@lno}{\setcounter{ALC@line}{0}\setcounter{ALC@rem}{0}% - \itemsep\z@ \itemindent\z@ \listparindent\z@% - \partopsep\z@ \parskip\z@ \parsep\z@% - \labelsep 0.5em \topsep 0.2em% -\ifthenelse{\equal{#1}{0}} - {\labelwidth 0.5em } - {\labelwidth 1.2em } -\leftmargin\labelwidth \addtolength{\leftmargin}{\labelsep} - \ALC@tlm\labelsep - } -} -{\end{list}} - - - - - - - - - - - - - - - diff --git a/tags/pisi-1.0_beta2/doc/dependency.pdf b/tags/pisi-1.0_beta2/doc/dependency.pdf deleted file mode 100644 index 7f9dd07f9d2a463bf4aec39ea5ac5c5eaab449a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119423 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 -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id BE4C284D16; - Wed, 7 Sep 2005 20:15:15 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id 128A11878DE; - Wed, 7 Sep 2005 20:09:27 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id 8A1AD1878D6 - for ; - Wed, 7 Sep 2005 20:09:13 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 56F5B908AE; Wed, 7 Sep 2005 20:15:02 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from [192.168.1.5] (unknown [85.97.87.38]) - by uludag.org.tr (Postfix) with ESMTP id 0057B84D16 - for ; Wed, 7 Sep 2005 20:15:01 +0300 (EEST) -From: Eray Ozkural -Organization: Pardus -To: cekirdek@uludag.org.tr -Date: Wed, 7 Sep 2005 20:15:04 +0300 -User-Agent: KMail/1.7.2 -MIME-Version: 1.0 -Message-Id: <200509072015.04792.eray@uludag.org.tr> -Cc: -Subject: [Cekirdek] [PISI Design] Dandik Fedora'nin component treesi -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============1420878072==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 3643 -X-Length: 4136 - ---===============1420878072== -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -Bu aslinda mandrake'ye gore biraz daha akli basinda ve daha -onemlisi component mantigina uygun bir liste, bir iki degisiklik -disinda bu listeyle baslamakta fayda var. Bir de tabii gentoo'nun -kendi listesi var, onu da gentoo'cular gonderebilir mi listeye lutfen? - -Bu dedigim gibi iki seviyeli bir tree, oldukca iyi aslinda.... sadece -dedigim gibi component/category karisimi biraz onun disinda gayet -guzel... Bir de baktim "group" demisler, group da iyi bir sozcuk aslinda -degistirmeye gerek yok degil mi component lafini? - -Saygilar, - -Desktop - X11 - GNOME - KDE -Applications - Editors - Engineering and Scientific - Graphical Internet - Text-based Internet - Office/Productivity - Sound and Video - Authoring and Publishing - Graphics - Games and Entertainment -Servers - Server Configuration Tools - Web Server - Mail Server - Windows File Server - DNS Name Server - FTP Server - PostgreSQL Database - MySQL Database - News Server - Network Servers - Legacy Network Server -Development - Development Tools - X Software Development - GNOME "" - KDE "" - Legacy "" - Java Development - Eclipse -System - Language Support (includes fonts and input methods) - Administration Tools - System Tools - Printing Support - --- -Eray Ozkural (exa), Uludag Gelistiricisi -http://cekirdek.uludag.org.tr/~eray http://www.kde.org -http://www.cs.bilkent.edu.tr/~erayo http://www.malfunct.com - ---===============1420878072== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============1420878072==-- - -From gurer@uludag.org.tr Wed Sep 7 22:04:45 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id 00FBF380AA; - Wed, 7 Sep 2005 22:04:23 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id 4BEDB1878F8; - Wed, 7 Sep 2005 21:58:34 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id CBC0E159028 - for ; - Wed, 7 Sep 2005 21:58:32 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 5EB758654F; Wed, 7 Sep 2005 22:04:21 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from cable73-96.anadolu.kablonet.com.tr (unknown [195.174.73.96]) - (using SSLv3 with cipher RC4-MD5 (128/128 bits)) - (No client certificate requested) - by uludag.org.tr (Postfix) with ESMTP id D92BD380AA - for ; Wed, 7 Sep 2005 22:04:20 +0300 (EEST) -From: =?ISO-8859-1?Q?G=FCrer_=D6zen?= -To: cekirdek@uludag.org.tr -In-Reply-To: <200509072015.04792.eray@uludag.org.tr> -References: <200509072015.04792.eray@uludag.org.tr> -Organization: TUBITAK - UEKAE -Date: Wed, 07 Sep 2005 22:04:45 +0300 -Message-Id: <1126119885.10981.13.camel@localhost> -Mime-Version: 1.0 -X-Mailer: Evolution 2.2.3 -Cc: -Subject: [Cekirdek] component hadisesi -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============1294830247==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 3648 -X-Length: 4903 - ---===============1294830247== -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Kanalda meren, exa, çağlar, ben biraz fikir teatisinde bulunduk. Teati -dedim de çay çekti canım. Özetlen: - -Component bir görev için bir araya gelmiş ve görevin ayrı parçalarını -yapan paketler dedik. Kullanım amacı kullanıcının bir alt sistemi (kde, -tex) bir hamlede kurabilmesini sağlamak, gerektiğinde dependency olarak -kullanılmak. - -Aynı işi yapan farklı programların bir grubu (library, editor, archiver, -vs) kesinlikle component olmuyor. - -Temel olarak iki tipi var: - -KDE (kicker, kwm, kdm, kopete, vs) -burda aynı koddan türemiş ve bize masaüstü sağlayan paketlerin bir -componenti var. - -Base (kernel, grub, libc, bash, vs) -burda ayrı kodlardan gelen ve bize açılıp çalışabilen bir sistem -sağlayan paketlerin bir componenti var. - -Aynı paket birden fazla componente dahil olmuyor, bu component değil -bağımlılık ilişkisi. Örnek: -libxml2 is a part of Gnome -kopete (a partof KDE) depends on libxml2 (bunu uydurdum, kopete -libxml2 kullanmıyor olabilir) - -Yani componenti *asıl* olarak kod ilişkisi belirliyor, ama örneğin base -paketinde direk kod ilişkisi yoksa da, birbirleriyle çok içiçe iş yapan -programları bir component altında grupladık. İkincil kriter birlikte -çalışma. - -Karma bi örnek: -Tex componenti içinde aynı koddan gelen kpathsea, tetex,vs paketleri var -diyelim, ama farklı kodu olan hevea da buraya girebilir, çünkü html -generate edebilen bir tex sistemi için gerekli. - -Hiçbir componente ait olmayan, sadece dependency ve category ilişkileri -olan paketler olabilir. Bunlar mesela other diye bi dizinde -(componentler aynı zamanda paket deposundaki dizinler, bu şart değil ama -kolaylık) tutulur. - -Componentleri hiyerarşiye koymak kötü bi fikir değil, fedoranın ana -grupları bu konuda fena değil. - -Kafa karışıklığı kalmadı sanırım. Kategorileri konuşmadık daha :) - -Bu vesileyle yavaş yavaş pisi depomuzu a/ b/ c/ lerden kurtarıp -component bazlı dizinlere geçirmeye başlayalım dedik. - - - ---===============1294830247== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============1294830247==-- - diff --git a/tags/pisi-1.0_beta2/doc/notes/component-notes.txt b/tags/pisi-1.0_beta2/doc/notes/component-notes.txt deleted file mode 100644 index 10d9be84..00000000 --- a/tags/pisi-1.0_beta2/doc/notes/component-notes.txt +++ /dev/null @@ -1,167 +0,0 @@ -component'larla ilgili notlar - -1. Temel feature'lar (Eray) --------------------- - -Iki yerde component tag'i tanimladik simdiye kadar, bir -source'larda bir de binary'lerde. Binary'de tanimlanan component default -olarak source'daki tanimi inherit ediyor ve tanimlanan component'i override -edebiliyor. - -Bir component temel olarak bir meta-package, icerisinde paketler olan -bir paket. Bir component'in icerisinde bir takim source'lar ve bir takim -binary'ler bulunuyor diye bakabiliriz. Sanirim query'leri bu sekilde yapmak -mumkun olmali. - -$ pisi list-components -$ pisi info system.base - Source packages in system.base: - .... - .... - Binary packages in system.base: - .... - .... - -gibi ozellikler eklemeyi umit ediyorum. - -Source'larin component tag'leri de, gene sadece bir senaryo konusuyorum, -direkt olarak directory structure'indan inherit alinacak. Ayni zamanda o pspec -icin de bir tane component tanimlananack default olarak, ve bu component o -scope'da tanimlanmis olan butun binary package'lari icerecek. - -Ornegin diyelim ki a/b/c/pspec.xml var ve c1 c2 c3 seklinde uc tane paket -tanimliyor. Hic bir component tanimi yapilmadigi zaman otomatik olarak bir -a.b.c component'i olusturulacak, ve bu component'in icerisinde c1 c2 c3 -bulunacak. - -$ pisi info a.b.c - Source packages: - c - oldur beni yarim sen olmazsan biterim - Binary packages: - c1 - bu aksam demlenmemek sonum olur benim - c2 - sincaplarla konustum butun gece - c3 - her gul gordugumde icim kan aglar - -Bu varsayilan davranis, ama bunu degistirmek mumkun olacak. Burada yamuk -gozukebilecek bir sey var, o da tek bir paket oldugunda sanki biraz -redundancy olmasi, o takdirde bir optimizasyon olarak, diyelim ki -a/b/c/pspec.xml'in icerisinde tek bir paket tanimli c1 - -$ pisi info a.b - .... - c1 - dil dil dillerdeyim - -olabilir bu durumda, bu genel agac mantiginda bir sorun yaratmayacaktir. - - -2. Temel tanım (Barış) - -fiziksel aitlik: kdebase'den çıkan kcontrol gibi; grup aitliği: pdf -göstericileri gibi... - - -3. Database XML ayrımı (Barış) - -Component database'i ile component.xml ayrı olmalı. Component database, -pisi'nin pisi-index.xml dosyasını okuyarak oluşturacağı bir veritabanı. Hangi -paketler hangi componentlere dahil, vs. sorguları bu veritabanından -yapılacak. - -Pspec dosyasını hatırlayalım. İçerisinde bir diye bir tag var. -Oluşturulacak paketin hangi component'e ait olduğunu belirtiyor. Bu bilgi -pisi-index.xml dosyasına da koyulmalı. - -4. PL modüllerine benzerlik (Eray) - -component tag'leri Java ya da python'daki gibi -directory yapisindan cikiyor. Yani pisi bir programlama dili olsaydi -component'lar module'ler ya da package'larla es anlamli olacakti. - -5. Mereology ve Eray'ın açıklama çabaları (Eray) - -PartOf iliskisi hakkında su kadarini soylemek yeter: eger a b'nin bir parcasiysa, -a'nin fonksiyonu b'nin fonksiyonunun bir parcasidir. Bu da fiziksel sistemler -icin bir principle of compositionality'nin varligindan hareket eder [*] - -Genel olarak da software engineering ve AI camiasinda module'un tanimi gayet -iyi bilinir. Bir modul icerisindeki bagimliliklar yogundur. Moduller arasindaki -bagimliliklar zayiftir. - -Bu tanim sadece software engineering'de degil, nesneler arasindaki -benzerliklerin incelendigi bir cok disiplinde kullanilan informal bir tanim, -ama tabii ki formule dokulmus bir ton hali var.Sırf bu tanımı taban alarak -yazılmış başarılı kümeleme (clustering) algoritmaları var. - -Modulerlik tanimi verilen *fiziksel* modul ve parcasi olma iliskisiyle -birlesince birlikte install edilip remove edilme yahut ortak bağımlılıklara -sahip olma tanımlarına götürür. - -Bu tanımı analiz edebilmek için parcasi olma iliskisininin anlamini -korumamiz yeterli. Temel olarak - -  kol insanin parcasidir - -iliskisi burada yer aliyor.  Eger - -  a partof b - -turu iliskilerde a paket ya da component, ve b component ise, a ve b'nin -iliskisinin kol ve insan iliskisi gibi olmasini bekleriz. Eger bu parca-butun -iliskisini ihlal ediyorsa o zaman muhtemelen yanlis bir iliski bulunmus -demektir. - -Bunun turlu sonuclari da onem sirasina gore soyle dizilebilir: - -1. Fonksiyonlarin bolunebilmesi prensibinden: (basit bir sonuç) -   a's function is part-of b's function - - orneğin kolun fonksiyonu insanın total fonksiyonunun bir parçasıdır. - -paket ornegi: pisi'nin fonksiyonu olan paket yükleme/çıkarma system.base'in fonksiyonunun, yani temel pardus sisteminin fonksiyonunun bir parçasıdır. - -2. Karmasik sistemlerde birbirine dayanan ufak parcalarin kararli yapilar -meydana getirmesi prensibinden: (evrimsel sonuç) - -   if a is a part-of c, and b is a part-of c, then it follows that a and b -may: -     a. have many interdependencies -     b. share in their origins -  (which are about the same thing) - -2b. sonucunun bizim durumumuza uygulanması, source code'un aynı kaynaktan -çıkması, birlikte inşa edilmeleri gibi şartları getirir. Bunun oldukça -olasi, en azindan insa metodlarinin ve kaynaklarının birbirine benzemesini -bekleriz. Yalniz, 2.a'daki bagimliliklar sadece insa ile degil ayni zamanda -calisma ile de alakalidir. Kaynakları farklı parçaların birbirine bağımlı -hale gelebilecegini unutmamak gerekir. - -Fedora'nin yaklasiminin hos tarafi, boyle teknik ayrintilara girmeden "package -group" mantigini kullanmasiydi, ama bizim belli bir anlami olan parca-butun -iliskisini korumamiz daha mantikli bir yazilim ontology'si ortaya -cikaracaktir. Onlarin yaklasimi ise "anything goes", grup ile kategori'nin -temel bir farki yok cunku, herhangi bir bakis acisi olabilir "grup". - - -6. Modulleri test etmek (!!) (Eray) ------------------------------------- - -PISI'deki seçilen implementation detaylari bir tanima cok fazla commitment -yapmiyor, implementation'ın getirdiği tek şey paketleri bir ağaca koymak. -Component'ların seçiminin ne kadar kaliteli olduğunu belirleyemiyor. -Paketlerin ve componentlarin secimi yapiyor, ki kritik olan o. -Yalnız modulerlik tanimindan ve part-of iliskisinin -  if a is part of b, and b is part of c, then a is part of c. -  if a is part of b, and b is not part of c, then a is not part of c. -gibi sonuclari getirmesinden hareketle (ki bunlar klasik computational -ontology) kismen test edebilecegimiz bir sekil aliyor ornegin bagimlilik -graph'ini cluster ederek, ya da her modul icin bir modulerlik sayisi -hesaplayarak. Daha az formal olarak da bu sonuçları kafamızda yürüterek -yaptığımız componentların ne kadar akla yatkın olduğunu bulabiliriz. - - -7. Cagların frugalware önerisi ------------------------------- - -http://ftp.frugalware.org/pub/frugalware/frugalware-current/source/ -adresindeki yerleşimin hem source hem de binary depo için uygulanmasını ve -kategori, componentların da bundan çıkartılmasını öneriyorum. diff --git a/tags/pisi-1.0_beta2/doc/notes/mandrake component _ group tree.txt b/tags/pisi-1.0_beta2/doc/notes/mandrake component _ group tree.txt deleted file mode 100644 index f6edd70f..00000000 --- a/tags/pisi-1.0_beta2/doc/notes/mandrake component _ group tree.txt +++ /dev/null @@ -1,879 +0,0 @@ -From eray@uludag.org.tr Thu Jul 21 15:54:55 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id 351D885A97; - Thu, 21 Jul 2005 15:55:08 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id 0742810A659; - Thu, 21 Jul 2005 15:52:59 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id BABCC10A654 - for ; - Thu, 21 Jul 2005 15:52:56 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 91D0C86099; Thu, 21 Jul 2005 15:55:05 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from [192.168.1.5] (unknown [85.99.19.56]) - by uludag.org.tr (Postfix) with ESMTP id 0143385A97 - for ; Thu, 21 Jul 2005 15:55:04 +0300 (EEST) -From: Eray Ozkural -Organization: Pardus -To: cekirdek@uludag.org.tr -Date: Thu, 21 Jul 2005 15:54:55 +0300 -User-Agent: KMail/1.7.2 -MIME-Version: 1.0 -Message-Id: <200507211554.55602.eray@uludag.org.tr> -Cc: -Subject: [Cekirdek] [PISI design] mandrake component / group tree -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============2130999829==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 1651 -X-Length: 4961 - ---===============2130999829== -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -Mandrake'de "group" diye geciyor terim. Belki daha iyidir component'dan. Bu -component lafi akil mi karistiriyor diye killaniyorum hala. - -Bu arada, mandrake'nin bu olayini tam begenmedim. Tamam System'in alti -bizim dusundugumuz gibi, ama gerisi biraz daha category mantiginda, -debian'inki gibi yapilmis. Aslinda Archiving, Books, Cluster, Sciences, -Development, Networking fena degil ama bizim daha anlamli birseyler yapmamiz -gerekebilir, bu vizyonunuzu daraltmasin. Ornegin bizde OpenOffice bir -component olacak. Ya bizim componentlari en iyi python module'leri gibi -dusunun, "alt" notasyonu da bunu gostermek icin '.' olsun. - -apps.office partof apps -apps.office.openoffice partof apps.office - -openoffice-libs partof apps.office.openoffice -openoffice-bin partof apps.office.openoffice - -ornegin - -buradaki tabii ki onemli sey component hiyerarsisinin *birlikte install -edilen* adamlara ihtimam etmesi. Ornegin asagida System.Base aynen boyle, bu -da guzel birsey! - -Altlarindaki paketleri yazmiyorum. - -Mandrake Group Tree --------------------------------- - -Accessibility -Archiving - Backup - Cd burning - Compression - Other -Books - Computer books - Howtos - Literature - Other -Cluster - Message Passing - Queueing Services -Communications -Configuration -Databases -Development - C - C++ - Databases - Debug - Gnome and GTK+ - Java - KDE and Qt - Kernel - Libraries - Other - Perl - Python -Documentation -Editors -Education -Emulators -File Tools -Games - Adventure - Arcade - Boards - Cards - Other - Puzzles - Sports - Strategy -Graphical desktop - Enlightenment - FVWM based - GNOME - Icewm - KDE - Other - Sawfish - WindowMakes - Xfce -Graphics -Monitoring -Networking - Chat - File transfer - Instant messaging - Instant Messaging - IRC - Mail - News - Other - Remote access - WWW -Office -Publishing -Sciences - Astronomy - Biology - Chemistry - Computer science - Geosciences - Mathematics - Other - Physics -System - Base - Configuration - Cryptography - Deployment - Fonts - Internationalization - Kernel and hardware - Libraries - Servers - X11 - XFree86 -Shells -Sounds -System -Terminals -Text tools -Toys -Video - --- -Eray - ---===============2130999829== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============2130999829==-- - -From serdar@uludag.org.tr Thu Jul 21 16:10:37 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id 6010F85F66; - Thu, 21 Jul 2005 16:12:48 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id 7E52910A661; - Thu, 21 Jul 2005 16:10:39 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id 2FAA4950E8 - for ; - Thu, 21 Jul 2005 16:10:37 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 5ECC486095; Thu, 21 Jul 2005 16:12:46 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from webmail.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id 5801F86094 - for ; Thu, 21 Jul 2005 16:12:46 +0300 (EEST) -Received: from 193.140.74.2 (SquirrelMail authenticated user serdar) - by webmail.uludag.org.tr with HTTP; - Thu, 21 Jul 2005 16:10:37 +0300 (EEST) -Message-ID: <51672.193.140.74.2.1121951437.squirrel@webmail.uludag.org.tr> -In-Reply-To: <200507211554.55602.eray@uludag.org.tr> -References: <200507211554.55602.eray@uludag.org.tr> -Date: Thu, 21 Jul 2005 16:10:37 +0300 (EEST) -Subject: Re: [Cekirdek] [PISI design] mandrake component / group tree -From: serdar@uludag.org.tr -To: cekirdek@uludag.org.tr -User-Agent: SquirrelMail/1.4.4 -MIME-Version: 1.0 -X-Priority: 3 (Normal) -Importance: Normal -Cc: -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============1295726599==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 1655 -X-Length: 7560 - ---===============1295726599== -Content-Type: text/plain;charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Selamlar.. - -Benim görüşüm, kullanıcının karşısına ilk anda bu kadar çok -kategori çıkarsa, çabucak refüze olacağıdır. Kapsamları daraltıp, -işi 2 kademe yerine 3-4 kademeye yaymak daha kullanışlı olur -sanıyorum. - -İyi bir örnek değil ama, freshmeat.net'te ki kategorilere bir bakabiliriz. - -# Adaptive Technologies (51 projects) -# Artistic Software (165 projects) -# Communications (5684 projects) -# Database (2022 projects) -# Desktop Environment (2373 projects) -# Documentation (172 projects) -# Education (896 projects) -# freshmeat.net (28 projects) -# Games/Entertainment (2720 projects) -# Home Automation (80 projects) -# Information Management (1259 projects) -# Internet (10220 projects) -# Multimedia (6251 projects) -# Office/Business (2066 projects) -# Other/Nonlisted Topic (261 projects) -# Printing (227 projects) -# Religion (50 projects) -# Scientific/Engineering (2705 projects) -# Security (1591 projects) -# Software Development (10758 projects) -# System (10314 projects) -# Terminals (321 projects) -# Text Editors (647 projects) -# Text Processing (2416 projects) -# Utilities (3056 projects) - -Bu listeden çıkarılabilecek bir sürü şey olabilir. Hatta minor -şeyler birleştirilip bir alt seviyede detaylandırılabilir. Freshmeat -bunları upuzun uzatıyor, böylece aradığını bulmak daha kolay -oluyor. - -Yukarıdaki liste çok uygun değil. Örneğin, Text Editors ile Office -ayrımı çoğu için anlam ifade etmez. Database ile -development/business'in ayrık durması da anlamsız bence, Databases -development ve belki business altında listlenebilir. - -Liste ne kadar uzun olursa, o kadar bıkkınlık verici olacaktır -sanıyorum. Bu yüzden de laf gelimi, her kademede en fazla 10 girdi -olacak şekilde daha derin listeler hazırlanmasının faydalı -olacağını düşünüyorum.. - -Saygı ve sevgiler.. - -> Mandrake'de "group" diye geciyor terim. Belki daha iyidir component'dan. -> Bu -> component lafi akil mi karistiriyor diye killaniyorum hala. -> -> Bu arada, mandrake'nin bu olayini tam begenmedim. Tamam System'in alti -> bizim dusundugumuz gibi, ama gerisi biraz daha category mantiginda, -> debian'inki gibi yapilmis. Aslinda Archiving, Books, Cluster, Sciences, -> Development, Networking fena degil ama bizim daha anlamli birseyler -> yapmamiz -> gerekebilir, bu vizyonunuzu daraltmasin. Ornegin bizde OpenOffice bir -> component olacak. Ya bizim componentlari en iyi python module'leri gibi -> dusunun, "alt" notasyonu da bunu gostermek icin '.' olsun. -> -> apps.office partof apps -> apps.office.openoffice partof apps.office -> -> openoffice-libs partof apps.office.openoffice -> openoffice-bin partof apps.office.openoffice -> -> ornegin -> -> buradaki tabii ki onemli sey component hiyerarsisinin *birlikte install -> edilen* adamlara ihtimam etmesi. Ornegin asagida System.Base aynen boyle, -> bu -> da guzel birsey! -> -> Altlarindaki paketleri yazmiyorum. -> -> Mandrake Group Tree -> -------------------------------- -> -> Accessibility -> Archiving -> Backup -> Cd burning -> Compression -> Other -> Books -> Computer books -> Howtos -> Literature -> Other -> Cluster -> Message Passing -> Queueing Services -> Communications -> Configuration -> Databases -> Development -> C -> C++ -> Databases -> Debug -> Gnome and GTK+ -> Java -> KDE and Qt -> Kernel -> Libraries -> Other -> Perl -> Python -> Documentation -> Editors -> Education -> Emulators -> File Tools -> Games -> Adventure -> Arcade -> Boards -> Cards -> Other -> Puzzles -> Sports -> Strategy -> Graphical desktop -> Enlightenment -> FVWM based -> GNOME -> Icewm -> KDE -> Other -> Sawfish -> WindowMakes -> Xfce -> Graphics -> Monitoring -> Networking -> Chat -> File transfer -> Instant messaging -> Instant Messaging -> IRC -> Mail -> News -> Other -> Remote access -> WWW -> Office -> Publishing -> Sciences -> Astronomy -> Biology -> Chemistry -> Computer science -> Geosciences -> Mathematics -> Other -> Physics -> System -> Base -> Configuration -> Cryptography -> Deployment -> Fonts -> Internationalization -> Kernel and hardware -> Libraries -> Servers -> X11 -> XFree86 -> Shells -> Sounds -> System -> Terminals -> Text tools -> Toys -> Video -> -> -- -> Eray -> _______________________________________________ -> Cekirdek mailing list -> Cekirdek@uludag.org.tr -> http://liste.uludag.org.tr/mailman/listinfo/cekirdek -> - - - ---===============1295726599== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============1295726599==-- - -From eray@uludag.org.tr Wed Jul 27 13:02:17 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id AABE08584B; - Wed, 27 Jul 2005 13:02:30 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id EAF71E558D; - Wed, 27 Jul 2005 12:59:53 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id CF155E558D - for ; - Wed, 27 Jul 2005 12:59:52 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 0B4998584E; Wed, 27 Jul 2005 13:02:29 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from [192.168.1.5] (unknown [85.99.19.56]) - by uludag.org.tr (Postfix) with ESMTP id 719658584B - for ; Wed, 27 Jul 2005 13:02:28 +0300 (EEST) -From: Eray Ozkural -Organization: Pardus -To: cekirdek@uludag.org.tr -Subject: Re: [Cekirdek] [PISI design] mandrake component / group tree -Date: Wed, 27 Jul 2005 13:02:17 +0300 -User-Agent: KMail/1.7.2 -References: <200507211554.55602.eray@uludag.org.tr> -In-Reply-To: <200507211554.55602.eray@uludag.org.tr> -MIME-Version: 1.0 -Message-Id: <200507271302.17641.eray@uludag.org.tr> -Cc: -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============2058226043==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 1835 -X-Length: 5701 - ---===============2058226043== -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -Buna bakip dusundunuz mu? Bakiniz, mandrake'nin daha cok kategorik -bir ayrim, cok component mantigina uymuyor. Fedora daha uygun aslinda ama o da -cok basit yararli olmak icin. - -On Thursday 21 July 2005 03:54 pm, Eray Ozkural wrote: -> Mandrake'de "group" diye geciyor terim. Belki daha iyidir component'dan. Bu -> component lafi akil mi karistiriyor diye killaniyorum hala. -> -> Bu arada, mandrake'nin bu olayini tam begenmedim. Tamam System'in alti -> bizim dusundugumuz gibi, ama gerisi biraz daha category mantiginda, -> debian'inki gibi yapilmis. Aslinda Archiving, Books, Cluster, Sciences, -> Development, Networking fena degil ama bizim daha anlamli birseyler -> yapmamiz gerekebilir, bu vizyonunuzu daraltmasin. Ornegin bizde OpenOffice -> bir component olacak. Ya bizim componentlari en iyi python module'leri gibi -> dusunun, "alt" notasyonu da bunu gostermek icin '.' olsun. -> -> apps.office partof apps -> apps.office.openoffice partof apps.office -> -> openoffice-libs partof apps.office.openoffice -> openoffice-bin partof apps.office.openoffice -> -> ornegin -> -> buradaki tabii ki onemli sey component hiyerarsisinin *birlikte install -> edilen* adamlara ihtimam etmesi. Ornegin asagida System.Base aynen boyle, -> bu da guzel birsey! -> -> Altlarindaki paketleri yazmiyorum. -> -> Mandrake Group Tree -> -------------------------------- -> -> Accessibility -> Archiving -> Backup -> Cd burning -> Compression -> Other -> Books -> Computer books -> Howtos -> Literature -> Other -> Cluster -> Message Passing -> Queueing Services -> Communications -> Configuration -> Databases -> Development -> C -> C++ -> Databases -> Debug -> Gnome and GTK+ -> Java -> KDE and Qt -> Kernel -> Libraries -> Other -> Perl -> Python -> Documentation -> Editors -> Education -> Emulators -> File Tools -> Games -> Adventure -> Arcade -> Boards -> Cards -> Other -> Puzzles -> Sports -> Strategy -> Graphical desktop -> Enlightenment -> FVWM based -> GNOME -> Icewm -> KDE -> Other -> Sawfish -> WindowMakes -> Xfce -> Graphics -> Monitoring -> Networking -> Chat -> File transfer -> Instant messaging -> Instant Messaging -> IRC -> Mail -> News -> Other -> Remote access -> WWW -> Office -> Publishing -> Sciences -> Astronomy -> Biology -> Chemistry -> Computer science -> Geosciences -> Mathematics -> Other -> Physics -> System -> Base -> Configuration -> Cryptography -> Deployment -> Fonts -> Internationalization -> Kernel and hardware -> Libraries -> Servers -> X11 -> XFree86 -> Shells -> Sounds -> System -> Terminals -> Text tools -> Toys -> Video - --- -Eray Ozkural (exa), Uludag Gelistiricisi -http://cekirdek.uludag.org.tr/~eray http://www.kde.org -http://www.cs.bilkent.edu.tr/~erayo http://www.malfunct.com - ---===============2058226043== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============2058226043==-- - -From eray@uludag.org.tr Wed Sep 7 20:05:53 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id 8D2A084F4B; - Wed, 7 Sep 2005 20:06:04 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id 086A718789A; - Wed, 7 Sep 2005 20:00:16 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id F039818789A - for ; - Wed, 7 Sep 2005 20:00:02 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 401CE8F9B9; Wed, 7 Sep 2005 20:05:51 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from [192.168.1.5] (unknown [85.97.87.38]) - by uludag.org.tr (Postfix) with ESMTP id A4EC084F4B - for ; Wed, 7 Sep 2005 20:05:50 +0300 (EEST) -From: Eray Ozkural -Organization: Pardus -To: cekirdek@uludag.org.tr -Subject: Re: [Cekirdek] [PISI design] mandrake component / group tree -Date: Wed, 7 Sep 2005 20:05:53 +0300 -User-Agent: KMail/1.7.2 -References: <200507211554.55602.eray@uludag.org.tr> -In-Reply-To: <200507211554.55602.eray@uludag.org.tr> -MIME-Version: 1.0 -Message-Id: <200509072005.53482.eray@uludag.org.tr> -Cc: -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============1083705676==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 3642 -X-Length: 5765 - ---===============1083705676== -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -bunu gormus muydunuz? - -genelde iki seviye ana component'lari belirtmek icin yeterli -mandrake'nin kafasinin karismasi icin kategorilerle componentlari -karismasi yeterli olmus, yani asagidaki bircok sey aslinda component -*degil* kategori. - -On Thursday 21 July 2005 03:54 pm, Eray Ozkural wrote: -> Mandrake'de "group" diye geciyor terim. Belki daha iyidir component'dan. Bu -> component lafi akil mi karistiriyor diye killaniyorum hala. -> -> Bu arada, mandrake'nin bu olayini tam begenmedim. Tamam System'in alti -> bizim dusundugumuz gibi, ama gerisi biraz daha category mantiginda, -> debian'inki gibi yapilmis. Aslinda Archiving, Books, Cluster, Sciences, -> Development, Networking fena degil ama bizim daha anlamli birseyler -> yapmamiz gerekebilir, bu vizyonunuzu daraltmasin. Ornegin bizde OpenOffice -> bir component olacak. Ya bizim componentlari en iyi python module'leri gibi -> dusunun, "alt" notasyonu da bunu gostermek icin '.' olsun. -> -> apps.office partof apps -> apps.office.openoffice partof apps.office -> -> openoffice-libs partof apps.office.openoffice -> openoffice-bin partof apps.office.openoffice -> -> ornegin -> -> buradaki tabii ki onemli sey component hiyerarsisinin *birlikte install -> edilen* adamlara ihtimam etmesi. Ornegin asagida System.Base aynen boyle, -> bu da guzel birsey! -> -> Altlarindaki paketleri yazmiyorum. -> -> Mandrake Group Tree -> -------------------------------- -> -> Accessibility -> Archiving -> Backup -> Cd burning -> Compression -> Other -> Books -> Computer books -> Howtos -> Literature -> Other -> Cluster -> Message Passing -> Queueing Services -> Communications -> Configuration -> Databases -> Development -> C -> C++ -> Databases -> Debug -> Gnome and GTK+ -> Java -> KDE and Qt -> Kernel -> Libraries -> Other -> Perl -> Python -> Documentation -> Editors -> Education -> Emulators -> File Tools -> Games -> Adventure -> Arcade -> Boards -> Cards -> Other -> Puzzles -> Sports -> Strategy -> Graphical desktop -> Enlightenment -> FVWM based -> GNOME -> Icewm -> KDE -> Other -> Sawfish -> WindowMakes -> Xfce -> Graphics -> Monitoring -> Networking -> Chat -> File transfer -> Instant messaging -> Instant Messaging -> IRC -> Mail -> News -> Other -> Remote access -> WWW -> Office -> Publishing -> Sciences -> Astronomy -> Biology -> Chemistry -> Computer science -> Geosciences -> Mathematics -> Other -> Physics -> System -> Base -> Configuration -> Cryptography -> Deployment -> Fonts -> Internationalization -> Kernel and hardware -> Libraries -> Servers -> X11 -> XFree86 -> Shells -> Sounds -> System -> Terminals -> Text tools -> Toys -> Video - --- -Eray Ozkural (exa), Uludag Gelistiricisi -http://cekirdek.uludag.org.tr/~eray http://www.kde.org -http://www.cs.bilkent.edu.tr/~erayo http://www.malfunct.com - ---===============1083705676== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============1083705676==-- - diff --git a/tags/pisi-1.0_beta2/doc/notes/release hikayesi.txt b/tags/pisi-1.0_beta2/doc/notes/release hikayesi.txt deleted file mode 100644 index 9fb1b4e6..00000000 --- a/tags/pisi-1.0_beta2/doc/notes/release hikayesi.txt +++ /dev/null @@ -1,110 +0,0 @@ -From eray@uludag.org.tr Thu Jul 28 16:42:47 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from liste.uludag.org.tr (pisi.uludag.org.tr [193.140.100.210]) - by uludag.org.tr (Postfix) with ESMTP id 0CE2C75758; - Thu, 28 Jul 2005 16:43:24 +0300 (EEST) -Received: from pisi.uludag.org.tr (localhost [127.0.0.1]) - by liste.uludag.org.tr (Postfix) with ESMTP id 2FD2D109DF1; - Thu, 28 Jul 2005 16:40:43 +0300 (EEST) -X-Original-To: cekirdek@liste.uludag.org.tr -Delivered-To: cekirdek@liste.uludag.org.tr -Received: from uludag.org.tr (comar.uludag.org.tr [193.140.100.220]) - by liste.uludag.org.tr (Postfix) with ESMTP id B4AAA109DDB - for ; - Thu, 28 Jul 2005 16:40:40 +0300 (EEST) -Received: by uludag.org.tr (Postfix) - id 5D432858B5; Thu, 28 Jul 2005 16:43:21 +0300 (EEST) -Delivered-To: cekirdek@uludag.org.tr -Received: from [192.168.1.5] (unknown [85.99.19.56]) - by uludag.org.tr (Postfix) with ESMTP id CC4ED75758 - for ; Thu, 28 Jul 2005 16:43:19 +0300 (EEST) -From: Eray Ozkural -Organization: Pardus -To: cekirdek@uludag.org.tr -Date: Thu, 28 Jul 2005 16:42:47 +0300 -User-Agent: KMail/1.7.2 -MIME-Version: 1.0 -Message-Id: <200507281642.47792.eray@uludag.org.tr> -Cc: -Subject: [Cekirdek] [PISI design] release hikayesi -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============1945860385==" -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 1875 -X-Length: 4330 - ---===============1945860385== -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -selamlar, - -dun konustuklarimiz uzerine biraz yatip dusundum. bir ara haci -kuslugu yapmisim ben de ve bir durumu gozden kacirmisim. -dun caglar ve murat'in getirdigi 2. oneriyle karisik bir sey yapmamiz -gerekebilir. benim kafam mi dagilmis ne kusura bakmayin. ama -o kadar onemli degil. - -soyle bir sorun var. - -simdi bir source var x diye, 5. release'de - -icindeki sadece bir paketi ornegin x2'yi etkileyecek bir degisiklik yaptik. - -bu durumda x1 ve x3'un build numaralari artmiyor. ama source release -numaralari mi artiyor? tamam buraya kadar ok. ama build sistemi -bu paketlerden yeni bir paket dosyasi yapip repository'e koymuyor bu -durumda, yani source release'i arttigi halde build nosu degismedigi icin -yeni paket koyulmayacak ve indekslenmeyecek bu mantikli mi? mantikli -degilse nasil bir cozum bulunur? - -bunun yani sira, simdi bu source release degistiginde, eger paketi build -*edersek*, bir yerde metadata degismek zorunda degil mi? hangi source'un -hangi release'inden build edildigini kaydetmek zorundayiz yanlis mi -dusunuyorum. hemen kizmayin butun bu olaylari basimiza ben sarmadim, bir -sekilde evrimlesti :) - -not: galiba olay suna geliyor, tamam build no degismediyse ozunde bu paket -bir onceki source release'inde kalmistir deriz, yani yeni bir dosya kesinlikle -koymayiz repository'e cunku install dosyalari ve metadata, release numarasi -disinda ayni kalacak. offffff. - -su anda multiple repository olayinin ilkel versiyonunu kodluyorum bu arada. - -gorusuruz, - --- -Eray Ozkural (exa), Uludag Gelistiricisi -http://cekirdek.uludag.org.tr/~eray http://www.kde.org -http://www.cs.bilkent.edu.tr/~erayo http://www.malfunct.com - ---===============1945860385== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/mailman/listinfo/cekirdek - ---===============1945860385==-- - diff --git a/tags/pisi-1.0_beta2/doc/notes/source release ve binary build numaralari.txt b/tags/pisi-1.0_beta2/doc/notes/source release ve binary build numaralari.txt deleted file mode 100644 index 345de3e2..00000000 --- a/tags/pisi-1.0_beta2/doc/notes/source release ve binary build numaralari.txt +++ /dev/null @@ -1,125 +0,0 @@ -From eray@uludag.org.tr Tue Jun 28 18:49:13 2005 -Return-Path: -X-Original-To: eray@uludag.org.tr -Delivered-To: eray@uludag.org.tr -Received: from uludag.org.tr (localhost [127.0.0.1]) - by uludag.org.tr (Postfix) with ESMTP id 80D2653C00C; - Tue, 28 Jun 2005 16:07:58 +0300 (EEST) -X-Original-To: cekirdek@uludag.org.tr -Delivered-To: cekirdek@uludag.org.tr -Received: from [192.168.3.131] (unknown [193.140.73.11]) - by uludag.org.tr (Postfix) with ESMTP id 0B6B753C00C - for ; Tue, 28 Jun 2005 16:07:57 +0300 (EEST) -From: Eray Ozkural -To: cekirdek@uludag.org.tr -Date: Tue, 28 Jun 2005 15:49:13 +0000 -User-Agent: KMail/1.8.1 -MIME-Version: 1.0 -Message-Id: <200506281549.13525.eray@uludag.org.tr> -Subject: [Cekirdek] source release ve binary build numaralari -X-BeenThere: cekirdek@liste.uludag.org.tr -X-Mailman-Version: 2.1.5 -Precedence: list -Reply-To: cekirdek@uludag.org.tr -List-Id: cekirdek.liste.uludag.org.tr -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Content-Type: multipart/mixed; - boundary="===============2126904290==" -Mime-version: 1.0 -Sender: cekirdek-bounces@liste.uludag.org.tr -Errors-To: cekirdek-bounces@liste.uludag.org.tr -X-UID: 865 -X-Length: 4347 - ---===============2126904290== -Content-Type: text/plain; - charset="us-ascii" -Content-Transfer-Encoding: 7bit -Content-Disposition: inline - -yigitler, - -bu post'da dun tartistigimiz bir konuyu ilgilendiren -paket versiyonu numaralarina tam bir aciklik getirmeye -calisacagim. - -Bir PISI source'u uc tane sayiyla belirlenir: - name, version, release - -Burada version "convenience" icin bulunur. name + release -ise her zaman *ayni* PISI source build islemine sebep olur. -Bundan kasit su. version ve release tamamen bagimsiz. -release 0 ile baslar. ornegin kdevelop - -ilk basta -name: kdevelop, version: 3.4.1, release: 0 -dir - -Bu paketin yeni versiyonlariyla biz ugrastikca, yaptigimiz -her update, en minikleri dahi, release'i arttirir, ve her zaman -bir arttirir (daha aciklayacagim), ama hic bir zaman geriye -gitmez (0'lanmaz ornegin). - -ileride: -name: kdevelop, version: 3.4.2, release: 3 -olabilir ornegin. - -Eger paketin gelistirildigi *distribution* source'u dahilinde -bir versiyon dallanmasi varsa, ancak bu durumda release'e -branch'ler eklenir. - -Diyelim ki yukaridaki paket pardus 1.0'in parcasiydi. simdi -pardus 1.0.1 diye bir branch olusturulmak istendi, ornegin -bu UEKAE overlay'ine karsilik gelsin. Bu durumda, versiyon -iliskisini eksiksiz bicimde belirtmek icin: -name: kdevelop, version: 3.4.2, release: 3.1 - -demek yeterli olacaktir. Ekledigimiz '.1' suffix'i bize butun -dal bilgisini verir. Boylece eksik hicbirsey olmaz. - -Binary package'lara gelince. Bir binary package dort -stringle her zaman bulunabilir. - name, version, build, architecture - -burada name + build, *bir binary distribution* dahilinde, -ornegin Pardus 1.0 x86 icin yapilmis tek ve tek bir paketi -her zaman gosterir. - -Build, o architecture icin, o paketin kacinci kere build -edildigini gosterir. Her paket release'inde en fazla bir -artar. - -Bunu daha once tartistigimiz gibi tamamen incremental -build script'inin buldugu md5'larla hesapliyoruz. - -Binary package'larin build numarasi icin bir dallanma/budaklanma -semasi henuz onermiyorum, ama bana su anda ayni -source package'lar gibi birsey yapilabilir geliyor. Bana buradaki -en kritik mesele source ve binary package'larini, ve upstream -version string'lerle kendi, SVN-tarzi version string'lerimizi -karistirmamamiz. - -Kaplan gunler, - --- -Eray - ---===============2126904290== -Content-Type: text/plain; charset="iso-8859-9" -MIME-Version: 1.0 -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline - -_______________________________________________ -Cekirdek mailing list -Cekirdek@uludag.org.tr -http://liste.uludag.org.tr/cgi-bin/mailman/listinfo/cekirdek - ---===============2126904290==-- - diff --git a/tags/pisi-1.0_beta2/doc/package_versions.pdf b/tags/pisi-1.0_beta2/doc/package_versions.pdf deleted file mode 100644 index 09228904c19bf06a5944ab1ece161d251ea6dd4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102463 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

nzVU3^#+3QhQbz#8#0oK8w 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 OLUYN>uiI$E_5T2T{V?4C diff --git a/tags/pisi-1.0_beta2/doc/package_versions.tex b/tags/pisi-1.0_beta2/doc/package_versions.tex deleted file mode 100644 index 25b52f5a..00000000 --- a/tags/pisi-1.0_beta2/doc/package_versions.tex +++ /dev/null @@ -1,186 +0,0 @@ -\documentclass[a4paper,11pt]{article} - -\title{P\.IS\.I Packages: Version Policy v0.2} -\date{\today} -\author{Eray \"Ozkural and T. Bar\i{}\c s Metin} - - -\begin{document} -\maketitle - -\section*{Revision History} -\begin{itemize} -\item v0.1: Bar\i\c s Metin wrote the first version preparing the outline, -detailed Source Version Section, and started the Section on Release Number. -\item v0.2: Eray \"Ozkural wrote a detailed introduction, added - explanations of release and build numbers, reorganized a bit. -\end{itemize} - -\section{Introduction} - -This document explains the \emph{version policy} that applies to -P\.IS\.I packages. Classically, the issue of distinguishing source and -binary distributions unambiguously has not received a rigorous -treatment in the context of LINUX distributions. We have identified -several shortcomings of the usual practices of extending the original -version with suffixes and prefixes, colorfully illustrated in the -following common problems. - -\begin{description} - -\item[The problem of future downgrades] -The distribution chooses to use a previous version of the package in -the next release. There is no way to indicate this, so ad-hoc -solutions such as version prefixes are used. It is -impossible to denote a future dependency that requires at least this -distribution source release in this case, either. - -\item[The problem of redundant distributions] -A trivial patch has been applied to the source. While few binary -packages have been affected by this change, all binary packages -built from the source are redistributed. - -\item[The problem of underdetermined rebuilds] -There have been rapid changes in the system, and although no -changes have been made to the package source, a new binary -distribution must be prepared. - -\end{description} - -We have devised a slightly new approach in order to alleviate these -problems. Our solution consists of encoding the history of source and -binary package developments in separate version strings we call release and -build numbers. - -Since the source version is usually used by the users and developers -to identify software, we retain the notion of a source version in -P\.IS\.I as a convenience. - -In the following sections, we explain the components of our -versioning scheme. - -\subsection{Source Version} - -Source version is the version number provided by the -upstream maintainer of the source archive used in package. It must -always be the same as the upstream version used. - -\textbf{Example}: If the upstream archive name is -\emph{bash-3.0.tar.gz} the version number of the package is \emph{3.0} - -\subsubsection{Version Suffixes} - -There is a pre-defined list of suffixes a package version can -take. - -\begin{itemize} - \item \textbf{alpha} Source/Package is in alpha state - \item \textbf{beta} Source/Package is in beta state - \item \textbf{pre} Source/Pacgage passed the beta state but stable - version is not relased yet. - \item \textbf{rc} Source/Package is a release-candidate. - \item \textbf{p} Source/Package is released and some patches are - applied after the release. This is the patch level. -\end{itemize} - -The suffix should be written after the special separator -character \textbf{\_}. And there must allways be a number after a -suffix. \textbf{Example}: packagename-1.0\_beta1 - -The basic order of the priorities for suffixes is:\newline -\emph{p $>$ (no suffix) $>$ rc $>$ pre $>$ beta $>$ alpha}. - -The scope of a source version string is global in the literal -sense. It shall not vary from repository to repository. - -The support for these special suffixes as well as usual alphanumeric -version string ordering has been implemented in P\.IS\.I. - -\section{Identifying Package Sources} - -A P\.IS\.I source has three identity elements written under -\texttt{SOURCE} tag: name, source version, and source release number. -We usually say just version and release number/release instead of -source version and source release number, respectively. Name is available in -the \texttt{} tag. Version and release are available in the last -\texttt{} element of \texttt{} tag of a \texttt{PSPEC}. - -The name of a source package is constant throughout its revision -history. The version is the original version, given by its -programmers. Release is a positive integer. Name and release -is sufficient to uniquely identify a particular PISI source revision. -That is, version and release are independent. - -\subsection{Release Number} - -Release number is the number of the changes that are made to the -package source since the initial version in the distribution source. A -change can be a patch applied to the source archive, modification in -the actions.py, pspec.xml or any file in the source package -directory. This change is indicated in \texttt{} tags manually -by the package maintainer. - -The initial release of a package is by default \texttt{1}. The release -number always increments by $1$ in each revision in the -\texttt{History}, even the slightest ones, but it never decrements. - -The scope of the release number is a given distribution, regardless of -its version, e.g. Pardus. - -In the future, PISI will have strict checks for release numbers. - -\subsection{Dependency Specifications} - -We allow a package to use both source version and release to identify -a particular version or a range of package versions. - -\section{Identifying Binary packages} - -A PISI binary package is produced from a PISI source package. It has a -name that is constant throughout the history of the source package, -and it inherits the source version and release number from the source -package. However, a binary package has in addition a binary build -number. Shortly, build number or just build. For each of the -architecture targets, e.g. particular binaries, it also has an -architecture tag. - -A binary package is uniquely identified by its name, build number, and -architecture regardless of the source version. - -\section{Build Number} - -Similarly to source release number, binary build number is the number -of changes that are made to a binary package. By change, we mean any -bit change. The existence of a change is tested by comparing the -cryptographic checksums in files.xml with those of the previous build, and the -build number is automatically determined by the P\.IS\.I build system. -The build number starts from $1$ as in release number, and increments -by one with each binary change. - -The user never interferes with the build number himself. However, if -the user fails to provide the previous build, then a package without -a build number is built. A package without a build number is evaluated -on the basis of release number, which is guaranteed to exist. - -The scope of a build number is a given distribution build environment -for a particular architecture, which may vary from repository to -repository. Therefore, it is not used in dependency -specifications. However, the system does assume that a build of a -given package and architecture is unique in a given repository. - -\section{Package File Names} - -A P\.IS\.I binary package file name contains all the components relevant -to its identification, separated by dashes: -\begin{verbatim} - ---.pisi -\end{verbatim} - -\section{Future Work} - -In the future, it may be necessary to extend the notion of release -number and build number to support branches and forks of a -distribution. A proposal was to have CVS-like branching, but it -was dismissed as unnecessary. - -\end{document} diff --git a/tags/pisi-1.0_beta2/doc/prettyref.sty b/tags/pisi-1.0_beta2/doc/prettyref.sty deleted file mode 100644 index 67940f3b..00000000 --- a/tags/pisi-1.0_beta2/doc/prettyref.sty +++ /dev/null @@ -1,37 +0,0 @@ -%% -%% This is file `prettyref.sty', -%% generated with the docstrip utility. -%% -%% The original source files were: -%% -%% prettyref.dtx (with options: `style') -%% -%% Copyright (c) 1995 Kevin Ruland -%% -%% -%% prettyref v3.0 -%% -%% Copyright 1995,1998. by Kevin Ruland kevin@rodin.wustl.edu -%% -\ProvidesPackage{prettyref}[1998/07/09 v3.0] -\def\newrefformat#1#2{% - \@namedef{pr@#1}##1{#2}} -\newrefformat{eq}{\textup{(\ref{#1})}} -\newrefformat{lem}{Lemma \ref{#1}} -\newrefformat{thm}{Theorem \ref{#1}} -\newrefformat{cha}{Chapter \ref{#1}} -\newrefformat{sec}{Section \ref{#1}} -\newrefformat{tab}{Table \ref{#1} on page \pageref{#1}} -\newrefformat{fig}{Figure \ref{#1} on page \pageref{#1}} -\def\prettyref#1{\@prettyref#1:} -\def\@prettyref#1:#2:{% - \expandafter\ifx\csname pr@#1\endcsname\relax% - \PackageWarning{prettyref}{Reference format #1\space undefined}% - \ref{#1:#2}% - \else% - \csname pr@#1\endcsname{#1:#2}% - \fi% -} -\endinput -%% -%% End of file `prettyref.sty'. diff --git a/tags/pisi-1.0_beta2/pisi-cli b/tags/pisi-1.0_beta2/pisi-cli deleted file mode 100755 index 5fbec621..00000000 --- a/tags/pisi-1.0_beta2/pisi-cli +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import sys -import locale -import traceback -import exceptions - -import pisi.ui -import pisi.context as ctx -from pisi.cli.pisicli import PisiCLI - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -def handle_exception(exception, value, tb): - - ui = pisi.cli.CLI() # make a temporary UI - show_traceback = False - if exception == exceptions.KeyboardInterrupt: - ui.error(_("Keyboard Interrupt: Exiting...")) - sys.exit(1) - elif isinstance(value, pisi.Error): - ui.error(_("Fatal Error. Program Terminated.")) - show_traceback = ctx.get_option('debug') - elif isinstance(value, pisi.Exception): - show_traceback = True - ui.error(_(""" -Unhandled internal exception. -Please file a bug report. (http://bugs.uludag.org.tr)""")) - else: - # For any other exception (possibly Python exceptions) show - # the traceback! - show_traceback = ctx.get_option('debug') - ui.error(_("System Error. Program Terminated.")) - - ui.error("%s: %s\n" % (exception, value)) - - ui.info(_("Please use 'pisi help' for general help.")) - - if show_traceback: - ui.info(_("Traceback:")) - traceback.print_tb(tb) - else: - ui.info(_("Use --debug to see a traceback.")) - - sys.exit(1) - -if __name__ == "__main__": - - sys.excepthook = handle_exception - - locale.setlocale(locale.LC_ALL, '') - cli = PisiCLI() - cli.run_command() diff --git a/tags/pisi-1.0_beta2/pisi-spec.dtd b/tags/pisi-1.0_beta2/pisi-spec.dtd deleted file mode 100644 index 075d9459..00000000 --- a/tags/pisi-1.0_beta2/pisi-spec.dtd +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tags/pisi-1.0_beta2/pisi.e3p b/tags/pisi-1.0_beta2/pisi.e3p deleted file mode 100644 index 38d51f48..00000000 --- a/tags/pisi-1.0_beta2/pisi.e3p +++ /dev/null @@ -1,484 +0,0 @@ - - - - - - - Python - Qt - The package management software of Pardus distribution. - - PiSi Development Team - - - -

tools - ebuild2pisi.py - - - tools - cat-db.py - - - tests - popt - actions.py - - - tests - zip - actions.py - - - tests - unzip - actions.py - - - tests - configfiletests.py - - - tests - sourcedbtests.py - - - tests - utiltests.py - - - tests - installdbtests.py - - - tests - run.py - - - tests - metadatatests.py - - - tests - constantstests.py - - - tests - fetchertests.py - - - tests - archivetests.py - - - tests - versiontests.py - - - tests - actionsapitests.py - - - tests - specfiletests.py - - - tests - packagetests.py - - - tests - packagedbtests.py - - - tests - graphtests.py - - - pisi - actionsapi - get.py - - - pisi - actionsapi - shelltools.py - - - pisi - actionsapi - variables.py - - - pisi - actionsapi - autotools.py - - - pisi - actionsapi - pisitools.py - - - pisi - actionsapi - kde.py - - - pisi - actionsapi - __init__.py - - - pisi - actionsapi - libtools.py - - - pisi - actionsapi - coreutils.py - - - pisi - cli - pisicli.py - - - pisi - cli - __init__.py - - - pisi - cli - commands.py - - - pisi - lockeddbshelve.py - - - pisi - specfile.py - - - pisi - package.py - - - pisi - __init__.py - - - pisi - build.py - - - pisi - packagedb.py - - - pisi - files.py - - - pisi - config.py - - - pisi - index.py - - - pisi - repodb.py - - - pisi - ui.py - - - pisi - util.py - - - pisi - dependency.py - - - pisi - metadata.py - - - pisi - pgraph.py - - - pisi - operations.py - - - pisi - context.py - - - pisi - sourcefetcher.py - - - pisi - graph.py - - - pisi - sourcearchive.py - - - pisi - configfile.py - - - pisi - sourcedb.py - - - pisi - installdb.py - - - pisi - constants.py - - - pisi - fetcher.py - - - pisi - archive.py - - - pisi - version.py - - - setup.py - - - pisi - actionsapi - pisitoolsfunctions.py - - - tools - repostats.py - - - pisi - uri.py - - - pisi - api.py - - - TODO - - - tools - fetchAll.py - - - pisi - actionsapi - pythonmodules.py - - - pisi - actionsapi - scons.py - - - pisi - cli - colors.py - - - pisi-cli - - - pisi - actionsapi - perlmodules.py - - - pisi - comariface.py - - - po - tr.po - - - pisi - oo.py - - - tools - update-environ.py - - - tools - convert_history.py - - - tests - dependencytests.py - - - pisi - atomicoperations.py - - - tests - ootests.py - - - tests - testcase.py - - - tools - fix_old_metadata_files.py - - - tests - xmlexttests.py - - - tests - filestests.py - - - pisi - component.py - - - tests - autoxmltests.py - - - pisi - pxml - xmlextpiks.py - - - pisi - pxml - autoxml.py - - - pisi - pxml - xmlfilemdom.py - - - pisi - pxml - xmlextmdom.py - - - pisi - pxml - __init__.py - - - pisi - pxml - xmlfile.py - - - pisi - pxml - xmlext.py - - - pisi - pxml - xmlfilecdom.py - - - pisi - pxml - xmlextcdom.py - - - pisi - pxml - xmlfilepiks.py - - - tools - find-lib-deps.py - - - tools - svndist.py - - - tools - rmcomp-source-repo.py - - - tools - check-source-repo.py - - - - - - - - - - - pisi-cli - - - tests - beta-light.sh - - - tests - beta-upgrade.sh - - - tests - beta.sh - - - tests - sandbox - - - tests - beta-remoterepo.sh - - - - pisi-cli - - - Subversion - {'status': [], 'log': [], 'global': [], 'update': [], 'remove': [], 'add': [], 'tag': [], 'export': [], 'diff': [], 'commit': [], 'checkout': [], 'history': []} - {'standardLayout': 1} - - - - - - - - - diff --git a/tags/pisi-1.0_beta2/pisi/__init__.py b/tags/pisi-1.0_beta2/pisi/__init__.py deleted file mode 100644 index bf7bb9c7..00000000 --- a/tags/pisi-1.0_beta2/pisi/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# PiSi version - -__version__ = "1.0_beta2" - -__all__ = [ 'api', 'packagedb', 'installdb' ] - -class Exception(Exception): - """Class of exceptions that must be caught and handled within PISI""" - def __str__(self): - s = '' - for x in self.args: - if s != '': - s += '\n' - s += x.encode('utf-8') - return s - -class Error(Exception): - """Class of exceptions that lead to program termination""" - pass - -# FIXME: can't do this due to name clashes in config and other singletons booo -#from pisi.api import * diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/__init__.py b/tags/pisi-1.0_beta2/pisi/actionsapi/__init__.py deleted file mode 100644 index eeba55a7..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import pisi - -class Error(pisi.Error): - pass - -class Exception(pisi.Exception): - pass - -import pisi.context as ctx - -def error(msg): - if ctx.config.get_option('ignore_action_errors'): - ctx.ui.error(msg) - else: - raise Error(msg) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/autotools.py b/tags/pisi-1.0_beta2/pisi/actionsapi/autotools.py deleted file mode 100644 index 8491ca00..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/autotools.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Standard Python Modules -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get as get -from pisi.actionsapi.shelltools import system -from pisi.actionsapi.shelltools import can_access_file -from pisi.actionsapi.libtools import gnuconfig_update - -class ConfigureError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - if can_access_file('config.log'): - ctx.ui.error(_('Please attach the config.log to your bug report:\n%s/config.log') % os.getcwd()) - -class MakeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class InstallError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class RunTimeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def configure(parameters = ''): - '''configure source with given parameters = "--with-nls --with-libusb --with-something-usefull"''' - if can_access_file('configure'): - gnuconfig_update() - - args = './configure \ - --prefix=/%s \ - --host=%s \ - --mandir=/%s \ - --infodir=/%s \ - --datadir=/%s \ - --sysconfdir=/%s \ - --localstatedir=/%s \ - %s' % (get.defaultprefixDIR(), \ - get.HOST(), get.manDIR(), \ - get.infoDIR(), get.dataDIR(), \ - get.confDIR(), get.localstateDIR(), parameters) - - if system(args): - raise ConfigureError(_('Configure failed.')) - else: - raise ConfigureError(_('No configure script found.')) - -def rawConfigure(parameters = ''): - '''configure source with given parameters = "--prefix=/usr --libdir=/usr/lib --with-nls"''' - if can_access_file('configure'): - gnuconfig_update() - - if system('./configure %s' % parameters): - raise ConfigureError(_('Configure failed.')) - else: - raise ConfigureError(_('No configure script found.')) - -def compile(parameters = ''): - #FIXME: Only one package uses this until now, hmmm - system('%s %s %s' % (get.CC(), get.CFLAGS(), parameters)) - -def make(parameters = ''): - '''make source with given parameters = "all" || "doc" etc.''' - if system('make %s' % parameters): - raise MakeError(_('Make failed.')) - -def install(parameters = '', argument = 'install'): - '''install source into install directory with given parameters''' - if can_access_file('makefile') or can_access_file('Makefile') or can_access_file('GNUmakefile'): - args = 'make prefix=%(prefix)s/%(defaultprefix)s \ - datadir=%(prefix)s/%(data)s \ - infodir=%(prefix)s/%(info)s \ - localstatedir=%(prefix)s/%(localstate)s \ - mandir=%(prefix)s/%(man)s \ - sysconfdir=%(prefix)s/%(conf)s \ - %(parameters)s \ - %(argument)s' % {'prefix': get.installDIR(), - 'defaultprefix': get.defaultprefixDIR(), - 'man': get.manDIR(), - 'info': get.infoDIR(), - 'localstate': get.localstateDIR(), - 'conf': get.confDIR(), - 'data': get.dataDIR(), - 'parameters': parameters, - 'argument':argument} - - if system(args): - raise InstallError(_('Install failed.')) - else: - raise InstallError(_('No Makefile found.')) - -def rawInstall(parameters = '', argument = 'install'): - '''install source into install directory with given parameters = PREFIX=%s % get.installDIR()''' - if can_access_file('makefile') or can_access_file('Makefile') or can_access_file('GNUmakefile'): - if system('make %s %s' % (parameters, argument)): - raise InstallError(_('Install failed.')) - else: - raise InstallError(_('No Makefile found.')) - -def aclocal(parameters = ''): - '''generates an aclocal.m4 based on the contents of configure.in.''' - if system('aclocal %s' % parameters): - raise RunTimeError(_('Running aclocal failed.')) - -def autoconf(parameters = ''): - '''generates a configure script''' - if system('autoconf %s' % parameters): - raise RunTimeError(_('Running autoconf failed.')) - -def autoreconf(parameters = ''): - '''re-generates a configure script''' - if system('autoreconf %s' % parameters): - raise RunTimeError(_('Running autoconf failed.')) - -def automake(parameters = ''): - '''generates a makefile''' - if system('automake %s' % parameters): - raise RunTimeError(_('Running automake failed.')) - -def autoheader(parameters = ''): - '''generates templates for configure''' - if system('autoheader %s' % parameters): - raise RunTimeError(_('Running autoheader failed.')) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/coreutils.py b/tags/pisi-1.0_beta2/pisi/actionsapi/coreutils.py deleted file mode 100644 index 83f8ede1..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/coreutils.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python -#-*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Standard Python Modules -import re -import sys -from itertools import izip -from itertools import imap -from itertools import count -from itertools import ifilter -from itertools import ifilterfalse - -# ActionsAPI -import pisi.actionsapi - -def cat(filename): - return file(filename).xreadlines() - -class grep: - '''keep only lines that match the regexp''' - def __init__(self, pat, flags = 0): - self.fun = re.compile(pat, flags).match - def __ror__(self, input): - return ifilter(self.fun, input) - -class tr: - '''apply arbitrary transform to each sequence element''' - def __init__(self, transform): - self.tr = transform - def __ror__(self, input): - return imap(self.tr, input) - -class printto: - '''print sequence elements one per line''' - def __init__(self, out = sys.stdout): - self.out = out - def __ror__(self,input): - for line in input: - print >> self.out, line - -printlines = printto(sys.stdout) - -class terminator: - def __init__(self,method): - self.process = method - def __ror__(self,input): - return self.process(input) - -aslist = terminator(list) -asdict = terminator(dict) -astuple = terminator(tuple) -join = terminator(''.join) -enum = terminator(enumerate) - -class sort: - def __ror__(self,input): - ll = list(input) - ll.sort() - return ll -sort = sort() - -class uniq: - def __ror__(self,input): - for i in input: - try: - if i == prev: - continue - except NameError: - pass - prev = i - yield i -uniq = uniq() diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/get.py b/tags/pisi-1.0_beta2/pisi/actionsapi/get.py deleted file mode 100644 index 0fee8cf4..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/get.py +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Standart Python Modules -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# PISI Modules -import pisi.actionsapi -import pisi.context as ctx - -# ActionsAPI Modules -from variables import glb - -class BinutilsError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -# Globals -env = glb.env -dirs = glb.dirs - -def curDIR(): - '''returns current work directory's path''' - return os.getcwd() - -def curKERNEL(): - '''returns currently running kernel's version''' - versionString = file("/proc/version").readline() - return versionString.split()[2] - -def curPYTHON(): - ''' returns currently used python's version''' - return os.path.basename(os.readlink("/usr/bin/python")) - -def ENV(environ): - '''returns any given environ variable''' - try: - return os.environ[environ]; - except KeyError: - return None - -# PİSİ Related Functions - -def pkgDIR(): - '''returns the path of binary packages''' - '''Default: /var/cache/pisi/packages''' - return env.pkg_dir - -def workDIR(): - return env.work_dir - -def installDIR(): - '''returns the path of binary packages''' - return env.install_dir - -# PSPEC Related Functions - -def srcNAME(): - return env.src_name - -def srcVERSION(): - return env.src_version - -def srcRELEASE(): - return env.src_release - -def srcTAG(): - return "%s-%s-%s" % (env.src_name, env.src_version, env.src_release) - -def srcDIR(): - return "%s-%s" % (env.src_name, env.src_version) - -# Build Related Functions - -def HOST(): - return env.host - -def CHOST(): - # FIXME: Currently it behave same as HOST, - # but will be used for cross-compiling when PİSİ ready... - return env.host - -def CFLAGS(): - return env.cflags - -def CXXFLAGS(): - return env.cxxflags - -def LDFLAGS(): - return env.ldflags - -# Directory Related Functions - -def docDIR(): - return dirs.doc - -def sbinDIR(): - return dirs.sbin - -def infoDIR(): - return dirs.info - -def manDIR(): - return dirs.man - -def dataDIR(): - return dirs.data - -def confDIR(): - return dirs.conf - -def localstateDIR(): - return dirs.localstate - -def defaultprefixDIR(): - return dirs.defaultprefix - -def kdeDIR(): - # FIXME: Get followings from env.d or somewhere else - return dirs.kde - -def qtDIR(): - # FIXME: Get followings from env.d or somewhere else - return dirs.qt - -def qtLIBDIR(): - # FIXME: Get followings from env.d or somewhere else - return '%s/lib/' % qtDIR() - -# Binutils Variables - -def existBinary(bin): - # determine if path has binary - path = os.environ['PATH'].split(':') - for directory in path: - if os.path.exists(os.path.join(directory, bin)): - return True - return False - -def getBinutilsInfo(util): - cross_build_name = '%s-%s' % (HOST(), util) - if not existBinary(cross_build_name): - if not existBinary(util): - raise BinutilsError(_('Util %s cannot be found') % util) - else: - ctx.ui.debug(_('Warning: %s does not exist, using plain name %s') \ - % (cross_build_name, util)) - return util - else: - return cross_build_name - -def AR(): - return getBinutilsInfo('ar') - -def AS(): - return getBinutilsInfo('as') - -def CC(): - return getBinutilsInfo('gcc') - -def CXX(): - return getBinutilsInfo('g++') - -def LD(): - return getBinutilsInfo('ld') - -def NM(): - return getBinutilsInfo('nm') - -def RANLIB(): - return getBinutilsInfo('ranlib') - -def F77(): - return getBinutilsInfo('f77') - -def GCJ(): - return getBinutilsInfo('gcj') diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/kde.py b/tags/pisi-1.0_beta2/pisi/actionsapi/kde.py deleted file mode 100644 index 99c21ff6..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/kde.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# standard python modules -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get as get -from pisi.actionsapi.shelltools import system -from pisi.actionsapi.shelltools import can_access_file - -class ConfigureError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - if can_access_file('config.log'): - ctx.ui.error(_('\n!!! Please attach the config.log to your bug report:\n%s/config.log') % os.getcwd()) - -class MakeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class InstallError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def configure(parameters = ''): - ''' parameters = '--with-nls --with-libusb --with-something-usefull ''' - if can_access_file('configure'): - args = './configure \ - --prefix=%s \ - --host=%s \ - --with-x \ - --enable-mitshm \ - --with-xinerama \ - --with-qt-dir=%s \ - --enable-mt \ - --with-qt-libraries=%s \ - --disable-dependency-tracking \ - --disable-debug \ - %s' % (get.kdeDIR(), get.HOST(), get.qtDIR(), get.qtLIBDIR(), parameters) - - if system(args): - raise ConfigureError(_('Configure failed.')) - else: - raise ConfigureError(_('No configure script found.')) - -def make(parameters = ''): - '''make source with given parameters = "all" || "doc" etc.''' - if system('make %s' % parameters): - raise MakeError(_('Make failed.')) - -def install(parameters = 'install'): - if can_access_file('Makefile'): - args = 'make DESTDIR=%s destdir=%s %s' % (get.installDIR(), get.installDIR(), parameters) - - if system(args): - raise InstallError(_('Install failed.')) - else: - raise InstallError(_('No Makefile found.')) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/libtools.py b/tags/pisi-1.0_beta2/pisi/actionsapi/libtools.py deleted file mode 100644 index c60c3c9b..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/libtools.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Standard Python Modules -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi-Core Modules -import pisi.context as ctx -from pisi.util import join_path - -# ActionsAPI Modules -import pisi.actionsapi -from pisi.actionsapi.shelltools import * -import pisi.actionsapi.get as get - -class RunTimeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def preplib(sourceDirectory = '/usr/lib'): - sourceDirectory = join_path(get.installDIR(), sourceDirectory) - if can_access_directory(sourceDirectory): - if system('/sbin/ldconfig -n -N %s' % sourceDirectory): - raise RunTimeError(_('Running ldconfig failed.')) - -def gnuconfig_update(): - ''' copy newest config.* onto source\'s ''' - for root, dirs, files in os.walk(os.getcwd()): - for file in files: - if file in ['config.sub', 'config.guess']: - targetFile = os.path.join(root, file) - if os.path.islink(targetFile): - unlink(targetFile) - copy('/usr/share/gnuconfig/%s' % file, join_path(root, file)) - ctx.ui.info(_('GNU Config Update Finished.')) - -def libtoolize(parameters = ''): - if system('/usr/bin/libtoolize %s' % parameters): - raise RunTimeError(_('Running libtoolize failed.')) - -def gen_usr_ldscript(dynamicLib): - - makedirs('%s/usr/lib' % get.installDIR()) - - destinationFile = open('%s/usr/lib/%s' % (get.installDIR(), dynamicLib), 'w') - content = ''' -/* GNU ld script - Since Pardus has critical dynamic libraries - in /lib, and the static versions in /usr/lib, - we need to have a "fake" dynamic lib in /usr/lib, - otherwise we run into linking problems. -*/ -GROUP ( /lib/%s ) -''' % dynamicLib - - destinationFile.write(content) - destinationFile.close() - chmod('%s/usr/lib/%s' % (get.installDIR(), dynamicLib)) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/perlmodules.py b/tags/pisi-1.0_beta2/pisi/actionsapi/perlmodules.py deleted file mode 100644 index 06925b3b..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/perlmodules.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# standard python modules -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get as get -from pisi.actionsapi.shelltools import system -from pisi.actionsapi.shelltools import can_access_file -from pisi.actionsapi.shelltools import export - -class ConfigureError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class MakeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class InstallError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def configure(parameters = ''): - '''configure source with given parameters.''' - export('PERL_MM_USE_DEFAULT', '1') - if can_access_file('Build.PL'): - if system('perl Build.PL installdirs=vendor destdir=%s' % get.installDIR()): - raise CompileError, _('Configure failed.') - else: - if system('perl Makefile.PL %s PREFIX=/usr INSTALLDIRS=vendor DESTDIR=%s' % (parameters, get.installDIR())): - raise CompileError, _('Configure failed.') - -def make(parameters = ''): - '''make source with given parameters.''' - if can_access_file('Makefile'): - if system('make %s' % parameters): - raise MakeError, _('Make failed.') - else: - if system('perl Build build'): - raise MakeError, _('perl build failed.') - -def install(parameters = 'install'): - '''install source with given parameters.''' - if can_access_file('Makefile'): - if system('make %s' % parameters): - raise InstallError, _('Make failed.') - else: - if system('perl Build install'): - raise MakeError, _('perl install failed.') - -# FIXME: fix_local_pod % update_pod diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/pisitools.py b/tags/pisi-1.0_beta2/pisi/actionsapi/pisitools.py deleted file mode 100644 index 81c2b50d..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/pisitools.py +++ /dev/null @@ -1,240 +0,0 @@ -#!/usr/bin/python -#-*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -'''supports globs in sourceFile arguments''' - - -# Standart Python Modules -import os -import glob -import sys -import fileinput -import re - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx -from pisi.util import join_path - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get as get -from pisi.actionsapi.pisitoolsfunctions import * -from pisi.actionsapi.shelltools import * - -from pisi.actionsapi import error - -def dobin(sourceFile, destinationDirectory = '/usr/bin'): - '''insert a executable file into /bin or /usr/bin''' - ''' example call: pisitools.dobin("bin/xloadimage", "/bin", "xload") ''' - executable_insinto(join_path(get.installDIR(), destinationDirectory), sourceFile) - -def dodir(destinationDirectory): - '''creates a directory tree''' - makedirs(join_path(get.installDIR(), destinationDirectory)) - -def dodoc(*sourceFiles): - '''inserts the files in the list of files into /usr/share/doc/PACKAGE''' - readable_insinto(join_path(get.installDIR(), join_path('/usr/share/doc', get.srcTAG())), *sourceFiles) - -def doexe(sourceFile, destinationDirectory): - '''insert a executable file into destination directory''' - - ''' example call: pisitools.doexe("kde-3.4.sh", "/etc/X11/Sessions")''' - executable_insinto(join_path(get.installDIR(), destinationDirectory), sourceFile) - -def dohard(sourceFile, destinationFile): - '''creates hard link between sourceFile and destinationFile''' - #FIXME: How can i use hard-links in Python? - ctx.ui.warning('*** Hard links not implemented yet') - -def dohtml(*sourceFiles): - '''inserts the files in the list of files into /usr/share/doc/PACKAGE/html''' - - ''' example call: pisitools.dohtml("doc/doxygen/html/*")''' - destionationDirectory = join_path(get.installDIR(), 'usr/share/doc' ,get.srcTAG(), 'html') - - if not can_access_directory(destionationDirectory): - makedirs(destionationDirectory) - - allowed_extensions = ['.png', '.gif', '.html', '.htm', '.jpg', '.css', '.js'] - disallowed_directories = ['CVS'] - - for sourceFile in sourceFiles: - for source in glob.glob(sourceFile): - if os.path.isfile(source) and os.path.splitext(source)[1] in allowed_extensions: - system('install -m0644 "%s" %s' % (source, destionationDirectory)) - if os.path.isdir(source) and os.path.basename(source) not in disallowed_directories: - for root, dirs, files in os.walk(source): - for source in files: - if os.path.splitext(source)[1] in allowed_extensions: - makedirs(destionationDirectory) - system('install -m0644 %s %s' % (join_path(root, source), destionationDirectory)) - -def doinfo(*sourceFiles): - '''inserts the into files in the list of files into /usr/share/info''' - readable_insinto(join_path(get.installDIR(), get.infoDIR()), *sourceFiles) - -def dolib(sourceFile, destinationDirectory = '/usr/lib'): - '''insert the library into /usr/lib''' - - '''example call: pisitools.dolib_a("libz.a")''' - '''example call: pisitools.dolib_a("libz.so")''' - sourceFile = join_path(os.getcwd(), sourceFile) - destinationDirectory = join_path(get.installDIR(), destinationDirectory) - - lib_insinto(sourceFile, destinationDirectory, 755) - -def dolib_a(sourceFile, destinationDirectory = '/usr/lib'): - '''insert the static library into /usr/lib with permission 0644''' - - '''example call: pisitools.dolib_a("staticlib/libvga.a")''' - sourceFile = join_path(os.getcwd(), sourceFile) - destinationDirectory = join_path(get.installDIR(), destinationDirectory) - - lib_insinto(sourceFile, destinationDirectory, 644) - -def dolib_so(sourceFile, destinationDirectory = '/usr/lib'): - '''insert the static library into /usr/lib with permission 0755''' - - '''example call: pisitools.dolib_so("pppd/plugins/minconn.so")''' - sourceFile = join_path(os.getcwd(), sourceFile) - destinationDirectory = join_path(get.installDIR(), destinationDirectory) - - lib_insinto(sourceFile, destinationDirectory, 755) - -def doman(*sourceFiles): - '''inserts the man pages in the list of files into /usr/share/man/''' - - '''example call: pisitools.doman("man.1", "pardus.*")''' - manDIR = join_path(get.installDIR(), get.manDIR()) - if not can_access_directory(manDIR): - makedirs(manDIR) - - for sourceFile in sourceFiles: - for source in glob.glob(sourceFile): - try: - pageName, pageDirectory = source[:source.rindex('.')], \ - source[source.rindex('.')+1:] - except ValueError: - error(_('ActionsAPI [doman]: Wrong man page file: %s') % (source)) - - makedirs(join_path(manDIR, '/man%s' % pageDirectory)) - system('install -m0644 %s %s' % (source, join_path(manDIR, '/man%s' % pageDirectory))) - -def domo(sourceFile, locale, destinationFile ): - '''inserts the mo files in the list of files into /usr/share/locale/LOCALE/LC_MESSAGES''' - - '''example call: pisitools.domo("po/tr.po", "tr", "pam_login.mo")''' - - system('msgfmt %s' % sourceFile) - makedirs('%s/usr/share/locale/%s/LC_MESSAGES/' % (get.installDIR(), locale)) - move('messages.mo', '%s/usr/share/locale/%s/LC_MESSAGES/%s' % (get.installDIR(), locale, destinationFile)) - -def domove(sourceFile, destination, destinationFile = ''): - '''moves sourceFile/Directory into destinationFile/Directory''' - - ''' example call: pisitools.domove("/usr/bin/bash", "/bin/bash")''' - ''' example call: pisitools.domove("/usr/bin/", "/usr/sbin")''' - makedirs(join_path(get.installDIR(), destination)) - - for file in glob.glob(join_path(get.installDIR(), sourceFile)): - if not destinationFile: - move(file, join_path(get.installDIR(), join_path(destination, os.path.basename(file)))) - else: - move(file, join_path(get.installDIR(), join_path(destination, destinationFile))) - -def rename(sourceFile, destinationFile): - ''' renames sourceFile as destinationFile''' - - ''' example call: pisitools.rename("/usr/bin/bash", "bash.old") ''' - ''' the result of the previous example would be "/usr/bin/bash.old" ''' - - baseDir = os.path.dirname(sourceFile) - - try: - os.rename(join_path(get.installDIR(), sourceFile), join_path(get.installDIR(), baseDir, destinationFile)) - except OSError: - error(_('ActionsAPI [rename]: No such file or directory: %s') % (sourceFile)) - -def dosed(sourceFiles, findPattern, replacePattern = ''): - '''replaces patterns in sourceFiles''' - - ''' example call: pisitools.dosed("/etc/passwd", "caglar", "cem")''' - ''' example call: pisitools.dosym("/etc/passwd", "caglar")''' - ''' example call: pisitools.dosym("/etc/pass*", "caglar")''' - ''' example call: pisitools.dosym("Makefile", "(?m)^(HAVE_PAM=.*)no", r"\1yes")''' - - for sourceFile in glob.glob(sourceFiles): - if can_access_file(sourceFile): - for line in fileinput.input(sourceFile, inplace = 1): - #FIXME: In-place filtering is disabled when standard input is read - line = re.sub(findPattern, replacePattern, line) - sys.stdout.write(line) - else: - raise FileError(_('File does not exist or permission denied: %s') % sourceFile) - -def dosbin(sourceFile, destinationDirectory = '/usr/sbin'): - '''insert a executable file into /sbin or /usr/sbin''' - - ''' example call: pisitools.dobin("bin/xloadimage", "/sbin") ''' - executable_insinto(join_path(get.installDIR(), destinationDirectory), sourceFile) - -def dosym(sourceFile, destinationFile): - '''creates soft link between sourceFile and destinationFile''' - - ''' example call: pisitools.dosym("/usr/bin/bash", "/bin/bash")''' - makedirs(join_path(get.installDIR(), os.path.dirname(destinationFile))) - - try: - os.symlink(sourceFile, join_path(get.installDIR() ,destinationFile)) - except OSError: - error(_('ActionsAPI [dosym]: File exists: %s') % (sourceFile)) - -def insinto(destinationDirectory, sourceFile, destinationFile = ''): - '''insert a sourceFile into destinationDirectory as a destinationFile with same uid/guid/permissions''' - makedirs(join_path(get.installDIR(), destinationDirectory)) - - if not destinationFile: - for file in glob.glob(sourceFile): - if can_access_file(file): - copy(file, join_path(get.installDIR(), join_path(destinationDirectory, os.path.basename(file)))) - else: - copy(sourceFile, join_path(get.installDIR(), join_path(destinationDirectory, destinationFile))) - -def newdoc(sourceFile, destinationFile): - '''inserts a sourceFile into /usr/share/doc/PACKAGE/ directory as a destinationFile''' - destinationDirectory = '' #490 - destinationDirectory = os.path.dirname(destinationFile) - destinationFile = os.path.basename(destinationFile) - # Use copy instead of move or let build-install scream like file not found! - copy(sourceFile, destinationFile) - readable_insinto(join_path(get.installDIR(), 'usr/share/doc', get.srcTAG(), destinationDirectory), destinationFile) - -def newman(sourceFile, destinationFile): - '''inserts a sourceFile into /usr/share/man/manPREFIX/ directory as a destinationFile''' - # Use copy instead of move or let build-install scream like file not found! - copy(sourceFile, destinationFile) - doman(destinationFile) - -def remove(sourceFile): - '''removes sourceFile''' - for file in glob.glob(join_path(get.installDIR(), sourceFile)): - unlink(file) - -def removeDir(destinationDirectory): - '''removes destinationDirectory and its subtrees''' - for directory in glob.glob(join_path(get.installDIR(), destinationDirectory)): - unlinkDir(directory) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/pisitoolsfunctions.py b/tags/pisi-1.0_beta2/pisi/actionsapi/pisitoolsfunctions.py deleted file mode 100644 index 1fa7be63..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/pisitoolsfunctions.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python -#-*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Generic functions for common usage of pisitools # - -# Standart Python Modules -import os -import glob - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx - -# ActionsAPI Modules -import pisi.actionsapi -from pisi.actionsapi.shelltools import * - -class FileError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class ArgumentError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def executable_insinto(destinationDirectory, *sourceFiles): - '''insert a executable file into destinationDirectory''' - - if not sourceFiles or not destinationDirectory: - raise ArgumentError(_('Insufficient arguments.')) - - if not can_access_directory(destinationDirectory): - makedirs(destinationDirectory) - - for sourceFile in sourceFiles: - for source in glob.glob(sourceFile): - # FIXME: use an internal install routine for these - system('install -m0755 -o root -g root %s %s' % (source, destinationDirectory)) - -def readable_insinto(destinationDirectory, *sourceFiles): - '''inserts file list into destinationDirectory''' - - if not sourceFiles or not destinationDirectory: - raise ArgumentError(_('Insufficient arguments.')) - - if not can_access_directory(destinationDirectory): - makedirs(destinationDirectory) - - for sourceFile in sourceFiles: - for source in glob.glob(sourceFile): - system('install -m0644 %s %s' % (source, destinationDirectory)) - -def lib_insinto(sourceFile, destinationDirectory, permission = 0644): - '''inserts a library fileinto destinationDirectory with given permission''' - - if not sourceFile or not destinationDirectory: - raise ArgumentError(_('Insufficient arguments.')) - - if not can_access_directory(destinationDirectory): - makedirs(destinationDirectory) - - if os.path.islink(sourceFile): - os.symlink(os.path.realpath(sourceFile), os.path.join(destinationDirectory, sourceFile)) - else: - system('install -m%s %s %s' % (permission, sourceFile, destinationDirectory)) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/pythonmodules.py b/tags/pisi-1.0_beta2/pisi/actionsapi/pythonmodules.py deleted file mode 100644 index 92ea0b59..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/pythonmodules.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# standard python modules -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get as get -from pisi.actionsapi.shelltools import system, can_access_file -from pisi.actionsapi.pisitools import dodoc - -class CompileError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class InstallError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class RunTimeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def compile(parameters = ''): - '''compile source with given parameters.''' - if system('python setup.py build %s' % (parameters)): - raise CompileError, _('Make failed.') - -def install(parameters = ''): - '''does python setup.py install''' - if system('python setup.py install --root=%s --no-compile %s' % (get.installDIR(), parameters)): - raise InstallError, _('Install failed.') - - DDOCS = 'CHANGELOG COPYRIGHT KNOWN_BUGS MAINTAINERS PKG-INFO \ - CONTRIBUTORS LICENSE COPYING* Change* MANIFEST* README*' - - for doc in DDOCS: - if can_access_file(doc): - pisitools.dodoc(doc) - -def run(parameters = ''): - '''executes parameters with python''' - if system('python %s' % (parameters)): - raise RunTimeError, _('Running %s failed.') % parameters diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/scons.py b/tags/pisi-1.0_beta2/pisi/actionsapi/scons.py deleted file mode 100644 index c992986f..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/scons.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - - -# Pisi Modules -import pisi.context as ctx - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get as get -from pisi.actionsapi.shelltools import system - -class MakeError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -class InstallError(pisi.actionsapi.Error): - def __init__(self, value=''): - pisi.actionsapi.Error.__init__(self, value) - self.value = value - ctx.ui.error(value) - -def make(parameters = ''): - if system("scons %s" % parameters): - raise MakeError(_('Make failed.')) - -def install(parameters = 'install'): - if system("scons prefix=%s %s" % (get.installDIR(), parameters)): - raise InstallError(_('Install failed.')) diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/shelltools.py b/tags/pisi-1.0_beta2/pisi/actionsapi/shelltools.py deleted file mode 100644 index 36d2e18a..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/shelltools.py +++ /dev/null @@ -1,212 +0,0 @@ -#!/usr/bin/python -#-*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Standart Python Modules -import os -import glob -import shutil -import pwd -import grp - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# Pisi Modules -import pisi.context as ctx - -# ActionsAPI Modules -import pisi.actionsapi -import pisi.actionsapi.get - -from pisi.actionsapi import error - -def can_access_file(sourceFile): - '''test the existence of file''' - return os.access(sourceFile, os.F_OK) - -def can_access_directory(destinationDirectory): - '''test readability, writability and executablility of directory''' - return os.access(destinationDirectory, os.R_OK | os.W_OK | os.X_OK) - -def makedirs(destinationDirectory): - '''recursive directory creation function''' - try: - if not os.access(destinationDirectory, os.F_OK): - os.makedirs(destinationDirectory) - except OSError: - error(_('Cannot create directory %s') % destinationDirectory) - -def echo(destionationFile, content): - try: - f = open(destionationFile, 'a') - f.write("%s\n" % content) - f.close() - except IOError: - error(_('ActionsAPI [echo]: Can\'t append to file %s.') % (destionationFile)) - -def chmod(sourceFile, mode = 0755): - '''change the mode of sourceFile to the mode''' - for file in glob.glob(sourceFile): - if can_access_file(file): - try: - os.chmod(file, mode) - except OSError: - ctx.ui.error(_('ActionsAPI [chmod]: Operation not permitted: %s (mode: %s)') \ - % (file, mode)) - else: - ctx.ui.error(_('ActionsAPI [chmod]: File %s doesn\'t exists.') % (file)) - -def chown(sourceFile, uid = "root", gid = "root"): - '''change the owner and group id of sourceFile to uid and gid''' - if can_access_file(sourceFile): - try: - os.chown(sourceFile, pwd.getpwnam(uid)[2], grp.getgrnam(gid)[2]) - except OSError: - ctx.ui.error(_('ActionsAPI [chown]: Operation not permitted: %s (uid: %s, gid: %s)') \ - % (sourceFile, uid, gid)) - else: - ctx.ui.error(_('ActionsAPI [chown]: File %s doesn\'t exists.') % sourceFile) - -def sym(sourceFile, destinationFile): - '''creates symbolic link''' - try: - os.symlink(sourceFile, destinationFile) - except OSError: - ctx.ui.error(_('ActionsAPI [sym]: Permission denied: %s to %s') % (file, destinationFile)) - -def unlink(sourceFile): - '''remove the file path''' - if isFile(sourceFile) or isLink(sourceFile): - try: - os.unlink(sourceFile) - except OSError: - ctx.ui.error(_('ActionsAPI [unlink]: Permission denied: %s.') % (sourceFile)) - elif isDirectory(sourceFile): - pass - else: - ctx.ui.error(_('ActionsAPI [unlink]: File %s doesn\'t exists.') % (sourceFile)) - -def unlinkDir(sourceDirectory): - '''delete an entire directory tree''' - if isDirectory(sourceDirectory) or isLink(sourceDirectory): - try: - shutil.rmtree(sourceDirectory) - except OSError: - error(_('ActionsAPI [unlinkDir]: Operation not permitted: %s') % (sourceDirectory)) - elif isFile(sourceDirectory): - pass - else: - error(_('ActionsAPI [unlinkDir]: Directory %s doesn\'t exists.') % (sourceDirectory)) - -def move(sourceFile, destinationFile): - '''recursively move a sourceFile or directory to destinationFile''' - for file in glob.glob(sourceFile): - if isFile(file) or isLink(file) or isDirectory(file): - try: - shutil.move(file, destinationFile) - except OSError: - error(_('ActionsAPI [move]: Permission denied: %s to %s') % (file, destinationFile)) - else: - error(_('ActionsAPI [move]: File %s doesn\'t exists.') % (file)) - -def copy(sourceFile, destinationFile): - '''recursively copy a sourceFile or directory to destinationFile''' - for file in glob.glob(sourceFile): - if isFile(file) or isLink(file): - try: - shutil.copy(file, destinationFile) - except IOError: - error(_('ActionsAPI [copy]: Permission denied: %s to %s') % (file, destinationFile)) - elif isDirectory(file): - copytree(file, destinationFile) - else: - error(_('ActionsAPI [copy]: File %s does not exist.') % file) - -def copytree(source, destination, sym = False): - '''recursively copy an entire directory tree rooted at source''' - if isDirectory(source) or isLink(source): - try: - shutil.copytree(source, destination, sym) - except OSError, e: - error(_('ActionsAPI [copytree] %s to %s: %s') % (source, destination, e)) - else: - error(_('ActionsAPI [copytree]: Directory %s doesn\'t exists.') % (source)) - -def touch(sourceFile): - '''changes the access time of the 'sourceFile', or creates it if it is not exist''' - if glob.glob(sourceFile): - for file in glob.glob(sourceFile): - os.utime(file, None) - else: - try: - f = open(sourceFile, 'w') - f.close() - except IOError: - error(_('ActionsAPI [touch]: Permission denied: %s') % (sourceFile)) - -def cd(directoryName = ''): - '''change directory''' - current = os.getcwd() - if directoryName: - os.chdir(directoryName) - else: - os.chdir(os.path.dirname(current)) - -def ls(source): - '''listdir''' - if os.path.isdir(source): - return os.listdir(source) - else: - return glob.glob(source) - -def export(key, value): - '''export environ variable''' - os.environ[key] = value - -def isLink(sourceFile): - '''return True if sourceFile refers to a symbolic link''' - return os.path.islink(sourceFile) - -def isFile(sourceFile): - '''return True if sourceFile is an existing regular file''' - return os.path.isfile(sourceFile) - -def isDirectory(sourceDirectory): - '''Return True if sourceFile is an existing directory''' - return os.path.isdir(sourceDirectory) - -def realPath(sourceFile): - '''return the canonical path of the specified filename, eliminating any symbolic links encountered in the path''' - return os.path.realpath(sourceFile) - -def baseName(sourceFile): - '''return the base name of pathname sourceFile''' - return os.path.basename(sourceFile) - -def dirName(sourceFile): - '''return the directory name of pathname path''' - return os.path.dirname(sourceFile) - -def system(command): - #FIXME: might be better to merge this with util.run_batch - #FIXME: String formatting - command = command.replace(" ", " ") - ctx.ui.debug(_('executing %s') % command) - p = os.popen(command) - while 1: - line = p.readline() - if not line: - break - ctx.ui.debug(line[:-1]) - - return p.close() diff --git a/tags/pisi-1.0_beta2/pisi/actionsapi/variables.py b/tags/pisi-1.0_beta2/pisi/actionsapi/variables.py deleted file mode 100644 index f007e04c..00000000 --- a/tags/pisi-1.0_beta2/pisi/actionsapi/variables.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# Standard Python Modules -from os import getenv -from os import environ - -# Pisi-Core Modules -import pisi.context as ctx - -# Set individual information, that are generally needed for ActionsAPI - -def exportFlags(): - '''General flags used in actions API.''' - - # Build systems depend on these environment variables. That is why - # we export them instead of using as (instance) variables. - values = ctx.config.values - environ['HOST'] = values.build.host - environ['CFLAGS'] = values.build.cflags - environ['CXXFLAGS'] = values.build.cxxflags - environ['LDFLAGS'] = values.build.ldflags - -class Env(object): - '''General environment variables used in actions API''' - def __init__(self): - - exportFlags() - - self.__vars = { - 'pkg_dir': 'PKG_DIR', - 'work_dir': 'WORK_DIR', - 'install_dir': 'INSTALL_DIR', - 'src_name': 'SRC_NAME', - 'src_version': 'SRC_VERSION', - 'src_release': 'SRC_RELEASE', - 'host': 'HOST', - 'cflags': 'CFLAGS', - 'cxxflags': 'CXXFLAGS', - 'ldflags': 'LDFLAGS' - } - - def __getattr__(self, attr): - - # Using environment variables is somewhat tricky. Each time - # you need them you need to check for their value. - if self.__vars.has_key(attr): - return getenv(self.__vars[attr]) - else: - return None - -class Dirs: - '''General directories used in actions API.''' - # TODO: Eventually we should consider getting these from a/the - # configuration file - doc = 'usr/share/doc' - sbin = 'usr/sbin' - man = 'usr/share/man' - info = 'usr/share/info' - data = 'usr/share' - conf = 'etc' - localstate = 'var/lib' - defaultprefix = 'usr' - - #FIXME: Get these from config or somewhere else! - kde = '/usr/kde/3.4' - qt = '/usr/qt/3' - -def initVariables(): - ctx.env = Env() - ctx.dirs = Dirs() - return ctx - -glb = initVariables() diff --git a/tags/pisi-1.0_beta2/pisi/api.py b/tags/pisi-1.0_beta2/pisi/api.py deleted file mode 100644 index acc5da7a..00000000 --- a/tags/pisi-1.0_beta2/pisi/api.py +++ /dev/null @@ -1,347 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -"""Top level PISI interfaces. a facade to the entire PISI system""" - -import os -import sys -from os.path import exists - -ver = sys.version_info -if ver[0] <= 2 and ver[1] < 4: - from sets import Set as set - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi - -import pisi.context as ctx -from pisi.uri import URI -import pisi.util as util -import pisi.dependency as dependency -import pisi.pgraph as pgraph -import pisi.operations as operations -import pisi.packagedb as packagedb -import pisi.repodb -import pisi.installdb -import pisi.sourcedb -import pisi.component as component -from pisi.index import Index -import pisi.cli -from pisi.operations import install, remove, upgrade -from pisi.atomicoperations import resurrect_package -from pisi.metadata import MetaData -from pisi.files import Files - -class Error(pisi.Error): - pass - -def init(database = True, options = None, ui = None, comar = True): - """Initialize PiSi subsystem""" - - import pisi.config - ctx.config = pisi.config.Config(options) - - # TODO: this is definitely not dynamic beyond this point! - ctx.comar = comar and not ctx.config.get_option('ignore_comar') - - if ui is None: - if options: - pisi.context.ui = pisi.cli.CLI(options.debug) - else: - pisi.context.ui = pisi.cli.CLI() - else: - pisi.context.ui = ui - - # initialize repository databases - if database: - ctx.repodb = pisi.repodb.init() - ctx.installdb = pisi.installdb.init() - ctx.filesdb = pisi.files.FilesDB() - ctx.componentdb = pisi.component.ComponentDB() - packagedb.init_db() - pisi.sourcedb.init() - else: - ctx.repodb = None - ctx.installdb = None - ctx.filesdb = None - ctx.componentdb = None - ctx.ui.debug('PISI API initialized') - ctx.initialized = True - -def finalize(): - pisi.repodb.finalize() - pisi.installdb.finalize() - if ctx.filesdb != None: - ctx.filesdb.close() - if ctx.componentdb != None: - ctx.componentdb.close() - packagedb.finalize_db() - pisi.sourcedb.finalize() - ctx.ui.debug('PISI API finalized') - ctx.initialized = False - -def list_upgradable(): - ignore_build = ctx.config.options and ctx.config.options.ignore_build_no - - A = ctx.installdb.list_installed() - # filter packages that are not upgradable - Ap = [] - for x in A: - if not ctx.installdb.is_installed(x): - continue - (version, release, build) = ctx.installdb.get_version(x) - pkg = packagedb.get_package(x) - if ignore_build or (not build): - if release < pkg.release: - Ap.append(x) - elif build < pkg.build: - Ap.append(x) - else: - pass - #ctx.ui.info('Package %s cannot be upgraded. ' % x) - return Ap - - -def package_graph(A, ignore_installed = False): - """Construct a package relations graph, containing - all dependencies of packages A, if ignore_installed - option is True, then only uninstalled deps will - be added.""" - - ctx.ui.debug('A = %s' % str(A)) - - # try to construct a pisi graph of packages to - # install / reinstall - - G_f = pgraph.PGraph(packagedb) # construct G_f - - # find the "install closure" graph of G_f by package - # set A using packagedb - for x in A: - G_f.add_package(x) - B = A - #state = {} - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) - #print pkg - for dep in pkg.runtimeDependencies(): - if ignore_installed: - if dependency.installed_satisfies_dep(dep): - continue - if not dep.package in G_f.vertices(): - Bp.add(str(dep.package)) - G_f.add_dep(x, dep) - B = Bp - return G_f - -def configure_pending(): - # start with pending packages - # configure them in reverse topological order of dependency - A = ctx.installdb.list_pending() - G_f = pgraph.PGraph(packagedb) # construct G_f - for x in A.keys(): - G_f.add_package(x) - B = A - while len(B) > 0: - Bp = set() - for x in B.keys(): - pkg = packagedb.get_package(x) - for dep in pkg.runtimeDependencies(): - if dep.package in G_f.vertices(): - G_f.add_dep(x, dep) - B = Bp - if ctx.get_option('debug'): - G_f.write_graphviz(sys.stdout) - order = G_f.topological_sort() - order.reverse() - try: - import pisi.comariface as comariface - for x in order: - pkginfo = A[x] - pkgname = util.package_name(x, pkginfo.version, - pkginfo.release, - pkginfo.build, - False) - pkg_path = util.join_path(ctx.config.lib_dir(), - pkgname) - m = MetaData() - metadata_path = util.join_path(pkg_path, ctx.const.metadata_xml) - m.read(metadata_path) - for pcomar in m.package.providesComar: - scriptPath = util.join_path(pkg_path, - ctx.const.comar_dir, - pcomar.script) - comariface.register(pcomar, x, scriptPath) - comariface.run_postinstall(x) - ctx.installdb.clear_pending(x) - except ImportError: - raise Error(_("COMAR: comard not fully installed")) - -def info(package): - if package.endswith(ctx.const.package_suffix): - return info_file(package) - else: - return info_name(package) - -def info_file(package_fn): - from package import Package - - if not os.path.exists(package_fn): - raise Error (_('File %s not found') % package_fn) - - package = Package(package_fn) - package.read() - return package.metadata, package.files - -def info_name(package_name): - """fetch package information for a package""" - if packagedb.has_package(package_name): - package = packagedb.get_package(package_name) - from pisi.metadata import MetaData - metadata = MetaData() - metadata.package = package - #FIXME: get it from sourcedb - metadata.source = None - #TODO: fetch the files from server if possible - if ctx.installdb.is_installed(package.name): - files = ctx.installdb.files(package.name) - else: - files = None - return metadata, files - else: - raise Error(_('Package %s not found') % package_name) - -def index(dirs, output = 'pisi-index.xml'): - index = Index() - if not dirs: - dirs = ['.'] - for repo_dir in dirs: - ctx.ui.info(_('* Building index of PISI files under %s') % repo_dir) - index.index(repo_dir) - index.write(output) - ctx.ui.info(_('* Index file written')) - -def add_repo(name, indexuri): - repo = pisi.repodb.Repo(URI(indexuri)) - ctx.repodb.add_repo(name, repo) - ctx.ui.info(_('Repo %s added to system.') % name) - -def remove_repo(name): - if ctx.repodb.has_repo(name): - ctx.repodb.remove_repo(name) - ctx.ui.info(_('Repo %s removed from system.') % name) - else: - ctx.ui.error(_('Repository %s does not exist. Cannot remove.') - % name) - -def update_repo(repo): - - ctx.ui.info(_('* Updating repository: %s') % repo) - index = Index() - index.read_uri(ctx.repodb.get_repo(repo).indexuri.get_uri(), repo) - index.update_db(repo) - ctx.ui.info(_('\n* Package database updated.')) - - -# build functions... -def prepare_for_build(pspecfile, authInfo=None): - - url = URI(pspecfile) - if url.is_remote_file(): - from sourcefetcher import SourceFetcher - fs = SourceFetcher(url, authInfo) - url.uri = fs.fetch_all() - - import pisi.build - pb = pisi.build.Builder(url.uri) - - return pb - -def build(pspecfile, authInfo=None): - pb = prepare_for_build(pspecfile, authInfo) - pb.build() - -order = {"none": 0, - "unpack": 1, - "setupaction": 2, - "buildaction": 3, - "installaction": 4, - "buildpackages": 5} - -def __buildState_unpack(pb): - # unpack is the first state to run. - pb.fetch_source_archive() - pb.unpack_source_archive() - pb.apply_patches() - -def __buildState_setupaction(pb, last): - - if order[last] < order["unpack"]: - __buildState_unpack(pb) - pb.run_setup_action() - -def __buildState_buildaction(pb, last): - - if order[last] < order["setupaction"]: - __buildState_setupaction(pb, last) - pb.run_build_action() - -def __buildState_installaction(pb, last): - - if order[last] < order["buildaction"]: - __buildState_buildaction(pb, last) - pb.run_install_action() - -def __buildState_buildpackages(pb, last): - - if order[last] < order["installaction"]: - __buildState_installaction(pb, last) - pb.build_packages() - -def build_until(pspecfile, state, authInfo=None): - pb = prepare_for_build(pspecfile, authInfo) - pb.compile_action_script() - - last = pb.get_state() - ctx.ui.info("Last state was %s"%last) - - if not last: last = "none" - - if state == "unpack": - __buildState_unpack(pb) - return - - if state == "setupaction": - __buildState_setupaction(pb, last) - return - - if state == "buildaction": - __buildState_buildaction(pb, last) - return - - if state == "installaction": - __buildState_installaction(pb, last) - return - - __buildState_buildpackages(pb, last) - -def delete_cache(): - util.clean_dir(ctx.config.packages_dir()) - util.clean_dir(ctx.config.archives_dir()) - util.clean_dir(ctx.config.tmp_dir()) diff --git a/tags/pisi-1.0_beta2/pisi/archive.py b/tags/pisi-1.0_beta2/pisi/archive.py deleted file mode 100644 index 8e52e410..00000000 --- a/tags/pisi-1.0_beta2/pisi/archive.py +++ /dev/null @@ -1,242 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Archive module provides access to regular archive file types. -# maintainer baris and meren - -# standard library modules -import os -import stat -import tarfile -import zipfile - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# PiSi modules -import pisi -import pisi.util as util - -class ArchiveError(pisi.Error): - pass - - -class ArchiveBase(object): - """Base class for Archive classes.""" - def __init__(self, file_path, atype): - self.file_path = file_path - self.type = atype - - def unpack(self, target_dir, clean_dir = False): - self.target_dir = target_dir - # first we check if we need to clean-up our working env. - if os.path.exists(self.target_dir) and clean_dir: - util.clean_dir(self.target_dir) - - os.makedirs(self.target_dir) - - -class ArchiveBinary(ArchiveBase): - """ArchiveBinary handles binary archive files (usually distrubuted as - .bin files)""" - def __init__(self, file_path, arch_type = "binary"): - super(ArchiveBinary, self).__init__(file_path, arch_type) - - def unpack(self, target_dir, clean_dir = False): - super(ArchiveBinary, self).unpack(target_dir, clean_dir) - - # we can't unpack .bin files. we'll just move them to target - # directory and leave the dirty job to actions.py ;) - import shutil - target_file = os.path.join(target_dir, os.path.basename(self.file_path)) - shutil.copyfile(self.file_path, target_file) - - -class ArchiveTar(ArchiveBase): - """ArchiveTar handles tar archives depending on the compression - type. Provides access to tar, tar.gz and tar.bz2 files. - - This class provides the unpack magic for tar archives.""" - def __init__(self, file_path, arch_type = "tar"): - super(ArchiveTar, self).__init__(file_path, arch_type) - - def unpack(self, target_dir, clean_dir = False): - """Unpack tar archive to a given target directory(target_dir).""" - super(ArchiveTar, self).unpack(target_dir, clean_dir) - - rmode = "" - if self.type == 'tar': - rmode = 'r:' - elif self.type == 'targz': - rmode = 'r:gz' - elif self.type == 'tarbz2': - rmode = 'r:bz2' - else: - raise ArchiveError(_("Archive type not recognized")) - - tar = tarfile.open(self.file_path, rmode) - oldwd = os.getcwd() - os.chdir(self.target_dir) - for tarinfo in tar: - tar.extract(tarinfo) - os.chdir(oldwd) - tar.close() - - -class ArchiveZip(ArchiveBase): - """ArchiveZip handles zip archives. - - Being a zip archive PISI packages also use this class - extensively. This class provides unpacking and packing magic for - zip archives.""" - - symmagic = 2716663808 #long of hex val '0xA1ED0000L' - - def __init__(self, file_path, arch_type = "zip", mode = 'r'): - super(ArchiveZip, self).__init__(file_path, arch_type) - - self.zip_obj = zipfile.ZipFile(self.file_path, mode) - - def close(self): - """Close the zip archive.""" - self.zip_obj.close() - - def add_to_archive(self, file_name): - """Add file or directory path to the zip file""" - # It's a pity that zipfile can't handle unicode strings. Grrr! - file_name = str(file_name) - if os.path.isdir(file_name) and not os.path.islink(file_name): - self.zip_obj.writestr(file_name + '/', '') - attr_obj = self.zip_obj.getinfo(file_name + '/') - attr_obj.external_attr = stat.S_IMODE(os.stat(file_name)[0]) << 16L - for f in os.listdir(file_name): - self.add_to_archive(os.path.join(file_name, f)) - else: - if os.path.islink(file_name): - dest = os.readlink(file_name) - attr = zipfile.ZipInfo() - attr.filename = file_name - attr.create_system = 3 - attr.external_attr = self.symmagic - self.zip_obj.writestr(attr, dest) - else: - self.zip_obj.write(file_name, file_name, zipfile.ZIP_DEFLATED) - - def add_basename_to_archive(self, file_name): - """Add only the basepath to the zip file. For example; if the given - file_name parameter is /usr/local/bin/somedir, this function - will create only the base directory/file somedir in the - archive.""" - cwd = os.getcwd() - path_name = os.path.dirname(file_name) - file_name = os.path.basename(file_name) - if path_name: - os.chdir(path_name) - self.add_to_archive(file_name) - os.chdir(cwd) - - def unpack_file_cond(self, pred, target_dir, archive_root = ''): - """Unpack/Extract a file according to predicate function filename -> - bool""" - zip_obj = self.zip_obj - for info in zip_obj.infolist(): - if pred(info.filename): # check if condition holds - - # below code removes that, so we find it here - is_dir = info.filename.endswith('/') - - # calculate output file name - if archive_root == '': - outpath = info.filename - else: - # change archive_root - if util.subpath(archive_root, info.filename): - outpath = util.removepathprefix(archive_root, - info.filename) - else: - continue # don't extract if not under - - ofile = os.path.join(target_dir, outpath) - - if is_dir: # this is a directory - d = os.path.join(target_dir, outpath) - if not os.path.isdir(d): - os.makedirs(d) - perm = info.external_attr - perm &= 0xFFFF0000 - perm >>= 16 - perm |= 0x00000100 - os.chmod(d, perm) - continue - - # check that output dir is present - util.check_dir(os.path.dirname(ofile)) - - # remove output file we might be overwriting. - # (also check for islink? for broken symlinks...) - if os.path.exists(ofile) or os.path.islink(ofile): - os.remove(ofile) - - if info.external_attr == self.symmagic: - target = zip_obj.read(info.filename) - os.symlink(target, ofile) - else: - perm = info.external_attr - perm &= 0x08FF0000 - perm >>= 16 - perm |= 0x00000100 - buff = open (ofile, 'wb') - file_content = zip_obj.read(info.filename) - buff.write(file_content) - buff.close() - os.chmod(ofile, perm) - - def unpack_files(self, paths, target_dir): - self.unpack_file_cond(lambda f:f in paths, target_dir) - - def unpack_dir(self, path, target_dir): - self.unpack_file_cond(lambda f:util.subpath(path, f), target_dir) - - def unpack_dir_flat(self, path, target_dir): - self.unpack_file_cond(lambda f:util.subpath(path, f), target_dir, path) - - def unpack(self, target_dir, clean_dir=False): - super(ArchiveZip, self).unpack(target_dir, clean_dir) - - self.unpack_file_cond(lambda f: True, target_dir) - self.close() - return - - -class Archive: - """Archive is the main factory for ArchiveClasses, regarding the - Abstract Factory Pattern :).""" - - def __init__(self, file_path, arch_type): - """accepted archive types: - targz, tarbz2, zip, tar""" - - handlers = { - 'targz': ArchiveTar, - 'tarbz2': ArchiveTar, - 'tar': ArchiveTar, - 'zip': ArchiveZip, - 'binary': ArchiveBinary - } - - self.archive = handlers.get(arch_type)(file_path, arch_type) - - def unpack(self, target_dir, clean_dir = False): - self.archive.unpack(target_dir, clean_dir) - - def unpack_files(self, files, target_dir): - self.archive.unpack_files(files, target_dir) diff --git a/tags/pisi-1.0_beta2/pisi/atomicoperations.py b/tags/pisi-1.0_beta2/pisi/atomicoperations.py deleted file mode 100644 index edcd8f54..00000000 --- a/tags/pisi-1.0_beta2/pisi/atomicoperations.py +++ /dev/null @@ -1,468 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# Package install operation - -# Author: Eray Ozkural - - -# for python 2.3 compatibility -import sys -ver = sys.version_info -if ver[0] <= 2 and ver[1] < 4: - from sets import Set as set - -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi - -import pisi.context as ctx -import pisi.packagedb as packagedb -import pisi.dependency as dependency -import pisi.util as util -from pisi.specfile import * -from pisi.package import Package -from pisi.metadata import MetaData -from pisi.files import Files -from pisi.uri import URI -import pisi.ui -#import conflicts - -class Error(pisi.Error): - pass - -# single package operations - -class AtomicOperation(object): - - def __init__(self, ignore_dep = None): - #self.package = package - if ignore_dep==None: - self.ignore_dep = ctx.config.get_option('ignore_dependency') - else: - self.ignore_dep = ignore_dep - - def run(self, package): - "perform an atomic package operation" - pass - - -class Install(AtomicOperation): - "Install class, provides install routines for pisi packages" - - def __init__(self, package_fname, ignore_dep = None): - "initialize from a file name" - super(Install, self).__init__(ignore_dep) - self.package = Package(package_fname) - self.package.read() - self.metadata = self.package.metadata - self.files = self.package.files - self.pkginfo = self.metadata.package - - def install(self, ask_reinstall = True): - "entry point" - ctx.ui.status(_('Installing %s, version %s, release %s, build %s') % - (self.pkginfo.name, self.pkginfo.version, - self.pkginfo.release, self.pkginfo.build)) - ctx.ui.notify(pisi.ui.installing, package = self.pkginfo, files = self.files) - self.ask_reinstall = ask_reinstall - self.check_requirements() - self.check_relations() - self.check_reinstall() - self.extract_install() - self.store_pisi_files() - if ctx.comar: - import pisi.comariface as comariface - self.register_comar_scripts() - comariface.run_postinstall(self.pkginfo.name) - self.update_databases() - self.update_environment() - ctx.ui.status() - if self.upgrade: - event = pisi.ui.upgraded - else: - event = pisi.ui.installed - ctx.ui.notify(event, package = self.pkginfo, files = self.files) - - def check_requirements(self): - """check system requirements""" - #TODO: IS THERE ENOUGH SPACE? - # what to do if / is split into /usr, /var, etc. - pass - - def check_relations(self): - # check conflicts - for pkg in self.metadata.package.conflicts: - if ctx.installdb.is_installed(self.pkginfo): - raise Error(_("Package conflicts %s") % pkg) - - # check dependencies - if not ctx.config.get_option('ignore_dependency'): - if not self.pkginfo.installable(): - ctx.ui.error(_('Dependencies for %s not satisfied') % - self.pkginfo.name) - raise Error(_("Package not installable")) - - # check if package is in database - # If it is not, put it into 3rd party packagedb - if not packagedb.has_package(self.pkginfo.name): - db = packagedb.thirdparty_packagedb - db.add_package(self.pkginfo) - - def check_reinstall(self): - "check reinstall, confirm action, and schedule reinstall" - - pkg = self.pkginfo - - self.reinstall = False - self.upgrade = False - if ctx.installdb.is_installed(pkg.name): # is this a reinstallation? - (iversion, irelease, ibuild) = ctx.installdb.get_version(pkg.name) - - # determine if same version - same_ver = False - ignore_build = ctx.config.options and ctx.config.options.ignore_build_no - if (not ibuild) or (not pkg.build) or ignore_build: - # we don't look at builds to compare two package versions - if pkg.version == iversion and pkg.release == irelease: - same_ver = True - else: - if pkg.build == ibuild: - same_ver = True - - if same_ver: - if self.ask_reinstall: - if not ctx.ui.confirm(_('Re-install same version package?')): - raise Error(_('Package re-install declined')) - else: - upgrade = False - # is this an upgrade? - # determine and report the kind of upgrade: version, release, build - if pkg.version > iversion: - ctx.ui.info(_('Upgrading to new upstream version')) - upgrade = True - elif pkg.release > irelease: - ctx.ui.info(_('Upgrading to new distribution release')) - upgrade = True - elif ((not ignore_build) and ibuild and pkg.build - and pkg.build > ibuild): - ctx.ui.info(_('Upgrading to new distribution build')) - upgrade = True - self.upgrade = upgrade - - # is this a downgrade? confirm this action. - if self.ask_reinstall and (not upgrade): - if pkg.version < iversion: - x = _('Downgrade to old upstream version?') - elif pkg.release < irelease: - x = _('Downgrade to old distribution release?') - else: - x = _('Downgrade to old distribution build?') - if not ctx.ui.confirm(x): - raise Error(_('Package downgrade declined')) - - - # schedule for reinstall - self.old_files = ctx.installdb.files(pkg.name) - self.old_path = ctx.installdb.pkg_dir(pkg.name, iversion, irelease) - self.reinstall = True - Remove(pkg.name).run_preremove() - - def extract_install(self): - "unzip package in place" - - ctx.ui.info(_('Extracting files')) - self.package.extract_dir_flat('install', ctx.config.dest_dir()) - - if self.reinstall: - # remove left over files - new = set(map(lambda x: str(x.path), self.files.list)) - old = set(map(lambda x: str(x.path), self.old_files.list)) - leftover = old - new - old_fileinfo = {} - for fileinfo in self.old_files.list: - old_fileinfo[str(fileinfo.path)] = fileinfo - for path in leftover: - Remove.remove_file( old_fileinfo[path] ) - - def store_pisi_files(self): - """put files.xml, metadata.xml, actions.py and COMAR scripts - somewhere in the file system. We'll need these in future...""" - - ctx.ui.info(_('Storing %s, ') % ctx.const.files_xml) - self.package.extract_file(ctx.const.files_xml, self.package.pkg_dir()) - - ctx.ui.info(_('Storing %s.') % ctx.const.metadata_xml) - self.package.extract_file(ctx.const.metadata_xml, self.package.pkg_dir()) - - for pcomar in self.metadata.package.providesComar: - fpath = os.path.join(ctx.const.comar_dir, pcomar.script) - # comar prefix is added to the pkg_dir while extracting comar - # script file. so we'll use pkg_dir as destination. - ctx.ui.info(_('Storing %s') % fpath) - self.package.extract_file(fpath, self.package.pkg_dir()) - - def register_comar_scripts(self): - "register COMAR scripts" - - for pcomar in self.metadata.package.providesComar: - scriptPath = os.path.join(self.package.comar_dir(),pcomar.script) - import pisi.comariface - pisi.comariface.register(pcomar, self.metadata.package.name, - scriptPath) - - def update_databases(self): - "update databases" - - if self.reinstall: - Remove(self.metadata.package.name).remove_db() - Remove.remove_pisi_files(self.old_path) - - # installdb - ctx.installdb.install(self.metadata.package.name, - self.metadata.package.version, - self.metadata.package.release, - self.metadata.package.build, - self.metadata.package.distribution) - - # filesdb - ctx.filesdb.add_files(self.metadata.package.name, self.files) - - # installed packages - packagedb.inst_packagedb.add_package(self.pkginfo) - - def update_environment(self): - # check if we have any shared objects or anything under - # /etc/env.d - shared = False - for x in self.files.list: - if x.path.endswith('.so') or x.path.startswith('/etc/env.d'): - shared = True - break - if not ctx.get_option('bypass_ldconfig'): - if shared: - ctx.ui.info(_("Regenerating /etc/ld.so.cache...")) - util.env_update() - else: - ctx.ui.warning(_("Bypassing ldconfig")) - -def install_single(pkg, upgrade = False): - """install a single package from URI or ID""" - url = URI(pkg) - # Check if we are dealing with a remote file or a real path of - # package filename. Otherwise we'll try installing a package from - # the package repository. - if url.is_remote_file() or os.path.exists(url.uri): - install_single_file(pkg, upgrade) - else: - install_single_name(pkg, upgrade) - -# FIXME: Here and elsewhere pkg_location must be a URI -def install_single_file(pkg_location, upgrade = False): - """install a package file""" - Install(pkg_location).install(not upgrade) - -def install_single_name(name, upgrade = False): - """install a single package from ID""" - # find package in repository - repo = packagedb.which_repo(name) - if repo: - repo = ctx.repodb.get_repo(repo) - pkg = packagedb.get_package(name) - - # FIXME: let pkg.packageURI be stored as URI type rather than string - pkg_uri = URI(pkg.packageURI) - if pkg_uri.is_absolute_path(): - pkg_path = str(pkg.packageURI) - else: - pkg_path = os.path.join(os.path.dirname(repo.indexuri.get_uri()), - str(pkg_uri.path())) - - ctx.ui.debug(_("Package URI: %s") % pkg_path) - - # Package will handle remote file for us! - install_single_file(pkg_path, upgrade) - else: - raise Error(_("Package %s not found in any active repository.") % name) - - -class Remove(AtomicOperation): - - def __init__(self, package_name, ignore_dep = None): - super(Remove, self).__init__(ignore_dep) - self.package_name = package_name - - def run(self): - """Remove a single package""" - inst_packagedb = packagedb.inst_packagedb - self.package = packagedb.get_package(self.package_name) - self.files = ctx.installdb.files(self.package_name) - - ctx.ui.status(_('Removing package %s') % self.package_name) - if not ctx.installdb.is_installed(self.package_name): - raise Exception(_('Trying to remove nonexistent package ') - + self.package_name) - - self.check_dependencies() - - self.run_preremove() - - for fileinfo in self.files.list: - self.remove_file(fileinfo) - - self.remove_db() - self.remove_pisi_files(self.package.pkg_dir()) - ctx.ui.status() - ctx.ui.notify(pisi.ui.removed, package = self.package, files = self.files) - - def check_dependencies(self): - #we only have to check the dependencies to ensure the - #system will be consistent after this removal - pass - # is there any package who depends on this package? - - def remove_file(fileinfo): - fpath = pisi.util.join_path(ctx.config.dest_dir(), fileinfo.path) - # TODO: We have to store configuration files for futher - # usage. Currently we'are doing it like rpm does, saving - # with a prefix and leaving the user to edit it. In the future - # we'll have a plan for these configuration files. - if fileinfo.type == ctx.const.conf: - if os.path.isfile(fpath): - os.rename(fpath, fpath + ".pisi") - else: - # check if file is removed manually. - # And we don't remove directories! - # TODO: remove directory if there is nothing under it? - if os.path.isfile(fpath) or os.path.islink(fpath): - os.unlink(fpath) - else: - ctx.ui.warning(_('Not removing non-file, non-link %s') % fpath) - - remove_file = staticmethod(remove_file) - - def run_preremove(self): - if ctx.comar: - import pisi.comariface as comariface - comariface.run_preremove(self.package_name) - else: - # TODO: store this somewhere - pass - - def remove_pisi_files(path): - util.clean_dir(path) - - remove_pisi_files = staticmethod(remove_pisi_files) - - def remove_db(self): - ctx.installdb.remove(self.package_name) - ctx.filesdb.remove_files(ctx.installdb.files(self.package_name)) - #FIXME: this looks like a mistake! - packagedb.remove_package(self.package_name) - - -def remove_single(package_name): - Remove(package_name).run() - -def __is_virtual_upgrade(metadata): - - pkg = metadata.package - - (iversion, irelease, ibuild) = ctx.installdb.get_version(pkg.name) - - upgrade = False - if pkg.version > iversion: - upgrade = True - elif pkg.release > irelease: - upgrade = True - elif (ibuild and pkg.build and pkg.build > ibuild): - upgrade = True - - return upgrade - -def virtual_install(metadata, files): - """Recreate the package info for rebuilddb command""" - pkg = metadata.package - - # normally this can't be true. Just for backward compatibility - # TODO: for speed only ctx.installdb.install exception can be - # handled but this is much cleaner - if ctx.installdb.is_installed(pkg.name): - if __is_virtual_upgrade(metadata): - ctx.installdb.remove(pkg.name) - packagedb.remove_package(pkg.name) - ctx.filesdb.remove_files(ctx.installdb.files(pkg.name)) - else: - return - - pkginfo = metadata.package - - # installdb - ctx.installdb.install(metadata.package.name, - metadata.package.version, - metadata.package.release, - metadata.package.build, - metadata.package.distribution) - - # filesdb - ctx.filesdb.add_files(metadata.package.name, files) - - # installed packages - packagedb.inst_packagedb.add_package(pkginfo) - -def resurrect_package(package_fn): - """Resurrect the package in the PiSi databases""" - - from os.path import exists - - metadata_xml = util.join_path(ctx.config.lib_dir(), package_fn, ctx.const.metadata_xml) - if not exists(metadata_xml): - raise Error, _("Metadata XML '%s' cannot be found") % metadata_xml - - metadata = MetaData() - metadata.read(metadata_xml) - - errs = metadata.errors() - if errs: - util.Checks.print_errors(errs) - raise Error, _("MetaData format wrong (%s)") % package_fn - - # FIXME: there won't be any previous versions of the same package under /var/lib/pisi - # therefore there won't be any need for this check and __is_virtual_upgrade function - # this is just for backward compatibility for sometime - - # yes, this is an ugly hack - passed = False - if ctx.installdb.is_installed(metadata.package.name): - passed = True - - if not passed: - ctx.ui.info(_('* Adding \'%s\' to db... ') % (metadata.package.name), noln=True) - - files_xml = util.join_path(ctx.config.lib_dir(), package_fn, ctx.const.files_xml) - if not exists(files_xml): - raise Error, _("Files XML '%s' cannot be found") % files_xml - - files = Files() - files.read(files_xml) - - if files.errors(): - raise Error, _("Invalid %s") % ctx.const.files_xml - - import pisi.atomicoperations - pisi.atomicoperations.virtual_install(metadata, files) - if not passed: - ctx.ui.info(_('OK.')) diff --git a/tags/pisi-1.0_beta2/pisi/build.py b/tags/pisi-1.0_beta2/pisi/build.py deleted file mode 100644 index 672f71bb..00000000 --- a/tags/pisi-1.0_beta2/pisi/build.py +++ /dev/null @@ -1,594 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# package bulding stuff -# maintainer: baris and meren - -# python standard library -import os -import sys -import glob - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.util as util -import pisi.context as ctx -import pisi.dependency as dependency -import pisi.operations as operations -from pisi.sourcearchive import SourceArchive -from pisi.files import Files, File as FileInfo -from pisi.fetcher import fetch_url -from pisi.uri import URI -from pisi.metadata import MetaData -from pisi.package import Package -import pisi.component as component - - -class Error(pisi.Error): - pass - - -# Helper Functions -def get_file_type(path, pinfoList): - """Return the file type of a path according to the given PathInfo - list""" - # The usage of depth is somewhat confusing. It is used for finding - # the best match to paths(in pinfolist). For an example, if paths - # contain ['/usr/share','/usr/share/doc'] and path is - # /usr/share/doc/filename our iteration over paths should match - # the second item. - depth = 0 - ftype = "" - path = "/"+path # we need a real path. - for pinfo in pinfoList: - if util.subpath(pinfo.path, path): - length = len(pinfo.path) - if depth < length: - depth = length - ftype = pinfo.fileType - return ftype - -def check_path_collision(package, pkgList): - """This function will check for collision of paths in a package with - the paths of packages in pkgList. The return value will be the - list containing the paths that collide.""" - collisions = [] - for pinfo in package.files: - for pkg in pkgList: - if pkg is package: - continue - for path in pkg.files: - # if pinfo.path is a subpath of path.path like - # the example below. path.path is marked as a - # collide. Exp: - # pinfo.path: /usr/share - # path.path: /usr/share/doc - if util.subpath(pinfo.path, path.path): - collisions.append(path.path) - ctx.ui.error(_('Path %s belongs in multiple packages') % - path.path) - return collisions - -# a dynamic build context -from pisi.specfile import SpecFile - - -class BuildContext(object): - """Build Context""" - - def __init__(self, pspecfile): - super(BuildContext, self).__init__() - self.set_spec_file(pspecfile) - - def set_spec_file(self, pspecfile): - self.pspecfile = pspecfile - spec = SpecFile() - spec.read(pspecfile) - self.spec = spec - - # directory accessor functions - - # pkg_x_dir: per package directory for storing info type x - - def pkg_dir(self): - "package build directory" - packageDir = self.spec.source.name + '-' + \ - self.spec.source.version + '-' + self.spec.source.release - return util.join_path(ctx.config.dest_dir(), ctx.config.values.dirs.tmp_dir, - packageDir) - - def pkg_work_dir(self): - return self.pkg_dir() + ctx.const.work_dir_suffix - - def pkg_install_dir(self): - return self.pkg_dir() + ctx.const.install_dir_suffix - - -class Builder: - """Provides the package build and creation routines""" - def __init__(self, pspec): - self.bctx = BuildContext(pspec) - self.pspecdir = os.path.dirname(os.path.realpath(self.bctx.pspecfile)) - self.spec = self.bctx.spec - self.sourceArchive = SourceArchive(self.bctx) - - self.set_environment_vars() - - self.actionLocals = None - self.actionGlobals = None - self.srcDir = None - - def set_state(self, state): - stateFile = util.join_path(self.bctx.pkg_work_dir(), "pisiBuildState") - open(stateFile, "w").write(state) - - def get_state(self): - stateFile = util.join_path(self.bctx.pkg_work_dir(), "pisiBuildState") - if not os.path.exists(stateFile): # no state - return None - return open(stateFile, "r").read() - - def build(self): - """Build the package in one shot.""" - - ctx.ui.info(_("Building PISI source package: %s") % self.spec.source.name) - util.xterm_title(_("Building PISI source package: %s\n") % self.spec.source.name) - - self.compile_action_script() - - # check if all patch files exists, if there are missing no need to unpack! - self.patch_exists() - - self.check_build_dependencies() - - self.get_component() - - self.fetch_source_archive() - self.unpack_source_archive() - - # apply the patches and prepare a source directory for build. - self.apply_patches() - - self.run_setup_action() - self.run_build_action() - self.run_install_action() - - # after all, we are ready to build/prepare the packages - return self.build_packages() - - def set_environment_vars(self): - """Sets the environment variables for actions API to use""" - evn = { - "PKG_DIR": self.bctx.pkg_dir(), - "WORK_DIR": self.bctx.pkg_work_dir(), - "INSTALL_DIR": self.bctx.pkg_install_dir(), - "SRC_NAME": self.spec.source.name, - "SRC_VERSION": self.spec.source.version, - "SRC_RELEASE": self.spec.source.release - } - os.environ.update(evn) - - # First check icecream, if not found use ccache, no need to use both - # together (according to kde-wiki it cause performance loss) - if os.path.exists("/opt/icecream/bin/gcc"): - # Add icecream directory for support distributed compiling :) - os.environ["PATH"] = "/opt/icecream/bin/:" + os.environ["PATH"] - ctx.ui.info(_("IceCream detected. Make sure your daemon is up and running...")) - elif os.path.exists("/usr/lib/ccache/bin/gcc"): - # Add ccache directory for support Compiler Cache :) - os.environ["PATH"] = "/usr/lib/ccache/bin/:" + os.environ["PATH"] - ctx.ui.info(_("CCache detected...")) - - def get_component(self): - if not self.spec.source.partOf: - ctx.ui.warning(_('PartOf tag not defined, looking for component')) - parentdir = os.path.realpath(self.pspecdir + '/../') - url = util.join_path(parentdir, 'component.xml') - progress = ctx.ui.Progress - if URI(url).is_remote_file(): - fetch_url(url, self.bctx.pkg_work_dir(), progress) - path = util.join_path(self.bctx.pkg_work_dir(), 'component.xml') - else: - if not os.path.exists(url): - raise Exception(_('Cannot find component.xml in upper directory')) - path = url - comp = component.Component() - comp.read(path) - ctx.ui.info(_('Source is part of %s component') % comp.name) - self.spec.source.partOf = comp.name - self.spec.override_tags() - - def fetch_source_archive(self): - ctx.ui.info(_("Fetching source from: %s") % self.spec.source.archive.uri) - self.sourceArchive.fetch() - ctx.ui.info(_("Source archive is stored: %s/%s") - %(ctx.config.archives_dir(), self.spec.source.archive.name)) - - def unpack_source_archive(self): - ctx.ui.info(_("Unpacking archive...")) - self.sourceArchive.unpack() - ctx.ui.info(_(" unpacked (%s)") % self.bctx.pkg_work_dir()) - self.set_state("unpack") - - def run_setup_action(self): - # Run configure, build and install phase - ctx.ui.action(_("Setting up source...")) - self.run_action_function(ctx.const.setup_func) - self.set_state("setupaction") - - def run_build_action(self): - ctx.ui.action(_("Building source...")) - self.run_action_function(ctx.const.build_func) - self.set_state("buildaction") - - def run_install_action(self): - ctx.ui.action(_("Installing...")) - - # Before install make sure install_dir is clean - if os.path.exists(self.bctx.pkg_install_dir()): - util.clean_dir(self.bctx.pkg_install_dir()) - - # install function is mandatory! - self.run_action_function(ctx.const.install_func, True) - self.set_state("installaction") - - def compile_action_script(self): - """Compiles actions.py and sets the actionLocals and actionGlobals""" - specdir = os.path.dirname(self.bctx.pspecfile) - scriptfile = util.join_path(specdir, ctx.const.actions_file) - try: - localSymbols = globalSymbols = {} - buf = open(scriptfile).read() - exec compile(buf, "error", "exec") in localSymbols, globalSymbols - except IOError, e: - raise Error(_("Unable to read Action Script (%s): %s") %(scriptfile,e)) - except SyntaxError, e: - raise Error(_("SyntaxError in Action Script (%s): %s") %(scriptfile,e)) - - self.actionLocals = localSymbols - self.actionGlobals = globalSymbols - self.srcDir = self.pkg_src_dir() - - def pkg_src_dir(self): - """Returns the real path of WorkDir for an unpacked archive.""" - try: - workdir = self.actionGlobals['WorkDir'] - except KeyError: - workdir = self.spec.source.name + "-" + self.spec.source.version - - return util.join_path(self.bctx.pkg_work_dir(), workdir) - - def run_action_function(self, func, mandatory=False): - """Calls the corresponding function in actions.py. - - If mandatory parameter is True, and function is not present in - actionLocals pisi.build.Error will be raised.""" - # we'll need our working directory after actionscript - # finished its work in the archive source directory. - curDir = os.getcwd() - os.chdir(self.srcDir) - - - if func in self.actionLocals: - self.actionLocals[func]() - else: - if mandatory: - Error, _("unable to call function from actions: %s") %func - - os.chdir(curDir) - - def check_build_dependencies(self): - """fail if dependencies not satisfied""" - - build_deps = set(self.spec.source.buildDependencies) - - if not ctx.get_option('bypass_safety'): - if ctx.componentdb.has_component('system.devel'): - build_deps_names = set([x.package for x in build_deps]) - devel_deps_names = set(ctx.componentdb.get_component('system.devel').packages) - extra_names = devel_deps_names - build_deps_names - ctx.ui.warning(_('Safety switch: following extra packages in system.devel will be installed: ') + - util.strlist(extra_names)) - extra_deps = [dependency.Dependency(package = x) for x in extra_names] - build_deps = build_deps.union(extra_deps) - else: - ctx.ui.warning(_('Safety switch: the component system.devel cannot be found')) - - # find out the build dependencies that are not satisfied... - dep_unsatis = [] - for dep in build_deps: - if not dependency.installed_satisfies_dep(dep): - dep_unsatis.append(dep) - - if dep_unsatis: - ctx.ui.info(_("Unsatisfied Build Dependencies:")) - for dep in dep_unsatis: - ctx.ui.warning(dep.package) - if not ctx.config.get_option('ignore_dependency'): - if ctx.ui.confirm( - _('Do you want to install the unsatisfied build dependencies')): - ctx.ui.info(_('Installing build dependencies.')) - operations.install([dep.package for dep in dep_unsatis]) - else: - raise Error(_('Cannot build package due to unsatisfied build dependencies')) - else: - ctx.ui.warning(_('Ignoring build dependencies.')) - - def patch_exists(self): - """check existence of patch files declared in PSPEC""" - - files_dir = os.path.abspath(util.join_path(self.pspecdir, - ctx.const.files_dir)) - for patch in self.spec.source.patches: - patchFile = util.join_path(files_dir, patch.filename) - if not os.access(patchFile, os.F_OK): - raise Error(_("Patch file is missing: %s\n") % patch.filename) - - def apply_patches(self): - files_dir = os.path.abspath(util.join_path(self.pspecdir, - ctx.const.files_dir)) - - for patch in self.spec.source.patches: - patchFile = util.join_path(files_dir, patch.filename) - if patch.compressionType: - patchFile = util.uncompress(patchFile, - compressType=patch.compressionType, - targetDir=ctx.config.tmp_dir()) - - ctx.ui.action(_("* Applying patch: %s") % patch.filename) - util.do_patch(self.srcDir, patchFile, level=patch.level, target=patch.target) - - def strip_install_dir(self): - """strip install directory""" - ctx.ui.action(_("Stripping files..")) - install_dir = self.bctx.pkg_install_dir() - try: - nostrip = self.actionGlobals['NoStrip'] - util.strip_directory(install_dir, nostrip) - except KeyError: - util.strip_directory(install_dir) - - def gen_metadata_xml(self, package): - """Generate the metadata.xml file for build source. - - metadata.xml is composed of the information from specfile plus - some additional information.""" - metadata = MetaData() - metadata.from_spec(self.spec.source, package) - - metadata.package.distribution = ctx.config.values.general.distribution - metadata.package.distributionRelease = ctx.config.values.general.distribution_release - metadata.package.architecture = "Any" - - size, d = 0, self.bctx.pkg_install_dir() - - for path in package.files: - size += util.dir_size(util.join_path(d, path.path)) - - metadata.package.installedSize = size - - # build no - if ctx.config.options.ignore_build_no: - metadata.package.build = None # means, build no information n/a - ctx.ui.warning(_('build number is not available.')) - else: - metadata.package.build = self.calc_build_no(metadata.package.name) - - metadata_xml_path = util.join_path(self.bctx.pkg_dir(), ctx.const.metadata_xml) - metadata.write(metadata_xml_path) - self.metadata = metadata - - def gen_files_xml(self, package): - """Generates files.xml using the path definitions in specfile and - the files produced by the build system.""" - files = Files() - install_dir = self.bctx.pkg_install_dir() - - # FIXME: We need to expand globs before trying to calculate hashes - # Not on the fly like now. - - # we'll exclude collisions in get_file_hashes. Having a - # collisions list is not wrong, we must just handle it :). - # sure -- exa - collisions = check_path_collision(package, self.spec.packages) - # FIXME: material collisions after expanding globs must be - # reported as errors, and an exception must be raised - - d = {} - def add_path(path): - # add the files under material path - for fpath, fhash in util.get_file_hashes(path, collisions, install_dir): - frpath = util.removepathprefix(install_dir, fpath) # relative path - ftype = get_file_type(frpath, package.files) - try: # broken links and empty dirs can cause problem - fsize = os.path.getsize(fpath) - except OSError: - fsize = None - d[frpath] = FileInfo(path=frpath, type=ftype, size=fsize, hash=fhash) - - for pinfo in package.files: - wildcard_path = util.join_path(install_dir, pinfo.path) - for path in glob.glob(wildcard_path): - add_path(path) - - for (p, fileinfo) in d.iteritems(): - files.append(fileinfo) - - files_xml_path = util.join_path(self.bctx.pkg_dir(), ctx.const.files_xml) - files.write(files_xml_path) - self.files = files - - def calc_build_no(self, package_name): - """Calculate build number""" - - # find previous build in output dir and packages dir - found = [] - def locate_package_names(files): - for fn in files: - fn = fn.decode('utf-8') - if util.is_package_name(fn, package_name): - old_package_fn = util.join_path(root, fn) - ctx.ui.info('(found old version %s)' % old_package_fn) - old_pkg = Package(old_package_fn, 'r') - old_pkg.read(util.join_path(ctx.config.tmp_dir(), 'oldpkg')) - if str(old_pkg.metadata.package.name) != package_name: - ctx.ui.warning('Skipping %s with wrong pkg name ' % - old_package_fn) - continue - old_build = old_pkg.metadata.package.build - found.append( (old_package_fn, old_build) ) - - for root, dirs, files in os.walk(ctx.config.options.output_dir): - dirs = [] # don't recurse - locate_package_names(files) - for root, dirs, files in os.walk(ctx.config.packages_dir()): - locate_package_names(files) - - if not found: - return 1 - ctx.ui.warning(_('(no previous build found, setting build no to 1.)')) - else: - a = filter(lambda (x,y): y != None, found) - ctx.ui.debug(str(a)) - if a: - # sort in order of increasing build number - a.sort(lambda x,y : cmp(x[1],y[1])) - old_package_fn = a[-1][0] # get the last one - old_build = a[-1][1] - else: - old_build = None - - # compare old files.xml with the new one.. - old_pkg = Package(old_package_fn, 'r') - old_pkg.read(util.join_path(ctx.config.tmp_dir(), 'oldpkg')) - - # FIXME: TAKE INTO ACCOUNT MINOR CHANGES IN METADATA - changed = False - fnew = self.files.list - fold = old_pkg.files.list - fold.sort(lambda x,y : cmp(x.path,y.path)) - fnew.sort(lambda x,y : cmp(x.path,y.path)) - if len(fnew) != len(fold): - changed = True - else: - for i in range(len(fold)): - fo = fold.pop(0) - fn = fnew.pop(0) - if fo.path != fn.path: - changed = True - break - else: - if fo.hash != fn.hash: - changed = True - break - ctx.ui.debug('old build number: %s' % old_build) - - # set build number - if old_build is None: - ctx.ui.warning(_('(old package lacks a build no, setting build no to 0.)')) - return 0 - elif changed: - ctx.ui.info(_('There are changes, incrementing build no to %d') % (old_build + 1)) - return old_build + 1 - else: - ctx.ui.info(_('There is no change from previous build %d ') % old_build) - return old_build - - def build_packages(self): - """Build each package defined in PSPEC file. After this process there - will be .pisi files hanging around, AS INTENDED ;)""" - - from copy import deepcopy - - # Strip install directory before building .pisi packages. - self.strip_install_dir() - - package_names = [] - - for package in self.spec.packages: - # store additional files - c = os.getcwd() - os.chdir(self.pspecdir) - install_dir = self.bctx.pkg_dir() + ctx.const.install_dir_suffix - tmp_aF = [] - for afile in package.additionalFiles: - destdir = util.join_path(install_dir, os.path.dirname(afile.target)) - for src in glob.glob(util.join_path(ctx.const.files_dir, afile.filename)): - tmp_afile_obj = deepcopy(afile) - tmp_afile_obj.filename = src[len(ctx.const.files_dir) + 1:] - tmp_aF.append(tmp_afile_obj) - destfile = os.path.basename(afile.target) - if not destfile: destfile = os.path.basename(src) - ctx.ui.debug(_("Copying additional file: '%s' to '%s' as '%s'") \ - % (src, destdir, destfile)) - util.copy_file(src, util.join_path(destdir, destfile)) - if afile.permission: - # mode is octal! - os.chmod(util.join_path(destdir, destfile), int(afile.permission, 8)) - - package.additionalFiles = tmp_aF - - os.chdir(c) - - ctx.ui.action(_("** Building package %s") % package.name); - - ctx.ui.info(_("Generating %s,") % ctx.const.files_xml) - self.gen_files_xml(package) - - ctx.ui.info(_("Generating %s,") % ctx.const.metadata_xml) - self.gen_metadata_xml(package) - - ctx.ui.info(_("Creating PISI package %s.") % package.name) - - name = util.package_name(package.name, - self.spec.source.version, - self.spec.source.release, - self.metadata.package.build) - pkg = Package(name, 'w') - package_names.append(name) - - # add comar files to package - os.chdir(self.pspecdir) - for pcomar in package.providesComar: - fname = util.join_path(ctx.const.comar_dir, - pcomar.script) - pkg.add_to_package(fname) - - # add xmls and files - os.chdir(self.bctx.pkg_dir()) - - pkg.add_to_package(ctx.const.metadata_xml) - pkg.add_to_package(ctx.const.files_xml) - - # Now it is time to add files to the packages using newly - # created files.xml - files = Files() - files.read(ctx.const.files_xml) - for finfo in files.list: - pkg.add_to_package("install/" + finfo.path) - - pkg.close() - os.chdir(c) - self.set_state("buildpackages") - util.xterm_title_reset() - ctx.ui.info(_("Done.")) - - if ctx.config.values.general.autoclean is True: - ctx.ui.info(_("Cleaning Build Directory...")) - util.clean_dir(self.bctx.pkg_dir()) - else: - ctx.ui.info(_("Keeping Build Directory")) - - return package_names diff --git a/tags/pisi-1.0_beta2/pisi/cli/README b/tags/pisi-1.0_beta2/pisi/cli/README deleted file mode 100644 index 5ad52a09..00000000 --- a/tags/pisi-1.0_beta2/pisi/cli/README +++ /dev/null @@ -1,23 +0,0 @@ -Writing commands: ------------------ - -TODO: this is a *bit* out of date now. - -Subclass from Command. - -Be careful not to import PiSi modules before Command is run, e.g. -do it in run() method. This is necessary to prevent an obscure -initialization error. - -We used to import pisi.operations in pisi.cli - -This prevented pisi.operations from having the current global -pisi.ui.ui because it's loaded before the UI is set! So, despite -what you might understand from the python FAQ 1.2.3 -http://www.python.org/doc/faq/programming.html#how-do-i-share-global-variables-across-modules -you have to be careful about the initialization order when using -singleton modules. - -Another way to solve this is to ensure that the global module is -always imported again in every function it is called (see -ui.CLI.confirm() ) but this is more expensive. diff --git a/tags/pisi-1.0_beta2/pisi/cli/__init__.py b/tags/pisi-1.0_beta2/pisi/cli/__init__.py deleted file mode 100644 index fa6d49ad..00000000 --- a/tags/pisi-1.0_beta2/pisi/cli/__init__.py +++ /dev/null @@ -1,137 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import sys -import locale - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context as ctx -from pisi.ui import UI -import pisi.ui as ui -from pisi.cli.colors import colorize - - -class Error(pisi.Error): - pass - - -class Exception(pisi.Exception): - pass - - -def printu(obj, err = False): - if not isinstance(obj, unicode): - obj = unicode(obj) - if err: - out = sys.stderr - else: - out = sys.stdout - out.write(obj.encode('utf-8')) - out.flush() - -class CLI(UI): - "Command Line Interface" - - def __init__(self, show_debug = False, show_verbose = False): - super(CLI, self).__init__(show_debug, show_verbose) - - def output(self, msg, err = False): - if type(msg)==type(unicode()): - msg = msg.encode('utf-8') - if err: - out = sys.stderr - else: - out = sys.stdout - out.write(msg) - out.flush() - - def info(self, msg, verbose = False, noln = False): - # TODO: need to look at more kinds of info messages - # let's cheat from KDE :) - if noln: - msgend = '' - else: - msgend = '\n' - if verbose and self.show_verbose: - self.output(msg + msgend) - elif not verbose: - self.output(msg + msgend) - - def warning(self,msg): - if ctx.get_option('no_color'): - self.output(_('Warning: ') + msg + '\n', err=True) - else: - self.output(colorize(msg + '\n', 'purple'), err=True) - - def error(self,msg): - if ctx.get_option('no_color'): - self.output(_('Error: ') + msg + '\n', err=True) - else: - self.output(colorize(msg + '\n', 'red'), err=True) - - def action(self,msg): - #TODO: this seems quite redundant? - self.output(colorize(msg + '\n', 'green')) - - def choose(self, msg, opts): - print msg - for i in range(0,len(opts)): - print i + 1, opts(i) - while True: - s = raw_input(msg + colorize('1-%d' % len(opts), 'red')) - try: - opt = int(s) - if 1 <= opt and opt <= len(opts): - return opts(opt-1) - except (Exception,e): - pass - - def confirm(self, msg): - if ctx.config.options and ctx.config.options.yes_all: - return True - while True: - import re - yesexpr = re.compile(locale.nl_langinfo(locale.YESEXPR)) - - prompt = msg + colorize(_(' (yes/no)'), 'red') - s = raw_input(prompt.encode('utf-8')) - if yesexpr.search(s): - return True - - return False - - def display_progress(self, **ka): - out = '\r%-30.30s %3d%% %12.2f %s' % \ - (ka['filename'], ka['percent'], ka['rate'], ka['symbol']) - self.output(out) - if ka['percent'] == 100: - self.output(colorize(_(' [complete]\n'), 'gray')) - - def status(self, msg = None): - if msg: - self.output(colorize(msg + '\n', 'purple')) - - def notify(self, event, **keywords): - if event == ui.installed: - msg = _('Installed %s') % keywords['package'].name - elif event == ui.removed: - msg = _('Removed %s') % keywords['package'].name - elif event == ui.upgraded: - msg = _('Upgraded %s') % keywords['package'].name - else: - msg = None - if msg: - self.output(colorize(msg + '\n', 'cyan')) diff --git a/tags/pisi-1.0_beta2/pisi/cli/colors.py b/tags/pisi-1.0_beta2/pisi/cli/colors.py deleted file mode 100644 index 12fd4911..00000000 --- a/tags/pisi-1.0_beta2/pisi/cli/colors.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# Colors module provides some color codes for console output. - -import pisi.context as ctx - -colors = {'black' : "\033[30m", - 'red' : "\033[31m", - 'green' : "\033[32m", - 'yellow' : "\033[33m", - 'blue' : "\033[34m", - 'purple' : "\033[35m", - 'cyan' : "\033[36m", - 'white' : "\033[37m", - 'brightblack' : "\033[01;30m", - 'brightred' : "\033[01;31m", - 'brightgreen' : "\033[01;32m", - 'brightyellow' : "\033[01;33m", - 'brightblue' : "\033[01;34m", - 'brightmagenta' : "\033[01;35m", - 'brightcyan' : "\033[01;36m", - 'brightwhite' : "\033[01;37m", - 'underlineblack' : "\033[04;30m", - 'underlinered' : "\033[04;31m", - 'underlinegreen' : "\033[04;32m", - 'underlineyellow' : "\033[04;33m", - 'underlineblue' : "\033[04;34m", - 'underlinemagenta' : "\033[04;35m", - 'underlinecyan' : "\033[04;36m", - 'underlinewhite' : "\033[04;37m", - 'blinkingblack' : "\033[05;30m", - 'blinkingred' : "\033[05;31m", - 'blinkinggreen' : "\033[05;32m", - 'blinkingyellow' : "\033[05;33m", - 'blinkingblue' : "\033[05;34m", - 'blinkingmagenta' : "\033[05;35m", - 'blinkingcyan' : "\033[05;36m", - 'blinkingwhite' : "\033[05;37m", - 'backgroundblack' : "\033[07;30m", - 'backgroundred' : "\033[07;31m", - 'backgroundgreen' : "\033[07;32m", - 'backgroundyellow' : "\033[07;33m", - 'backgroundblue' : "\033[07;34m", - 'backgroundmagenta' : "\033[07;35m", - 'backgroundcyan' : "\033[07;36m", - 'backgroundwhite' : "\033[07;37m", - 'default' : "\033[0m" } - -def colorize(msg, color): - """Colorize the given message for console output""" - if colors.has_key(color) and not ctx.get_option('no_color'): - return colors[color] + msg + colors['default'] - else: - return msg diff --git a/tags/pisi-1.0_beta2/pisi/cli/commands.py b/tags/pisi-1.0_beta2/pisi/cli/commands.py deleted file mode 100644 index 488c2fe7..00000000 --- a/tags/pisi-1.0_beta2/pisi/cli/commands.py +++ /dev/null @@ -1,1183 +0,0 @@ -# -*- coding:utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import sys -from optparse import OptionParser - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.cli -import pisi.context as ctx -from pisi.uri import URI -import pisi.util as util -import pisi.api as api -import pisi.packagedb as packagedb - -class Error(pisi.Error): - pass - - -class Command(object): - """generic help string for any command""" - - # class variables - - cmd = [] - cmd_dict = {} - - def commands_string(): - s = '' - list = [x.name[0] for x in Command.cmd] - list.sort() - for x in list: - s += x + '\n' - return s - commands_string = staticmethod(commands_string) - - def get_command(cmd, fail=False): - - if Command.cmd_dict.has_key(cmd): - return Command.cmd_dict[cmd]() - - if fail: - raise Error(_("Unrecognized command: %s") % cmd) - else: - return None - get_command = staticmethod(get_command) - - # instance variabes - - def __init__(self): - # now for the real parser - import pisi - self.comar = False - self.parser = OptionParser(usage=getattr(self, "__doc__"), - version="%prog " + pisi.__version__) - self.options() - self.commonopts() - (self.options, self.args) = self.parser.parse_args() - self.args.pop(0) # exclude command arg - - self.process_opts() - - def commonopts(self): - '''common options''' - p = self.parser - p.add_option("-D", "--destdir", action="store", default = None, - help = _("change the system root for pisi commands")) - p.add_option("-y", "--yes-all", action="store_true", - default=False, help = _("assume yes in all yes/no queries")) - p.add_option("-u", "--username", action="store") - p.add_option("-p", "--password", action="store") - p.add_option("-P", action="store_true", dest="getpass", default=False, - help=_("get password from the command line")) - p.add_option("-v", "--verbose", action="store_true", - dest="verbose", default=False, - help=_("detailed output")) - p.add_option("-d", "--debug", action="store_true", - default=False, help=_("show debugging information")) -# p.add_option("-n", "--dry-run", action="store_true", default=False, -# help = _("do not perform any action, just show what\ -# would be done")) - p.add_option("-N", "--no-color", action="store_true", default=False, - help = _("print like a man")) - return p - - def options(self): - """This is a fall back function. If the implementer module provides an - options function it will be called""" - pass - - def process_opts(self): - self.check_auth_info() - - # make destdir absolute - if self.options.destdir: - dir = str(self.options.destdir) - import os.path - if not os.path.exists(dir): - pisi.cli.printu(_('Destination directory %s does not exist. Creating directory.\n') % dir) - os.makedirs(dir) - self.options.destdir = os.path.realpath(dir) - - - def check_auth_info(self): - username = self.options.username - password = self.options.password - - # TODO: We'll get the username, password pair from a configuration - # file from users home directory. Currently we need user to - # give it from the user interface. - # if not username and not password: - # if someauthconfig.username and someauthconfig.password: - # self.authInfo = (someauthconfig.username, - # someauthconfig.password) - # return - if username and password: - self.authInfo = (username, password) - return - - if username and self.options.getpass: - from getpass import getpass - password = getpass(_("Password: ")) - self.authInfo = (username, password) - else: - self.authInfo = None - - def init(self, database = True): - """initialize PiSi components""" - - # NB: command imports here or in the command class run fxns - import pisi.api - pisi.api.init(database = database, options = self.options, - comar = self.comar) - - def finalize(self): - """do cleanup work for PiSi components""" - pisi.api.finalize() - - def get_name(self): - return self.__class__.name - - def format_name(self): - (name, shortname) = self.get_name() - if shortname: - return "%s (%s)" % (name, shortname) - else: - return name - - def help(self): - """print help for the command""" - ctx.ui.info(self.format_name() + ': ') - trans = gettext.translation('pisi', fallback=True) - ctx.ui.info(trans.ugettext(self.__doc__) + '\n') - ctx.ui.info(self.parser.format_option_help()) - - def die(self): - """exit program""" - #FIXME: not called from anywhere? - ctx.ui.error(_('Command terminated abnormally.')) - sys.exit(-1) - - -class autocommand(type): - def __init__(cls, name, bases, dict): - super(autocommand, cls).__init__(name, bases, dict) - Command.cmd.append(cls) - name = getattr(cls, 'name', None) - if name is None: - raise pisi.cli.Error(_('Command lacks name')) - longname, shortname = name - def add_cmd(cmd): - if Command.cmd_dict.has_key(cmd): - raise pisi.cli.Error(_('Duplicate command %s') % cmd) - else: - Command.cmd_dict[cmd] = cls - add_cmd(longname) - if shortname: - add_cmd(shortname) - - -class Help(Command): - """Prints help for given commands. - -Usage: help [ ... ] - -If run without parameters, it prints the general help.""" - - __metaclass__ = autocommand - - def __init__(self): - #TODO? Discard Help's own usage doc in favor of general usage doc - #self.__doc__ = usage_text - #self.__doc__ += commands_string() - super(Help, self).__init__() - - name = ("help", "h") - - def run(self): - if not self.args: - self.parser.set_usage(usage_text) - pisi.cli.printu(self.parser.format_help()) - return - - self.init(database = False) - - for arg in self.args: - obj = Command.get_command(arg, True) - obj.help() - ctx.ui.info('') - - self.finalize() - - -class Clean(Command): - """Clean stale locks.""" - - __metaclass__ = autocommand - - def __init__(self): - super(Clean, self).__init__() - - name = ("clean", None) - - def run(self): - self.init() - pisi.util.clean_locks() - self.finalize() - - -class DeleteCache(Command): - """Delete cache files""" - - __metaclass__ = autocommand - - def __init__(self): - super(DeleteCache, self).__init__() - - name = ("delete-cache", None) - - def run(self): - self.init(database=False) - pisi.api.delete_cache() - - -class Graph(Command): - """Graph package relations. -Usage: graph [ ...] - -Write a graph of package relations, tracking dependency and -conflicts relations starting from given packages. -""" - - __metaclass__ = autocommand - - def __init__(self): - super(Graph, self).__init__() - - def options(self): - self.parser.add_option("-a", "--all", action="store_true", - default=False, - help=_("graph all available packages")) - self.parser.add_option("-o", "--output", action="store", - default='pgraph.dot', - help=_("dot output file")) - - name = ("graph", None) - - def all_packages(self): - a = set() - from pisi import packagedb - for repo in ctx.repodb.list(): - pkg_db = packagedb.get_db(repo) - a = a.union(pkg_db.list_packages()) - return a - - def run(self): - self.init() - if ctx.get_option('all'): - ctx.ui.info(_('Plotting a graph of relations among all available packages')) - a = self.all_packages() - else: - if self.args: - a = self.args - else: - # if A is empty, then graph all packages - ctx.ui.info(_('Plotting a graph of relations among all installed packages')) - a = ctx.installdb.list_installed() - g = pisi.api.package_graph(a) - g.write_graphviz(file(ctx.get_option('output'), 'w')) - self.finalize() - -# option mixins - -def buildno_opts(self): - self.parser.add_option("", "--ignore-build-no", action="store_true", - default=False, - help=_("do not take build no into account.")) - -def ignoredep_opt(self): - p = self.parser - p.add_option("-E", "--ignore-dependency", action="store_true", - default=False, - help=_("do not take dependency information into account")) - - -class Build(Command): - """Build a PISI package using a pspec.xml file - -Usage: build - -You can give a URI of the pspec.xml file. PISI will -fetch all necessary files and build the package for you. -""" - __metaclass__ = autocommand - - def __init__(self): - super(Build, self).__init__() - - name = ("build", "bi") - - def options(self): - buildno_opts(self) - ignoredep_opt(self) - self.parser.add_option("-O", "--output-dir", action="store", default=".", - help=_("output directory for produced packages")) - self.parser.add_option("-A", "--ignore-action-errors", - action="store_true", default=False, - help=_("bypass errors from ActionsAPI")) - - - def run(self): - if not self.args: - self.help() - return - - self.init(database = True) - ctx.ui.info('Output directory: %s\n' % ctx.config.options.output_dir) - for arg in self.args: - pisi.api.build(arg, self.authInfo) - self.finalize() - - -class PackageOp(Command): - """Abstract package operation command""" - - def __init__(self): - super(PackageOp, self).__init__() - self.comar = True - - def options(self): - p = self.parser - p.add_option("-B", "--ignore-comar", action="store_true", - default=False, help=_("bypass comar configuration agent")) - p.add_option("-S", "--bypass-safety", action="store_true", - default=False, help=_("bypass safety switch")) - ignoredep_opt(self) - - def init(self): - super(PackageOp, self).init(True) - - def finalize(self): - #self.finalize_db() - pass - - -class Install(PackageOp): - """Install PISI packages - -Usage: install ... - -You may use filenames, URIs or package names for packages. If you have -specified a package name, it should exist in a specified repository. - -You can also specify components instead of package names, which will be -expanded to package names. -""" - __metaclass__ = autocommand - - def __init__(self): - super(Install, self).__init__() - - name = "install", "it" - - def options(self): - super(Install, self).options() - p = self.parser - p.add_option("", "--bypass-ldconfig", action="store_true", - default=False, help=_("Bypass ldconfig phase")) - buildno_opts(self) - - def run(self): - if not self.args: - self.help() - return - - self.init() - pisi.api.install(self.args) - self.finalize() - - -class Upgrade(PackageOp): - """Upgrade PISI packages - -Usage: Upgrade [ ... ] - -: package name - -Upgrades the entire system if no package names are given - -You may use only package names to specify packages because -the package upgrade operation is defined only with respect -to repositories. If you have specified a package name, it -should exist in the package repositories. If you just want to -reinstall a package from a pisi file, use the install command. - -You can also specify components instead of package names, which will be -expanded to package names. -""" - - __metaclass__ = autocommand - - def __init__(self): - super(Upgrade, self).__init__() - - name = ("upgrade", "up") - - def options(self): - super(Upgrade, self).options() - buildno_opts(self) - p = self.parser - p.add_option("", "--bypass-ldconfig", action="store_true", - default=False, help=_("Bypass ldconfig phase")) - self.parser.add_option("-e", "--eager", action="store_true", - default=False, help=_("eager upgrades")) - - def run(self): - self.init() - - if not self.args: - packages = ctx.installdb.list_installed() - else: - packages = self.args - - pisi.api.upgrade(packages) - self.finalize() - - -class Remove(PackageOp): - """Remove PISI packages - -Usage: remove ... - -Remove package(s) from your system. Just give the package names to remove. - -You can also specify components instead of package names, which will be -expanded to package names. -""" - __metaclass__ = autocommand - - def __init__(self): - super(Remove, self).__init__() - - name = ("remove", "rm") - - def run(self): - if not self.args: - self.help() - return - - self.init() - pisi.api.remove(self.args) - self.finalize() - - -class ConfigurePending(PackageOp): - """configure pending packages - """ - - __metaclass__ = autocommand - - def __init__(self): - super(ConfigurePending, self).__init__() - - name = ("configure-pending", "cp") - - def run(self): - - self.init() - pisi.api.configure_pending() - self.finalize() - - -class Info(Command): - """Display package information - -Usage: info ... - -""" - __metaclass__ = autocommand - - def __init__(self): - super(Info, self).__init__() - - name = ("info", "i") - - def options(self): - self.parser.add_option("-f", "--files", action="store_true", - default=False, - help=_("show a list of package files.")) - self.parser.add_option("-F", "--files-path", action="store_true", - default=False, - help=_("Show only paths.")) - - def run(self): - if not self.args: - self.help() - return - - self.init(True) - for arg in self.args: - if ctx.componentdb.has_component(arg): - component = ctx.componentdb.get_component(arg) - #if self.options.long: - ctx.ui.info(unicode(component)) - else: # then assume it was a package - self.printinfo_package(arg) - self.finalize() - - def printinfo_package(self, arg): - import os.path - - metadata, files = pisi.api.info(arg) - ctx.ui.info(unicode(metadata.package)) - revdeps = [x[0] for x in packagedb.get_rev_deps(arg)] - print _('Reverse Dependencies:'), util.strlist(revdeps) - if self.options.files or self.options.files_path: - if files: - print _('\nFiles:') - for fileinfo in files.list: - if self.options.files: - print fileinfo - else: - print fileinfo.path - else: - ctx.ui.warning(_('File information not available')) - - -class Index(Command): - """Index PISI files in a given directory - -Usage: index - -This command searches for all PiSi files in a directory, collects PiSi -tags from them and accumulates the information in an output XML file, -named by default 'pisi-index.xml'. In particular, it indexes both -source and binary packages. -""" - __metaclass__ = autocommand - - def __init__(self): - super(Index, self).__init__() - - name = ("index", "ix") - - def options(self): - self.parser.add_option("-a", "--absolute-uris", action="store_true", - default=False, - help=_("store absolute links for indexed files.")) - self.parser.add_option("-o", "--output", action="store", - default='pisi-index.xml', - help=_("index output file")) - - def run(self): - - self.init() - from pisi.api import index - if len(self.args)>0: - index(self.args, ctx.get_option('output')) - elif len(self.args)==0: - ctx.ui.info( _('Indexing current directory.')) - index('.', ctx.get_option('output')) - self.finalize() - - -class ListInstalled(Command): - """Print the list of all installed packages - -Usage: list-installed - -""" - - __metaclass__ = autocommand - - def __init__(self): - super(ListInstalled, self).__init__() - - name = ("list-installed", "li") - - def options(self): - self.parser.add_option("-l", "--long", action="store_true", - default=False, help="show in long format") - self.parser.add_option("-i", "--install-info", action="store_true", - default=False, help="show detailed install info") - - def run(self): - self.init(True) - list = ctx.installdb.list_installed() - list.sort() - if self.options.install_info: - ctx.ui.info(_('Package Name |St| Version| Rel.| Build| Distro| Date')) - print '========================================================================' - for pkg in list: - package = pisi.packagedb.inst_packagedb.get_package(pkg) - inst_info = ctx.installdb.get_info(pkg) - if self.options.long: - ctx.ui.info(unicode(package)) - ctx.ui.info(unicode(inst_info)) - elif self.options.install_info: - ctx.ui.info('%-15s | %s ' % (package.name, inst_info.one_liner())) - else: - ctx.ui.info('%15s - %s ' % (package.name, package.summary)) - self.finalize() - -class RebuildDb(Command): - """Rebuild Databases - -Usage: rebuilddb [ ... ] - -Rebuilds the PiSi databases - -If package specs are given, they should be the names of package dirs under /var/lib/pisi -""" - __metaclass__ = autocommand - - def __init__(self): - super(RebuildDb, self).__init__() - - name = ("rebuild-db", "rdb") - - def run(self): - - self.init() - - if self.args: - for package_fn in self.args: - pisi.api.resurrect_package(package_fn) - else: - #FIXME: Confirm icin init, unlink icin finalize, rebuild_db icin init lazim :) - if ctx.ui.confirm(_('Rebuild PISI databases?')): - self.finalize() - import os - for db in os.listdir(ctx.config.db_dir()): - os.unlink(pisi.util.join_path(ctx.config.db_dir(), db)) - self.init(database=True) - self.rebuild_db() - - self.finalize() - - def rebuild_db(self): - import os - for package_fn in os.listdir(ctx.config.lib_dir()): - if not package_fn == "scripts": - pisi.api.resurrect_package(package_fn) - -class UpdateRepo(Command): - """Update repository databases - -Usage: update-repo [ ... ] - -: repository name -Synchronizes the PiSi databases with the current repository. -If no repository is given, all repositories are updated. -""" - __metaclass__ = autocommand - - def __init__(self): - super(UpdateRepo, self).__init__() - - name = ("update-repo", "ur") - - def run(self): - self.init(database = True) - - if self.args: - repos = self.args - else: - repos = ctx.repodb.list() - - for repo in repos: - pisi.api.update_repo(repo) - self.finalize() - - -class AddRepo(Command): - """Add a repository - -Usage: add-repo - -: name of repository to add -: URI of index file - -NB: We support only local files (e.g., /a/b/c) and http:// URIs at the moment -""" - __metaclass__ = autocommand - - def __init__(self): - super(AddRepo, self).__init__() - - name = ("add-repo", "ar") - - def run(self): - - if len(self.args)>=2: - self.init() - name = self.args[0] - indexuri = self.args[1] - pisi.api.add_repo(name, indexuri) - if ctx.ui.confirm(_('Update PISI database for repository %s?') % name): - pisi.api.update_repo(name) - self.finalize() - else: - self.help() - return - - -class RemoveRepo(Command): - """Remove repositories - -Usage: remove-repo ... - -Remove all repository information from the system. -""" - __metaclass__ = autocommand - - def __init__(self): - super(RemoveRepo, self).__init__() - - name = ("remove-repo", "rr") - - def run(self): - - if len(self.args)>=1: - self.init() - for repo in self.args: - pisi.api.remove_repo(repo) - self.finalize() - else: - self.help() - return - - -class ListRepo(Command): - """List repositories - -Usage: list-repo - -Lists currently tracked repositories. -""" - __metaclass__ = autocommand - - def __init__(self): - super(ListRepo, self).__init__() - - name = ("list-repo", "lr") - - def run(self): - - self.init() - for repo in ctx.repodb.list(): - ctx.ui.info(repo) - print ' ', ctx.repodb.get_repo(repo).indexuri.get_uri() - self.finalize() - - -class ListAvailable(Command): - """List available packages in the repositories - -Usage: list-available [ ... repon ] - -Gives a brief list of PiSi packages published in the repository. -""" - __metaclass__ = autocommand - - def __init__(self): - super(ListAvailable, self).__init__() - - name = ("list-available", "la") - - def options(self): - self.parser.add_option("-l", "--long", action="store_true", - default=False, help="show in long format") - - def run(self): - - self.init(True) - - if self.args: - for arg in self.args: - self.print_packages(arg) - else: - # print for all repos - for repo in ctx.repodb.list(): - ctx.ui.info(_("Repository : %s\n") % repo) - self.print_packages(repo) - self.finalize() - - def print_packages(self, repo): - from pisi import packagedb - from colors import colorize - - pkg_db = packagedb.get_db(repo) - list = pkg_db.list_packages() - installed_list = ctx.installdb.list_installed() - list.sort() - for p in list: - package = pkg_db.get_package(p) - if self.options.long: - ctx.ui.info(unicode(package)) - else: - lenp = len(p) - if p in installed_list: - p = colorize(p, 'cyan') - p = p + ' ' * max(0, 15 - lenp) - ctx.ui.info('%s - %s ' % (p, unicode(package.summary))) - -class ListComponents(Command): - """List available components - -Usage: list-components - -Gives a brief list of PiSi components published in the repositories. -""" - __metaclass__ = autocommand - - def __init__(self): - super(ListComponents, self).__init__() - - name = ("list-components", "lc") - - def options(self): - self.parser.add_option("-l", "--long", action="store_true", - default=False, help="show in long format") - - def run(self): - - self.init(True) - - list = ctx.componentdb.list_components() - list.sort() - for p in list: - component = ctx.componentdb.get_component(p) - if self.options.long: - ctx.ui.info(unicode(component)) - else: - lenp = len(p) - #if p in installed_list: - # p = colorize(p, 'cyan') - p = p + ' ' * max(0, 15 - lenp) - ctx.ui.info('%s - %s ' % (component.name, unicode(component.summary))) - self.finalize() - - -class ListUpgrades(Command): - """List packages to be upgraded - -Usage: list-upgrades [ ... repon ] - -""" - __metaclass__ = autocommand - - def __init__(self): - super(ListUpgrades, self).__init__() - - name = ("list-upgrades", "lu") - - def options(self): - self.parser.add_option("-l", "--long", action="store_true", - default=False, help="show in long format") - self.parser.add_option("-i", "--install-info", action="store_true", - default=False, help=_("show detailed install info")) - buildno_opts(self) - - def run(self): - self.init(True) - list = pisi.api.list_upgradable() - list.sort() - if self.options.install_info: - ctx.ui.info(_('Package Name |St| Version| Rel.| Build| Distro| Date')) - print '========================================================================' - for pkg in list: - package = pisi.packagedb.inst_packagedb.get_package(pkg) - inst_info = ctx.installdb.get_info(pkg) - if self.options.long: - ctx.ui.info(package) - print inst_info - elif self.options.install_info: - ctx.ui.info('%-15s | %s ' % (package.name, inst_info.one_liner())) - else: - ctx.ui.info('%15s - %s ' % (package.name, package.summary)) - self.finalize() - - -class ListPending(Command): - """List pending packages""" - - __metaclass__ = autocommand - - def __init__(self): - super(ListPending, self).__init__() - - name = ("list-pending", "lp") - - def run(self): - self.init(True) - - list = ctx.installdb.list_pending() - for p in list.keys(): - print p - - self.finalize() - - -class Search(Command): - """Search packages - -Usage: search - -#FIXME: fill this later -""" - pass - -class SearchFile(Command): - """Search for a file - -Usage: search-file ... - -Finds the installed package which contains the specified file. -""" - __metaclass__ = autocommand - - def __init__(self): - super(SearchFile, self).__init__() - - name = ("search-file", "sf") - - def options(self): - self.parser.add_option("-l", "--long", action="store_true", - default=False, help="show in long format") - self.parser.add_option("-f", "--fuzzy", action="store_true", - default=False, help=_("fuzzy search")) - - # and what does exact mean? -- exa - @staticmethod #fuck python 2.3 compatibility I don't care about it - def search_exact(path): - files = [] - path = path.lstrip('/') #FIXME: this shouldn't be necessary :/ - - if not ctx.config.options.fuzzy: - if ctx.filesdb.has_file(path): - files.append(ctx.filesdb.get_file(path)) - else: - #FIXME: this linear search thing is not working well -- exa - files = ctx.filesdb.get_files(path) - - if files: - for (pkg_name, file_info) in files: - #FIXME: files of the same package can be grouped under package name - ctx.ui.info(_("Package %s has file %s") % (pkg_name, file_info.path)) - if ctx.config.options.long: - ctx.ui.info(_('Type: %s, Hash: %s') % (file_info.type, - file_info.hash)) - else: - ctx.ui.error(_("Path '%s' does not belong to an installed package") % path) - - def run(self): - - self.init(True) - - if not self.args: - self.help() - return - - # search among existing files - for path in self.args: - ctx.ui.info(_('Searching for %s') % path) - import os.path - if os.path.exists(path): - path = os.path.realpath(path) - self.search_exact(path) - - self.finalize() - - -# Partial build commands - - -class BuildUntil(Build): - """Run the build process partially - -Usage: -sStateName build-until - -where states are: -unpack, setupaction, buildaction, installaction, buildpackages - -You can give an URI of the pspec.xml file. PISI will fetch all -necessary files and unpack the source and prepare a source directory -for you. -""" - __metaclass__ = autocommand - - def __init__(self): - super(BuildUntil, self).__init__() - - name = ("build-until", "bu") - - def options(self): - super(BuildUntil, self).options() - self.parser.add_option("-s", action="store", dest="state") - - def run(self): - - if not self.args: - self.help() - return - - self.init() - state = self.options.state - - for arg in self.args: - pisi.api.build_until(arg, state, self.authInfo) - self.finalize() - - -class BuildUnpack(Build): - """Unpack the source archive - -Usage: build-unpack - -TODO: desc. -""" - __metaclass__ = autocommand - - def __init__(self): - super(BuildUnpack, self).__init__() - - name = ("build-unpack", "biu") - - def run(self): - if not self.args: - self.help() - return - - self.init() - for arg in self.args: - pisi.api.build_until(arg, "unpack", self.authInfo) - self.finalize() - - -class BuildSetup(Build): - """Setup the source - -Usage: build-setup - -TODO: desc. -""" - __metaclass__ = autocommand - - def __init__(self): - super(BuildSetup, self).__init__() - - name = ("build-setup", "bis") - - def run(self): - if not self.args: - self.help() - return - - self.init() - for arg in self.args: - pisi.api.build_until(arg, "setupaction", - self.authInfo) - self.finalize() - - -class BuildBuild(Build): - """Setup the source - -Usage: build-build - -TODO: desc. -""" - __metaclass__ = autocommand - - def __init__(self): - super(BuildBuild, self).__init__() - - name = ("build-build", "bib") - - def run(self): - if not self.args: - self.help() - return - - self.init() - for arg in self.args: - pisi.api.build_until(arg, "buildaction", self.authInfo) - self.finalize() - - -class BuildInstall(Build): - """Install to the sandbox - -Usage: build-install - -TODO: desc. -""" - __metaclass__ = autocommand - - def __init__(self): - super(BuildInstall, self).__init__() - - name = ("build-install", "bii") - - def run(self): - if not self.args: - self.help() - return - - self.init() - for arg in self.args: - pisi.api.build_until(arg, "installaction", - self.authInfo) - self.finalize() - - -class BuildPackage(Build): - """Setup the source - -Usage: build-build - -TODO: desc. -""" - - __metaclass__ = autocommand - - def __init__(self): - super(BuildPackage, self).__init__() - - name = ("build-package", "bip") - - def run(self): - if not self.args: - self.help() - return - - self.init() - for arg in self.args: - pisi.api.build_until(arg, "buildpackages", self.authInfo) - self.finalize() - -usage_text1 = _("""%prog [options] [arguments] - -where is one of: - -""") - -usage_text2 = _(""" -Use \"%prog help \" for help on a specific command. -""") - -usage_text = (usage_text1 + Command.commands_string() + usage_text2) diff --git a/tags/pisi-1.0_beta2/pisi/cli/pisicli.py b/tags/pisi-1.0_beta2/pisi/cli/pisicli.py deleted file mode 100644 index 6a097d3a..00000000 --- a/tags/pisi-1.0_beta2/pisi/cli/pisicli.py +++ /dev/null @@ -1,110 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import sys -from optparse import OptionParser - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.cli -from pisi.cli import printu -from pisi.uri import URI -from pisi.cli.commands import * - -class ParserError(pisi.Exception): - pass - -class Error(pisi.Error): - pass - -class PreParser(OptionParser): - """consumes any options, and finds arguments from command line""" - - def __init__(self, version): - OptionParser.__init__(self, usage=usage_text, version=version) - - def error(self, msg): - raise ParserError, msg - - def parse_args(self, args=None): - self.opts = [] - self.rargs = self._get_args(args) - self._process_args() - return (self.opts, self.args) - - def _process_args(self): - args = [] - rargs = self.rargs - if not self.allow_interspersed_args: - first_arg = False - while rargs: - arg = rargs[0] - def option(): - if not self.allow_interspersed_args and first_arg: - self.error_(('Options must precede non-option arguments')) - self.opts.append(rargs[0][2:]) - del rargs[0] - return - # We handle bare "--" explicitly, and bare "-" is handled by the - # standard arg handler since the short arg case ensures that the - # len of the opt string is greater than 1. - if arg == "--": - del rargs[0] - break - elif arg[0:2] == "--": - # process a single long option (possibly with value(s)) - option() - elif arg[:1] == "-" and len(arg) > 1: - # process a cluster of short options (possibly with - # value(s) for the last one only) - option() - else: # then it must be an argument - args.append(arg) - del rargs[0] - self.args = args - - -class PisiCLI(object): - - def __init__(self): - # first construct a parser for common options - # this is really dummy - self.parser = PreParser(version="%prog " + pisi.__version__) - - try: - opts, args = self.parser.parse_args() - if len(args)==0: # more explicit than using IndexError - if 'version' in opts: - self.parser.print_version() - sys.exit(0) - raise Error(_('No command given')) - #self.die() - cmd_name = args[0] - except ParserError: - raise Error(_('Command line parsing error')) - #self.die() - - self.command = Command.get_command(cmd_name) - if not self.command: - raise Error(_("Unrecognized command: %s") % cmd_name) - #self.die() - - def die(self): - #raise Error('') - printu('\n' + self.parser.format_help()) - sys.exit(1) - - def run_command(self): - self.command.run() diff --git a/tags/pisi-1.0_beta2/pisi/comariface.py b/tags/pisi-1.0_beta2/pisi/comariface.py deleted file mode 100644 index d2845c6d..00000000 --- a/tags/pisi-1.0_beta2/pisi/comariface.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Baris Metin -# Gurer Ozen - -import comar - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context as ctx - -class Error(pisi.Error): - pass - -def make_com(): - try: - import comar - comard = comar.Link() - return comard - except ImportError: - raise Error(_("COMAR: comard not fully installed")) - except comar.Error: - raise Error(_("COMAR: comard not running or defunct")) - -def register(pcomar, name, path): - ctx.ui.info(_("Registering COMAR script %s") % pcomar.script) - com = make_com() - assert(com) - com.register(pcomar.om, name, path) - - while 1: - reply = com.read_cmd() - if reply[0] == com.RESULT: - break - else: - raise Error, _("COMAR.register ERROR!") - -def run_postinstall(package_name): - "run postinstall scripts trough COMAR" - - com = make_com() - assert(com) - ctx.ui.info(_("Running post-install script for %s") % package_name) - com.call_package("System.Package.postInstall", package_name) - while 1: - reply = com.read_cmd() - if reply[0] == com.RESULT: - break - elif reply[0] == com.NONE: # package has no postInstall script - break - elif reply[0] == com.FAIL: - e = _("COMAR.call_package(System.Package.postInstall, %s) failed!: %s") % ( - package_name, reply[2]) - raise Error, e - else: - raise Error, _("COMAR.call_package ERROR: %d") % reply[0] - -def run_preremove(package_name): - - com = make_com() - assert(com) - - # First, call preRemove script! - ctx.ui.info(_("Running pre-remove script for %s") % package_name) - com.call_package("System.Package.preRemove", package_name) - while 1: - reply = com.read_cmd() - if reply[0] == com.RESULT: - break - elif reply[0] == com.NONE: # package has no preRemove script - break - elif reply[0] == com.FAIL: - e = _("COMAR.call_package(System.Package.preRemove, %s) failed!: %s") % ( - package_name, reply[2]) - raise Error, e - else: - raise Error, _("COMAR.call_package ERROR: %d") % reply[0] - - # and then, remove package's Comar Scripts... - ctx.ui.info(_("Unregistering COMAR scripts for %s") % package_name) - com.remove(package_name) - while 1: - reply = com.read_cmd() - if reply[0] == com.RESULT: - break - elif reply[1] == com.ERROR: - raise Error, "COMAR.remove failed!" diff --git a/tags/pisi-1.0_beta2/pisi/component.py b/tags/pisi-1.0_beta2/pisi/component.py deleted file mode 100644 index 63b10808..00000000 --- a/tags/pisi-1.0_beta2/pisi/component.py +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Author: Eray Ozkural - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.pxml.xmlfile as xmlfile -import pisi.pxml.autoxml as autoxml -import pisi.lockeddbshelve as shelve - -class Error(pisi.Error): - pass - -__metaclass__ = autoxml.autoxml - - -class Distribution: - t_Name = [autoxml.Text, autoxml.mandatory] - t_Description = [autoxml.LocalText, autoxml.mandatory] - t_Version = [autoxml.Text, autoxml.mandatory] - t_Type = [autoxml.Text, autoxml.mandatory] - t_Dependencies = [ [autoxml.Text], autoxml.optional, "Dependencies/Distribution"] - - -class Component(xmlfile.XmlFile): - "representation for component declarations" - - __metaclass__ = autoxml.autoxml - - tag = "PISI" - - t_Name = [autoxml.String, autoxml.mandatory] # fully qualified name - - # component name in other languages, for instance in Turkish - # LocalName for system.base could be sistem.taban or "Taban Sistem", - # this could be useful for GUIs - t_LocalName = [autoxml.LocalText, autoxml.mandatory] - - # Information about the component - t_Summary = [autoxml.LocalText, autoxml.mandatory] - t_Description = [autoxml.LocalText, autoxml.mandatory] - #t_Icon = [autoxml.Binary, autoxml.mandatory] - - # Dependencies to other components - t_Dependencies = [ [autoxml.String], autoxml.optional, "Dependencies/Component"] - - # the parts of this component. - # to be filled by the component database, thus it is optional. - t_Packages = [ [autoxml.String], autoxml.optional, "Parts/Package"] - - # TODO: this is probably not necessary since we use fully qualified - # module names (like in Java) - #t_PartOf = [autoxml.Text, autoxml.mandatory] - -#FIXME: recursive declarations do not work! -#class ComponentTree(xmlfile.XmlFile): -# "index representation for the component structure" -# -# __metaclass__ = autoxml.autoxml -# -# tag = "Component" -# -# t_Name = [autoxml.Text, autoxml.mandatory] # fully qualified name -# #t_Icon = [autoxml.Binary, autoxml.mandatory] -# t_Dependencies = [ [autoxml.Text], autoxml.optional, "Component"] -# #t_Parts = [ [pisi.component.ComponentTree], autoxml.optional, "Component"] - -class ComponentDB(object): - """a database of components""" - - #FIXME: we might need a database per repo in the future - def __init__(self): - self.d = shelve.LockedDBShelf('components') - - def close(self): - self.d.close() - - def has_component(self, name): - return self.d.has_key(str(name)) - - def get_component(self, name): - if not self.has_component(name): - self.d[name] = Component(name = name) - return self.d[name] - - def list_components(self): - list = [] - for (pkg, x) in self.d.iteritems(): - list.append(pkg) - return list - - def update_component(self, component): - if self.d.has_key(component.name): - # preserve the list of packages - component.packages = self.d[component.name].packages - self.d[component.name] = component - - def add_package(self, component_name, package): - component = self.get_component(component_name) - component.packages.append(package) - self.d[component_name] = component # update - - def remove_package(self, component_name, package): - if not self.has_component(component_name): - raise Error(_('Information for component %s not available') % component_name) - component = self.get_component(component_name) - component.packages.remove(package) - self.d[component_name] = component # update - - def clear(self): - self.d.clear() - - def remove_component(self, name): - name = str(name) - del self.d[name] diff --git a/tags/pisi-1.0_beta2/pisi/config.py b/tags/pisi-1.0_beta2/pisi/config.py deleted file mode 100644 index 1f49127e..00000000 --- a/tags/pisi-1.0_beta2/pisi/config.py +++ /dev/null @@ -1,100 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Baris Metin -# Eray Ozkural - -""" -PISI Configuration module is used for gathering and providing -regular PISI configurations. -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context as ctx -from pisi.configfile import ConfigurationFile -import pisi.util -from pisi.util import join_path as join - -class Error(pisi.Error): - pass - -class Options(object): - def __getattr__(self, name): - if not self.__dict__.has_key(name): - return None - else: - return self.__dict__[name] - -class Config(object): - """Config Singleton""" - - def __init__(self, options = Options()): - self.options = options - self.values = ConfigurationFile("/etc/pisi/pisi.conf") - - def get_option(self, opt): - if self.options: - if hasattr(self.options, opt): - return getattr(self.options, opt) - return None - - # directory accessor functions - # here is how it goes - # x_dir: system wide directory for storing info type x - # pkg_x_dir: per package directory for storing info type x - - def dest_dir(self): - dir = self.get_option('destdir') - if dir: - dir = str(dir) - else: - dir = self.values.general.destinationdirectory - import os.path - if not os.path.exists(dir): - ctx.ui.warning( _('Destination directory %s does not exist. Creating it.') % dir) - os.makedirs(dir) - return dir - - def subdir(self, path): - dir = join(self.dest_dir(), path) - pisi.util.check_dir(dir) - return dir - - def lib_dir(self): - return self.subdir(self.values.dirs.lib_dir) - - def db_dir(self): - return self.subdir(self.values.dirs.db_dir) - - def archives_dir(self): - return self.subdir(self.values.dirs.archives_dir) - - def packages_dir(self): - return self.subdir(self.values.dirs.packages_dir) - - def index_dir(self): - return self.subdir(self.values.dirs.index_dir) - - def tmp_dir(self): - return self.subdir(self.values.dirs.tmp_dir) - - # bu dizini neden kullanıyoruz? Yalnızca index.py içerisinde - # kullanılıyor ama /var/tmp/pisi/install gibi bir dizine niye - # ihtiyacımız var? (baris) - def install_dir(self): - return self.tmp_dir() + ctx.const.install_dir_suffix - -#TODO: remove this -config = Config() diff --git a/tags/pisi-1.0_beta2/pisi/configfile.py b/tags/pisi-1.0_beta2/pisi/configfile.py deleted file mode 100644 index fd145c61..00000000 --- a/tags/pisi-1.0_beta2/pisi/configfile.py +++ /dev/null @@ -1,139 +0,0 @@ -# -*- conding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# PISI Configuration File module, obviously, is used to read from the -# configuration file. Module also defines default values for -# configuration parameters. -# -# Configuration file is located in /etc/pisi/pisi.conf by default, -# having an INI like format like below. -# -#[general] -#destinationdirectory = /tmp -#autoclean = False -# -#[build] -#host = i686-pc-linux-gnu -#CFLAGS= -mtune=i686 -O2 -pipe -fomit-frame-pointer -#CXXFLAGS= -mtune=i686 -O2 -pipe -fomit-frame-pointer -#LDFLAGS= -# -#[directories] -#lib_dir = /var/lib/pisi -#db_dir = /var/db/pisi -#archives_dir = /var/cache/pisi/archives -#packages_dir = /var/cache/pisi/packages -#index_dir = /var/cache/pisi/index -#tmp_dir = /var/tmp/pisi -#icon_theme_dir = /usr/share/icons/Tulliana-1.0 - -import os -from ConfigParser import ConfigParser, NoSectionError - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi - -class Error(pisi.Error): - pass - -class GeneralDefaults: - """Default values for [general] section""" - destinationdirectory = "/" - autoclean = False - distribution = "Pardus" - distribution_release = "0.1" - -class BuildDefaults: - """Default values for [build] section""" - host = "i686-pc-linux-gnu" - CFLAGS = "-mtune=i686 -O2 -pipe -fomit-frame-pointer" - CXXFLAGS = "-mtune=i686 -O2 -pipe -fomit-frame-pointer" - LDFLAGS = "" - -class DirsDefaults: - "Default values for [directories] section" - lib_dir = "/var/lib/pisi" - db_dir = "/var/db/pisi" - archives_dir = "/var/cache/pisi/archives" - packages_dir = "/var/cache/pisi/packages" - index_dir = "/var/cache/pisi/index" - tmp_dir = "/var/tmp/pisi" - icon_theme_dir = "/usr/share/icons/Tulliana-1.0" - - -class ConfigurationSection(object): - """ConfigurationSection class defines a section in the configuration - file, using defaults (above) as a fallback.""" - def __init__(self, section, items=[]): - self.items = items - - if section == "general": - self.defaults = GeneralDefaults - elif section == "build": - self.defaults = BuildDefaults - elif section == "directories": - self.defaults = DirsDefaults - else: - e = _("No section by name '%s'") % section - raise Error, e - - self.section = section - - def __getattr__(self, attr): - - # first search for attribute in the items provided in the - # configuration file. - if self.items: - for item in self.items: - if item[0] == attr: - return item[1] - - # then fall back to defaults - if hasattr(self.defaults, attr): - return getattr(self.defaults, attr) - - return "" - - # We'll need to access configuration keys by their names as a - # string. Like; ["default"]... - def __getitem__(self, key): - return self.__getattr__(key) - - -class ConfigurationFile(object): - """Parse and get configuration values from the configuration file""" - def __init__(self, filePath): - parser = ConfigParser() - self.filePath = filePath - - parser.read(self.filePath) - - try: - generalitems = parser.items("general") - except NoSectionError: - generalitems = [] - self.general = ConfigurationSection("general", generalitems) - - try: - builditems = parser.items("build") - except NoSectionError: - builditems = [] - self.build = ConfigurationSection("build", builditems) - - try: - dirsitems = parser.items("directories") - except NoSectionError: - dirsitems = [] - self.dirs = ConfigurationSection("directories", dirsitems) diff --git a/tags/pisi-1.0_beta2/pisi/constants.py b/tags/pisi-1.0_beta2/pisi/constants.py deleted file mode 100644 index dfb4d9d8..00000000 --- a/tags/pisi-1.0_beta2/pisi/constants.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# PISI constants. -# If you have a "magic" constant value this is where it should be -# defined. - -# Author: Baris Metin - -# global variables here - -import pisi.constants - -const = pisi.constants.Constants() - -config = None - -def get_option(opt): - return config and config.get_option(opt) - -# default UI is CLI -ui = None # not now - -installdb = None -repodb = None - -comar = None - -initialized = False - -#def register(_impl): -# """ Register a UI implementation""" -# ui = _impl diff --git a/tags/pisi-1.0_beta2/pisi/dependency.py b/tags/pisi-1.0_beta2/pisi/dependency.py deleted file mode 100644 index f95f214f..00000000 --- a/tags/pisi-1.0_beta2/pisi/dependency.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Author: Eray Ozkural - -"""dependency analyzer""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -#import pisi.db as db -import pisi.context as ctx -import pisi.packagedb as packagedb -from pisi.version import Version -import pisi.pxml.autoxml as autoxml -from pisi.util import Checks - -class Dependency: - - __metaclass__ = autoxml.autoxml - - s_Package = [autoxml.String, autoxml.mandatory] - a_versionFrom = [autoxml.String, autoxml.optional] - a_versionTo = [autoxml.String, autoxml.optional] - a_releaseFrom = [autoxml.String, autoxml.optional] - a_releaseTo = [autoxml.String, autoxml.optional] - - def __str__(self): - s = self.package - if self.versionFrom: - s += 'ver >= ' + self.versionFrom - if self.versionTo: - s += 'ver <= ' + self.versionTo - if self.releaseFrom: - s += 'rel >= ' + self.releaseFrom - if self.releaseTo: - s += 'rel <= ' + self.releaseTo - return s - - def satisfies(self, pkg_name, version, release): - """determine if a package ver. satisfies given dependency spec""" - ret = True - v = Version(version) - if self.versionFrom: - ret &= v >= Version(self.versionFrom) - if self.versionTo: - ret &= v <= Version(self.versionTo) - if self.releaseFrom: - ret &= v <= Version(self.releaseFrom) - if self.releaseTo: - ret &= v <= Version(self.releaseTo) - return ret - -def dict_satisfies_dep(dict, depinfo): - """determine if a package in a dictionary satisfies given dependency spec""" - pkg_name = depinfo.package - if not dict.has_key(pkg_name): - return False - else: - pkg = dict[pkg_name] - (version, release) = (pkg.version, pkg.release) - return depinfo.satisfies(pkg_name, version, release) - -def installed_satisfies_dep(depinfo): - """determine if a package in *repository* satisfies given -dependency spec""" - pkg_name = depinfo.package - if not ctx.installdb.is_installed(pkg_name): - return False - else: - pkg = packagedb.inst_packagedb.get_package(pkg_name) - (version, release) = (pkg.version, pkg.release) - return depinfo.satisfies(pkg_name, version, release) - -def repo_satisfies_dep(depinfo): - """determine if a package in *repository* satisfies given -dependency spec""" - pkg_name = depinfo.package - if not packagedb.has_package(pkg_name): - return False - else: - pkg = packagedb.get_package(pkg_name) - (version, release) = (pkg.version, pkg.release) - return depinfo.satisfies(pkg_name, version, release) - -def satisfies_dependencies(pkg, deps, sat = installed_satisfies_dep): - for dep in deps: - if not sat(dep): - ctx.ui.error(_('Package %s does not satisfy dependency %s') % - (pkg,dep)) - return False - return True - -def satisfies_runtime_deps(pkg): - deps = packagedb.get_package(pkg).runtimeDependencies() - return satisfies_dependencies(pkg, deps) - -def installable(pkg): - """calculate if pkg name is installable currently - which means it has to satisfy both install and runtime dependencies""" - if not packagedb.has_package(pkg): - ctx.ui.info(_("Package %s is not present in the package database") % pkg); - return False - elif satisfies_runtime_deps(pkg): - return True - else: - return False diff --git a/tags/pisi-1.0_beta2/pisi/fetcher.py b/tags/pisi-1.0_beta2/pisi/fetcher.py deleted file mode 100644 index 062a6641..00000000 --- a/tags/pisi-1.0_beta2/pisi/fetcher.py +++ /dev/null @@ -1,304 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -"""Yet another Pisi module for fetching files from various sources. Of -course, this is not limited to just fetching source files. We fetch -all kinds of things: source tarballs, index files, packages, and God -knows what.""" - -# python standard library modules -import urllib2 -import urllib -import ftplib -import os -import socket -import sys -from mimetypes import guess_type -from mimetools import Message -from base64 import encodestring -from shutil import move -from time import time - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# pisi modules -import pisi -import pisi.util as util -import pisi.context as ctx -from pisi.uri import URI - -class FetchError(pisi.Error): - pass - - -# helper functions -def fetch_url(url, dest, progress=None): - fetch = Fetcher(url, dest) - fetch.progress = progress - fetch.fetch() - if progress: - pass - #ctx.ui.info('\n') - - -class Fetcher: - """Fetcher can fetch a file from various sources using various - protocols.""" - def __init__(self, url, dest): - if not isinstance(url, URI): - url = URI(url) - - self.scheme = url.scheme() - self.url = url - self.filedest = dest - util.check_dir(self.filedest) - self.percent = 0 - self.rate = 0.0 - self.progress = None - self.existsize = 0 - - def fetch (self): - """Return value: Fetched file's full path..""" - - if not self.url.filename(): - self.err(_("Filename error")) - - if not os.access(self.filedest, os.W_OK): - self.err(_("Access denied to write to dest dir")) - - archivefile = os.path.join(self.filedest, self.url.filename()) - - if self.url.is_local_file(): - self.fetchLocalFile(archivefile + ".part") - else: - self.fetchRemoteFile(archivefile + ".part") - - move(archivefile + ".part", archivefile) - return archivefile - - def _do_grab(self, fileURI, dest, totalsize): - symbols = [' B/s', 'KB/s', 'MB/s', 'GB/s'] - bs, tt, = 1024, int(time()) - size = existsize = self.existsize - symbol, depth = "B/s", 0 - st = time() - chunk = fileURI.read(bs) - size += len(chunk) - if self.progress: - p = self.progress(totalsize, existsize) - self.percent = p.update(size) - self.complete = False - while chunk: - dest.write(chunk) - chunk = fileURI.read(bs) - size += len(chunk) - ct = time() - if int(tt) != int(ct): - self.rate = (size - existsize) / (ct - st) - while self.rate > 1000 and depth < 3: - self.rate /= 1024 - depth += 1 - symbol, depth = symbols[depth], 0 - tt = time() - if self.progress: - if p.update(size): - self.percent = p.percent - if not self.complete: - ctx.ui.display_progress(filename = self.url.filename(), - percent = self.percent, - rate = self.rate, - symbol = symbol) - if self.percent == 100: #FIXME: will be superseded by a - self.complete = True # working progress interface - - dest.close() - - def fetchLocalFile (self, archivefile): - url = self.url - - if not os.access(url.path(), os.F_OK): - self.err(_("No such file or no permission to read")) - - dest = open(archivefile, "w") - totalsize = os.path.getsize(url.path()) - fileObj = open(url.path()) - self._do_grab(fileObj, dest, totalsize) - - def fetchRemoteFile (self, archivefile): - from httplib import HTTPException - - if os.path.exists(archivefile): - if self.scheme == "http" or self.scheme == "https" or self.scheme == "ftp": - self.existsize = os.path.getsize(archivefile) - dest = open(archivefile, "ab") - else: - dest = open(archivefile, "wb") - - uri = self.url.uri - - try: - fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri))) - headers = fileObj.info() - except ValueError, e: - self.err(_('Cannot fetch %s; value error: %s') % (uri, e)) - except IOError, e: - self.err(_('Cannot fetch %s; %s') % (uri, e)) - except OSError, e: - self.err(_('Cannot fetch %s; %s') % (uri, e)) - except HTTPException, e: - self.err(_('Cannot fetch %s; (%s): %s') % (uri, e.__class__.__name__, e)) - - try: - totalsize = int(headers['Content-Length']) + self.existsize - except: - totalsize = 0 - - self._do_grab(fileObj, dest, totalsize) - - def formatRequest(self, request): - if self.url.auth_info(): - enc = encodestring("%s:%s" % self.url.auth_info()) - request.add_header('Authorization', 'Basic %s' % enc) - - range_handlers = { - 'http' : HTTPRangeHandler, - 'https': HTTPRangeHandler, - 'ftp' : FTPRangeHandler - } - - if self.existsize and range_handlers.has_key(self.scheme): - opener = urllib2.build_opener(range_handlers.get(self.scheme)()) - urllib2.install_opener(opener) - request.add_header('Range', 'bytes=%d-' % self.existsize) - - return request - - def err (self, error): - raise FetchError(error) - -class HTTPRangeHandler(urllib2.BaseHandler): - """ - "to override the urllib2 error: 'Error 206: Partial Content' - this reponse from the HTTP server is already what we expected to get. - Don't give up, resume downloading.. - """ - - def http_error_206(self, request, fp, errcode, msg, headers): - return urllib.addinfourl(fp, headers, request.get_full_url()) - - def http_error_416(self, request, fp, errcode, msg, headers): - # HTTP 1.1's 'Range Not Satisfiable' error.. - raise FetchError(_('Requested range not satisfiable')) - - -class FTPRangeHandler(urllib2.FTPHandler): - """ - FTP Range support.. - """ - def ftp_open(self, req): - host = req.get_host() - host, port = urllib.splitport(host) - if port is None: - port = ftplib.FTP_PORT - - try: - host = socket.gethostbyname(host) - except socket.error, msg: - raise FetchError(msg) - path, attrs = urllib.splitattr(req.get_selector()) - dirs = path.split('/') - dirs = map(urllib.unquote, dirs) - dirs, file = dirs[:-1], dirs[-1] - if dirs and not dirs[0]: - dirs = dirs[1:] - try: - fw = self.connect_ftp('', '', host, port, dirs) - type = file and 'I' or 'D' - for attr in attrs: - attr, value = urllib.splitattr(attr) - if attr.lower() == 'type' and \ - value in ('a', 'A', 'i', 'I', 'd', 'D'): - type = value.upper() - - rawr = req.headers.get('Range', None) - rest = int(rawr.split("=")[1].rstrip("-")) - - fp, retrlen = fw.retrfile(file, type, rest) - - fb, lb = rest, retrlen - if retrlen is None or retrlen == 0: - raise FetchError(_('Requested Range Not Satisfiable')) - retrlen = lb - fb - if retrlen < 0: - # beginning of range is larger than file - raise FetchError(_('Requested Range Not Satisfiable')) - - headers = "" - mtype = guess_type(req.get_full_url())[0] - if mtype: - headers += "Content-Type: %s\n" % mtype - if retrlen is not None and retrlen >= 0: - headers += "Content-Length: %d\n" % retrlen - - try: - from cStringIO import StringIO - except ImportError, msg: - from StringIO import StringIO - - return urllib.addinfourl(fp, Message(StringIO(headers)), req.get_full_url()) - except ftplib.all_errors, msg: - raise IOError, (_('ftp error'), msg), sys.exc_info()[2] - - def connect_ftp(self, user, passwd, host, port, dirs): - fw = ftpwrapper('', '', host, port, dirs) - return fw - -class ftpwrapper(urllib.ftpwrapper): - def retrfile(self, file, type, rest=None): - self.endtransfer() - if type in ('d', 'D'): cmd = 'TYPE A'; isdir = 1 - else: cmd = 'TYPE ' + type; isdir = 0 - try: - self.ftp.voidcmd(cmd) - except ftplib.all_errors: - self.init() - self.ftp.voidcmd(cmd) - conn = None - if file and not isdir: - try: - self.ftp.nlst(file) - except ftplib.error_perm, reason: - raise IOError, (_('ftp error'), reason), sys.exc_info()[2] - # Restore the transfer mode! - self.ftp.voidcmd(cmd) - try: - cmd = 'RETR ' + file - conn = self.ftp.ntransfercmd(cmd, rest) - except ftplib.error_perm, reason: - if str(reason)[:3] == '501': - # workaround for REST not suported error - fp, retrlen = self.retrfile(file, type) - fp = RangeableFileObject(fp, (rest,'')) - return (fp, retrlen) - elif str(reason)[:3] != '550': - raise IOError, (_('ftp error'), reason), sys.exc_info()[2] - if not conn: - self.ftp.voidcmd('TYPE A') - if file: cmd = 'LIST ' + file - else: cmd = 'LIST' - conn = self.ftp.ntransfercmd(cmd) - self.busy = 1 - return (urllib.addclosehook(conn[0].makefile('rb'), - self.endtransfer), conn[1]) - diff --git a/tags/pisi-1.0_beta2/pisi/files.py b/tags/pisi-1.0_beta2/pisi/files.py deleted file mode 100644 index d4cc3104..00000000 --- a/tags/pisi-1.0_beta2/pisi/files.py +++ /dev/null @@ -1,80 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# Files module provides access to files.xml. files.xml is genarated -# during the build process of a package and used in installation. - -# Authors: Eray Ozkural - -import pisi.pxml.autoxml as autoxml -from pisi.util import Checks -import pisi.lockeddbshelve as shelve - -class File: - """File holds the information for a File node/tag in files.xml""" - - __metaclass__ = autoxml.autoxml - - t_Path = [ autoxml.String, autoxml.mandatory ] - t_Type = [ autoxml.String, autoxml.mandatory ] - t_Size = [ autoxml.Long, autoxml.optional ] - t_Hash = [ autoxml.String, autoxml.optional, "SHA1Sum" ] - - def __str__(self): - s = "%s, type: %s, size: %s, sha1sum: %s" % (self.path, self.type, - self.size, self.hash) - return s - -class Files(autoxml.XmlFile): - - __metaclass__ = autoxml.autoxml - - tag = "Files" - - t_List = [ [File], autoxml.optional, "File"] - - def append(self, fileinfo): - self.list.append(fileinfo) - -class FilesDB(shelve.LockedDBShelf): - - def __init__(self): - shelve.LockedDBShelf.__init__(self, 'files') - - def add_files(self, pkg_name, files): - for x in files.list: - self[str(x.path)] = (pkg_name, x) - - def remove_files(self, files): - for x in files.list: - self.delete(str(x.path)) - - def has_file(self, path): - return self.has_key(str(path)) - - def get_file(self, path): - path = str(path) - if not self.has_key(path): - return None - else: - return self[path] - - def get_files(self, glob): - import fnmatch - - glob = str(glob) - infos = [] - for key in self.keys(): - if fnmatch.fnmatch(key, glob): - infos.append(self[key]) - - return infos diff --git a/tags/pisi-1.0_beta2/pisi/graph.py b/tags/pisi-1.0_beta2/pisi/graph.py deleted file mode 100644 index b0fb817f..00000000 --- a/tags/pisi-1.0_beta2/pisi/graph.py +++ /dev/null @@ -1,161 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -# the most simple minded digraph class ever - - -# for python 2.3 compatibility -import sys -ver = sys.version_info -if ver[0] <= 2 and ver[1] < 4: - from sets import Set as set - -import pisi - -# not an error! - -class CycleException(pisi.Exception): - pass - -class Digraph(object): - - def __init__(self): - self.__v = set() - self.__adj = {} - self.__vdata = {} - self.__edata = {} - - def vertices(self): - "return set of vertex descriptors" - return self.__v - - def edges(self): - "return a list of edge descriptors" - list = [] - for u in self.__v: - for v in self.__u: - list.append( (u,v) ) - return list - - def from_list(self, el): - "convert a list of edges (u,v) to graph" - for (u,v) in el: - self.add_edge(u,v) - - def add_vertex(self, u, data = None): - "add vertex u, optionally with data" - assert not u in self.__v - self.__v.add(u) - self.__adj[u] = set() - if data: - self.__vdata[u] = data - self.__edata[u] = {} - - def add_edge(self, u, v, edata = None, udata = None, vdata = None): - "add edge u -> v" - if not u in self.__v: - self.add_vertex(u, udata) - if not v in self.__v: - self.add_vertex(v, vdata) - self.__adj[u].add(v) - if edata != None: - self.__edata[u][v] = edata - - def add_biedge(self, u, v, edata = None): - self.add_edge(u, v, edata) - self.add_edge(v, u, edata) - - def set_vertex_data(self, u, data): - self.__vdata[u] = data - - def vertex_data(self, u): - return self.__vdata[u] - - def edge_data(self, u, v): - return self.__edata[u][v] - - def has_vertex(self, u): - return u in self.__v - - def has_edge(self, u,v): - if u in self.__v: - return v in self.__adj[u] - else: - return False - - def adj(self, u): - return self.__adj[u] - - def dfs(self, finish_hook = None): - self.color = {} - self.p = {} - self.d = {} - self.f = {} - for u in self.__v: - self.color[u] = 'w' # mark white (unexplored) - self.p[u] = None - self.time = 0 - for u in self.__v: - if self.color[u] == 'w': - self.dfs_visit(u, finish_hook) - - def dfs_visit(self, u, finish_hook): - self.color[u] = 'g' # mark green (discovered) - self.d[u] = self.time = self.time + 1 - for v in self.adj(u): - if self.color[v] == 'w': # explore unexplored vertices - self.p[v] = u - self.dfs_visit(v, finish_hook) - elif self.color[v] == 'g': # cycle detected - raise CycleException - self.color[u] = 'b' # mark black (completed) - if finish_hook: - finish_hook(u) - self.f[u] = self.time = self.time + 1 - - def cycle_free(self): - try: - self.dfs() - return True - except CycleException: - return False - - def topological_sort(self): - list = [] - self.dfs(lambda u: list.append(u)) - list.reverse() - return list - - def id_str(self, u): - s = str(u) - return s.replace('-', '_') - - def write_graphviz(self, f): - f.write('digraph G {\n') - for u in self.vertices(): - f.write(self.id_str(u)) - self.write_graphviz_vlabel(f, u) - f.write(';\n') - f.write('\n') - for u in self.vertices(): - for v in self.adj(u): - f.write( self.id_str(u) + ' -> ' + self.id_str(v)) - self.write_graphviz_elabel(f, u, v) - f.write(';\n') - f.write('\n') - f.write('}\n') - - def write_graphviz_vlabel(self, f, u): - pass - - def write_graphviz_elabel(self, f, u, v): - pass - diff --git a/tags/pisi-1.0_beta2/pisi/index.py b/tags/pisi-1.0_beta2/pisi/index.py deleted file mode 100644 index c1101835..00000000 --- a/tags/pisi-1.0_beta2/pisi/index.py +++ /dev/null @@ -1,130 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Author: Eray Ozkural - - -"""PISI source/package index""" - - -import os - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context as ctx -import pisi.specfile as specfile -import pisi.metadata as metadata -import pisi.packagedb as packagedb -import pisi.util as util -from pisi.package import Package -from pisi.pxml.xmlfile import XmlFile -import pisi.pxml.autoxml as autoxml -from pisi.uri import URI -import pisi.component as component -import pisi.specfile as specfile - -class Error(pisi.Error): - pass - -class Index(XmlFile): - __metaclass__ = autoxml.autoxml - - tag = "PISI" - - t_Sources = [ [specfile.Source], autoxml.optional, "Source"] - t_Packages = [ [metadata.Package], autoxml.optional, "Package"] - t_Components = [ [component.Component], autoxml.optional, "Component"] - - def read_uri(self, filename, repo = None): - """Read PSPEC file""" - - self.filepath = filename - url = URI(filename) - if url.is_remote_file(): - from fetcher import fetch_url - assert repo - dest = os.path.join(ctx.config.index_dir(), repo) - if not os.path.exists(dest): - os.makedirs(dest) - fetch_url(url, dest, ctx.ui.Progress) - - self.filepath = os.path.join(dest, url.filename()) - - self.read(self.filepath) - - def index(self, repo_uri): - self.repo_dir = repo_uri - for root, dirs, files in os.walk(repo_uri): - for fn in files: - if fn.endswith(ctx.const.package_suffix): - ctx.ui.info(_('Adding %s to package index') % fn) - self.add_package(os.path.join(root, fn), repo_uri) - if fn == 'component.xml': - ctx.ui.info(_('Adding %s to component index') % fn) - self.add_component(os.path.join(root, fn)) - #if fn == 'pspec.xml': - # self.add_source(os.path.join(root, fn), repo_uri) - - def update_db(self, repo): - pkgdb = packagedb.get_db(repo) - pkgdb.clear() - for comp in self.components: - ctx.componentdb.update_component(comp) - for pkg in self.packages: - pkgdb.add_package(pkg) - - def add_package(self, path, repo_uri): - package = Package(path, 'r') - # extract control files - util.clean_dir(ctx.config.install_dir()) - package.extract_PISI_files(ctx.config.install_dir()) - - md = metadata.MetaData() - md.read(os.path.join(ctx.config.install_dir(), ctx.const.metadata_xml)) - if ctx.config.options and ctx.config.options.absolute_uris: - md.package.packageURI = os.path.realpath(path) - else: # create relative path by default - # TODO: in the future we'll do all of this with purl/pfile/&helpers - # After that, we'll remove the ugly repo_uri parameter from this - # function. - md.package.packageURI = util.removepathprefix(repo_uri, path) - # check package semantics - errs = md.errors() - if md.errors(): - ctx.ui.error(_('Package %s: metadata corrupt') % md.package.name) - ctx.ui.error(str(Error(*errs))) - else: - self.packages.append(md.package) - - def add_component(self, path): - comp = component.Component() - try: - comp.read(path) - self.components.append(comp) - except: - ctx.ui.error(_('Component in %s is corrupt') % path) - #ctx.ui.error(str(Error(*errs))) - - def add_source(self, path): - ctx.ui.info(_('Adding %s to source index') % fn) - sf = specfile.SpecFile() - sf.read(path) - errs = sf.errors() - if sf.errors(): - ctx.ui.error(_('SpecFile in %s is corrupt') % path) - ctx.ui.error(str(Error(*errs))) - else: - self.sources.append(sf.source) - - #TODO: add source diff --git a/tags/pisi-1.0_beta2/pisi/installdb.py b/tags/pisi-1.0_beta2/pisi/installdb.py deleted file mode 100644 index 36547df2..00000000 --- a/tags/pisi-1.0_beta2/pisi/installdb.py +++ /dev/null @@ -1,190 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# -# installation database -# -# Author: Eray Ozkural - -# System -import os -import fcntl - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# PiSi -import pisi -import pisi.context as ctx -import pisi.lockeddbshelve as shelve -from pisi.files import Files -import pisi.util as util -from pisi.util import join_path as join - - -class InstallDBError(pisi.Error): - pass - - -class InstallInfo: - # some data is replicated from packagedb.inst_packagedb - # we store as an object, hey, we can waste O(1) space. - # this is also easier to modify in the future, without - # requiring database upgrades! wow! - def __init__(self, state, version, release, build, distribution): - self.state = state - self.version = version - self.release = release - self.build = build - self.distribution = distribution - import time - self.time = time.localtime() - - def one_liner(self): - import time - time_str = time.strftime("%d %b %Y %H:%M", self.time) - s = '%2s|%10s|%6s|%6s|%8s|%12s' % (self.state, self.version, self.release, - self.build, self.distribution, - time_str) - return s - - state_map = { 'i': _('installed'), 'ip':_('installed-pending'), - 'r':_('removed'), 'p': _('purged') } - - def __str__(self): - s = _("State: %s\nVersion: %s, Release: %s, Build: %s\n") % \ - (InstallInfo.state_map[self.state], self.version, - self.release, self.build) - import time - time_str = time.strftime("%d %b %Y %H:%M", self.time) - s += _('Distribution: %s, Install Time: %s\n') % (self.distribution, - time_str) - return s - - -class InstallDB: - - def __init__(self): - self.d = shelve.LockedDBShelf('install') - self.dp = shelve.LockedDBShelf('configpending') - self.files_dir = join(ctx.config.db_dir(), 'files') - - def close(self): - self.d.close() - self.dp.close() - - def files_name(self, pkg, version, release): - pkg_dir = self.pkg_dir(pkg, version, release) - return join(pkg_dir, ctx.const.files_xml) - - def files(self, pkg): - pkg = str(pkg) - pkginfo = self.d[pkg] - files = Files() - files.read(self.files_name(pkg,pkginfo.version,pkginfo.release)) - return files - - def pkg_dir(self, pkg, version, release): - return join(ctx.config.lib_dir(), pkg + '-' + version + '-' + release) - - def is_recorded(self, pkg): - pkg = str(pkg) - return self.d.has_key(pkg) - - def is_installed(self, pkg): - pkg = str(pkg) - if self.is_recorded(pkg): - info = self.d[pkg] - return info.state=='i' or info.state=='ip' - else: - return False - - def list_installed(self): - list = [] - for (pkg, info) in self.d.iteritems(): - if info.state=='i' or info.state=='ip': - list.append(pkg) - return list - - def list_pending(self): - dict = {} - for (pkg, x) in self.dp.iteritems(): - pkginfo = self.d[pkg] - dict[pkg] = pkginfo - return dict - - def get_info(self, pkg): - pkg = str(pkg) - return self.d[pkg] - - def get_version(self, pkg): - pkg = str(pkg) - info = self.d[pkg] - return (info.version, info.release, info.build) - - def is_removed(self, pkg): - pkg = str(pkg) - if self.is_recorded(pkg): - info = self.d[pkg] - return info.state=='r' - else: - return False - - def install(self, pkg, version, release, build, distro = ""): - """install package with specific version, release, build""" - pkg = str(pkg) - if self.is_installed(pkg): - raise InstallDBError(_("Already installed")) - if ctx.config.get_option('ignore_comar'): - state = 'ip' - self.dp[pkg] = True - else: - state = 'i' - - self.d[pkg] = InstallInfo(state, version, release, build, distro) - - def clear_pending(self, pkg): - pkg = str(pkg) - info = self.d[pkg] - assert info.state == 'ip' - info.state = 'i' - self.d[pkg] = info - del self.dp[pkg] - - def remove(self, pkg): - pkg = str(pkg) - info = self.d[pkg] - info.state = 'r' - self.d[pkg] = info - - def purge(self, pkg): - pkg = str(pkg) - if self.d.has_key(pkg): - del self.d[pkg] - - -db = None - -def init(): - global db - if db: - return db - - db = InstallDB() - return db - -def finalize(): - global db - if db: - db.close() - db = None - diff --git a/tags/pisi-1.0_beta2/pisi/lockeddbshelve.py b/tags/pisi-1.0_beta2/pisi/lockeddbshelve.py deleted file mode 100644 index dafb7e56..00000000 --- a/tags/pisi-1.0_beta2/pisi/lockeddbshelve.py +++ /dev/null @@ -1,91 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# -# Authors: Eray Ozkural - -import bsddb.dbshelve as shelve -import bsddb.db as db -import os -import fcntl - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context - -class Error(pisi.Error): - pass - -class LockedDBShelf(shelve.DBShelf): - """A simple wrapper to implement locking for bsddb's dbshelf""" - - def __init__(self, dbname, mode=0644, - filetype=db.DB_HASH, dbenv=None): - shelve.DBShelf.__init__(self, dbenv) - filename = os.path.join( pisi.context.config.db_dir(), dbname + '.bdb') - if os.access(os.path.dirname(filename), os.W_OK): - flags = 'w' - elif os.access(filename, os.R_OK): - flags = 'r' - else: - raise Error(_('Cannot attain read or write access to database %s') % dbname) - self.open(filename, dbname, filetype, flags, mode) - - def __del__(self): - # superclass does something funky, we don't need that - pass - - def open(self, filename, dbname, filetype, flags=db.DB_CREATE, mode=0644): - self.filename = filename - self.closed = False - #print 'open', filename - if type(flags) == type(''): - sflag = flags - if sflag == 'r': - flags = db.DB_RDONLY - elif sflag == 'rw': - flags = 0 - elif sflag == 'w': - flags = db.DB_CREATE - elif sflag == 'c': - flags = db.DB_CREATE - elif sflag == 'n': - flags = db.DB_TRUNCATE | db.DB_CREATE - else: - raise Error, _("Flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags") - self.flags = flags - pisi.util.check_dir(pisi.context.config.db_dir()) - if self.flags != db.DB_RDONLY: - self.lock() - return self.db.open(filename, dbname, filetype, flags, mode) - - def lock(self): - self.lockfile = file(self.filename + '.lock', 'w') - try: - fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) - except IOError: - raise Error(_("Another instance of PISI is running. Try later!")) - - - def close(self): - if self.closed: - return - self.db.close() - if self.flags != db.DB_RDONLY: - self.unlock() - self.closed = True - - def unlock(self): - self.lockfile.close() - os.unlink(self.filename + '.lock') diff --git a/tags/pisi-1.0_beta2/pisi/metadata.py b/tags/pisi-1.0_beta2/pisi/metadata.py deleted file mode 100644 index 30935855..00000000 --- a/tags/pisi-1.0_beta2/pisi/metadata.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -"Package Operations: install/remove/upgrade" - -import os -import sys -ver = sys.version_info -if ver[0] <= 2 and ver[1] < 4: - from sets import Set as set - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context as ctx -from pisi.uri import URI -import pisi.util as util -import pisi.dependency as dependency -import pisi.pgraph as pgraph -import pisi.packagedb as packagedb -import pisi.repodb -import pisi.installdb -from pisi.index import Index -import pisi.cli -import pisi.atomicoperations as atomicoperations - -class Error(pisi.Error): - pass - -# high level operations -def install(packages): - """install a list of packages (either files/urls, or names)""" - - # FIXME: this function name "install" makes impossible to import - # and use install module directly. - from pisi.atomicoperations import Error as InstallError - - # determine if this is a list of files/urls or names - if packages[0].endswith('.pisi'): # they all have to! - return install_pkg_files(packages) - else: - return install_pkg_names(packages) - -def install_pkg_files(package_URIs): - """install a number of pisi package files""" - from package import Package - - ctx.ui.debug('A = %s' % str(package_URIs)) - - for x in package_URIs: - if not x.endswith(ctx.const.package_suffix): - raise Error(_('Mixing file names and package names not supported yet.')) - - if ctx.config.get_option('ignore_dependency'): - # simple code path then - for x in package_URIs: - atomicoperations.install_single_file(x) - return # short circuit - - # read the package information into memory first - # regardless of which distribution they come from - d_t = {} - dfn = {} - for x in package_URIs: - package = Package(x) - package.read() - name = str(package.metadata.package.name) - d_t[name] = package.metadata.package - dfn[name] = x - - def satisfiesDep(dep): - # is dependency satisfied among available packages - # or packages to be installed? - return dependency.installed_satisfies_dep(dep) \ - or dependency.dict_satisfies_dep(d_t, dep) - - # for this case, we have to determine the dependencies - # that aren't already satisfied and try to install them - # from the repository - dep_unsatis = [] - for name in d_t.keys(): - pkg = d_t[name] - deps = pkg.runtimeDependencies() - for dep in deps: - if not satisfiesDep(dep): - dep_unsatis.append(dep) - - # now determine if these unsatisfied dependencies could - # be satisfied by installing packages from the repo - - # if so, then invoke install_pkg_names - extra_packages = [x.package for x in dep_unsatis] - if extra_packages: - ctx.ui.info(_("""The following packages will be installed -in the respective order to satisfy extra dependencies: -""") + util.strlist(extra_packages)) - if not ctx.ui.confirm(_('Do you want to continue?')): - raise Error(_('External dependencies not satisfied')) - install_pkg_names(extra_packages) - - class PackageDB: - def get_package(self, key): - return d_t[str(key)] - - packagedb = PackageDB() - - A = d_t.keys() - - if len(A)==0: - ctx.ui.info(_('No packages to install.')) - return - - # try to construct a pisi graph of packages to - # install / reinstall - - G_f = pgraph.PGraph(packagedb) # construct G_f - - # find the "install closure" graph of G_f by package - # set A using packagedb - for x in A: - G_f.add_package(x) - B = A - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) - for dep in pkg.runtimeDependencies(): - if dependency.dict_satisfies_dep(d_t, dep): - if not dep.package in G_f.vertices(): - Bp.add(str(dep.package)) - G_f.add_dep(x, dep) - B = Bp - if ctx.config.get_option('debug'): - G_f.write_graphviz(sys.stdout) - order = G_f.topological_sort() - order.reverse() - ctx.ui.info(_('Installation order: ') + util.strlist(order) ) - for x in order: - atomicoperations.install_single_file(dfn[x]) - -def check_conflicts(order): - """check if upgrading to the latest versions will cause havoc - done in a simple minded way without regard for dependencies of - conflicts, etc.""" - B_0 = B = set(order) - C = set() - # calculate conflict closure - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) # get latest version! - #TODO: read conflicts from a conflicts db... - for conflict in pkg.conflicts: - if ctx.installdb.is_installed(self.pkginfo): - Bp.add(conflict) - C.add(conflict) - B = Bp - if B_0.intersection(C): - raise Error(_("Selected packages %s and %s are in conflict.") % (x, pkg)) - if C: - if not ctx.ui.confirm(_('Remove the following conflicting packages?')): - #raise Error(_("Package %s conflicts installed package %s") % (x, pkg)) - raise Error(_("Conflicts remain")) - -def expand_components(A): - Ap = set() - for x in A: - if ctx.componentdb.has_component(x): - Ap = Ap.union(ctx.componentdb.get_component(x).packages) - else: - Ap.add(x) - return Ap - -def install_pkg_names(A): - """This is the real thing. It installs packages from - the repository, trying to perform a minimum number of - installs""" - - # A was a list, remove duplicates and expand components - A_0 = A = expand_components(set(A)) - ctx.ui.debug('A = %s' % str(A)) - - if len(A)==0: - ctx.ui.info(_('No packages to install.')) - return - - if ctx.config.get_option('ignore_dependency'): - # simple code path then - for x in A: - atomicoperations.install_single_name(x) - return # short circuit - - - # try to construct a pisi graph of packages to - # install / reinstall - - G_f = pgraph.PGraph(packagedb) # construct G_f - - # find the "install closure" graph of G_f by package - # set A using packagedb - for x in A: - G_f.add_package(x) - B = A - - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) - for dep in pkg.runtimeDependencies(): - ctx.ui.debug('checking %s' % str(dep)) - # we don't deal with already *satisfied* dependencies - if not dependency.installed_satisfies_dep(dep): - if not dep.package in G_f.vertices(): - Bp.add(str(dep.package)) - G_f.add_dep(x, dep) - B = Bp - if ctx.config.get_option('debug'): - G_f.write_graphviz(sys.stdout) - order = G_f.topological_sort() - order.reverse() - check_conflicts(order) - ctx.ui.info(_("""The following minimal list of packages will be installed -in the respective order to satisfy dependencies: -""") + util.strlist(order)) - if len(order) > len(A_0): - if not ctx.ui.confirm(_('Do you want to continue?')): - return False - for x in order: - atomicoperations.install_single_name(x) - -def upgrade(A): - upgrade_pkg_names(A) - -def upgrade_pkg_names(A = []): - """Re-installs packages from the repository, trying to perform - a maximum number of upgrades.""" - - ignore_build = ctx.config.options and ctx.config.options.ignore_build_no - - if not A: - # if A is empty, then upgrade all packages - A = ctx.installdb.list_installed() - - # filter packages that are not upgradable - A_0 = A = expand_components(set(A)) - Ap = [] - for x in A: - if x.endswith('.pisi'): - ctx.ui.debug(_("Warning: package *name* ends with '.pisi'")) - if not ctx.installdb.is_installed(x): - ctx.ui.info(_('Package %s is not installed.') % x) - continue - (version, release, build) = ctx.installdb.get_version(x) - pkg = packagedb.get_package(x) - - # First check version. If they are same, check release. Again - # if releases are same and checking buildno is premitted, - # check build number. - if version < pkg.version: - Ap.append(x) - elif version == pkg.version: - if release < pkg.release: - Ap.append(x) - if release == pkg.release and build and not ignore_build: - if build < pkg.build: - Ap.append(x) - else: - #ctx.ui.info('Package %s cannot be upgraded. ' % x) - ctx.ui.info(_('Package %s is already at its latest \ -version %s, release %s, build %s.') - % (x, pkg.version, pkg.release, pkg.build)) - A = set(Ap) - - if len(A)==0: - ctx.ui.info(_('No packages to upgrade.')) - return True - - ctx.ui.debug('A = %s' % str(A)) - - # try to construct a pisi graph of packages to - # install / reinstall - - G_f = pgraph.PGraph(packagedb) # construct G_f - - # find the "install closure" graph of G_f by package - # set A using packagedb - for x in A: - G_f.add_package(x) - B = A - - def upgradable(dep): - #pre dep.package is installed - (v,r,b) = ctx.installdb.get_version(dep.package) - rep_pkg = packagedb.get_package(dep.package) - (vp,rp,bp) = (rep_pkg.version, rep_pkg.release, - rep_pkg.build) - if ignore_build or (not b) or (not bp): - # if we can't look at build - if r >= rp: # installed already new - return False - elif b and bp and b >= bp: - return False - return True - - # TODO: conflicts - - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) - for dep in pkg.runtimeDependencies(): - # add packages that can be upgraded - if dependency.repo_satisfies_dep(dep): - #TODO: distinguish must upgrade and upgradable - if ctx.installdb.is_installed(dep.package): - if not ctx.get_option('eager'): - if dependency.installed_satisfies_dep(dep): - continue - else: - if not upgradable(dep): - continue - if not dep.package in G_f.vertices(): - Bp.add(str(dep.package)) - G_f.add_dep(x, dep) - else: - raise Error(_("Reverse dependency %s cannot be satisfied") % rev_dep) - B = Bp - # now, search reverse dependencies to see if anything - # should be upgraded - B = A - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) - rev_deps = packagedb.get_rev_deps(x) - for (rev_dep, depinfo) in rev_deps: - if not ctx.get_option('eager'): - # add unsatisfied reverse dependencies - if packagedb.has_package(rev_dep) and \ - (not dependency.installed_satisfies_dep(depinfo)): - if not dependency.repo_satisfies_dep(dep): - raise Error(_("Reverse dependency %s cannot be satisfied") % rev_dep) - if not rev_dep in G_f.vertices(): - Bp.add(rev_dep) - G_f.add_plain_dep(rev_dep, x) - else: - if not rev_dep in G_f.vertices(): - Bp.add(rev_dep) - G_f.add_plain_dep(rev_dep, x) - B = Bp - - if ctx.config.get_option('debug'): - G_f.write_graphviz(sys.stdout) - order = G_f.topological_sort() - order.reverse() - check_conflicts(order) - ctx.ui.info(_("""The following packages will be upgraded:\n""") + - util.strlist(order)) - if len(order) > len(A_0): - if not ctx.ui.confirm(_('Do you want to continue?')): - return False - for x in order: - atomicoperations.install_single_name(x, True) - -def remove(A): - """remove set A of packages from system (A is a list of package names)""" - - # filter packages that are not installed - A_0 = A = expand_components(set(A)) - - if not ctx.get_option('bypass_safety'): - if ctx.componentdb.has_component('system.base'): - refused = A.intersection(set(ctx.componentdb.get_component('system.base').packages)) - ctx.ui.warning(_('Safety switch: cannot remove the following packages in system.base: ') + - util.strlist(refused)) - A = A - set(ctx.componentdb.get_component('system.base').packages) - else: - ctx.ui.warning(_('Safety switch: the component system.base cannot be found')) - - Ap = [] - for x in A: - if ctx.installdb.is_installed(x): - Ap.append(x) - else: - ctx.ui.info(_('Package %s does not exist. Cannot remove.') % x) - A = set(Ap) - - if len(A)==0: - ctx.ui.info(_('No packages to remove.')) - return - - # try to construct a pisi graph of packages to - # install / reinstall - - G_f = pgraph.PGraph(packagedb) # construct G_f - - # find the (install closure) graph of G_f by package - # set A using packagedb - for x in A: - G_f.add_package(x) - B = A - while len(B) > 0: - Bp = set() - for x in B: - pkg = packagedb.get_package(x) - rev_deps = packagedb.get_rev_deps(x) - for (rev_dep, depinfo) in rev_deps: - # we don't deal with unsatisfied dependencies - if packagedb.has_package(rev_dep) and \ - dependency.installed_satisfies_dep(depinfo): - if not rev_dep in G_f.vertices(): - Bp.add(rev_dep) - G_f.add_plain_dep(rev_dep, x) - B = Bp - if ctx.config.get_option('debug'): - G_f.write_graphviz(sys.stdout) - order = G_f.topological_sort() - ctx.ui.info(_("""The following minimal list of packages will be removed -in the respective order to satisfy dependencies: -""") + util.strlist(order)) - if len(order) > len(A_0): - if not ctx.ui.confirm(_('Do you want to continue?')): - ctx.ui.warning(_('Package removal declined')) - return False - for x in order: - if ctx.installdb.is_installed(x): - atomicoperations.remove_single(x) - else: - ctx.ui.info(_('Package %s is not installed. Cannot remove.') % x) diff --git a/tags/pisi-1.0_beta2/pisi/package.py b/tags/pisi-1.0_beta2/pisi/package.py deleted file mode 100644 index 2e436450..00000000 --- a/tags/pisi-1.0_beta2/pisi/package.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# package abstraction -# provides methods to add/remove files, extract control files - -# maintainer: baris and meren - -from os.path import join, exists - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.context as ctx -import pisi.archive as archive -from pisi.uri import URI -from pisi.metadata import MetaData -from pisi.files import Files -import pisi.util as util - -class Error(pisi.Error): - pass - - -class Package: - """PISI Package Class provides access to a pisi package (.pisi - file).""" - def __init__(self, packagefn, mode='r'): - self.filepath = packagefn - url = URI(packagefn) - - if url.is_remote_file(): - from fetcher import fetch_url - dest = ctx.config.packages_dir() - self.filepath = join(dest, url.filename()) - - # FIXME: exists is not enough, also sha1sum check needed - # when implemented in pisi-index.xml - if not exists(self.filepath): - fetch_url(url, dest, ctx.ui.Progress) - else: - ctx.ui.info(_('%s [cached]') % url.filename()) - - self.impl = archive.ArchiveZip(self.filepath, 'zip', mode) - - def add_to_package(self, fn): - """Add a file or directory to package""" - self.impl.add_to_archive(fn) - - def close(self): - """Close the package archive""" - self.impl.close() - - def extract(self, outdir): - """Extract entire package contents to directory""" - self.extract_dir('', outdir) # means package root - - def extract_files(self, paths, outdir): - """Extract paths to outdir""" - self.impl.unpack_files(paths, outdir) - - def extract_file(self, path, outdir): - """Extract file with path to outdir""" - self.extract_files([path], outdir) - - def extract_dir(self, dir, outdir): - """Extract directory recursively, this function - copies the directory archiveroot/dir to outdir""" - self.impl.unpack_dir(dir, outdir) - - def extract_dir_flat(self, dir, outdir): - """Extract directory recursively, this function - unpacks the *contents* of directory archiveroot/dir inside outdir - this is the function used by the installer""" - self.impl.unpack_dir_flat(dir, outdir) - - def extract_PISI_files(self, outdir): - """Extract PISI control files: metadata.xml, files.xml, - action scripts, etc.""" - self.extract_files([ctx.const.metadata_xml, ctx.const.files_xml], outdir) - self.extract_dir('config', outdir) - - def read(self, outdir = None): - if not outdir: - outdir = ctx.config.tmp_dir() - - # extract control files - self.extract_PISI_files(outdir) - - self.metadata = MetaData() - self.metadata.read( join(outdir, ctx.const.metadata_xml) ) - errs = self.metadata.errors() - if errs: - util.Checks.print_errors(errs) - raise Error, _("MetaData format wrong") - - self.files = Files() - self.files.read( join(outdir, ctx.const.files_xml) ) - if self.files.errors(): - raise Error, _("Invalid %s") % ctx.const.files_xml - - def pkg_dir(self): - packageDir = self.metadata.package.name + '-' \ - + self.metadata.package.version + '-' \ - + self.metadata.package.release - - return join( ctx.config.lib_dir(), packageDir) - - def comar_dir(self): - return join(self.pkg_dir(), ctx.const.comar_dir) diff --git a/tags/pisi-1.0_beta2/pisi/packagedb.py b/tags/pisi-1.0_beta2/pisi/packagedb.py deleted file mode 100644 index 6fc7ce9d..00000000 --- a/tags/pisi-1.0_beta2/pisi/packagedb.py +++ /dev/null @@ -1,172 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# package database -# interface for update/query to local package repository - -# Authors: Eray Ozkural -# Baris Metin - -# we basically store everything in PackageInfo class -# yes, we are cheap - -import bsddb.dbshelve as shelve -import os, fcntl -from bsddb import db - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.util as util -import pisi.context as ctx -import pisi.lockeddbshelve as shelve - -class Error(pisi.Error): - pass - -class PackageDB(object): - """PackageDB class provides an interface to the package database with - a delegated dbshelve object""" - def __init__(self, id): - self.d = shelve.LockedDBShelf('package-%s' % id ) - self.dr = shelve.LockedDBShelf('revdep-%s' % id ) - - def close(self): - self.d.close() - self.dr.close() - - def has_package(self, name): - name = str(name) - return self.d.has_key(name) - - def get_package(self, name): - name = str(name) - return self.d[name] - - def get_rev_deps(self, name): - name = str(name) - if self.dr.has_key(name): - return self.dr[name] - else: - return [] - - def list_packages(self): - list = [] - for (pkg, x) in self.d.iteritems(): - list.append(pkg) - return list - - #TODO: list_upgrades? - - def add_package(self, package_info): - name = str(package_info.name) - self.d[name] = package_info - for dep in package_info.runtimeDependencies(): - dep_name = str(dep.package) - if self.dr.has_key(dep_name): - self.dr[dep_name].append( (name, dep) ) - else: - self.dr[dep_name] = [ (name, dep) ] - # add component - ctx.componentdb.add_package(package_info.partOf, package_info.name) - - def clear(self): - self.d.clear() - - def remove_package(self, name): - name = str(name) - package_info = self.d[name] - del self.d[name] - #FIXME: what's happening to dr? - ctx.componentdb.remove_package(package_info.partOf, package_info.name) - -packagedbs = {} - -def add_db(name): - pisi.packagedb.packagedbs[name] = PackageDB('repo-' + name) - -def get_db(name): - return pisi.packagedb.packagedbs[name] - -def remove_db(name): - del pisi.packagedb.packagedbs[name] - #FIXME: erase database file? - -def has_package(name): - repo = which_repo(name) - if repo or thirdparty_packagedb.has_package(name) or inst_packagedb.has_package(name): - return True - return False - -def which_repo(name): - import pisi.repodb - for repo in pisi.repodb.db.list(): - if get_db(repo).has_package(name): - return repo - return None - -def get_package(name): - repo = which_repo(name) - if repo: - return get_db(repo).get_package(name) - if thirdparty_packagedb.has_package(name): - return thirdparty_packagedb.get_package(name) - if inst_packagedb.has_package(name): - return inst_packagedb.get_package(name) - raise Error(_('get_package: package %s not found') % name) - -def get_rev_deps(name): - repo = which_repo(name) - if repo: - return get_db(repo).get_rev_deps(name) - if thirdparty_packagedb.has_package(name): - return thirdparty_packagedb.get_rev_deps(name) - if inst_packagedb.has_package(name): - return inst_packagedb.get_rev_deps(name) - - return [] - -def remove_package(name): - # remove the guy from the tracking databases - inst_packagedb.remove_package(name) - if thirdparty_packagedb.has_package(name): - thirdparty_packagedb.remove_package(name) - -# tracking databases for non-repository information - -thirdparty_packagedb = inst_packagedb = None - -def init_db(): - global thirdparty_packagedb - global inst_packagedb - - if not thirdparty_packagedb: - thirdparty_packagedb = PackageDB('thirdparty') - if not pisi.packagedb.inst_packagedb: - inst_packagedb = PackageDB('installed') - -def finalize_db(): - global thirdparty_packagedb - global inst_packagedb - global packagedbs - - if thirdparty_packagedb: - thirdparty_packagedb.close() - thirdparty_packagedb = None - - if inst_packagedb: - inst_packagedb.close() - inst_packagedb = None - - packagedbs.clear() diff --git a/tags/pisi-1.0_beta2/pisi/pgraph.py b/tags/pisi-1.0_beta2/pisi/pgraph.py deleted file mode 100644 index ce7d4d99..00000000 --- a/tags/pisi-1.0_beta2/pisi/pgraph.py +++ /dev/null @@ -1,81 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# PISI package relation graph that represents the state of packagedb - -from graph import * - -# Cache the results from packagedb queries in a graph - -class PGraph(Digraph): - - def __init__(self, packagedb): - super(PGraph, self).__init__() - self.packagedb = packagedb - - def add_package(self, pkg): - pkg1 = self.packagedb.get_package(pkg) - self.add_vertex(str(pkg), (pkg1.version, pkg1.release)) - - def add_plain_dep(self, pkg1name, pkg2name): - pkg1data = None - if not pkg1name in self.vertices(): - pkg1 = self.packagedb.get_package(pkg1name) - pkg1data = (pkg1.version, pkg1.release) - pkg2data = None - if not pkg2name in self.vertices(): - pkg2 = self.packagedb.get_package(pkg2name) - pkg2data = (pkg2.version, pkg2.release) - self.add_edge(str(pkg1name), str(pkg2name), ('d', None), - pkg1data, pkg2data ) - - def add_dep(self, pkg, depinfo): - pkg1data = None - if not pkg in self.vertices(): - pkg1 = self.packagedb.get_package(pkg) - pkg1data = (pkg1.version, pkg1.release) - pkg2data = None - if not depinfo.package in self.vertices(): - pkg2 = self.packagedb.get_package(depinfo.package) - pkg2data = (pkg2.version, pkg2.release) - self.add_edge(str(pkg), str(depinfo.package), ('d', depinfo), - pkg1data, pkg2data ) - - def add_rev_dep(self, depinfo, pkg): - pkg1data = None - if not pkg in self.vertices(): - pkg1 = self.packagedb.get_package(depinfo.package) - pkg1data = (pkg1.version, pkg1.release) - pkg2data = None - if not depinfo.package in self.vertices(): - pkg2 = self.packagedb.get_package(pkg) - pkg2data = (pkg2.version, pkg2.release) - self.add_edge(str(depinfo.package), str(pkg), ('d', depinfo), - pkg1data, pkg2data ) - - def add_conflict(self, pkg, conflinfo): - pkg1data = None - if not pkg in self.vertices(): - pkg1 = self.packagedb.get_package(pkg) - pkg1data = (pkg1.version, pkg1.release) - pkg2data = None - if not pkg in self.vertices(): - pkg2 = self.packagedb.get_package(conflinfo.package) - pkg2data = (pkg2.version, pkg2.release) - - self.add_biedge(str(pkg), str(conflinfo.package), ('c', conflinfo) - , pkg1data, pkg2data ) - - def write_graphviz_vlabel(self, f, u): - (v, r) = self.vertex_data(u) - f.write('[ label = \"' + str(u) + '(' + str(v) + ',' + str(r) + ')\" ]') - diff --git a/tags/pisi-1.0_beta2/pisi/pxml/__init__.py b/tags/pisi-1.0_beta2/pisi/pxml/__init__.py deleted file mode 100644 index 67d1fd25..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import sys -import locale - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi - -class Error(pisi.Error): - pass diff --git a/tags/pisi-1.0_beta2/pisi/pxml/autoxml.py b/tags/pisi-1.0_beta2/pisi/pxml/autoxml.py deleted file mode 100644 index 71b8ea18..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/autoxml.py +++ /dev/null @@ -1,814 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# -# Authors: Eray Ozkural -# Gurer Ozen -# Baris Metin - - -""" - autoxml is a metaclass for automatic XML translation, using - a miniature type system. (w00t!) This is based on an excellent - high-level XML processing prototype that Gurer prepared. - - Method names are mixedCase for compatibility with minidom, - an old library. -""" - -# System -import locale -import codecs -import types -import formatter -import sys -from StringIO import StringIO -#import xml.dom.minidom as mdom -#from xml.parsers.expat import ExpatError - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# PiSi -import pisi -# TODO: find the appropriate xmlext implementation and import from there -from pisi.pxml.xmlext import * -from pisi.pxml.xmlfile import XmlFile -import pisi.context as ctx -import pisi.util as util -import pisi.oo as oo - -class Error(pisi.Error): - pass - -# requirement specs - -mandatory, optional = range(2) # poor man's enum - -# basic types - -String = types.StringType -Text = types.UnicodeType -Integer = types.IntType -Long = types.LongType -Float = types.FloatType - -#class datatype(type): -# def __init__(cls, name, bases, dict): -# """entry point for metaclass code""" -# # standard initialization -# super(autoxml, cls).__init__(name, bases, dict) - -class LocalText(dict): - """Handles XML tags with localized text""" - - def __init__(self, tag = "", req = optional): - self.tag = tag - self.req = req - dict.__init__(self) - - def decode(self, node, errs, where = ""): - # flags, tag name, instance attribute - assert self.tag != '' - nodes = getAllNodes(node, self.tag) - if not nodes: - if self.req == mandatory: - errs.append(where + ': ' + _("At least one '%s' tag should have local text") % - self.tag ) - else: - for node in nodes: - #lang = getNodeAttribute(node, "xml:lang") - lang = node.getAttributeNS(XML_NS, 'lang') - c = getNodeText(node) - if not c: - errs.append(where + ': ' + _("'%s' language of tag '%s' is empty") % - (lang, self.tag)) - # FIXME: check for dups and 'en' - if not lang: - lang = 'en' - self[lang] = c - - def encode(self, node, errs): - assert self.tag != '' - for key in self.iterkeys(): - newnode = newNode(node, self.tag) - newnode.setAttributeNS(XML_NS, 'xml:lang', key) - newtext = newTextNode(node, self[key]) - newnode.appendChild(newtext) - node.appendChild(newnode) - - @staticmethod - def get_lang(): - try: - (lang, encoding) = locale.getlocale() - if not lang: - (lang, encoding) = locale.getdefaultlocale() - return lang[0:2] - except: - raise Error(_('LocalText: unable to get either current or default locale')) - - def errors(self, where = unicode()): - errs = [] - langs = [ LocalText.get_lang(), 'tr', 'en' ] - if not util.any(lambda x : self.has_key(x), langs): - errs.append( where + ': ' + _("Tag should have at least the current locale, or failing that an English or Turkish version")) - #FIXME: check if all entries are unicode - return errs - - def format(self, f, errs): - L = LocalText.get_lang() - if self.has_key(L): - f.add_flowing_data(self[L]) - elif self.has_key('en'): - # fallback to English, blah - f.add_flowing_data(self['en']) - elif self.has_key('tr'): - # fallback to Turkish - f.add_flowing_data(self['tr']) - else: - errs.append(_("Tag should have at least the current locale, or failing that an English or Turkish version")) - - #FIXME: factor out these common routines - def print_text(self, file = sys.stdout): - w = Writer(file) # plain text - f = formatter.AbstractFormatter(w) - errs = [] - self.format(f, errs) - if errs: - for x in errs: - ctx.ui.warning(x) - - def __str__(self): - L = LocalText.get_lang() - if self.has_key(L): - return unicode(self[L]) - elif self.has_key('en'): - # fallback to English, blah - return unicode(self['en']) - elif self.has_key('tr'): - # fallback to Turkish - return unicode(self['tr']) - else: - return '' - -class Writer(formatter.DumbWriter): - """adds unicode support""" - - def __init__(self, file=None, maxcol=78): - formatter.DumbWriter.__init__(self, file, maxcol) - - def send_literal_data(self, data): - self.file.write(data.encode("utf-8")) - i = data.rfind('\n') - if i >= 0: - self.col = 0 - data = data[i+1:] - data = data.expandtabs() - self.col = self.col + len(data) - self.atbreak = 0 - - -class autoxml(oo.autosuper, oo.autoprop): - """High-level automatic XML transformation interface for xmlfile. - The idea is to declare a class for each XML tag. Inside the - class the tags and attributes nested in the tag are further - elaborated. A simple example follows: - - class Employee: - __metaclass__ = autoxml - t_Name = [xmlfile.Text, xmlfile.mandatory] - a_Type = [xmlfile.Integer, xmlfile.optional] - - This class defines a tag and an attribute nested in Employee - class. Name is a string and type is an integer, called basic - types. - While the tag is mandatory, the attribute may be left out. - - Other basic types supported are: xmlfile.Float, xmlfile.Double - and (not implemented yet): xmlfile.Binary - - By default, the class name is taken as the corresponding tag, - which may be overridden by defining a tag attribute. Thus, - the same tag may also be written as: - - class EmployeeXML: - ... - tag = 'Employee' - ... - - In addition to basic types, we allow for two kinds of complex - types: class types and list types. - - A declared class can be nested in another class as follows - - class Position: - __metaclass__ = autoxml - t_Name = [xmlfile.Text, xmlfile.mandatory] - t_Description = [xmlfile.Text, xmlfile.optional] - - which we can add to our Employee class. - - class Employee: - __metaclass__ = autoxml - t_Name = [xmlfile.Text, xmlfile.mandatory] - a_Type = [xmlfile.Integer, xmlfile.optional] - t_Position = [Position, xmlfile.mandatory] - - Note some unfortunate redundancy here with Position; this is - justified by the implementation (kidding). Still, you might - want to assign a different name than the class name that - goes in there, which may be fully qualified. - - There is more! Suppose we want to define a company, with - of course many employees. - - class Company: - __metaclass__ = autoxml - t_Employees = [ [Employee], xmlfile.mandatory, 'Employees/Employee'] - - Logically, inside the Company/Employees tag, we will have several - Employee tags, which are inserted to the Employees instance variable of - Company in order of appearance. We can define lists of any other valid - type. Here we used a list of an autoxml class defined above. - - The mandatory flag here asserts that at least one such record - is to be found. - - You see, it works like magic, when it works of course. All of it - done without a single brain exploding. - - """ - - - def __init__(cls, name, bases, dict): - """entry point for metaclass code""" - #print 'generating class', name - - # standard initialization - super(autoxml, cls).__init__(name, bases, dict) - - xmlfile_support = XmlFile in bases - - cls.autoxml_bases = filter(lambda base: isinstance(base, autoxml), bases) - - #TODO: initialize class attribute __xml_tags - #setattr(cls, 'xml_variables', []) - - # default class tag is class name - if not dict.has_key('tag'): - cls.tag = name - - # generate helper routines, for each XML component - names = [] - inits = [] - decoders = [] - encoders = [] - errorss = [] - formatters = [] - order = dict.keys() - order.sort() - #TODO: there should be at most one str member, and it should be the first - for var in order: - if var.startswith('t_') or var.startswith('a_') or var.startswith('s_'): - name = var[2:] - if var.startswith('a_'): - x = autoxml.gen_attr_member(cls, name) - elif var.startswith('t_'): - x = autoxml.gen_tag_member(cls, name) - elif var.startswith('s_'): - x = autoxml.gen_str_member(cls, name) - (name, init, decoder, encoder, errors, format_x) = x - names.append(name) - inits.append(init) - decoders.append(decoder) - encoders.append(encoder) - errorss.append(errors) - formatters.append(format_x) - - # generate top-level helper functions - cls.initializers = inits - def initialize(self, **args): - if xmlfile_support: - # totally dailywtf - #if args.has_key('tag'): - # tag = args['tag'] - #else: - # tag = self.__class__.tag # ought to be autoxml - #XmlFile.__init__(self, tag = tag) - if not args.has_key('tag'): - XmlFile.__init__(self, tag = cls.tag) - for base in cls.autoxml_bases: - base.__init__(self) - #super(cls, self).__init__(tag = tag) cooperative shit disabled for now - for init in inits:#self.__class__.initializers: - init(self) - for x in args.iterkeys(): - setattr(self, x, args[x]) - # init hook - if hasattr(self, 'init'): - self.init(tag) - - cls.__init__ = initialize - - cls.decoders = decoders - def decode(self, node, errs, where = unicode(cls.tag)): - for base in cls.autoxml_bases: - base.decode(self, node, errs, where) - for decode_member in decoders:#self.__class__.decoders: - decode_member(self, node, errs, where) - if hasattr(self, 'decode_hook'): - self.decode_hook(node, errs, where) - cls.decode = decode - - cls.encoders = encoders - def encode(self, node, errs): - for base in cls.autoxml_bases: - base.encode(self, node, errs) - for encode_member in encoders:#self.__class__.encoders: - encode_member(self, node, errs) - if hasattr(self, 'encode_hook'): - self.encode_hook(node, errs) - cls.encode = encode - - cls.errorss = errorss - def errors(self, where = unicode(name)): - errs = [] - for base in cls.autoxml_bases: - errs.extend(base.errors(self, where)) - for errors in errorss:#self.__class__.errorss: - errs.extend(errors(self, where)) - if hasattr(self, 'errors_hook'): - errs.extend(self.errors_hook(where)) - return errs - cls.errors = errors - def check(self): - errs = self.errors() - if errs: - errs.append(_("autoxml.check: '%s' errors") % len(errs)) - raise Error(*errs) - cls.check = check - - cls.formatters = formatters - def format(self, f, errs): - for base in cls.autoxml_bases: - base.format(self, f, errs) - for formatter in formatters:#self.__class__.formatters: - formatter(self, f, errs) - cls.format = format - def print_text(self, file = sys.stdout): - w = Writer(file) # plain text - f = formatter.AbstractFormatter(w) - errs = [] - self.format(f, errs) - if errs: - for x in errs: - ctx.ui.warning(x) - cls.print_text = print_text - if not dict.has_key('__str__'): - def str(self): - strfile = StringIO() - self.print_text(strfile) - str = strfile.getvalue() - strfile.close() - return str - cls.__str__ = str - - if not dict.has_key('__eq__'): - def equal(self, other): - for name in names: - try: - if getattr(self, name) != getattr(other, name): - return False - except: - return False - return True - def notequal(self, other): - return not self.__eq__(other) - cls.__eq__ = equal - cls.__ne__ = notequal - - if xmlfile_support: - def read(self, filename, keepDoc = False): - "read XML file and decode it into a python object" - self.readxml(filename) - errs = [] - self.decode(self.rootNode(), errs) - if hasattr(self, 'read_hook'): - self.read_hook(errs) - if errs: - errs.append(_("autoxml.read: File '%s' has errors") % filename) - raise Error(*errs) - - if not keepDoc: - self.unlink() # get rid of the tree - - errs = self.errors() - if errs: - errs.append(_("autoxml.read: File '%s' has errors") % filename) - raise Error(*errs) - - def write(self, filename, keepDoc = False): - "encode the contents of the python object into an XML file" - errs = self.errors() - if errs: - errs.append(_("autoxml.write: object validation has failed")) - raise Error(*errs) - errs = [] - self.newDocument() - self.encode(self.rootNode(), errs) - if hasattr(self, 'write_hook'): - self.write_hook(errs) - if errs: - errs.append(_("autoxml.write: File encoding '%s' has errors") % filename) - raise Error(*errs) - self.writexml(filename) - if not keepDoc: - self.unlink() # get rid of the tree - - cls.read = read - cls.write = write - - - def gen_attr_member(cls, attr): - """generate readers and writers for an attribute member""" - #print 'attr:', attr - spec = getattr(cls, 'a_' + attr) - tag_type = spec[0] - assert type(tag_type) == type(type) - def readtext(node, attr): - return getNodeAttribute(node, attr) - def writetext(node, attr, text): - #print 'write attr', attr, text - node.setAttributeNS(XML_NS, attr, text) - anonfuns = cls.gen_anon_basic(attr, spec, readtext, writetext) - return cls.gen_named_comp(attr, spec, anonfuns) - - def gen_tag_member(cls, tag): - """generate helper funs for tag member of class""" - #print 'tag:', tag - spec = getattr(cls, 't_' + tag) - anonfuns = cls.gen_tag(tag, spec) - return cls.gen_named_comp(tag, spec, anonfuns) - - def gen_tag(cls, tag, spec): - """generate readers and writers for the tag""" - tag_type = spec[0] - if type(tag_type) is types.TypeType and \ - autoxml.basic_cons_map.has_key(tag_type): - def readtext(node, tagpath): - #print 'read tag', node, tagpath - return getNodeText(node, tagpath) - def writetext(node, tagpath, text): - #print 'write tag', node, tagpath, text - addText(node, tagpath, text) - return cls.gen_anon_basic(tag, spec, readtext, writetext) - elif type(tag_type) is types.ListType: - return cls.gen_list_tag(tag, spec) - elif tag_type is LocalText: - return cls.gen_insetclass_tag(tag, spec) - elif type(tag_type) is autoxml or type(tag_type) is types.TypeType: - return cls.gen_class_tag(tag, spec) - else: - raise Error(_('gen_tag: unrecognized tag type %s in spec') % - str(tag_type)) - - def gen_str_member(cls, token): - """generate readers and writers for a string member""" - spec = getattr(cls, 's_' + token) - tag_type = spec[0] - assert type(tag_type) == type(type) - def readtext(node, blah): - #node.normalize() # piksemel doesn't have this - return getNodeText(node) - def writetext(node, blah, text): - addText(node, "", text) - anonfuns = cls.gen_anon_basic(token, spec, readtext, writetext) - return cls.gen_named_comp(token, spec, anonfuns) - - def gen_named_comp(cls, token, spec, anonfuns): - """generate a named component tag/attr. a decoration of - anonymous functions that do not bind to variable names""" - name = cls.mixed_case(token) - token_type = spec[0] - req = spec[1] - (init_a, decode_a, encode_a, errors_a, format_a) = anonfuns - - def init(self): - """initialize component""" - setattr(self, name, init_a()) - - def decode(self, node, errs, where): - """decode component from DOM node""" - setattr(self, name, decode_a(node, errs, where + '.' + unicode(name))) - - def encode(self, node, errs): - """encode self inside, possibly new, DOM node using xml""" - if hasattr(self, name): - value = getattr(self, name) - else: - value = None - encode_a(node, value, errs) - - def errors(self, where): - errs = [] - if hasattr(self, name): - value = getattr(self,name) - errs.extend(errors_a(value, where + '.' + name)) - else: - if req == mandatory: - errs.append(where + ': ' + _('Mandatory variable %s not available') % name) - return errs - - def format(self, f, errs): - if hasattr(self, name): - value = getattr(self,name) - f.add_literal_data(token + ': ') - format_a(value, f, errs) - f.add_line_break() - else: - if req == mandatory: - errs.append(_('Mandatory variable %s not available') % name) - - return (name, init, decode, encode, errors, format) - - def mixed_case(cls, identifier): - """helper function to turn token name into mixed case""" - if identifier is "": - return "" - else: - if identifier[0]=='I': - lowly = 'i' # because of pythonic idiots we can't choose locale in lower - else: - lowly = identifier[0].lower() - return lowly + identifier[1:] - - def tagpath_head_last(cls, tagpath): - "returns split of the tag path into last tag and the rest" - try: - lastsep = tagpath.rindex('/') - except ValueError, e: - return ('', tagpath) - return (tagpath[:lastsep], tagpath[lastsep+1:]) - - def parse_spec(cls, token, spec): - """decompose member specification""" - name = cls.mixed_case(token) - token_type = spec[0] - req = spec[1] - - if len(spec)>=3: - path = spec[2] # an alternative path specified - elif type(token_type) is type([]): - if type(token_type[0]) is autoxml: - # if list of class, by default nested like in most PSPEC - path = token + '/' + token_type[0].tag - else: - # if list of ordinary type, just take the name for - path = token - elif type(token_type) is autoxml: - # if a class, by default its tag - path = token_type.tag - else: - path = token # otherwise it's the same name as - # the token - return name, token_type, req, path - - def gen_anon_basic(cls, token, spec, readtext, writetext): - """Generate a tag or attribute with one of the basic - types like integer. This has got to be pretty generic - so that we can invoke it from the complex types such as Class - and List. The readtext and writetext arguments achieve - the DOM text access for this datatype.""" - - name, token_type, req, tagpath = cls.parse_spec(token, spec) - - def initialize(): - """default value for all basic types is None""" - return None - - def decode(node, errs, where): - """decode from DOM node, the value, watching the spec""" - text = readtext(node, token) - #print 'read text ', text - if text: - try: - value = autoxml.basic_cons_map[token_type](text) - except: - value = None - errs.append(where + ': ' + _('Type mismatch: read text cannot be decoded')) - return value - else: - if req == mandatory: - errs.append(where + ': ' + _('Mandatory token %s not available') % token) - return None - - def encode(node, value, errs): - """encode given value inside DOM node""" - if value: - writetext(node, token, unicode(value)) - else: - if req == mandatory: - errs.append(_('Mandatory token %s not available') % token) - - def errors(value, where): - errs = [] - if value and not isinstance(value, token_type): - errs.append(where + ': ' + _('Type mismatch. Expected %s, got %s') % - (token_type, type(value)) ) - return errs - - def format(value, f, errs): - """format value for pretty printing""" - f.add_literal_data(unicode(value)) - - return initialize, decode, encode, errors, format - - def gen_class_tag(cls, tag, spec): - """generate a class datatype""" - name, tag_type, req, path = cls.parse_spec(tag, spec) - - def make_object(): - obj = tag_type.__new__(tag_type) - obj.__init__(tag=tag, req=req) - return obj - - def init(): - return make_object() - - def decode(node, errs, where): - node = getNode(node, tag) - if node: - try: - obj = make_object() - obj.decode(node, errs, where) - return obj - except Error: - errs.append(where + ': '+ _('Type mismatch: DOM cannot be decoded')) - else: - if req == mandatory: - errs.append(where + ': ' + _('Mandatory argument not available')) - return None - - def encode(node, obj, errs): - if node and obj: - try: - #FIXME: this doesn't look pretty - classnode = newNode(node, tag) - obj.encode(classnode, errs) - node.appendChild(classnode) - except Error: - if req == mandatory: - # note: we can receive an error if obj has no content - errs.append(_('Object cannot be encoded')) - else: - if req == mandatory: - errs.append(_('Mandatory argument not available')) - - def errors(obj, where): - return obj.errors(where) - - def format(obj, f, errs): - try: - obj.format(f, errs) - except Error: - if req == mandatory: - errs.append(_('Mandatory argument not available')) - return (init, decode, encode, errors, format) - - def gen_list_tag(cls, tag, spec): - """generate a list datatype. stores comps in tag/comp_tag""" - name, tag_type, req, path = cls.parse_spec(tag, spec) - - pathcomps = path.split('/') - comp_tag = pathcomps.pop() - list_tagpath = util.makepath(pathcomps, sep='/', relative=True) - - if len(tag_type) != 1: - raise Error(_('List type must contain only one element')) - - x = cls.gen_tag(comp_tag, [tag_type[0], mandatory]) - (init_item, decode_item, encode_item, errors_item, format_item) = x - - def init(): - return [] - - def decode(node, errs, where): - l = [] - nodes = getAllNodes(node, path) - #print node, tag + '/' + comp_tag, nodes - if len(nodes)==0 and req==mandatory: - errs.append(where + ': ' + _('Mandatory list empty')) - ix = 1 - for node in nodes: - dummy = newNode(node, "Dummy") - dummy.appendChild(node) - l.append(decode_item(dummy, errs, where + unicode("[%s]" % ix))) - #l.append(decode_item(node, errs, where + unicode("[%s]" % ix))) - ix += 1 - return l - - def encode(node, l, errs): - dom = node.ownerDocument - if l and len(l) > 0: - for item in l: - if list_tagpath: - listnode = addNode(node, list_tagpath, branch = False) - else: - listnode = node - encode_item(listnode, item, errs) - #encode_item(node, item, errs) - else: - if req is mandatory: - errs.append(_('Mandatory list empty')) - - def errors(l, where): - errs = [] - ix = 1 - for node in l: - errs.extend(errors_item(node, where + '[%s]' % ix)) - ix += 1 - return errs - - def format(l, f, errs): - # TODO: indent here - ix = 1 - length = len(l) - for node in l: - f.add_flowing_data(str(ix) + ': ') - format_item(node, f, errs) - if ix != length: - f.add_flowing_data(', ') - ix += 1 - - return (init, decode, encode, errors, format) - - def gen_insetclass_tag(cls, tag, spec): - """generate a class datatype that is highly integrated - don't worry if that means nothing to you. this is a silly - hack to implement local text quickly. it's not the most - elegant thing in the world. it's basically a copy of - class tag""" - name, tag_type, req, path = cls.parse_spec(tag, spec) - - def make_object(): - obj = tag_type.__new__(tag_type) - obj.__init__(tag=tag, req=req) - return obj - - def init(): - return make_object() - - def decode(node, errs, where): - if node: - try: - obj = make_object() - obj.decode(node, errs, where) - return obj - except Error: - errs.append(where + ': ' + _('Type mismatch: DOM cannot be decoded')) - else: - if req == mandatory: - errs.append(where + ': ' + _('Mandatory argument not available')) - return None - - def encode(node, obj, errs): - if node and obj: - try: - #FIXME: this doesn't look pretty - obj.encode(node, errs) - except Error: - if req == mandatory: - # note: we can receive an error if obj has no content - errs.append(_('Object cannot be encoded')) - else: - if req == mandatory: - errs.append(_('Mandatory argument not available')) - - def errors(obj, where): - return obj.errors(where) - - def format(obj, f, errs): - try: - obj.format(f, errs) - except Error: - if req == mandatory: - errs.append(_('Mandatory argument not available')) - - return (init, decode, encode, errors, format) - - basic_cons_map = { - types.StringType : str, - types.UnicodeType : unicode, - types.IntType : int, - types.FloatType : float, - types.LongType : long - } diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlext.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlext.py deleted file mode 100644 index ea7dbdeb..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlext.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural - -try: - zimbabwe # comment out to disable piks - from xmlextpiks import * -except: - try: - from xmlextcdom import * - except: - print 'xmlext: cDomlette/piksemel implementation cannot be loaded, falling back to minidom' - from xmlextmdom import * - - -from xml.dom import XHTML_NAMESPACE, XML_NAMESPACE -XHTML_NS = unicode(XHTML_NAMESPACE) -XML_NS = unicode(XML_NAMESPACE) diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlextcdom.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlextcdom.py deleted file mode 100644 index ae713679..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlextcdom.py +++ /dev/null @@ -1,203 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin -# Faik Uygur - -""" - xmlext is a helper module for accessing XML files using - xml.dom.minidom . It is a convenient wrapper for some - DOM functions, and provides path based get/add functions - as in KDE API. - - function names are mixedCase for compatibility with minidom, - an 'old library' - - this implementation uses cDomlette from 4suite.org - adapted from the minidom implementation by Faik Uygur and fixed by Eray -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import Ft -from Ft.Xml.Domlette import implementation -from Ft.Xml import ParsePath -from Ft.Xml.Domlette import NonvalidatingReader - -import pisi - -class XmlError(pisi.Error): - "named this way because the class if mostly used with an import *" - pass - -# Document wrappers - -def newDocument(tag): - # create a document and return document root - doc = implementation.createDocument(None, tag, None) - return doc.documentElement - -def parse(filename): - # parse file and return document root - try: - doc = ParsePath(filename) - return doc.documentElement - except Ft.FtException, e: - raise Error(_("File '%s' has invalid XML: %s") % (filename, str(e))) - -def newNode(node, tag): - return node.ownerDocument.createElementNS(None, tag) - -def newTextNode(node, text): - return node.ownerDocument.createTextNode(text) - -# Node related wrappers - -def getNodeAttribute(node, attrname): - """get named attribute from DOM node""" - if not node.hasAttributeNS(None, attrname): - return None - else: - return node.getAttributeNS(None, attrname) - -def getChildElts(node): - """get only child elements""" - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes) - -def getTagByName(parent, childName): - return [x for x in parent.childNodes - if x.nodeType == x.ELEMENT_NODE and x.tagName == childName] - -def getNodeText(node, tagpath = ""): - """get the first child and expect it to be text!""" - if tagpath!="": - node = getNode(node, tagpath) - try: - child = node.childNodes[0] - except IndexError: - return None - except AttributeError: # no node by that name - return None - if child.nodeType == child.TEXT_NODE: - # in any case, strip whitespaces... - return child.data.strip() - else: - raise XmlError(_("getNodeText: Expected text node, got something else!")) - -def getChildText(node_s, tagpath): - """get the text of a child at the end of a tag path""" - node = getNode(node_s, tagpath) - if not node: - return None - return getNodeText(node) - -def getNode(node, tagpath): - """returns the *first* matching node for given tag path.""" - - assert type(tagpath)==str - tags = tagpath.split('/') - assert len(tags)>0 - - # iterative code to search for the path - for tag in tags: - currentNode = None - for child in node.childNodes: - if child.nodeType == node.ELEMENT_NODE and child.tagName == tag: - currentNode = child - break - if not currentNode: - return None - else: - node = currentNode - return currentNode - -def getAllNodes(node, tagPath): - """retrieve all nodes that match a given tag path.""" - - #FIXME: better tag split - tags = tagPath.split('/') - - if len(tags) == 0: - return [] - - nodeList = [node] # basis case - - for tag in tags: - results = map(lambda x: getTagByName(x, tag), nodeList) - nodeList = [] - for x in results: - nodeList.extend(x) - pass # emacs indentation error, keep it here - - if len(nodeList) == 0: - return [] - - return nodeList - -def createTagPath(node, tags): - """create new child at the end of a tag chain starting from node - no matter what""" - if len(tags)==0: - return node - dom = node.ownerDocument - for tag in tags: - node = node.appendChild(dom.createElementNS(None, tag)) - return node - -def addTagPath(node, tags, newnode=None): - """add newnode at the end of a tag chain, smart one""" - node = createTagPath(node, tags) - if newnode: # node to add specified - node.appendChild(newnode) - return node - -def addNode(node, tagpath, newnode = None, branch=True): - """add a new node at the end of the tree and returns it - if newnode is given adds that node, too.""" - - assert type(tagpath)==str - tags = [] - if tagpath != "": - tags = tagpath.split('/') # tag chain - else: - addTagPath(node, [], newnode) - return node #FIXME: is this correct!?!? - - assert len(tags)>0 # we want a chain - - # iterative code to search for the path - - if branch: - rem = 1 - else: - rem = 0 - - while len(tags) > rem: - tag = tags.pop(0) - nodeList = getTagByName(node, tag) - if len(nodeList) == 0: # couldn't find - tags.insert(0, tag) # put it back in - return addTagPath(node, tags, newnode) - else: - node = nodeList[len(nodeList)-1] # discard other matches - else: - # had only one tag.. - return addTagPath(node, tags, newnode) - - return node - -def addText(node, tagPath, text, branch = True): - newnode = newTextNode(node, text) - return addNode(node, tagPath, newnode, branch = branch) diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlextmdom.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlextmdom.py deleted file mode 100644 index 37d10cca..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlextmdom.py +++ /dev/null @@ -1,198 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -""" - xmlext is a helper module for accessing XML files using - xml.dom.minidom . It is a convenient wrapper for some - DOM functions, and provides path based get/add functions - as in KDE API. - - function names are mixedCase for compatibility with minidom, - an 'old library' - - note: this is a particularly inefficient implementation of xmlext. -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import xml.dom.minidom as mdom -from xml.parsers.expat import ExpatError - -import pisi - -class XmlError(pisi.Error): - "named this way because the class if mostly used with an import *" - pass - -# Document wrappers - -def newDocument(tag): - impl = mdom.getDOMImplementation() - dom = impl.createDocument(None, tag, None) - return dom.documentElement - -def parse(filename): - try: - dom = mdom.parse(filename) - return dom.documentElement - except ExpatError, inst: - raise Error(_("File '%s' has invalid XML: %s\n") % (fileName, - str(inst))) - -def newNode(node, tag): - return node.ownerDocument.createElement(tag) - -def newTextNode(node, text): - return node.ownerDocument.createTextNode(text) - -# Node related wrappers - -def getNodeAttribute(node, attrname): - """get named attribute from DOM node""" - if not node.hasAttribute(attrname): - return None - return node.getAttribute(attrname) - -def getChildElts(node): - """get only child elements""" - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes) - -def getTagByName(parent, childName): - return [x for x in parent.childNodes - if x.nodeType == x.ELEMENT_NODE and x.tagName == childName] - -def getNodeText(node, tagpath = ""): - """get the first child and expect it to be text!""" - if tagpath!="": - node = getNode(node, tagpath) - try: - child = node.childNodes[0] - except IndexError: - return None - except AttributeError: # no node by that name - return None - if child.nodeType == child.TEXT_NODE: - # in any case, strip whitespaces... - return child.data.strip() - else: - raise XmlError(_("getNodeText: Expected text node, got something else!")) - -def getChildText(node_s, tagpath): - """get the text of a child at the end of a tag path""" - node = getNode(node_s, tagpath) - if not node: - return None - return getNodeText(node) - -def getNode(node, tagpath): - """returns the *first* matching node for given tag path.""" - - assert type(tagpath)==str - tags = tagpath.split('/') - assert len(tags)>0 - - # iterative code to search for the path - for tag in tags: - currentNode = None - for child in node.childNodes: - if child.nodeType == node.ELEMENT_NODE and child.tagName == tag: - currentNode = child - break - if not currentNode: - return None - else: - node = currentNode - return currentNode - -def getAllNodes(node, tagPath): - """retrieve all nodes that match a given tag path.""" - - #FIXME: better tag split - tags = tagPath.split('/') - - if len(tags) == 0: - return [] - - nodeList = [node] # basis case - - for tag in tags: - results = map(lambda x: getTagByName(x, tag), nodeList) - nodeList = [] - for x in results: - nodeList.extend(x) - pass # emacs indentation error, keep it here - - if len(nodeList) == 0: - return [] - - return nodeList - -def createTagPath(node, tags): - """create new child at the end of a tag chain starting from node - no matter what""" - if len(tags)==0: - return node - dom = node.ownerDocument - for tag in tags: - node = node.appendChild(dom.createElement(tag)) - return node - -def addTagPath(node, tags, newnode=None): - """add newnode at the end of a tag chain, smart one""" - node = createTagPath(node, tags) - if newnode: # node to add specified - node.appendChild(newnode) - return node - -def addNode(node, tagpath, newnode = None, branch=True): - """add a new node at the end of the tree and returns it - if newnode is given adds that node, too.""" - - assert type(tagpath)==str - tags = [] - if tagpath != "": - tags = tagpath.split('/') # tag chain - else: - addTagPath(node, [], newnode) - return node #FIXME: is this correct!?!? - - assert len(tags)>0 # we want a chain - - # iterative code to search for the path - - if branch: - rem = 1 - else: - rem = 0 - - while len(tags) > rem: - tag = tags.pop(0) - nodeList = getTagByName(node, tag) - if len(nodeList) == 0: # couldn't find - tags.insert(0, tag) # put it back in - return addTagPath(node, tags, newnode) - else: - node = nodeList[len(nodeList)-1] # discard other matches - else: - # had only one tag.. - return addTagPath(node, tags, newnode) - - return node - -def addText(node, tagPath, text, branch = True): - newnode = newTextNode(node, text) - return addNode(node, tagPath, newnode, branch = branch) diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlextpiks.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlextpiks.py deleted file mode 100644 index c4eca52e..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlextpiks.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -""" - some helper functions for high-level access to XML structures - - this implementation uses piksemel, a fast C-based XML library - - function names are mixedCase for compatibility with minidom, - an old library -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -from piksemel import * - -class XmlError(pisi.Error): - "named this way because the class if mostly used with an import *" - pass - -def getNodeAttribute(node, attrname): - """get named attribute from DOM node""" - return node.getAttribute(attrname) - -def getChildElts(node): - """get only child elements""" - return [x for x in parent.childNodes if x.type() == TAG ] - -def getTagByName(parent, childName): - return [x for x in parent if x.type() == TAG and x.name() == childName] - -def getNodeText(node, tagpath = ""): - """get the first child and expect it to be text!""" - if tagpath!="": - node = getNode(node, tagpath) - try: - child = node.firstChild() - except IndexError: - return None - except AttributeError: # no node by that name - return None - if child.type() == CDATA: #FIXME: ??? TEXT type? - # in any case, strip whitespaces... :/ you don't like it? - return child.data().strip() - else: - raise XmlError(_("getNodeText: Expected text node, got something else!")) - -def getChildText(node_s, tagpath): - """get the text of a child at the end of a tag path""" - node = getNode(node_s, tagpath) - if not node: - return None - return getNodeText(node) - -def getNode(node, tagpath): - """returns the *first* matching node for given tag path.""" - - assert type(tagpath)==str - tags = tagpath.split('/') - assert len(tags)>0 - - # iterative code to search for the path - for tag in tags: - currentNode = None - for child in node.tags(): - if child.name() == tag: - currentNode = child - break - if not currentNode: - return None - else: - node = currentNode - return currentNode - -def getAllNodes(node, tagPath): - """retrieve all nodes that match a given tag path.""" - - #FIXME: better tag split - tags = tagPath.split('/') - - if len(tags) == 0: - return [] - - nodeList = [node] # basis case - - for tag in tags: - results = map(lambda x: getTagByName(x, tag), nodeList) - nodeList = [] - for x in results: - nodeList.extend(x) - pass # emacs indentation error, keep it here - - if len(nodeList) == 0: - return [] - - return nodeList - -def createTagPath(node, tags): - """create new child at the end of a tag chain starting from node - no matter what""" - if len(tags)==0: - return node - for tag in tags: - node = node.appendTag(tag) - return node - -def addTagPath(node, tags, newnode=None): - """add newnode at the end of a tag chain, smart one""" - node = createTagPath(node, tags) - if newnode: # node to add specified - node.appendTag(newnode) - return node - -def addNode(node, tagpath, newnode = None, branch=True): - """add a new node at the end of the tree and returns it - if newnode is given adds that node, too.""" - - assert type(tagpath)==str - tags = [] - if tagpath != "": - tags = tagpath.split('/') # tag chain - else: - addTagPath(node, [], newnode) - return node #FIXME: is this correct!?!? - - assert len(tags)>0 # we want a chain - - # iterative code to search for the path - - if branch: - rem = 1 - else: - rem = 0 - - while len(tags) > rem: - tag = tags.pop(0) - nodeList = getTagByName(node, tag) - if len(nodeList) == 0: # couldn't find - tags.insert(0, tag) # put it back in - return addTagPath(node, tags, newnode) - else: - node = nodeList[len(nodeList)-1] # discard other matches - else: - # had only one tag.. - return addTagPath(node, tags, newnode) - - return node - -def addText(node, tagPath, text, branch = True): - node = addNode(node, tagPath, branch = branch) - return node.appendData(text) - - -# cannot be implemented with piksemel -#def newNode(node, tag): -# return Node(tag) - -# cannot be implemented with piksemel :( -#def newTextNode(node, text): -# return Node(text) diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlfile.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlfile.py deleted file mode 100644 index 529018c9..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlfile.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural - -try: - horagata # comment out to disable piks - #from xmlfilepiks import * -except: - try: - from xmlfilecdom import * - except: - print 'xmlext: cDomlette/piksemel implementation cannot be loaded, falling back to minidom' - from xmlfilemdom import * diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlfilecdom.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlfilecdom.py deleted file mode 100644 index 8805534d..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlfilecdom.py +++ /dev/null @@ -1,168 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -""" - XmlFile class further abstracts a dom object using the - high-level dom functions provided in xmlext module (and sorely lacking - in xml.dom :( ) - - function names are mixedCase for compatibility with minidom, - an 'old library' - - this implementation uses cDomlette from 4suite.org - adapted from the minidom implementation by Faik Uygur and fixed by Eray -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import codecs -import exceptions - -import Ft -from Ft.Xml.Domlette import implementation -from Ft.Xml.Domlette import NonvalidatingReader -from Ft.Xml import Parse, ParsePath -from Ft.Xml.Domlette import Print, PrettyPrint -from xml.dom import XHTML_NAMESPACE, XML_NAMESPACE - -XHTML_NS = unicode(XHTML_NAMESPACE) -XML_NS = unicode(XML_NAMESPACE) - -import pisi -from pisi.pxml.xmlextcdom import * - -class Error(pisi.Error): - pass - -class XmlFile(object): - """A class to help reading and writing an XML file""" - - def __init__(self, tag): - self.rootTag = tag - - def newDocument(self): - """clear DOM""" - self.doc = implementation.createDocument(None, self.rootTag, None) - - def unlink(self): - """deallocate DOM structure""" - del self.doc - - def rootNode(self): - """returns root document element""" - return self.doc.documentElement - - def readxml(self, path): - try: - self.doc = ParsePath(path) - return self.doc.documentElement - except Ft.FtException, e: - raise Error(_("File '%s' has invalid XML: %s") % (path, str(e)) ) - except exceptions.ValueError, e: - raise Error(_("File '%s' not found") % path ) - - def writexml(self, path): - f = file(path, 'w') - PrettyPrint(self.rootNode(), stream = f) - f.close() - - def verifyRootTag(self): - actual_roottag = self.rootNode().tagName - if actual_roottag != self.rootTag: - raise Error(_("Root tagname %s not identical to %s as expected") % - (actual_roottag, self.rootTag) ) - - # construction helpers - - def newNode(self, tag): - return self.doc.createElementNS(None, tag) - - def newTextNode(self, text): - return self.doc.createTextNode(text) - - def newAttribute(self, attr): - return self.doc.createAttribute(attr) - - # read helpers - - def getNode(self, tagPath = ""): - """returns the *first* matching node for given tag path.""" - self.verifyRootTag() - return getNode(self.doc.documentElement, tagPath) - - def getNodeText(self, tagPath): - """returns the text of *first* matching node for given tag path.""" - node = self.getNode(tagPath) - if not node: - return None - return getNodeText(node) - - def getAllNodes(self, tagPath): - """returns all nodes matching a given tag path.""" - self.verifyRootTag() - return getAllNodes(self.doc.documentElement, tagPath) - - def getChildren(self, tagpath): - """ returns the children of the given path""" - node = self.getNode(tagpath) - return node.childNodes - - # get only elements of a given type - #FIXME: this doesn't work - def getChildrenWithType(self, tagpath, type): - """ returns the children of the given path, only with given type """ - node = self.getNode(tagpath) - return filter(lambda x:x.nodeType == type, node.childNodes) - - # get only child elements - def getChildElts(self, tagpath): - """ returns the children of the given path, only with given type """ - node = self.getNode(tagpath) - try: - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, - node.childNodes) - except AttributeError: - return None - - # write helpers - - def addNode(self, tagPath, newnode = None): - "this adds the newnode under given tag path" - self.verifyRootTag() - return addNode(self.doc.documentElement, tagPath, newnode) - - def addNodeUnder(self, node, tagPath, newnode = None): - "this adds the new stuff under node and then following tag path" - self.verifyRootTag() - return addNode(node, tagPath, newnode) - - def addChild(self, newnode): - "add a new child node right under root element document" - self.doc.documentElement.appendChild(newnode) - - def addText(self, node, text): - "add text to node" - node.appendChild(self.newTextNode(text)) - - def addTextNode(self, tagPath, text): - "add a text node with given tag path" - node = self.addNode(tagPath, self.newTextNode(text)) - return node - - def addTextNodeUnder(self, node, tagPath, text): - "add a text node under given node with tag path (phew)" - return self.addNodeUnder(node, tagPath, self.newTextNode(text)) diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlfilemdom.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlfilemdom.py deleted file mode 100644 index bd91e702..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlfilemdom.py +++ /dev/null @@ -1,159 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -""" - XmlFile class further abstracts a dom object using the - high-level dom functions provided in xmlext module (and sorely lacking - in xml.dom :( ) - - function names are mixedCase for compatibility with minidom, - an 'old library' - - note: this is a particularly inefficient implementation of xmlfile -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import xml.dom.minidom as mdom -from xml.parsers.expat import ExpatError -import codecs - -import pisi -from pisi.pxml.xmlextcdom import * - -class Error(pisi.Error): - "named this way because the class if mostly used with an import *" - pass - -class XmlFile(object): - """A class to help reading and writing an XML file""" - - def __init__(self, tag): - self.rootTag = tag - - def newDocument(self): - """clear DOM""" - impl = mdom.getDOMImplementation() - self.doc = impl.createDocument(None, self.rootTag, None) - - def unlink(self): - """deallocate DOM structure""" - self.doc.unlink() - del self.doc - - def rootNode(self): - """returns root document element""" - return self.doc.documentElement - - def readxml(self, fileName): - try: - self.doc = mdom.parse(fileName) - except ExpatError, inst: - raise Error(_("File '%s' has invalid XML: %s\n") % (fileName, - str(inst))) - - def writexml(self, fileName): - f = codecs.open(fileName,'w', "utf-8") - f.write(self.doc.toprettyxml()) - f.close() - - def verifyRootTag(self): - actual_roottag = self.rootNode().tagName - if actual_roottag != self.rootTag: - raise Error(_("Root tagname %s not identical to %s as expected") % - (actual_roottag, self.rootTag) ) - - # construction helpers - - def newNode(self, tag): - return self.doc.createElement(tag) - - def newTextNode(self, text): - return self.doc.createTextNode(text) - - def newAttribute(self, attr): - return self.doc.createAttribute(attr) - - # read helpers - - def getNode(self, tagPath = ""): - """returns the *first* matching node for given tag path.""" - self.verifyRootTag() - return getNode(self.doc.documentElement, tagPath) - - def getNodeText(self, tagPath): - """returns the text of *first* matching node for given tag path.""" - node = self.getNode(tagPath) - if not node: - return None - return getNodeText(node) - - def getAllNodes(self, tagPath): - """returns all nodes matching a given tag path.""" - self.verifyRootTag() - return getAllNodes(self.doc.documentElement, tagPath) - - def getChildren(self, tagpath): - """ returns the children of the given path""" - node = self.getNode(tagpath) - return node.childNodes - - # get only elements of a given type - #FIXME: this doesn't work - def getChildrenWithType(self, tagpath, type): - """ returns the children of the given path, only with given type """ - node = self.getNode(tagpath) - return filter(lambda x:x.nodeType == type, node.childNodes) - - # get only child elements - def getChildElts(self, tagpath): - """ returns the children of the given path, only with given type """ - node = self.getNode(tagpath) - try: - return filter(lambda x:x.nodeType == x.ELEMENT_NODE, - node.childNodes) - except AttributeError: - return None - - # write helpers - - def addNode(self, tagPath, newnode = None): - "this adds the newnode under given tag path" - self.verifyRootTag() - return addNode(self.doc.documentElement, tagPath, newnode) - - def addNodeUnder(self, node, tagPath, newnode = None): - "this adds the new stuff under node and then following tag path" - self.verifyRootTag() - return addNode(node, tagPath, newnode) - - def addChild(self, newnode): - "add a new child node right under root element document" - self.doc.documentElement.appendChild(newnode) - - def addText(self, node, text): - "add text to node" - node.appendChild(self.newTextNode(text)) - - def addTextNode(self, tagPath, text): - "add a text node with given tag path" - node = self.addNode(tagPath, self.newTextNode(text)) - return node - - def addTextNodeUnder(self, node, tagPath, text): - "add a text node under given node with tag path (phew)" - return self.addNodeUnder(node, tagPath, self.newTextNode(text)) diff --git a/tags/pisi-1.0_beta2/pisi/pxml/xmlfilepiks.py b/tags/pisi-1.0_beta2/pisi/pxml/xmlfilepiks.py deleted file mode 100644 index 9333e948..00000000 --- a/tags/pisi-1.0_beta2/pisi/pxml/xmlfilepiks.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Gurer Ozen -# Baris Metin -# Eray Ozkural - -# python standard library - -from os.path import join -from os import access, R_OK - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# pisi modules -import pisi -import pisi.util as util -import pisi.context as ctx -from pisi.archive import Archive -from pisi.uri import URI -from pisi.fetcher import fetch_url - -class Error(pisi.Error): - pass - -class SourceArchive: - """source archive. this is a class responsible for fetching - and unpacking a source archive""" - def __init__(self, bctx): - self.url = URI(bctx.spec.source.archive.uri) - self.archiveFile = join(ctx.config.archives_dir(), self.url.filename()) - self.archive = bctx.spec.source.archive - self.bctx = bctx - - def fetch(self, interactive=True): - if not self.is_cached(interactive): - if interactive: - progress = ctx.ui.Progress - else: - progress = None - fetch_url(self.url, ctx.config.archives_dir(), progress) - - def is_cached(self, interactive=True): - if not access(self.archiveFile, R_OK): - return False - - # check hash - if util.check_file_hash(self.archiveFile, self.archive.sha1sum): - if interactive: - ctx.ui.info(_('%s [cached]') % self.archive.name) - return True - - return False - - def unpack(self, clean_dir=True): - - # check archive file's integrity - if not util.check_file_hash(self.archiveFile, self.archive.sha1sum): - raise Error, _("unpack: check_file_hash failed") - - archive = Archive(self.archiveFile, self.archive.type) - archive.unpack(self.bctx.pkg_work_dir(), clean_dir) diff --git a/tags/pisi-1.0_beta2/pisi/sourcedb.py b/tags/pisi-1.0_beta2/pisi/sourcedb.py deleted file mode 100644 index d6ad53cf..00000000 --- a/tags/pisi-1.0_beta2/pisi/sourcedb.py +++ /dev/null @@ -1,74 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Author: Eray Ozkural - -""" -package source database -interface for update/query to local package repository -we basically store everything in sourceinfo class -yes, we are cheap -""" - -import bsddb.dbshelve as shelve -import os -import fcntl -from bsddb import db - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi.util as util -import pisi.context as ctx -import pisi.lockeddbshelve as shelve - -class SourceDB(object): - - def __init__(self): - self.d = shelve.LockedDBShelf('source') - - def close(self): - self.d.close() - - def has_source(self, name): - name = str(name) - return self.d.has_key(name) - - def get_source(self, name): - name = str(name) - return self.d[name] - - def add_source(self, source_info): - assert not source_info.errors() - name = str(source_info.name) - self.d[name] = source_info - - def remove_source(self, name): - name = str(name) - del self.d[name] - -sourcedb = None - -def init(): - global sourcedb - if sourcedb: - return sourcedb - - sourcedb = SourceDB() - return sourcedb - -def finalize(): - global sourcedb - if sourcedb: - sourcedb.close() - sourcedb = None - diff --git a/tags/pisi-1.0_beta2/pisi/sourcefetcher.py b/tags/pisi-1.0_beta2/pisi/sourcefetcher.py deleted file mode 100644 index e5ab333f..00000000 --- a/tags/pisi-1.0_beta2/pisi/sourcefetcher.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -from os.path import basename, dirname, join - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi.context as ctx -from pisi.uri import URI -from pisi.specfile import SpecFile - -class SourceFetcher(object): - def __init__(self, url, authInfo=None): - self.url = url - if authInfo: - self.url.set_auth_info(authInfo) - self.location = dirname(self.url.uri) - - pkgname = basename(dirname(self.url.path())) - self.dest = join(ctx.config.tmp_dir(), pkgname) - - def fetch_all(self): - # fetch pspec file - self.fetch() - pspec = join(self.dest, self.url.filename()) - self.spec = SpecFile() - self.spec.read(pspec) - - self.fetch_actionsfile() - self.fetch_patches() - self.fetch_comarfiles() - self.fetch_additionalFiles() - - return pspec - - def fetch_actionsfile(self): - actionsuri = join(self.location, ctx.const.actions_file) - self.url.uri = actionsuri - self.fetch() - - def fetch_patches(self): - spec = self.spec - for patch in spec.source.patches: - file_name = basename(patch.filename) - dir_name = dirname(patch.filename) - patchuri = join(self.location, - ctx.const.files_dir, dir_name, file_name) - self.url.uri = patchuri - target_dir = join(ctx.const.files_dir, dir_name) - self.fetch(target_dir) - - def fetch_comarfiles(self): - spec = self.spec - for package in spec.packages: - for pcomar in package.providesComar: - comaruri = join(self.location, - ctx.const.comar_dir, pcomar.script) - self.url.uri = comaruri - self.fetch(ctx.const.comar_dir) - - def fetch_additionalFiles(self): - spec = self.spec - for pkg in spec.packages: - for afile in pkg.additionalFiles: - file_name = basename(afile.filename) - dir_name = dirname(afile.filename) - afileuri = join(self.location, - ctx.const.files_dir, dir_name, file_name) - self.url.uri = afileuri - target_dir = join(ctx.const.files_dir, dir_name) - self.fetch(target_dir) - - def fetch(self, appendDest=""): - from fetcher import fetch_url - - ctx.ui.info(_("Fetching %s") % self.url.uri) - dest = join(self.dest, appendDest) - fetch_url(self.url, dest) - diff --git a/tags/pisi-1.0_beta2/pisi/specfile.py b/tags/pisi-1.0_beta2/pisi/specfile.py deleted file mode 100644 index d46c6531..00000000 --- a/tags/pisi-1.0_beta2/pisi/specfile.py +++ /dev/null @@ -1,270 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin - -""" - Specfile module is our handler for PSPEC files. PSPEC (PISI SPEC) - files are specification files for PISI source packages. This module - provides read and write routines for PSPEC files. -""" - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# standard python modules -from os.path import basename - -# pisi modules -from pisi.pxml.xmlfile import XmlFile -import pisi.pxml.autoxml as autoxml -import pisi.context as ctx -from pisi.dependency import Dependency -import pisi.dependency -import pisi.component as component -from pisi.util import Checks -import pisi.util as util - - -class Error(pisi.Error): - pass - -__metaclass__ = autoxml.autoxml - -class Packager: - - t_Name = [autoxml.Text, autoxml.mandatory] - t_Email = [autoxml.String, autoxml.mandatory] - - def __str__(self): - s = "%s <%s>" % (self.name, self.email) - return s - - -class AdditionalFile: - - s_Filename = [autoxml.String, autoxml.mandatory] - a_target = [autoxml.String, autoxml.mandatory] - a_permission = [autoxml.String, autoxml.optional] - - def __str__(self): - s = "%s -> %s " % (self.filename, self.target) - if self.permission: - s += '(%s)' % self.permission - return s - - -class Patch: - - s_Filename = [autoxml.String, autoxml.mandatory] - a_compressionType = [autoxml.String, autoxml.optional] - a_level = [autoxml.Integer, autoxml.optional] - a_target = [autoxml.String, autoxml.optional] - - #FIXME: what's the cleanest way to give a default value for reading level? - #def decode_hook(self, node, errs, where): - # if self.level == None: - # self.level = 0 - - def __str__(self): - s = self.filename - if self.compressionType: - s += ' (' + self.compressionType + ')' - if self.level: - s += ' level:' + self.level - if self.target: - s += ' target:' + self.target - return s - - -class Update: - - a_release = [autoxml.String, autoxml.mandatory] - t_Date = [autoxml.String, autoxml.mandatory] - t_Version = [autoxml.String, autoxml.mandatory] - t_Type = [autoxml.String, autoxml.optional] - - def __str__(self): - s = self.date - s += ", ver=" + self.version - s += ", rel=" + self.release - if self.type: - s += ", type=" + self.type - return s - - -class Path: - - s_Path = [autoxml.String, autoxml.mandatory] - a_fileType = [autoxml.String, autoxml.optional] - - def __str__(self): - s = self.path - s += ", type=" + self.fileType - return s - - -class ComarProvide: - - s_om = [autoxml.String, autoxml.mandatory] - a_script = [autoxml.String, autoxml.mandatory] - - def __str__(self): - # FIXME: descriptive enough? - s = self.script - s += ' (' + self.om + ')' - return s - - -class Archive: - - s_uri = [ autoxml.String, autoxml.mandatory ] - a_type =[ autoxml.String, autoxml.mandatory ] - a_sha1sum =[ autoxml.String, autoxml.mandatory ] - - def decode_hook(self, node, errs, where): - self.name = basename(self.uri) - - def __str__(self): - s = _('URI: %s, type: %s, sha1sum: %s') % (self.uri, self.type, self.sha1sum) - return s - - -class Source: - - t_Name = [autoxml.String, autoxml.mandatory] - t_Homepage = [autoxml.String, autoxml.optional] - t_Packager = [Packager, autoxml.mandatory] - t_Summary = [autoxml.LocalText, autoxml.mandatory] - t_Description = [autoxml.LocalText, autoxml.mandatory] - t_IsA = [ [autoxml.String], autoxml.mandatory] - t_PartOf = [autoxml.String, autoxml.optional] - t_Icon = [ autoxml.String, autoxml.optional] - t_License = [ [autoxml.String], autoxml.mandatory] - t_Archive = [Archive, autoxml.mandatory ] - t_Patches = [ [Patch], autoxml.optional] - t_BuildDependencies = [ [Dependency], autoxml.optional] - t_Version = [ autoxml.String, autoxml.optional] - t_Release = [ autoxml.String, autoxml.optional] - - -class Package: - - t_Name = [ autoxml.String, autoxml.mandatory ] - t_Summary = [ autoxml.LocalText, autoxml.optional ] - t_Description = [ autoxml.LocalText, autoxml.optional ] - t_IsA = [ [autoxml.String], autoxml.optional] - t_PartOf = [autoxml.String, autoxml.optional] - t_License = [ [autoxml.String], autoxml.optional] - t_Icon = [ autoxml.String, autoxml.optional] - t_PackageDependencies = [ [Dependency], autoxml.optional, "RuntimeDependencies/Dependency"] - t_ComponentDependencies = [ [autoxml.String], autoxml.optional, "RuntimeDependencies/Component"] - t_Files = [ [Path], autoxml.optional] - t_Conflicts = [ [autoxml.String], autoxml.optional, "Conflicts/Package"] - t_ProvidesComar = [ [ComarProvide], autoxml.optional, "Provides/COMAR"] - #t_RequiresComar = [ [autoxml.String], autoxml.mandatory, "Requires/COMAR"] - t_AdditionalFiles = [ [AdditionalFile], autoxml.optional] - t_History = [ [Update], autoxml.optional] - - def runtimeDependencies(self): - deps = self.packageDependencies - deps += [ ctx.componentdb.get_component[x].packages for x in self.componentDependencies ] - return deps - - def pkg_dir(self): - packageDir = self.name + '-' \ - + self.version + '-' \ - + self.release - - return util.join_path( ctx.config.lib_dir(), packageDir) - - def installable(self): - """calculate if pkg is installable currently""" - deps = self.runtimeDependencies() - return pisi.dependency.satisfies_dependencies(self.name, deps) - - def __str__(self): - s = _('Name: %s, version: %s, release: %s, build %s\n') % ( - self.name, self.version, self.release, self.build) - s += _('Summary: %s\n') % unicode(self.summary) - s += _('Description: %s\n') % unicode(self.description) - s += _('Component: %s\n') % unicode(self.partOf) - s += _('Provides: ') - for x in self.providesComar: - s += x.om - return s + '\n' - - -class SpecFile(XmlFile): - __metaclass__ = autoxml.autoxml #needed when we specify a superclass - - tag = "PISI" - - t_Source = [ Source, autoxml.mandatory] - t_Packages = [ [Package], autoxml.mandatory, "Package"] - t_History = [ [Update], autoxml.mandatory] - t_Components = [ [component.Component], autoxml.optional, "Component"] - - #we're not doing this with the init hook right now - #def init(self, tag = "PISI"): - #ignore tag - #autoxml.__init__(self, tag) - - def read_hook(self, errs): - """Read PSPEC file""" - self.merge_tags() - self.override_tags() - - def merge_tags(self): - """Merge tags from Source in Packages. Some tags in Packages merged - with the tags from Source. There is a more detailed - description in documents.""" - - # FIXME: copy only needed information - # no need to keep full history with comments in metadata.xml - self.source.history = self.history - - # To avoid tag duplication in PSPEC we need to get - # the last version and release information - # from the most recent History/Update. - if not self.source.version: - self.source.version = self.history[0].version - if not self.source.release: - self.source.release = self.history[0].release - - tmp = [] - for pkg in self.packages: - pkg.isA.extend(self.source.isA) - pkg.history = self.history - tmp.append(pkg) - self.packages = tmp - - def override_tags(self): - """Override tags from Source in Packages. Some tags in Packages - overrides the tags from Source. There is a more detailed - description in documents.""" - - tmp = [] - for pkg in self.packages: - if not pkg.summary: - pkg.summary = self.source.summary - if not pkg.description: - pkg.description = self.source.description - if not pkg.partOf: - pkg.partOf = self.source.partOf - if not pkg.license: - pkg.license = self.source.license - if not pkg.icon: - pkg.icon = self.source.icon - tmp.append(pkg) - self.packages = tmp diff --git a/tags/pisi-1.0_beta2/pisi/ui.py b/tags/pisi-1.0_beta2/pisi/ui.py deleted file mode 100644 index 7767646e..00000000 --- a/tags/pisi-1.0_beta2/pisi/ui.py +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# generic user interface -# -# Authors: Eray Ozkural -# A. Murat Eren - -import sys - -import pisi -import pisi.context as ctx - -installed, upgraded, removed, installing, removing = range(5) - -class UI(object): - "Abstract class for UI operations, derive from this." - - class Progress: - def __init__(self, totalsize, existsize = 0): - self.totalsize = totalsize - try: - self.percent = (existsize * 100) / totalsize - except: - self.percent = 0 - - def update(self, size): - if not self.totalsize: - return 100 - try: - self.percent = (size * 100) / self.totalsize - except: - self.percent = 0 - return self.percent - - def __init__(self, debuggy = False, verbose = False): - self.show_debug = debuggy - self.show_verbose = verbose - - def set_verbose(self, flag): - self.show_verbose = flag - - def set_debug(self, flag): - self.show_debug = flag - - def info(self, msg, verbose = False, noln = False): - "give an informative message" - pass - - def ack(self, msg): - "inform the user of an important event and wait for acknowledgement" - pass - - def debug(self, msg): - "show debugging info" - if self.show_debug: - self.info('DEBUG: ' + msg) - - def warning(self,msg): - "warn the user" - pass - - def error(self,msg): - "inform a (possibly fatal) error" - pass - - #FIXME: merge this with info, this just means "important message" - def action(self,msg): - "uh?" - pass - - def choose(self, msg, list): - "ask the user to choose from a list of alternatives" - pass - - def confirm(self, msg): - "ask a yes/no question" - pass - - def display_progress(self, pd): - "display progress" - pass - - def status(self, msg = None): - "set status, if not given clear it" - pass - - def notify(self, event, **keywords): - "notify UI of a significant event" - pass diff --git a/tags/pisi-1.0_beta2/pisi/uri.py b/tags/pisi-1.0_beta2/pisi/uri.py deleted file mode 100644 index 63baf2a8..00000000 --- a/tags/pisi-1.0_beta2/pisi/uri.py +++ /dev/null @@ -1,108 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Simplifies working with URLs, purl module provides common URL -# parsing and processing - -from urlparse import urlparse -from os.path import basename - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi.util as util - -class URI(object): - """URI class provides a URL parser and simplifies working with - URLs.""" - - def __init__(self, uri=None): - if uri: - self.set_uri(uri) - else: - self.__scheme = None - self.__location = None - self.__path = None - self.__filename = None - self.__params = None - self.__query = None - self.__fragment = None - self.__uri = None - - self.__authinfo = None - - def get_uri(self): - if self.__uri: - return self.__uri - return None - - def set_uri(self, uri): - # (scheme, location, path, params, query, fragment) - u = urlparse(uri, "file") - self.__scheme = u[0] - self.__location = u[1] - self.__path = u[2] - self.__filename = basename(self.__path) - self.__params = u[3] - self.__query = u[4] - self.__fragment = u[5] - - self.__uri = uri - - def is_local_file(self): - if self.scheme() == "file": - return True - else: - return False - - def is_remote_file(self): - return not self.is_local_file() - - def is_absolute_path(self): - return util.absolute_path(self.__path) - - def is_relative_path(self): - return not self.is_absolute_path() - - def set_auth_info(self, authTuple): - if not isinstance(authTuple, tuple): - raise Exception, _("setAuthInfo needs a tuple (user, pass)") - self.__authinfo = authTuple - - def auth_info(self): - return self.__authinfo - - def scheme(self): - return self.__scheme - - def location(self): - return self.__location - - def path(self): - return self.__path - - def filename(self): - return self.__filename - - def params(self): - return self.__params - - def query(self): - return self.__query - - def fragment(self): - return self.__fragment - - def __str__(self): - return self.get_uri() - - uri = property(get_uri, set_uri) diff --git a/tags/pisi-1.0_beta2/pisi/util.py b/tags/pisi-1.0_beta2/pisi/util.py deleted file mode 100644 index 2b736438..00000000 --- a/tags/pisi-1.0_beta2/pisi/util.py +++ /dev/null @@ -1,559 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -# misc. utility functions, including process and file utils - -# Authors: Eray Ozkural -# Baris Metin -# S. Caglar Onur -# A. Murat Eren - -# standard python modules -import os -import re -import sys -import sha -import shutil -import statvfs -import operator - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -# pisi modules -import pisi -import pisi.context as ctx - -class Error(pisi.Error): - pass - -class FileError(Error): - pass - - -######################### -# spec validation utility # -######################### - -class Checks: - def __init__(self): - self.list = [] - - def add(self, err): - self.list.append(err) - - def join(self, list): - self.list.extend(list) - - def has_tag(self, var, section, name): - if not var: - self.list.append(_("%s section should have a '%s' tag") % (section, name)) - - def has_error(): - return len(self.list)>0 - - def print_errors(list): - for x in list: - ctx.ui.error(x) - print_errors = staticmethod(print_errors) - -######################### -# string/list/functional# -######################### - -def every(pred, seq): - return reduce(operator.and_, map(pred, seq)) - -def any(pred, seq): - return reduce(operator.or_, map(pred, seq)) - -def unzip(seq): - return zip(*seq) - -def concat(l): - '''concatenate a list of lists''' - return reduce( operator.concat, l ) - -def strlist(l): - """concatenate string reps of l's elements""" - return "".join(map(lambda x: str(x) + ' ', l)) - -def multisplit(str, chars): - """ split str with any of chars""" - l = [str] - for c in chars: - l = concat(map(lambda x:x.split(c), l)) - return l - -def same(l): - '''check if all elements of a sequence are equal''' - if len(l)==0: - return True - else: - last = l.pop() - for x in l: - if x!=last: - return False - return True - -def prefix(a, b): - '''check if sequence a is a prefix of sequence b''' - if len(a)>len(b): - return False - for i in range(0,len(a)): - if a[i]!=b[i]: - return False - return True - -def remove_prefix(a,b): - "remove prefix a from sequence b" - assert prefix(a,b) - return b[len(a):] - - -############################## -# Process Releated Functions # -############################## - -def run_batch(cmd): - """run command non-interactively and report return value and output""" - ctx.ui.info(_('running ') + cmd) - a = os.popen(cmd) - lines = a.readlines() - ret = a.close() - ctx.ui.debug(_('return value %s') % ret) - successful = ret == None - if not successful: - ctx.ui.error(_('Failed command: %s') % cmd + strlist(lines)) - return (successful,lines) - -def xterm_title(message): - """sets message as a console window's title""" - return - #TODO: the last thing needed in util probably - #this is going to be moved to pisi.cli later - if os.environ.has_key("TERM") and sys.stderr.isatty(): - terminalType = os.environ["TERM"] - for term in ["xterm", "Eterm", "aterm", "rxvt", "screen", "kterm", "rxvt-unicode"]: - if terminalType.startswith(term): - sys.stderr.write("\x1b]2;"+str(message)+"\x07") - sys.stderr.flush() - break - -def xterm_title_reset(): - """resets console window's title""" - #TODO: this, too. - if os.environ.has_key("TERM"): - terminalType = os.environ["TERM"] - xterm_title(os.environ["TERM"]) - -############################# -# Path Processing Functions # -############################# - -def splitpath(a): - """split path into components and return as a list - os.path.split doesn't do what I want like removing trailing /""" - comps = a.split(os.path.sep) - if comps[len(comps)-1]=='': - comps.pop() - return comps - -def makepath(comps, relative = False, sep = os.path.sep): - """reconstruct a path from components""" - path = reduce(lambda x,y: x + sep + y, comps, '') - if relative: - return path[len(sep):] - else: - return path - -# I'm not sure how necessary this is. Ahem. -def commonprefix(l): - """an improved version of os.path.commonprefix, - returns a list of path components""" - common = [] - comps = map(splitpath, l) - for i in range(0, min(len,l)): - compi = map(lambda x: x[i], comps) # get ith slice - if same(compi): - common.append(compi[0]) - return common - -# but this one is necessary -def subpath(a, b): - "find if path a is before b in the directory tree" - return prefix(splitpath(a), splitpath(b)) - -def removepathprefix(prefix, path): - "remove path prefix a from b, finding the pathname rooted at a" - comps = remove_prefix(splitpath(prefix), splitpath(path)) - if len(comps) > 0: - return join_path(*tuple(comps)) - else: - return "" - -def absolute_path(path): - "determine if given @path is absolute" - comps = splitpath(path) - return comps[0] == '' - -def join_path(a, *p): - """Join two or more pathname components, inserting '/' as needed""" - """The python original version has a silly logic""" - path = a - for b in p: - b = b.lstrip('/') - if path == '' or path.endswith('/'): - path += b - else: - path += '/' + b - return path - -#################################### -# File/Directory Related Functions # -#################################### - -def check_file(file, mode = os.F_OK): - "shorthand to check if a file exists" - if not os.access(file, mode): - raise FileError("File " + file + " not found") - return True - -def check_dir(dir): - """check if directory exists, and create if it doesn't. - works recursively""" - dir = dir.strip().rstrip("/") - if not os.access(dir, os.F_OK): - os.makedirs(dir) - -def clean_dir(path): - "Remove all content of a directory (top)" - # don't reimplement the wheel - if os.path.exists(path): - shutil.rmtree(path) - -def dir_size(dir): - """ calculate the size of files under a dir - based on the os module example""" - # It's really hard to give an approximate value for package's - # installed size. Gettin a sum of all files' sizes if far from - # being true. Using 'du' command (like Debian does) can be a - # better solution :(. - # Not really, du calculates size on disk, this is much better -- exa - from os.path import getsize, islink, isdir, exists - join = join_path - - if exists(dir) and (not isdir(dir) and not islink(dir)): - #so, this is not a directory but file.. - return getsize(dir) - - def sizes(): - for root, dirs, files in os.walk(dir): - yield sum([getsize(join(root, name)) for name in files if not islink(join(root,name))]) - return sum( sizes() ) - -def copy_file(src,dest): - """copy source file to destination file""" - check_file(src) - check_dir(os.path.dirname(dest)) - shutil.copyfile(src, dest) - -# FIXME: this should be done in a much much simpler way -# as it stands, it seems to be a kludge to solve -# an unrelated problem -def get_file_hashes(top, excludePrefix=None, removePrefix=None): - """Generator function iterates over a toplevel path and returns the - (filePath, sha1Hash) tuples for all files. If excludePrefixes list - is given as a parameter, function will exclude the filePaths - matching those prefixes. The removePrefix string parameter will be - used to remove prefix from filePath while matching excludes, if - given.""" - - def sha1_sum(f, data=False): - func = None - if data: - func = sha1_data - else: - func = sha1_file - - try: - return func(f) - except FileError, e: - if os.path.islink(f): - ctx.ui.info(_("Including external link '%s'") % f) - elif os.path.isdir(f): - ctx.ui.info(_("Including directory '%s'") % f) - else: - raise e - return None - - # also handle single files - if os.path.isfile(top): - yield (top, sha1_sum(top)) - return - - def has_excluded_prefix(filename): - if excludePrefix and removePrefix: - tempfnam = remove_prefix(removePrefix, filename) - for p in excludePrefix: - if tempfnam.startswith(p): - return 1 - return 0 - - for root, dirs, files in os.walk(top, topdown=False): - #bug 339 - if os.path.islink(root) and not has_excluded_prefix(root): - #yield the symlink.. - #bug 373 - yield (root, sha1_sum(os.readlink(root), True)) - excludePrefix.append(remove_prefix(removePrefix, root) + "/") - continue - - #bug 397 - for dir in dirs: - d = join_path(root, dir) - if os.path.islink(d) and not has_excluded_prefix(d): - yield (d, sha1_sum(os.readlink(d), True)) - excludePrefix.append(remove_prefix(removePrefix, d) + "/") - - #bug 340 - if os.path.isdir(root) and not has_excluded_prefix(root): - parent, r, d, f = root, '', '', '' - for r, d, f in os.walk(parent, topdown=False): pass - if not f and not d: - yield (parent, sha1_sum(parent)) - - for fname in files: - f = join_path(root, fname) - if has_excluded_prefix(f): - continue - #bug 373 - elif os.path.islink(f): - yield (f, sha1_sum(os.readlink(f), True)) - else: - yield (f, sha1_sum(f)) - -def copy_dir(src, dest): - """copy source dir to destination dir recursively""" - shutil.copytree(src, dest) - -def check_file_hash(filename, hash): - """Check the files integrity with a given hash""" - if sha1_file(filename) == hash: - return True - - return False - -def sha1_file(filename): - """calculate sha1 hash of filename""" - # Broken links can cause problem! - try: - m = sha.new() - f = file(filename, 'rb') - for line in f: - m.update(line) - return m.hexdigest() - except IOError: - raise FileError(_("I/O Error: Cannot calculate SHA1 hash of %s") % filename) - -def sha1_data(data): - """calculate sha1 hash of given data""" - try: - m = sha.new() - m.update(data) - return m.hexdigest() - except: - raise Error(_("Cannot calculate SHA1 hash of given data")) - -def uncompress(patchFile, compressType="gz", targetDir=None): - """uncompresses a file and returns the path of the uncompressed - file""" - if targetDir: - filePath = join_path(targetDir, - os.path.basename(patchFile)) - else: - filePath = os.path.basename(patchFile) - - if compressType == "gz": - from gzip import GzipFile - obj = GzipFile(patchFile) - elif compressType == "bz2": - from bz2 import BZ2File - obj = BZ2File(patchFile) - - open(filePath, "w").write(obj.read()) - return filePath - - -def do_patch(sourceDir, patchFile, level = 0, target = ''): - """simple function to apply patches..""" - cwd = os.getcwd() - os.chdir(sourceDir) - - if level == None: - level = 0 - if target == None: - target = '' - - check_file(patchFile) - (successful, lines) = run_batch("patch -p%d %s< %s" % - (level, target, patchFile)) - if not successful: - raise Error(_("ERROR: patch (%s) failed: %s") % (patchFile, - strlist (lines))) - - os.chdir(cwd) - - -def strip_directory(top, excludelist=[]): - for root, dirs, files in os.walk(top): - for fn in files: - frpath = join_path(root, fn) - - # Some upstream sources have buggy libtool and ltmain.sh with them, - # which causes wrong path entries in *.la files. And these wrong path - # entries sometimes triggers compile-time errors or linkage problems. - # Instead of patching all these buggy sources and maintain these patches, - # PISI removes wrong paths... - extension = os.path.splitext(frpath)[1] - if extension == ".la": - # FIXME: I'm regular expr. idiot, so one can convert this to python... - os.system("sed -i -e 's~-L/var/tmp/pisi/[[:graph:]]* ~~g' %s" % frpath) - - # real path in .pisi package - p = '/' + removepathprefix(top, frpath) - strip = True - for exclude in excludelist: - if p.startswith(exclude): - strip = False - ctx.ui.debug("%s [%s]" %(p, "NoStrip")) - - if strip: - if strip_file(frpath): - ctx.ui.debug("%s [%s]" %(p, "stripped")) - - -def strip_file(filepath): - """strip a file""" - p = os.popen("file \"%s\"" % filepath) - o = p.read() - - def run_strip(f, flags=""): - p = os.popen("strip %s %s" %(flags, f)) - ret = p.close() - if ret: - ctx.ui.warning(_("strip command failed for file '%s'!") % f) - - if "current ar archive" in o: - run_strip(filepath, "-g") - return True - - elif "SB executable" in o: - run_strip(filepath) - return True - - elif "SB shared object" in o: - run_strip(filepath, "--strip-unneeded") - # FIXME: warn for TEXTREL - return True - - return False - -def partition_freespace(directory): - """ returns free space of given directory's partition """ - st = os.statvfs(directory) - return st[statvfs.F_BSIZE] * st[statvfs.F_BFREE] - -def clean_locks(top = '.'): - for root, dirs, files in os.walk(top): - for fn in files: - if fn.endswith('.lock'): - path = join_path(root, fn) - ctx.ui.info(_('Removing lock %s'), path) - os.unlink(path) - -######################################## -# Package/Repository Related Functions # -######################################## - -def package_name(name, version, release, build, prependSuffix=True): - fn = name + '-' + version + '-' + release - if build: - fn += '-' + str(build) - if prependSuffix: - fn += ctx.const.package_suffix - return fn - -def is_package_name(fn, package_name = None): - "check if fn is a valid filename for given package_name" - "if not given a package name, see if fn fits the package name rules" - if (package_name==None) or fn.startswith(package_name + '-'): - if fn.endswith(ctx.const.package_suffix): - # get version string, skip separator '-' - verstr = fn[len(package_name) + 1: - len(fn)-len(ctx.const.package_suffix)] - import string - for x in verstr.split('-'): - # weak rule: version components after '-' start with a digit - if x is '' or (not x[0] in string.digits): - return False - return True - return False - -def env_update(): - - ctx.ui.info(_('Updating environment...')) - env_dir = join_path(ctx.config.dest_dir(), "/etc/env.d") - profile_file = join_path(ctx.config.dest_dir(), "/etc/profile.env") - ldconf_file = join_path(ctx.config.dest_dir(), "/etc/ld.so.conf") - - if not os.path.exists(env_dir): - os.makedirs(env_dir, 0755) - - list = [] - for file in os.listdir(env_dir): - if not os.path.isdir(join_path(env_dir, file)): - list.append(file) - - list.sort() - - keys = {} - for file in list: - f = open(join_path(env_dir, file), "r") - for line in f: - if not re.search("^#", line.strip()): - currentLine = line.strip().split("=") - - try: - if keys.has_key(currentLine[0]): - keys[currentLine[0]] += ":" + currentLine[1].replace("\"", "") - else: - keys[currentLine[0]] = currentLine[1].replace("\"", "") - except IndexError: - pass - - # generate profile.env - f = open(profile_file, "w") - for key in keys: - f.write("export %s=\"%s\"\n" % (key, keys[key])) - f.close() - - # generate ld.so.conf - f = open(ldconf_file, "w") - if keys.has_key("LDPATH"): - for path in keys["LDPATH"].split(":"): - f.write("%s\n" % path) - f.close() - - # run ldconfig - run_batch("/sbin/ldconfig -X -r %s" % ctx.config.dest_dir()) diff --git a/tags/pisi-1.0_beta2/pisi/version.py b/tags/pisi-1.0_beta2/pisi/version.py deleted file mode 100644 index 785fc6a4..00000000 --- a/tags/pisi-1.0_beta2/pisi/version.py +++ /dev/null @@ -1,193 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: Eray Ozkural -# Baris Metin -# -# History: -# Eray wrote the first version -# Baris added support for the fancy keywords and -# alphanumeric version string components - - -"""version structure""" - - -import re -import string - -import pisi.util as util - - -# Basic rule is: -# p > (no suffix) > rc > pre > beta > alpha -keywords = {"alpha": 0, - "beta" : 1, - "pre" : 2, - "rc" : 3, - "NOKEY" : 4, - "p" : 5} - -# helper functions -def has_keyword(versionitem): - if versionitem._keyword != "NOKEY": - return True - - return False - - -class VersionItem: - _keyword = "NOKEY" - _value = 0 - - def __init__(self, itemstring): - - # special-case: 1.5p - # here "p" comes as a separate itemstring and conflicts with - # keyword "p". But keyword should allways contain an integer prefix. - # So, skipping looking for keywords if the length() is 1 makes the - # trick. - if len(itemstring) > 1: - - for keyword in keywords.keys(): - if itemstring.startswith(keyword): - - if self._keyword == "NOKEY": - self._keyword = keyword - else: - # longer match is correct - if len(keyword) > len(self._keyword): - self._keyword = keyword - - if self._keyword == "NOKEY": - if len(itemstring) == 1 and itemstring in string.ascii_letters: - # single letter version item ('a' to 'Z') - self._value = itemstring - else: - self._value = int(itemstring) - else: - # rest is the version item's value. And each must have - # one! - self._value = int(itemstring[len(self._keyword):]) - - def __str__(self): - return str(self._value) - - def __lt__(self,rhs): - l = keywords[self._keyword] - r = keywords[rhs._keyword] - if l < r: - return True - elif l == r: - return self._value < rhs._value - else: # l > r - return False - - def __le__(self,rhs): - l = keywords[self._keyword] - r = keywords[rhs._keyword] - if l < r: - return True - elif l == r: - return self._value <= rhs._value - else: # l > r - return False - - def __gt__(self,rhs): - l = keywords[self._keyword] - r = keywords[rhs._keyword] - if l > r: - return True - elif l == r: - return self._value > rhs._value - else: # l < r - return False - - def __ge__(self,rhs): - l = keywords[self._keyword] - r = keywords[rhs._keyword] - if l > r: - return True - elif l == r: - return self._value >= rhs._value - else: # l < r - return False - - def __eq__(self,rhs): - l = keywords[self._keyword] - r = keywords[rhs._keyword] - if l == r and self._value == rhs._value: - return True - return False - - - -class Version: - - def __init__(self, verstring): - self.comps = [] - for i in util.multisplit(verstring,'.-_'): - # some version strings can contain ascii chars at the - # back. As an example: 2.11a - # We split '11a' as two items like '11' and 'a' - s = re.compile("[a-z-A-Z]$").search(i) - if s: - head = i[:s.start()] - tail = s.group() - self.comps.append(VersionItem(head)) - self.comps.append(VersionItem(tail)) - else: - self.comps.append(VersionItem(i)) - - self.verstring = verstring - - def string(self): - return self.verstring - - def compare(self, rhs): - """this comparison routine is essentially a comparison routine - for two rationals in (0,1) interval. we compare two sequences - of digits one by one. We start with the leftmost digit - in the expansion. If they are equal, we proceed to the next. If - not we use the comparison operator. And we iterate to the left. - The result is, 0 if two are equal, -1 if self < rhs, and +1 - if self>rhs""" - lhs = self.comps - rhs = rhs.comps - # pad the short version string with zeros - if len(lhs) < len(rhs): - lhs.extend( [VersionItem('0')] * (len(rhs) - len(lhs)) ) - elif len(lhs) > len(rhs): - rhs.extend( [VersionItem('0')] * (len(lhs) - len(rhs)) ) - # now let's iterate from left to right - for (litem, ritem) in zip(lhs, rhs): - if litem < ritem: - return -1 - elif litem > ritem: - return +1 - return 0 - - # premature optimization is the root of all evil - - def __lt__(self,rhs): - return self.compare(rhs) < 0 - - def __le__(self,rhs): - return self.compare(rhs) <= 0 - - def __gt__(self,rhs): - return self.compare(rhs) > 0 - - def __ge__(self,rhs): - return self.compare(rhs) >= 0 - - def __eq__(self,rhs): - return self.compare(rhs) == 0 diff --git a/tags/pisi-1.0_beta2/po/pisi.pot b/tags/pisi-1.0_beta2/po/pisi.pot deleted file mode 100644 index c0678d89..00000000 --- a/tags/pisi-1.0_beta2/po/pisi.pot +++ /dev/null @@ -1,1673 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR ORGANIZATION -# FIRST AUTHOR , YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2005-11-18 16:13+EET\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: ENCODING\n" -"Generated-By: pygettext.py 1.5\n" - - -#: pisi-cli:31 -msgid "Keyboard Interrupt: Exiting..." -msgstr "" - -#: pisi-cli:34 -msgid "Fatal Error. Program Terminated." -msgstr "" - -#: pisi-cli:38 -msgid "" -"\n" -"Unhandled internal exception.\n" -"Please file a bug report. (http://bugs.uludag.org.tr)" -msgstr "" - -#: pisi-cli:45 -msgid "System Error. Program Terminated." -msgstr "" - -#: pisi-cli:49 -msgid "Please use 'pisi help' for general help." -msgstr "" - -#: pisi-cli:52 -msgid "Traceback:" -msgstr "" - -#: pisi-cli:55 -msgid "Use --debug to see a traceback." -msgstr "" - -#: pisi/actionsapi/autotools.py:36 -msgid "" -"Please attach the config.log to your bug report:\n" -"%s/config.log" -msgstr "" - -#: pisi/actionsapi/autotools.py:75 pisi/actionsapi/autotools.py:85 -#: pisi/actionsapi/kde.py:66 pisi/actionsapi/perlmodules.py:53 -#: pisi/actionsapi/perlmodules.py:56 -msgid "Configure failed." -msgstr "" - -#: pisi/actionsapi/autotools.py:77 pisi/actionsapi/autotools.py:87 -#: pisi/actionsapi/kde.py:68 -msgid "No configure script found." -msgstr "" - -#: pisi/actionsapi/autotools.py:96 pisi/actionsapi/kde.py:73 -#: pisi/actionsapi/perlmodules.py:62 pisi/actionsapi/perlmodules.py:71 -#: pisi/actionsapi/pythonmodules.py:50 pisi/actionsapi/scons.py:40 -msgid "Make failed." -msgstr "" - -#: pisi/actionsapi/autotools.py:119 pisi/actionsapi/autotools.py:127 -#: pisi/actionsapi/kde.py:80 pisi/actionsapi/pythonmodules.py:55 -#: pisi/actionsapi/scons.py:44 -msgid "Install failed." -msgstr "" - -#: pisi/actionsapi/autotools.py:121 pisi/actionsapi/autotools.py:129 -#: pisi/actionsapi/kde.py:82 -msgid "No Makefile found." -msgstr "" - -#: pisi/actionsapi/autotools.py:134 -msgid "Running aclocal failed." -msgstr "" - -#: pisi/actionsapi/autotools.py:139 pisi/actionsapi/autotools.py:144 -msgid "Running autoconf failed." -msgstr "" - -#: pisi/actionsapi/autotools.py:149 -msgid "Running automake failed." -msgstr "" - -#: pisi/actionsapi/autotools.py:154 -msgid "Running autoheader failed." -msgstr "" - -#: pisi/actionsapi/get.py:159 -msgid "Util %s cannot be found" -msgstr "" - -#: pisi/actionsapi/get.py:161 -msgid "Warning: %s does not exist, using plain name %s" -msgstr "" - -#: pisi/actionsapi/kde.py:35 -msgid "" -"\n" -"!!! Please attach the config.log to your bug report:\n" -"%s/config.log" -msgstr "" - -#: pisi/actionsapi/libtools.py:39 -msgid "Running ldconfig failed." -msgstr "" - -#: pisi/actionsapi/libtools.py:50 -msgid "GNU Config Update Finished." -msgstr "" - -#: pisi/actionsapi/libtools.py:54 -msgid "Running libtoolize failed." -msgstr "" - -#: pisi/actionsapi/perlmodules.py:65 -msgid "perl build failed." -msgstr "" - -#: pisi/actionsapi/perlmodules.py:74 -msgid "perl install failed." -msgstr "" - -#: pisi/actionsapi/pisitools.py:132 -msgid "ActionsAPI [doman]: Wrong man page file: %s" -msgstr "" - -#: pisi/actionsapi/pisitools.py:170 -msgid "ActionsAPI [rename]: No such file or directory: %s" -msgstr "" - -#: pisi/actionsapi/pisitools.py:187 -msgid "File does not exist or permission denied: %s" -msgstr "" - -#: pisi/actionsapi/pisitools.py:204 -msgid "ActionsAPI [dosym]: File exists: %s" -msgstr "" - -#: pisi/actionsapi/pisitoolsfunctions.py:46 -#: pisi/actionsapi/pisitoolsfunctions.py:60 -#: pisi/actionsapi/pisitoolsfunctions.py:73 -msgid "Insufficient arguments." -msgstr "" - -#: pisi/actionsapi/pythonmodules.py:67 -msgid "Running %s failed." -msgstr "" - -#: pisi/actionsapi/shelltools.py:47 -msgid "Cannot create directory %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:55 -msgid "ActionsAPI [echo]: Can't append to file %s." -msgstr "" - -#: pisi/actionsapi/shelltools.py:64 -msgid "ActionsAPI [chmod]: Operation not permitted: %s (mode: %s)" -msgstr "" - -#: pisi/actionsapi/shelltools.py:67 -msgid "ActionsAPI [chmod]: File %s doesn't exists." -msgstr "" - -#: pisi/actionsapi/shelltools.py:75 -msgid "ActionsAPI [chown]: Operation not permitted: %s (uid: %s, gid: %s)" -msgstr "" - -#: pisi/actionsapi/shelltools.py:78 -msgid "ActionsAPI [chown]: File %s doesn't exists." -msgstr "" - -#: pisi/actionsapi/shelltools.py:85 -msgid "ActionsAPI [sym]: Permission denied: %s to %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:93 -msgid "ActionsAPI [unlink]: Permission denied: %s." -msgstr "" - -#: pisi/actionsapi/shelltools.py:97 -msgid "ActionsAPI [unlink]: File %s doesn't exists." -msgstr "" - -#: pisi/actionsapi/shelltools.py:105 -msgid "ActionsAPI [unlinkDir]: Operation not permitted: %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:109 -msgid "ActionsAPI [unlinkDir]: Directory %s doesn't exists." -msgstr "" - -#: pisi/actionsapi/shelltools.py:118 -msgid "ActionsAPI [move]: Permission denied: %s to %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:120 -msgid "ActionsAPI [move]: File %s doesn't exists." -msgstr "" - -#: pisi/actionsapi/shelltools.py:129 -msgid "ActionsAPI [copy]: Permission denied: %s to %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:133 -msgid "ActionsAPI [copy]: File %s does not exist." -msgstr "" - -#: pisi/actionsapi/shelltools.py:141 -msgid "ActionsAPI [copytree] %s to %s: %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:143 -msgid "ActionsAPI [copytree]: Directory %s doesn't exists." -msgstr "" - -#: pisi/actionsapi/shelltools.py:155 -msgid "ActionsAPI [touch]: Permission denied: %s" -msgstr "" - -#: pisi/actionsapi/shelltools.py:204 -msgid "executing %s" -msgstr "" - -#: pisi/api.py:194 pisi/comariface.py:33 -msgid "COMAR: comard not fully installed" -msgstr "" - -#: pisi/api.py:206 -msgid "File %s not found" -msgstr "" - -#: pisi/api.py:228 -msgid "Package %s not found" -msgstr "" - -#: pisi/api.py:235 -msgid "* Building index of PISI files under %s" -msgstr "" - -#: pisi/api.py:238 -msgid "* Index file written" -msgstr "" - -#: pisi/api.py:243 -msgid "Repo %s added to system." -msgstr "" - -#: pisi/api.py:248 -msgid "Repo %s removed from system." -msgstr "" - -#: pisi/api.py:250 -msgid "Repository %s does not exist. Cannot remove." -msgstr "" - -#: pisi/api.py:255 -msgid "* Updating repository: %s" -msgstr "" - -#: pisi/api.py:259 -msgid "" -"\n" -"* Package database updated." -msgstr "" - -#: pisi/archive.py:84 -msgid "Archive type not recognized" -msgstr "" - -#: pisi/atomicoperations.py:77 -msgid "Installing %s, version %s, release %s, build %s" -msgstr "" - -#: pisi/atomicoperations.py:110 -msgid "Package conflicts %s" -msgstr "" - -#: pisi/atomicoperations.py:115 -msgid "Dependencies for %s not satisfied" -msgstr "" - -#: pisi/atomicoperations.py:117 -msgid "Package not installable" -msgstr "" - -#: pisi/atomicoperations.py:148 -msgid "Re-install same version package?" -msgstr "" - -#: pisi/atomicoperations.py:149 -msgid "Package re-install declined" -msgstr "" - -#: pisi/atomicoperations.py:155 -msgid "Upgrading to new upstream version" -msgstr "" - -#: pisi/atomicoperations.py:158 -msgid "Upgrading to new distribution release" -msgstr "" - -#: pisi/atomicoperations.py:162 -msgid "Upgrading to new distribution build" -msgstr "" - -#: pisi/atomicoperations.py:169 -msgid "Downgrade to old upstream version?" -msgstr "" - -#: pisi/atomicoperations.py:171 -msgid "Downgrade to old distribution release?" -msgstr "" - -#: pisi/atomicoperations.py:173 -msgid "Downgrade to old distribution build?" -msgstr "" - -#: pisi/atomicoperations.py:175 -msgid "Package downgrade declined" -msgstr "" - -#: pisi/atomicoperations.py:187 -msgid "Extracting files" -msgstr "" - -#: pisi/atomicoperations.py:205 -msgid "Storing %s, " -msgstr "" - -#: pisi/atomicoperations.py:208 -msgid "Storing %s." -msgstr "" - -#: pisi/atomicoperations.py:215 -msgid "Storing %s" -msgstr "" - -#: pisi/atomicoperations.py:257 -msgid "Regenerating /etc/ld.so.cache..." -msgstr "" - -#: pisi/atomicoperations.py:260 -msgid "Bypassing ldconfig" -msgstr "" - -#: pisi/atomicoperations.py:294 -msgid "Package URI: %s" -msgstr "" - -#: pisi/atomicoperations.py:299 -msgid "Package %s not found in any active repository." -msgstr "" - -#: pisi/atomicoperations.py:314 -msgid "Removing package %s" -msgstr "" - -#: pisi/atomicoperations.py:316 -msgid "Trying to remove nonexistent package " -msgstr "" - -#: pisi/atomicoperations.py:353 -msgid "Not removing non-file, non-link %s" -msgstr "" - -#: pisi/atomicoperations.py:433 -msgid "Metadata XML '%s' cannot be found" -msgstr "" - -#: pisi/atomicoperations.py:441 -msgid "MetaData format wrong (%s)" -msgstr "" - -#: pisi/atomicoperations.py:453 -msgid "* Adding '%s' to db... " -msgstr "" - -#: pisi/atomicoperations.py:457 -msgid "Files XML '%s' cannot be found" -msgstr "" - -#: pisi/atomicoperations.py:463 pisi/package.py:111 -msgid "Invalid %s" -msgstr "" - -#: pisi/atomicoperations.py:468 -msgid "OK." -msgstr "" - -#: pisi/build.py:80 -msgid "Path %s belongs in multiple packages" -msgstr "" - -#: pisi/build.py:146 -msgid "Building PISI source package: %s" -msgstr "" - -#: pisi/build.py:147 -msgid "" -"Building PISI source package: %s\n" -msgstr "" - -#: pisi/build.py:188 -msgid "IceCream detected. Make sure your daemon is up and running..." -msgstr "" - -#: pisi/build.py:192 -msgid "CCache detected..." -msgstr "" - -#: pisi/build.py:196 -msgid "PartOf tag not defined, looking for component" -msgstr "" - -#: pisi/build.py:205 -msgid "Cannot find component.xml in upper directory" -msgstr "" - -#: pisi/build.py:209 -msgid "Source is part of %s component" -msgstr "" - -#: pisi/build.py:214 -msgid "Fetching source from: %s" -msgstr "" - -#: pisi/build.py:216 -msgid "Source archive is stored: %s/%s" -msgstr "" - -#: pisi/build.py:220 -msgid "Unpacking archive..." -msgstr "" - -#: pisi/build.py:222 -msgid " unpacked (%s)" -msgstr "" - -#: pisi/build.py:227 -msgid "Setting up source..." -msgstr "" - -#: pisi/build.py:232 -msgid "Building source..." -msgstr "" - -#: pisi/build.py:237 -msgid "Installing..." -msgstr "" - -#: pisi/build.py:256 -msgid "Unable to read Action Script (%s): %s" -msgstr "" - -#: pisi/build.py:258 -msgid "SyntaxError in Action Script (%s): %s" -msgstr "" - -#: pisi/build.py:288 -msgid "unable to call function from actions: %s" -msgstr "" - -#: pisi/build.py:302 -msgid "Safety switch: following extra packages in system.devel will be installed: " -msgstr "" - -#: pisi/build.py:307 -msgid "Safety switch: the component system.devel cannot be found" -msgstr "" - -#: pisi/build.py:316 -msgid "Unsatisfied Build Dependencies:" -msgstr "" - -#: pisi/build.py:321 -msgid "Do you want to install the unsatisfied build dependencies" -msgstr "" - -#: pisi/build.py:322 -msgid "Installing build dependencies." -msgstr "" - -#: pisi/build.py:325 -msgid "Cannot build package due to unsatisfied build dependencies" -msgstr "" - -#: pisi/build.py:327 -msgid "Ignoring build dependencies." -msgstr "" - -#: pisi/build.py:337 -msgid "" -"Patch file is missing: %s\n" -msgstr "" - -#: pisi/build.py:350 -msgid "* Applying patch: %s" -msgstr "" - -#: pisi/build.py:355 -msgid "Stripping files.." -msgstr "" - -#: pisi/build.py:385 -msgid "build number is not available." -msgstr "" - -#: pisi/build.py:461 -msgid "(no previous build found, setting build no to 1.)" -msgstr "" - -#: pisi/build.py:498 -msgid "(old package lacks a build no, setting build no to 0.)" -msgstr "" - -#: pisi/build.py:501 -msgid "There are changes, incrementing build no to %d" -msgstr "" - -#: pisi/build.py:504 -msgid "There is no change from previous build %d " -msgstr "" - -#: pisi/build.py:532 -msgid "Copying additional file: '%s' to '%s' as '%s'" -msgstr "" - -#: pisi/build.py:543 -msgid "** Building package %s" -msgstr "" - -#: pisi/build.py:545 pisi/build.py:548 -msgid "Generating %s," -msgstr "" - -#: pisi/build.py:551 -msgid "Creating PISI package %s." -msgstr "" - -#: pisi/build.py:584 -msgid "Done." -msgstr "" - -#: pisi/build.py:587 -msgid "Cleaning Build Directory..." -msgstr "" - -#: pisi/build.py:590 -msgid "Keeping Build Directory" -msgstr "" - -#: pisi/cli/__init__.py:75 -msgid "Warning: " -msgstr "" - -#: pisi/cli/__init__.py:81 -msgid "Error: " -msgstr "" - -#: pisi/cli/__init__.py:109 -msgid " (yes/no)" -msgstr "" - -#: pisi/cli/__init__.py:121 -msgid "" -" [complete]\n" -msgstr "" - -#: pisi/cli/__init__.py:129 -msgid "Installed %s" -msgstr "" - -#: pisi/cli/__init__.py:131 -msgid "Removed %s" -msgstr "" - -#: pisi/cli/__init__.py:133 -msgid "Upgraded %s" -msgstr "" - -#: pisi/cli/commands.py:33 -#, docstring -msgid "generic help string for any command" -msgstr "" - -#: pisi/cli/commands.py:55 pisi/cli/pisicli.py:101 -msgid "Unrecognized command: %s" -msgstr "" - -#: pisi/cli/commands.py:76 -#, docstring -msgid "common options" -msgstr "" - -#: pisi/cli/commands.py:79 -msgid "change the system root for pisi commands" -msgstr "" - -#: pisi/cli/commands.py:81 -msgid "assume yes in all yes/no queries" -msgstr "" - -#: pisi/cli/commands.py:85 -msgid "get password from the command line" -msgstr "" - -#: pisi/cli/commands.py:88 -msgid "detailed output" -msgstr "" - -#: pisi/cli/commands.py:90 -msgid "show debugging information" -msgstr "" - -#: pisi/cli/commands.py:95 -msgid "print like a man" -msgstr "" - -#: pisi/cli/commands.py:99 -#, docstring -msgid "" -"This is a fall back function. If the implementer module provides an\n" -" options function it will be called" -msgstr "" - -#: pisi/cli/commands.py:111 -msgid "" -"Destination directory %s does not exist. Creating directory.\n" -msgstr "" - -#: pisi/cli/commands.py:134 -msgid "Password: " -msgstr "" - -#: pisi/cli/commands.py:140 -#, docstring -msgid "initialize PiSi components" -msgstr "" - -#: pisi/cli/commands.py:148 -#, docstring -msgid "do cleanup work for PiSi components" -msgstr "" - -#: pisi/cli/commands.py:162 -#, docstring -msgid "print help for the command" -msgstr "" - -#: pisi/cli/commands.py:169 -#, docstring -msgid "exit program" -msgstr "" - -#: pisi/cli/commands.py:171 -msgid "Command terminated abnormally." -msgstr "" - -#: pisi/cli/commands.py:181 -msgid "Command lacks name" -msgstr "" - -#: pisi/cli/commands.py:185 -msgid "Duplicate command %s" -msgstr "" - -#: pisi/cli/commands.py:194 -#, docstring -msgid "" -"Prints help for given commands.\n" -"\n" -"Usage: help [ ... ]\n" -"\n" -"If run without parameters, it prints the general help." -msgstr "" - -#: pisi/cli/commands.py:227 -#, docstring -msgid "Clean stale locks." -msgstr "" - -#: pisi/cli/commands.py:243 -#, docstring -msgid "Delete cache files" -msgstr "" - -#: pisi/cli/commands.py:258 -#, docstring -msgid "" -"Graph package relations.\n" -"Usage: graph [ ...]\n" -"\n" -"Write a graph of package relations, tracking dependency and\n" -"conflicts relations starting from given packages.\n" -msgstr "" - -#: pisi/cli/commands.py:273 -msgid "graph all available packages" -msgstr "" - -#: pisi/cli/commands.py:276 -msgid "dot output file" -msgstr "" - -#: pisi/cli/commands.py:291 -msgid "Plotting a graph of relations among all available packages" -msgstr "" - -#: pisi/cli/commands.py:298 -msgid "Plotting a graph of relations among all installed packages" -msgstr "" - -#: pisi/cli/commands.py:309 -msgid "do not take build no into account." -msgstr "" - -#: pisi/cli/commands.py:315 -msgid "do not take dependency information into account" -msgstr "" - -#: pisi/cli/commands.py:319 -#, docstring -msgid "" -"Build a PISI package using a pspec.xml file\n" -"\n" -"Usage: build \n" -"\n" -"You can give a URI of the pspec.xml file. PISI will\n" -"fetch all necessary files and build the package for you.\n" -msgstr "" - -#: pisi/cli/commands.py:337 -msgid "output directory for produced packages" -msgstr "" - -#: pisi/cli/commands.py:340 -msgid "bypass errors from ActionsAPI" -msgstr "" - -#: pisi/cli/commands.py:356 -#, docstring -msgid "Abstract package operation command" -msgstr "" - -#: pisi/cli/commands.py:365 -msgid "bypass comar configuration agent" -msgstr "" - -#: pisi/cli/commands.py:367 -msgid "bypass safety switch" -msgstr "" - -#: pisi/cli/commands.py:379 -#, docstring -msgid "" -"Install PISI packages\n" -"\n" -"Usage: install ... \n" -"\n" -"You may use filenames, URIs or package names for packages. If you have\n" -"specified a package name, it should exist in a specified repository.\n" -"\n" -"You can also specify components instead of package names, which will be\n" -"expanded to package names.\n" -msgstr "" - -#: pisi/cli/commands.py:400 pisi/cli/commands.py:444 -msgid "Bypass ldconfig phase" -msgstr "" - -#: pisi/cli/commands.py:414 -#, docstring -msgid "" -"Upgrade PISI packages\n" -"\n" -"Usage: Upgrade [ ... ]\n" -"\n" -": package name\n" -"\n" -"Upgrades the entire system if no package names are given\n" -"\n" -"You may use only package names to specify packages because\n" -"the package upgrade operation is defined only with respect \n" -"to repositories. If you have specified a package name, it\n" -"should exist in the package repositories. If you just want to\n" -"reinstall a package from a pisi file, use the install command.\n" -"\n" -"You can also specify components instead of package names, which will be\n" -"expanded to package names.\n" -msgstr "" - -#: pisi/cli/commands.py:446 -msgid "eager upgrades" -msgstr "" - -#: pisi/cli/commands.py:461 -#, docstring -msgid "" -"Remove PISI packages\n" -"\n" -"Usage: remove ... \n" -"\n" -"Remove package(s) from your system. Just give the package names to remove.\n" -"\n" -"You can also specify components instead of package names, which will be\n" -"expanded to package names.\n" -msgstr "" - -#: pisi/cli/commands.py:488 -#, docstring -msgid "" -"configure pending packages\n" -" " -msgstr "" - -#: pisi/cli/commands.py:506 -#, docstring -msgid "" -"Display package information\n" -"\n" -"Usage: info ... \n" -"\n" -msgstr "" - -#: pisi/cli/commands.py:521 -msgid "show a list of package files." -msgstr "" - -#: pisi/cli/commands.py:524 -msgid "Show only paths." -msgstr "" - -#: pisi/cli/commands.py:547 -msgid "Reverse Dependencies:" -msgstr "" - -#: pisi/cli/commands.py:550 -msgid "" -"\n" -"Files:" -msgstr "" - -#: pisi/cli/commands.py:557 -msgid "File information not available" -msgstr "" - -#: pisi/cli/commands.py:561 -#, docstring -msgid "" -"Index PISI files in a given directory\n" -"\n" -"Usage: index \n" -"\n" -"This command searches for all PiSi files in a directory, collects PiSi\n" -"tags from them and accumulates the information in an output XML file,\n" -"named by default 'pisi-index.xml'. In particular, it indexes both\n" -"source and binary packages.\n" -msgstr "" - -#: pisi/cli/commands.py:580 -msgid "store absolute links for indexed files." -msgstr "" - -#: pisi/cli/commands.py:583 -msgid "index output file" -msgstr "" - -#: pisi/cli/commands.py:592 -msgid "Indexing current directory." -msgstr "" - -#: pisi/cli/commands.py:598 -#, docstring -msgid "" -"Print the list of all installed packages \n" -"\n" -"Usage: list-installed\n" -"\n" -msgstr "" - -#: pisi/cli/commands.py:622 pisi/cli/commands.py:900 -msgid "Package Name |St| Version| Rel.| Build| Distro| Date" -msgstr "" - -#: pisi/cli/commands.py:637 -#, docstring -msgid "" -"Rebuild Databases\n" -"\n" -"Usage: rebuilddb [ ... ]\n" -"\n" -"Rebuilds the PiSi databases\n" -"\n" -"If package specs are given, they should be the names of package dirs under /var/lib/pisi\n" -msgstr "" - -#: pisi/cli/commands.py:661 -msgid "Rebuild PISI databases?" -msgstr "" - -#: pisi/cli/commands.py:678 -#, docstring -msgid "" -"Update repository databases\n" -"\n" -"Usage: update-repo [ ... ]\n" -"\n" -": repository name\n" -"Synchronizes the PiSi databases with the current repository.\n" -"If no repository is given, all repositories are updated.\n" -msgstr "" - -#: pisi/cli/commands.py:707 -#, docstring -msgid "" -"Add a repository\n" -"\n" -"Usage: add-repo \n" -"\n" -": name of repository to add\n" -": URI of index file\n" -"\n" -"NB: We support only local files (e.g., /a/b/c) and http:// URIs at the moment\n" -msgstr "" - -#: pisi/cli/commands.py:730 -msgid "Update PISI database for repository %s?" -msgstr "" - -#: pisi/cli/commands.py:739 -#, docstring -msgid "" -"Remove repositories\n" -"\n" -"Usage: remove-repo ... \n" -"\n" -"Remove all repository information from the system.\n" -msgstr "" - -#: pisi/cli/commands.py:765 -#, docstring -msgid "" -"List repositories\n" -"\n" -"Usage: list-repo\n" -"\n" -"Lists currently tracked repositories.\n" -msgstr "" - -#: pisi/cli/commands.py:788 -#, docstring -msgid "" -"List available packages in the repositories\n" -"\n" -"Usage: list-available [ ... repon ]\n" -"\n" -"Gives a brief list of PiSi packages published in the repository.\n" -msgstr "" - -#: pisi/cli/commands.py:815 -msgid "" -"Repository : %s\n" -msgstr "" - -#: pisi/cli/commands.py:839 -#, docstring -msgid "" -"List available components\n" -"\n" -"Usage: list-components\n" -"\n" -"Gives a brief list of PiSi components published in the repositories.\n" -msgstr "" - -#: pisi/cli/commands.py:876 -#, docstring -msgid "" -"List packages to be upgraded\n" -"\n" -"Usage: list-upgrades [ ... repon ]\n" -"\n" -msgstr "" - -#: pisi/cli/commands.py:892 -msgid "show detailed install info" -msgstr "" - -#: pisi/cli/commands.py:916 -#, docstring -msgid "List pending packages" -msgstr "" - -#: pisi/cli/commands.py:936 -#, docstring -msgid "" -"Search packages\n" -"\n" -"Usage: search \n" -"\n" -"#FIXME: fill this later\n" -msgstr "" - -#: pisi/cli/commands.py:945 -#, docstring -msgid "" -"Search for a file\n" -"\n" -"Usage: search-file ... \n" -"\n" -"Finds the installed package which contains the specified file.\n" -msgstr "" - -#: pisi/cli/commands.py:962 -msgid "fuzzy search" -msgstr "" - -#: pisi/cli/commands.py:980 -msgid "Package %s has file %s" -msgstr "" - -#: pisi/cli/commands.py:982 -msgid "Type: %s, Hash: %s" -msgstr "" - -#: pisi/cli/commands.py:985 -msgid "Path '%s' does not belong to an installed package" -msgstr "" - -#: pisi/cli/commands.py:997 -msgid "Searching for %s" -msgstr "" - -#: pisi/cli/commands.py:1010 -#, docstring -msgid "" -"Run the build process partially\n" -"\n" -"Usage: -sStateName build-until \n" -"\n" -"where states are:\n" -"unpack, setupaction, buildaction, installaction, buildpackages\n" -"\n" -"You can give an URI of the pspec.xml file. PISI will fetch all\n" -"necessary files and unpack the source and prepare a source directory\n" -"for you.\n" -msgstr "" - -#: pisi/cli/commands.py:1047 -#, docstring -msgid "" -"Unpack the source archive\n" -"\n" -"Usage: build-unpack \n" -"\n" -"TODO: desc.\n" -msgstr "" - -#: pisi/cli/commands.py:1072 -#, docstring -msgid "" -"Setup the source\n" -"\n" -"Usage: build-setup \n" -"\n" -"TODO: desc.\n" -msgstr "" - -#: pisi/cli/commands.py:1098 pisi/cli/commands.py:1149 -#, docstring -msgid "" -"Setup the source\n" -"\n" -"Usage: build-build \n" -"\n" -"TODO: desc.\n" -msgstr "" - -#: pisi/cli/commands.py:1123 -#, docstring -msgid "" -"Install to the sandbox\n" -"\n" -"Usage: build-install \n" -"\n" -"TODO: desc.\n" -msgstr "" - -#: pisi/cli/commands.py:1173 -msgid "" -"%prog [options] [arguments]\n" -"\n" -"where is one of:\n" -"\n" -msgstr "" - -#: pisi/cli/commands.py:1179 -msgid "" -"\n" -"Use \"%prog help \" for help on a specific command.\n" -msgstr "" - -#: pisi/cli/pisicli.py:92 -msgid "No command given" -msgstr "" - -#: pisi/cli/pisicli.py:96 -msgid "Command line parsing error" -msgstr "" - -#: pisi/comariface.py:35 -msgid "COMAR: comard not running or defunct" -msgstr "" - -#: pisi/comariface.py:38 -msgid "Registering COMAR script %s" -msgstr "" - -#: pisi/comariface.py:48 -msgid "COMAR.register ERROR!" -msgstr "" - -#: pisi/comariface.py:55 -msgid "Running post-install script for %s" -msgstr "" - -#: pisi/comariface.py:64 -msgid "COMAR.call_package(System.Package.postInstall, %s) failed!: %s" -msgstr "" - -#: pisi/comariface.py:68 pisi/comariface.py:89 -msgid "COMAR.call_package ERROR: %d" -msgstr "" - -#: pisi/comariface.py:76 -msgid "Running pre-remove script for %s" -msgstr "" - -#: pisi/comariface.py:85 -msgid "COMAR.call_package(System.Package.preRemove, %s) failed!: %s" -msgstr "" - -#: pisi/comariface.py:92 -msgid "Unregistering COMAR scripts for %s" -msgstr "" - -#: pisi/component.py:117 -msgid "Information for component %s not available" -msgstr "" - -#: pisi/config.py:66 -msgid "Destination directory %s does not exist. Creating it." -msgstr "" - -#: pisi/configfile.py:89 -msgid "No section by name '%s'" -msgstr "" - -#: pisi/constants.py:32 -msgid "Can't rebind constant: %s" -msgstr "" - -#: pisi/constants.py:38 -msgid "Can't unbind constant: %s" -msgstr "" - -#: pisi/dependency.py:98 -msgid "Package %s does not satisfy dependency %s" -msgstr "" - -#: pisi/dependency.py:111 -msgid "Package %s is not present in the package database" -msgstr "" - -#: pisi/fetcher.py:75 -msgid "Filename error" -msgstr "" - -#: pisi/fetcher.py:78 -msgid "Access denied to write to dest dir" -msgstr "" - -#: pisi/fetcher.py:131 -msgid "No such file or no permission to read" -msgstr "" - -#: pisi/fetcher.py:154 -msgid "Cannot fetch %s; value error: %s" -msgstr "" - -#: pisi/fetcher.py:156 pisi/fetcher.py:158 -msgid "Cannot fetch %s; %s" -msgstr "" - -#: pisi/fetcher.py:160 -msgid "Cannot fetch %s; (%s): %s" -msgstr "" - -#: pisi/fetcher.py:202 -msgid "Requested range not satisfiable" -msgstr "" - -#: pisi/fetcher.py:241 pisi/fetcher.py:245 -msgid "Requested Range Not Satisfiable" -msgstr "" - -#: pisi/fetcher.py:261 pisi/fetcher.py:282 pisi/fetcher.py:295 -msgid "ftp error" -msgstr "" - -#: pisi/index.py:71 -msgid "Adding %s to package index" -msgstr "" - -#: pisi/index.py:74 -msgid "Adding %s to component index" -msgstr "" - -#: pisi/index.py:105 -msgid "Package %s: metadata corrupt" -msgstr "" - -#: pisi/index.py:116 -msgid "Component in %s is corrupt" -msgstr "" - -#: pisi/index.py:120 -msgid "Adding %s to source index" -msgstr "" - -#: pisi/index.py:125 -msgid "SpecFile in %s is corrupt" -msgstr "" - -#: pisi/installdb.py:60 -msgid "installed" -msgstr "" - -#: pisi/installdb.py:60 -msgid "installed-pending" -msgstr "" - -#: pisi/installdb.py:61 -msgid "purged" -msgstr "" - -#: pisi/installdb.py:61 -msgid "removed" -msgstr "" - -#: pisi/installdb.py:64 -msgid "" -"State: %s\n" -"Version: %s, Release: %s, Build: %s\n" -msgstr "" - -#: pisi/installdb.py:69 -msgid "" -"Distribution: %s, Install Time: %s\n" -msgstr "" - -#: pisi/installdb.py:146 -msgid "Already installed" -msgstr "" - -#: pisi/lockeddbshelve.py:42 -msgid "Cannot attain read or write access to database %s" -msgstr "" - -#: pisi/lockeddbshelve.py:66 -msgid "Flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags" -msgstr "" - -#: pisi/lockeddbshelve.py:78 -msgid "Another instance of PISI is running. Try later!" -msgstr "" - -#: pisi/metadata.py:58 -msgid "" -"Build: % s, Distribution: %s, Dist. Release: %s\n" -msgstr "" - -#: pisi/metadata.py:60 -msgid "" -"Architecture: %s, Installed Size: %s\n" -msgstr "" - -#: pisi/operations.py:64 -msgid "Mixing file names and package names not supported yet." -msgstr "" - -#: pisi/operations.py:106 -msgid "" -"The following packages will be installed\n" -"in the respective order to satisfy extra dependencies:\n" -msgstr "" - -#: pisi/operations.py:109 pisi/operations.py:238 pisi/operations.py:372 -#: pisi/operations.py:434 -msgid "Do you want to continue?" -msgstr "" - -#: pisi/operations.py:110 -msgid "External dependencies not satisfied" -msgstr "" - -#: pisi/operations.py:122 pisi/operations.py:196 -msgid "No packages to install." -msgstr "" - -#: pisi/operations.py:149 -msgid "Installation order: " -msgstr "" - -#: pisi/operations.py:171 -msgid "Selected packages %s and %s are in conflict." -msgstr "" - -#: pisi/operations.py:173 -msgid "Remove the following conflicting packages?" -msgstr "" - -#: pisi/operations.py:175 -msgid "Conflicts remain" -msgstr "" - -#: pisi/operations.py:234 -msgid "" -"The following minimal list of packages will be installed\n" -"in the respective order to satisfy dependencies:\n" -msgstr "" - -#: pisi/operations.py:261 -msgid "Warning: package *name* ends with '.pisi'" -msgstr "" - -#: pisi/operations.py:263 -msgid "Package %s is not installed." -msgstr "" - -#: pisi/operations.py:281 -msgid "Package %s is already at its latest version %s, release %s, build %s." -msgstr "" - -#: pisi/operations.py:287 -msgid "No packages to upgrade." -msgstr "" - -#: pisi/operations.py:338 pisi/operations.py:354 -msgid "Reverse dependency %s cannot be satisfied" -msgstr "" - -#: pisi/operations.py:369 -msgid "" -"The following packages will be upgraded:\n" -msgstr "" - -#: pisi/operations.py:386 -msgid "Safety switch: cannot remove the following packages in system.base: " -msgstr "" - -#: pisi/operations.py:390 -msgid "Safety switch: the component system.base cannot be found" -msgstr "" - -#: pisi/operations.py:397 -msgid "Package %s does not exist. Cannot remove." -msgstr "" - -#: pisi/operations.py:401 -msgid "No packages to remove." -msgstr "" - -#: pisi/operations.py:430 -msgid "" -"The following minimal list of packages will be removed\n" -"in the respective order to satisfy dependencies:\n" -msgstr "" - -#: pisi/operations.py:435 -msgid "Package removal declined" -msgstr "" - -#: pisi/operations.py:441 -msgid "Package %s is not installed. Cannot remove." -msgstr "" - -#: pisi/package.py:53 pisi/sourcearchive.py:59 -msgid "%s [cached]" -msgstr "" - -#: pisi/package.py:106 -msgid "MetaData format wrong" -msgstr "" - -#: pisi/packagedb.py:127 -msgid "get_package: package %s not found" -msgstr "" - -#: pisi/pxml/autoxml.py:85 -msgid "At least one '%s' tag should have local text" -msgstr "" - -#: pisi/pxml/autoxml.py:93 -msgid "'%s' language of tag '%s' is empty" -msgstr "" - -#: pisi/pxml/autoxml.py:117 -msgid "LocalText: unable to get either current or default locale" -msgstr "" - -#: pisi/pxml/autoxml.py:123 pisi/pxml/autoxml.py:138 -msgid "Tag should have at least the current locale, or failing that an English or Turkish version" -msgstr "" - -#: pisi/pxml/autoxml.py:356 -msgid "autoxml.check: '%s' errors" -msgstr "" - -#: pisi/pxml/autoxml.py:408 pisi/pxml/autoxml.py:416 -msgid "autoxml.read: File '%s' has errors" -msgstr "" - -#: pisi/pxml/autoxml.py:423 -msgid "autoxml.write: object validation has failed" -msgstr "" - -#: pisi/pxml/autoxml.py:431 -msgid "autoxml.write: File encoding '%s' has errors" -msgstr "" - -#: pisi/pxml/autoxml.py:481 -msgid "gen_tag: unrecognized tag type %s in spec" -msgstr "" - -#: pisi/pxml/autoxml.py:528 pisi/pxml/autoxml.py:539 -msgid "Mandatory variable %s not available" -msgstr "" - -#: pisi/pxml/autoxml.py:607 -msgid "Type mismatch: read text cannot be decoded" -msgstr "" - -#: pisi/pxml/autoxml.py:611 pisi/pxml/autoxml.py:620 -msgid "Mandatory token %s not available" -msgstr "" - -#: pisi/pxml/autoxml.py:625 -msgid "Type mismatch. Expected %s, got %s" -msgstr "" - -#: pisi/pxml/autoxml.py:655 pisi/pxml/autoxml.py:777 -msgid "Type mismatch: DOM cannot be decoded" -msgstr "" - -#: pisi/pxml/autoxml.py:658 pisi/pxml/autoxml.py:674 pisi/pxml/autoxml.py:684 -#: pisi/pxml/autoxml.py:780 pisi/pxml/autoxml.py:794 pisi/pxml/autoxml.py:804 -msgid "Mandatory argument not available" -msgstr "" - -#: pisi/pxml/autoxml.py:671 pisi/pxml/autoxml.py:791 -msgid "Object cannot be encoded" -msgstr "" - -#: pisi/pxml/autoxml.py:696 -msgid "List type must contain only one element" -msgstr "" - -#: pisi/pxml/autoxml.py:709 pisi/pxml/autoxml.py:731 -msgid "Mandatory list empty" -msgstr "" - -#: pisi/pxml/xmlextcdom.py:58 pisi/pxml/xmlfilecdom.py:74 -msgid "File '%s' has invalid XML: %s" -msgstr "" - -#: pisi/pxml/xmlextcdom.py:97 pisi/pxml/xmlextmdom.py:92 -#: pisi/pxml/xmlextpiks.py:61 -msgid "getNodeText: Expected text node, got something else!" -msgstr "" - -#: pisi/pxml/xmlextmdom.py:53 pisi/pxml/xmlfilemdom.py:66 -#: pisi/pxml/xmlfilepiks.py:56 -msgid "" -"File '%s' has invalid XML: %s\n" -msgstr "" - -#: pisi/pxml/xmlfilecdom.py:76 -msgid "File '%s' not found" -msgstr "" - -#: pisi/pxml/xmlfilecdom.py:86 pisi/pxml/xmlfilemdom.py:77 -#: pisi/pxml/xmlfilepiks.py:67 -msgid "Root tagname %s not identical to %s as expected" -msgstr "" - -#: pisi/repodb.py:82 -msgid "Repository %s already exists" -msgstr "" - -#: pisi/sourcearchive.py:68 -msgid "unpack: check_file_hash failed" -msgstr "" - -#: pisi/sourcefetcher.py:87 -msgid "Fetching %s" -msgstr "" - -#: pisi/specfile.py:139 -msgid "URI: %s, type: %s, sha1sum: %s" -msgstr "" - -#: pisi/specfile.py:197 -msgid "" -"Name: %s, version: %s, release: %s, build %s\n" -msgstr "" - -#: pisi/specfile.py:199 -msgid "" -"Summary: %s\n" -msgstr "" - -#: pisi/specfile.py:200 -msgid "" -"Description: %s\n" -msgstr "" - -#: pisi/specfile.py:201 -msgid "" -"Component: %s\n" -msgstr "" - -#: pisi/specfile.py:202 -msgid "Provides: " -msgstr "" - -#: pisi/uri.py:78 -msgid "setAuthInfo needs a tuple (user, pass)" -msgstr "" - -#: pisi/util.py:60 -msgid "%s section should have a '%s' tag" -msgstr "" - -#: pisi/util.py:130 -msgid "running " -msgstr "" - -#: pisi/util.py:134 -msgid "return value %s" -msgstr "" - -#: pisi/util.py:137 -msgid "Failed command: %s" -msgstr "" - -#: pisi/util.py:293 -msgid "Including external link '%s'" -msgstr "" - -#: pisi/util.py:295 -msgid "Including directory '%s'" -msgstr "" - -#: pisi/util.py:367 -msgid "I/O Error: Cannot calculate SHA1 hash of %s" -msgstr "" - -#: pisi/util.py:376 -msgid "Cannot calculate SHA1 hash of given data" -msgstr "" - -#: pisi/util.py:412 -msgid "ERROR: patch (%s) failed: %s" -msgstr "" - -#: pisi/util.py:455 -msgid "strip command failed for file '%s'!" -msgstr "" - -#: pisi/util.py:482 -msgid "Removing lock %s" -msgstr "" - -#: pisi/util.py:515 -msgid "Updating environment..." -msgstr "" - -#: tools/repostats.py:337 -msgid "" -"Duplicate binary packages:\n" -"%s\n" -"%s\n" -msgstr "" - -#: tools/repostats.py:342 -msgid "Unknown file type '%s' in package '%s'" -msgstr "" - -#: tools/repostats.py:398 -msgid "" -"Duplicate source packages:\n" -"%s\n" -"%s\n" -msgstr "" - -#: tools/repostats.py:418 -msgid "Source package '%s' has wrong date format '%s'" -msgstr "" - -#: tools/repostats.py:431 -msgid "Source package '%s' has wrong release numbers" -msgstr "" - -#: tools/repostats.py:435 -msgid "Source package '%s' lacks release %d" -msgstr "" - -#: tools/repostats.py:443 -msgid "Source package '%s' has no first release" -msgstr "" - -#: tools/repostats.py:478 -msgid "Developer '%s <%s>' has another mail address '%s' in source package '%s'" -msgstr "" - -#: tools/repostats.py:561 -msgid "" -"Cannot parse '%s':\n" -"%s\n" -msgstr "" - -#: tools/repostats.py:639 -msgid "" -"Usage: repostats.py [OPTIONS] source-repo-path [binary-repo-path]\n" -msgstr "" - -#: tools/repostats.py:640 -msgid "" -"Dont generate the web site.\n" -msgstr "" - -#: tools/repostats.py:661 -msgid "" -"Scanning source repository...\n" -msgstr "" - -#: tools/repostats.py:665 -msgid "" -"Scanning binary packages...\n" -msgstr "" - -#: tools/repostats.py:670 -msgid "" -"Encountered %d errors! Fix them immediately!\n" -msgstr "" - -#: tools/repostats.py:678 -msgid "" -"These dependencies are not available in repository:\n" -msgstr "" - diff --git a/tags/pisi-1.0_beta2/po/tr.po b/tags/pisi-1.0_beta2/po/tr.po deleted file mode 100644 index 653f6c75..00000000 --- a/tags/pisi-1.0_beta2/po/tr.po +++ /dev/null @@ -1,1827 +0,0 @@ -# translation of tr.po to Türkçe -# PiSi Translation -# Copyright (C) 2005 Free Software Foundation, Inc. -# Eray Ozkural -# -# Eray Özkural , 2005. -# Eray Özkural , 2005. -msgid "" -msgstr "" -"Project-Id-Version: tr\n" -"POT-Creation-Date: 2005-11-18 16:13+EET\n" -"PO-Revision-Date: 2005-11-18 15:23+0200\n" -"Last-Translator: Eray Özkural \n" -"Language-Team: Türkçe \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: KBabel 1.11\n" - -#: pisi-cli:31 -msgid "Keyboard Interrupt: Exiting..." -msgstr "Klavye kesmesi: Çıkıyor... " - -#: pisi-cli:34 -msgid "Fatal Error. Program Terminated." -msgstr "Düzeltilemeyen Hata: Program Sonlandırıldı." - -#: pisi-cli:38 -msgid "" -"\n" -"Unhandled internal exception.\n" -"Please file a bug report. (http://bugs.uludag.org.tr)" -msgstr "" -"\n" -"Dahili hata.\n" -"Lütfen bir hata raporu hazırlayınız. (http://bugs.uludag.org.tr) " - -#: pisi-cli:45 -msgid "System Error. Program Terminated." -msgstr "Sistem Hatası: Program Sonlandırıldı. " - -#: pisi-cli:49 -msgid "Please use 'pisi help' for general help." -msgstr "Genel yardım için lütfen 'pisi help' komutunu kullanınız. " - -#: pisi-cli:52 -msgid "Traceback:" -msgstr "Geri-iz: " - -#: pisi-cli:55 -msgid "Use --debug to see a traceback." -msgstr "" -"Bir geri iz (traceback) görmek için lütfen --debug seçeneğini kullanın. " - -#: pisi/actionsapi/autotools.py:36 -msgid "" -"Please attach the config.log to your bug report:\n" -"%s/config.log" -msgstr "" -"Lütfen hata raporunuza config.log'u iliştiriniz:\n" -"%s/config.log" - -# pisi/actionsapi/autotools.py:75 :85 -#: pisi/actionsapi/autotools.py:75 pisi/actionsapi/autotools.py:85 -#: pisi/actionsapi/kde.py:66 pisi/actionsapi/perlmodules.py:53 -#: pisi/actionsapi/perlmodules.py:56 -msgid "Configure failed." -msgstr "Yapılandırma başarısızlığa uğradı." - -# pisi/actionsapi/autotools.py:77 :87 -#: pisi/actionsapi/autotools.py:77 pisi/actionsapi/autotools.py:87 -#: pisi/actionsapi/kde.py:68 -msgid "No configure script found." -msgstr "Yapılandırma betiği bulunamadı." - -#: pisi/actionsapi/autotools.py:96 pisi/actionsapi/kde.py:73 -#: pisi/actionsapi/perlmodules.py:62 pisi/actionsapi/perlmodules.py:71 -#: pisi/actionsapi/pythonmodules.py:50 pisi/actionsapi/scons.py:40 -msgid "Make failed." -msgstr "İnşa başarısızlığa uğradı." - -# pisi/actionsapi/autotools.py:119 :127 -#: pisi/actionsapi/autotools.py:119 pisi/actionsapi/autotools.py:127 -#: pisi/actionsapi/kde.py:80 pisi/actionsapi/pythonmodules.py:55 -#: pisi/actionsapi/scons.py:44 -msgid "Install failed." -msgstr "Yerleştirme başarısızlığa uğgradı." - -# pisi/actionsapi/autotools.py:121 :129 -#: pisi/actionsapi/autotools.py:121 pisi/actionsapi/autotools.py:129 -#: pisi/actionsapi/kde.py:82 -msgid "No Makefile found." -msgstr "Makefile bulunamadı." - -#: pisi/actionsapi/autotools.py:134 -msgid "Running aclocal failed." -msgstr "aclocal çalıştırılamadı." - -# pisi/actionsapi/autotools.py:139 :144 -#: pisi/actionsapi/autotools.py:139 pisi/actionsapi/autotools.py:144 -msgid "Running autoconf failed." -msgstr "autoconf çalıştırılamadı." - -#: pisi/actionsapi/autotools.py:149 -msgid "Running automake failed." -msgstr "automake çalıştırılamadı." - -#: pisi/actionsapi/autotools.py:154 -msgid "Running autoheader failed." -msgstr "autoheader çalıştırılamadı." - -#: pisi/actionsapi/get.py:159 -msgid "Util %s cannot be found" -msgstr "Araç %s bulunamıyor" - -#: pisi/actionsapi/get.py:161 -msgid "Warning: %s does not exist, using plain name %s" -msgstr "Uyarı: %s yok, düz ad %s kullanılıyor" - -#: pisi/actionsapi/kde.py:35 -msgid "" -"\n" -"!!! Please attach the config.log to your bug report:\n" -"%s/config.log" -msgstr "" -"\n" -"Lütfen hata raporunuza config.log'u iliştiriniz:\n" -"%s/config.log" - -#: pisi/actionsapi/libtools.py:39 -msgid "Running ldconfig failed." -msgstr "ldconfig çalıştırılamadı" - -#: pisi/actionsapi/libtools.py:50 -msgid "GNU Config Update Finished." -msgstr "GNU config güncellemesi bitti" - -#: pisi/actionsapi/libtools.py:54 -msgid "Running libtoolize failed." -msgstr "libtoolize çalıştırılamadı" - -# pisi/actionsapi/autotools.py:119 :127 -#: pisi/actionsapi/perlmodules.py:65 -msgid "perl build failed." -msgstr "perl build başarısızlığa uğgradı." - -# pisi/actionsapi/autotools.py:119 :127 -#: pisi/actionsapi/perlmodules.py:74 -msgid "perl install failed." -msgstr "perl install başarısızlığa uğgradı." - -#: pisi/actionsapi/pisitools.py:132 -msgid "ActionsAPI [doman]: Wrong man page file: %s" -msgstr "ActionsAPI [doman]: Yanlış man sayfası dosyası: %s" - -#: pisi/actionsapi/pisitools.py:170 -msgid "ActionsAPI [rename]: No such file or directory: %s" -msgstr "ActionsAPI [rename]: Böyle bir dosya ya da dizin bulunamadıy: %s" - -#: pisi/actionsapi/pisitools.py:187 -msgid "File does not exist or permission denied: %s" -msgstr "Dosya yok ya da erişim engellendi: %s" - -#: pisi/actionsapi/pisitools.py:204 -msgid "ActionsAPI [dosym]: File exists: %s" -msgstr "ActionsAPI [dosym]: %s dosyası bulunamadı." - -# pisi/actionsapi/pisitoolsfunctions.py:46 :59 -#: pisi/actionsapi/pisitoolsfunctions.py:46 -#: pisi/actionsapi/pisitoolsfunctions.py:60 -#: pisi/actionsapi/pisitoolsfunctions.py:73 -msgid "Insufficient arguments." -msgstr "Yetersiz argümanlar" - -#: pisi/actionsapi/pythonmodules.py:67 -msgid "Running %s failed." -msgstr "%s çalıştırılamadı" - -#: pisi/actionsapi/shelltools.py:47 -msgid "Cannot create directory %s" -msgstr "%s dizini yaratılamıyor." - -#: pisi/actionsapi/shelltools.py:55 -msgid "ActionsAPI [echo]: Can't append to file %s." -msgstr "ActionsAPI [echo]: %s dosyasına eklenemiyor." - -#: pisi/actionsapi/shelltools.py:64 -msgid "ActionsAPI [chmod]: Operation not permitted: %s (mode: %s)" -msgstr "ActionsAPI [chmod]: İşleme izin verilmedi: %s (mod: %s)" - -#: pisi/actionsapi/shelltools.py:67 -msgid "ActionsAPI [chmod]: File %s doesn't exists." -msgstr "ActionsAPI [chmod]: %s dosyası bulunamadı." - -#: pisi/actionsapi/shelltools.py:75 -msgid "ActionsAPI [chown]: Operation not permitted: %s (uid: %s, gid: %s)" -msgstr "ActionsAPI [chown]: İşleme izin verilmedi: %s (uid: %s, gid: %s)" - -#: pisi/actionsapi/shelltools.py:78 -msgid "ActionsAPI [chown]: File %s doesn't exists." -msgstr "ActionsAPI [chown]: %s dosyası bulunamadı." - -#: pisi/actionsapi/shelltools.py:85 -msgid "ActionsAPI [sym]: Permission denied: %s to %s" -msgstr "ActionsAPI [sym]: Erişim engellendi: %s -> %s" - -#: pisi/actionsapi/shelltools.py:93 -msgid "ActionsAPI [unlink]: Permission denied: %s." -msgstr "ActionsAPI [unlink]: Erişim engellendi: %s." - -#: pisi/actionsapi/shelltools.py:97 -msgid "ActionsAPI [unlink]: File %s doesn't exists." -msgstr "ActionsAPI [unlink]: %s dosyası bulunamadı." - -#: pisi/actionsapi/shelltools.py:105 -msgid "ActionsAPI [unlinkDir]: Operation not permitted: %s" -msgstr "ActionsAPI [unlinkDir]: İşleme izin verilmedi: %s" - -#: pisi/actionsapi/shelltools.py:109 -msgid "ActionsAPI [unlinkDir]: Directory %s doesn't exists." -msgstr "ActionsAPI [unlinkDir]: %s dizini bulunamadı." - -#: pisi/actionsapi/shelltools.py:118 -msgid "ActionsAPI [move]: Permission denied: %s to %s" -msgstr "ActionsAPI [move]: Erişim engellendi: %s -> %s" - -#: pisi/actionsapi/shelltools.py:120 -msgid "ActionsAPI [move]: File %s doesn't exists." -msgstr "ActionsAPI [move]: %s dosyası bulunamadı." - -#: pisi/actionsapi/shelltools.py:129 -msgid "ActionsAPI [copy]: Permission denied: %s to %s" -msgstr "ActionsAPI [copy]: Erişim engellendi: %s -> %s" - -#: pisi/actionsapi/shelltools.py:133 -msgid "ActionsAPI [copy]: File %s does not exist." -msgstr "ActionsAPI [copy]: %s dosyası bulunamadı." - -#: pisi/actionsapi/shelltools.py:141 -msgid "ActionsAPI [copytree] %s to %s: %s" -msgstr "ActionsAPI [copytree]: %s den %s'e: %s" - -#: pisi/actionsapi/shelltools.py:143 -msgid "ActionsAPI [copytree]: Directory %s doesn't exists." -msgstr "ActionsAPI [copytree]: %s dizini bulunamadı." - -#: pisi/actionsapi/shelltools.py:155 -msgid "ActionsAPI [touch]: Permission denied: %s" -msgstr "ActionsAPI [touch]: Erişim engellendi: %s" - -#: pisi/actionsapi/shelltools.py:204 -msgid "executing %s" -msgstr "%s çalıştırılıyor" - -#: pisi/api.py:194 pisi/comariface.py:33 -msgid "COMAR: comard not fully installed" -msgstr "COMAR: comard tam olarak yerleştirilmedi" - -#: pisi/api.py:206 -msgid "File %s not found" -msgstr "Dosya %s bulunamadı." - -#: pisi/api.py:228 -msgid "Package %s not found" -msgstr "Paket %s bulunamadı." - -#: pisi/api.py:235 -msgid "* Building index of PISI files under %s" -msgstr "* %s altındaki PISI dosyalarının bir endeksi yapılıyor." - -#: pisi/api.py:238 -msgid "* Index file written" -msgstr "* İndeks dosyası yazıldı." - -#: pisi/api.py:243 -msgid "Repo %s added to system." -msgstr "Depo %s sisteme eklendi." - -#: pisi/api.py:248 -msgid "Repo %s removed from system." -msgstr "Depo %s sistemden çıkarıldı." - -#: pisi/api.py:250 -msgid "Repository %s does not exist. Cannot remove." -msgstr "Depo %s yok. Kaldırılamıyor." - -#: pisi/api.py:255 -msgid "* Updating repository: %s" -msgstr "Depo %s güncelleniyor." - -#: pisi/api.py:259 -msgid "" -"\n" -"* Package database updated." -msgstr "" -"\n" -"* Paket veritabani güncellendi." - -#: pisi/archive.py:84 -msgid "Archive type not recognized" -msgstr "Arşiv tipi tanınmadı" - -#: pisi/atomicoperations.py:77 -msgid "Installing %s, version %s, release %s, build %s" -msgstr "%s paketi, versiyon %s, sürüm %s, inşa %s yerleştiriliyor." - -#: pisi/atomicoperations.py:110 -msgid "Package conflicts %s" -msgstr "Paket %s ile çatışmakta." - -#: pisi/atomicoperations.py:115 -msgid "Dependencies for %s not satisfied" -msgstr "%s için bağımlılıklar sağlanmadı." - -#: pisi/atomicoperations.py:117 -msgid "Package not installable" -msgstr "Paket yerleştirilebilir durumda değil." - -#: pisi/atomicoperations.py:148 -msgid "Re-install same version package?" -msgstr "Aynı versiyona sahip paketi yeniden yerleştireyim mi?" - -#: pisi/atomicoperations.py:149 -msgid "Package re-install declined" -msgstr "Paket yeniden yerleştirmeye izin verilmedi." - -#: pisi/atomicoperations.py:155 -msgid "Upgrading to new upstream version" -msgstr "Yeni versiyona yukseltiliyor." - -#: pisi/atomicoperations.py:158 -msgid "Upgrading to new distribution release" -msgstr "Yeni dağıtım sürümüne yukseltiliyor." - -#: pisi/atomicoperations.py:162 -msgid "Upgrading to new distribution build" -msgstr "Yeni dağıtım inşasına yukseltiliyor." - -#: pisi/atomicoperations.py:169 -msgid "Downgrade to old upstream version?" -msgstr "Eski kaynak versiyonuna dönülsün mu?" - -#: pisi/atomicoperations.py:171 -msgid "Downgrade to old distribution release?" -msgstr "Eski dağıtım sürümüne dönülsün mu?" - -#: pisi/atomicoperations.py:173 -msgid "Downgrade to old distribution build?" -msgstr "Eski dağıtım inşasına dönülsün mu?" - -#: pisi/atomicoperations.py:175 -msgid "Package downgrade declined" -msgstr "Paket eskileştirilmesine izin verilmedi." - -#: pisi/atomicoperations.py:187 -msgid "Extracting files" -msgstr "Dosyalar arşivden çıkartılıyor." - -#: pisi/atomicoperations.py:205 -msgid "Storing %s, " -msgstr "%s saklanıyor, " - -#: pisi/atomicoperations.py:208 -msgid "Storing %s." -msgstr "%s saklanıyor" - -#: pisi/atomicoperations.py:215 -msgid "Storing %s" -msgstr "%s saklanıyor" - -#: pisi/atomicoperations.py:257 -msgid "Regenerating /etc/ld.so.cache..." -msgstr "/etc/ld.so.cache yeniden yaratılıyor..." - -#: pisi/atomicoperations.py:260 -msgid "Bypassing ldconfig" -msgstr "ldconfig esgeçiliyor" - -#: pisi/atomicoperations.py:294 -msgid "Package URI: %s" -msgstr "Paket URI'ı: %s" - -#: pisi/atomicoperations.py:299 -msgid "Package %s not found in any active repository." -msgstr "Paket %s hiç bir etkin repo'da bulunamadı." - -#: pisi/atomicoperations.py:314 -msgid "Removing package %s" -msgstr "%s paketi kaldırılıyor." - -#: pisi/atomicoperations.py:316 -msgid "Trying to remove nonexistent package " -msgstr "Var olmayan paket kaldırılmaya çalışıldı." - -#: pisi/atomicoperations.py:353 -msgid "Not removing non-file, non-link %s" -msgstr "Dosya ya da bağ olmayan '%s' kaldırılmıyor." - -#: pisi/atomicoperations.py:433 -msgid "Metadata XML '%s' cannot be found" -msgstr "Metadata XML %s bulunamıyor" - -#: pisi/atomicoperations.py:441 -msgid "MetaData format wrong (%s)" -msgstr "MetaData biçimi yanlış (%s)" - -#: pisi/atomicoperations.py:453 -msgid "* Adding '%s' to db... " -msgstr "* '%s' veritabanına ekleniyor... " - -#: pisi/atomicoperations.py:457 -msgid "Files XML '%s' cannot be found" -msgstr "Files XML '%s' bulunamıyor" - -#: pisi/atomicoperations.py:463 pisi/package.py:111 -msgid "Invalid %s" -msgstr "Geçersiz %s" - -#: pisi/atomicoperations.py:468 -msgid "OK." -msgstr "Tamam." - -#: pisi/build.py:80 -msgid "Path %s belongs in multiple packages" -msgstr "Yol %s birden çok pakete ait" - -#: pisi/build.py:146 -msgid "Building PISI source package: %s" -msgstr "PISI kaynak paketi %s inşa ediliyor" - -#: pisi/build.py:147 -msgid "Building PISI source package: %s\n" -msgstr "PISI kaynak paketi inşa ediliyor: %s\n" - -#: pisi/build.py:188 -msgid "IceCream detected. Make sure your daemon is up and running..." -msgstr "" -"IceCream bulundu. Lütfen artalan sürecinizin çalıştığından emin olunuz." - -#: pisi/build.py:192 -msgid "CCache detected..." -msgstr "CCache bulundu..." - -#: pisi/build.py:196 -msgid "PartOf tag not defined, looking for component" -msgstr "PartOf imi tanımlanmamış, bileşen araştırılyor" - -#: pisi/build.py:205 -msgid "Cannot find component.xml in upper directory" -msgstr "'component.xml' üst dizinde bulunamıyor" - -#: pisi/build.py:209 -msgid "Source is part of %s component" -msgstr "Kaynak %s bileşeninin parçası" - -#: pisi/build.py:214 -msgid "Fetching source from: %s" -msgstr "Kaynak indiriliyor: %s" - -#: pisi/build.py:216 -msgid "Source archive is stored: %s/%s" -msgstr "Kaynak arşivi saklandı: %s/%s" - -#: pisi/build.py:220 -msgid "Unpacking archive..." -msgstr "Arşiv açılıyor..." - -#: pisi/build.py:222 -msgid " unpacked (%s)" -msgstr " açıldı (%s)" - -#: pisi/build.py:227 -msgid "Setting up source..." -msgstr "Kaynak kuruluyor" - -#: pisi/build.py:232 -msgid "Building source..." -msgstr "Kaynak inşa ediliyor..." - -#: pisi/build.py:237 -msgid "Installing..." -msgstr "Yerleştiriliyor..." - -#: pisi/build.py:256 -msgid "Unable to read Action Script (%s): %s" -msgstr "Action betiği okunamıyor (%s): %s" - -#: pisi/build.py:258 -msgid "SyntaxError in Action Script (%s): %s" -msgstr "Action betiğinde sözdizimi hatası (%s): %s" - -#: pisi/build.py:288 -msgid "unable to call function from actions: %s" -msgstr "fonksiyon eylemlerden çağırılamıyor: %s" - -#: pisi/build.py:302 -msgid "" -"Safety switch: following extra packages in system.devel will be installed: " -msgstr "" -"Emniyet mandalı: taban geliştirme sistemi system.devel'den izleyen paketler " -"ek olarak yüklenecek:" - -#: pisi/build.py:307 -msgid "Safety switch: the component system.devel cannot be found" -msgstr "Emniyet mandalı: geliştirme sistemi bileşeni system.devel bulunamadı" - -#: pisi/build.py:316 -msgid "Unsatisfied Build Dependencies:" -msgstr "Sağlanmamış inşa bağımlılıkları" - -#: pisi/build.py:321 -msgid "Do you want to install the unsatisfied build dependencies" -msgstr "Sağlanmamış inşa bağımlılıklarını kurmak istiyor musunuz? " - -#: pisi/build.py:322 -msgid "Installing build dependencies." -msgstr "İnşa bağımlılıklarını kuruyor. " - -#: pisi/build.py:325 -msgid "Cannot build package due to unsatisfied build dependencies" -msgstr "Sağlanmamış inşa bağımlılıkları yüzünden paket inşa edilemiyor" - -#: pisi/build.py:327 -msgid "Ignoring build dependencies." -msgstr "İnşa bağımlılıkları yoksayılıyor." - -#: pisi/build.py:337 -msgid "Patch file is missing: %s\n" -msgstr "Yama dosyası eksik: %s\n" - -#: pisi/build.py:350 -msgid "* Applying patch: %s" -msgstr "* Yama uygulanıyor: %s" - -#: pisi/build.py:355 -msgid "Stripping files.." -msgstr "Semboller temizleniyor..." - -#: pisi/build.py:385 -msgid "build number is not available." -msgstr "inşa sayısı (build number) bulunamadı" - -#: pisi/build.py:461 -msgid "(no previous build found, setting build no to 1.)" -msgstr "(önceki bir inşa bulunamadı, inşa numarası 1 yapılıyor)" - -#: pisi/build.py:498 -msgid "(old package lacks a build no, setting build no to 0.)" -msgstr "(önceki paketin bir inşa numarası yok, inşa numarası 0 yapılıyor)" - -#: pisi/build.py:501 -msgid "There are changes, incrementing build no to %d" -msgstr "Değişiklikler var, inşa nosu %d'ye arttırıldı." - -#: pisi/build.py:504 -msgid "There is no change from previous build %d " -msgstr "Bir önceki inşa %d'ye göre bir değişiklik yok." - -#: pisi/build.py:532 -msgid "Copying additional file: '%s' to '%s' as '%s'" -msgstr "Ek dosya kopyalanıyor: '%s' den '%s' e '%s' olarak" - -#: pisi/build.py:543 -msgid "** Building package %s" -msgstr "* Paket %s inşa ediliyor" - -# pisi/build.py:503 :506 -#: pisi/build.py:545 pisi/build.py:548 -msgid "Generating %s," -msgstr "%s yaratılıyor," - -#: pisi/build.py:551 -msgid "Creating PISI package %s." -msgstr "PISI paketi %s yaratılıyor." - -#: pisi/build.py:584 -msgid "Done." -msgstr "Bitti." - -#: pisi/build.py:587 -msgid "Cleaning Build Directory..." -msgstr "İnşa dizini siliniyor..." - -#: pisi/build.py:590 -msgid "Keeping Build Directory" -msgstr "İnşa dizini bırakılıyor " - -#: pisi/cli/__init__.py:75 -msgid "Warning: " -msgstr "Uyarı: " - -#: pisi/cli/__init__.py:81 -msgid "Error: " -msgstr "Hata: " - -#: pisi/cli/__init__.py:109 -msgid " (yes/no)" -msgstr " (evet/hayır)" - -#: pisi/cli/__init__.py:121 -msgid " [complete]\n" -msgstr " [bitti]\n" - -#: pisi/cli/__init__.py:129 -msgid "Installed %s" -msgstr "%s yerleştirildi " - -#: pisi/cli/__init__.py:131 -msgid "Removed %s" -msgstr "%s kaldırıldı" - -#: pisi/cli/__init__.py:133 -msgid "Upgraded %s" -msgstr "%s yükseltildi" - -#: pisi/cli/commands.py:33 -msgid "generic help string for any command" -msgstr "herhangi bir komut yardımı için yer tutucu" - -#: pisi/cli/commands.py:55 pisi/cli/pisicli.py:101 -msgid "Unrecognized command: %s" -msgstr "Tanınmayan komut: %s" - -#: pisi/cli/commands.py:76 -msgid "common options" -msgstr "ortak seçenekler" - -#: pisi/cli/commands.py:79 -msgid "change the system root for pisi commands" -msgstr "pisi komutları için sistem kök dizinini değiştir" - -#: pisi/cli/commands.py:81 -msgid "assume yes in all yes/no queries" -msgstr "bütün evet/hayır sorularında evet varsay" - -#: pisi/cli/commands.py:85 -msgid "get password from the command line" -msgstr "parolayı komut satırından al" - -#: pisi/cli/commands.py:88 -msgid "detailed output" -msgstr "detaylı çıktı" - -#: pisi/cli/commands.py:90 -msgid "show debugging information" -msgstr "hata ayıklama bilgisini göster" - -#: pisi/cli/commands.py:95 -msgid "print like a man" -msgstr "adam gibi yaz" - -#: pisi/cli/commands.py:99 -msgid "" -"This is a fall back function. If the implementer module provides an\n" -" options function it will be called" -msgstr "" - -#: pisi/cli/commands.py:111 -msgid "Destination directory %s does not exist. Creating directory.\n" -msgstr "Hedef dizini %s bulunamadı. Dizin yaratılıyor.\n" - -#: pisi/cli/commands.py:134 -msgid "Password: " -msgstr "Parola: " - -#: pisi/cli/commands.py:140 -msgid "initialize PiSi components" -msgstr "" - -#: pisi/cli/commands.py:148 -msgid "do cleanup work for PiSi components" -msgstr "" - -#: pisi/cli/commands.py:162 -msgid "print help for the command" -msgstr "komut için yardım yaz" - -#: pisi/cli/commands.py:169 -msgid "exit program" -msgstr "programdan çık" - -#: pisi/cli/commands.py:171 -msgid "Command terminated abnormally." -msgstr "Program anormal biçimde sonlandı." - -#: pisi/cli/commands.py:181 -msgid "Command lacks name" -msgstr "Komut adı eksik" - -#: pisi/cli/commands.py:185 -msgid "Duplicate command %s" -msgstr "Aynı adlı komut: %s" - -#: pisi/cli/commands.py:194 -msgid "" -"Prints help for given commands.\n" -"\n" -"Usage: help [ ... ]\n" -"\n" -"If run without parameters, it prints the general help." -msgstr "" -"Verilen komutlar için yardım metnini gösterir.\n" -"\n" -"Kullanım: help [ ... ]\n" -"\n" -"Eğer parametre verilmezse genel yardımı yazar." - -#: pisi/cli/commands.py:227 -msgid "Clean stale locks." -msgstr "Bayat kilitleri temizle." - -#: pisi/cli/commands.py:243 -msgid "Delete cache files" -msgstr "Önbellek dosyalarını sil" - -#: pisi/cli/commands.py:258 -msgid "" -"Graph package relations.\n" -"Usage: graph [ ...]\n" -"\n" -"Write a graph of package relations, tracking dependency and\n" -"conflicts relations starting from given packages.\n" -msgstr "" -"Paket ilişkilerini çiz.\n" -"Kullanım: graph ...\n" -"\n" -"Paket ilişkilerinin bir çizgesini, bağımlılık ve çatışma\n" -"ilişkilerini verilen paketlerden takip ederek yaz.\n" - -#: pisi/cli/commands.py:273 -msgid "graph all available packages" -msgstr "Bulunan bütün paketlerin çizgesini oluştur" - -#: pisi/cli/commands.py:276 -msgid "dot output file" -msgstr "dot çıktı dosyası" - -#: pisi/cli/commands.py:291 -msgid "Plotting a graph of relations among all available packages" -msgstr "Bulunan bütün paketlerin arasındaki ilişkilerin bir çizgesi basılıyor" - -#: pisi/cli/commands.py:298 -msgid "Plotting a graph of relations among all installed packages" -msgstr "Bütün kurulu paketler arasındaki ilişiklerin bir çizgesi hazırlanıyor " - -#: pisi/cli/commands.py:309 -msgid "do not take build no into account." -msgstr "inşa no'sunu dikkate alma" - -#: pisi/cli/commands.py:315 -msgid "do not take dependency information into account" -msgstr "bağımlılık bilgilerini dikkate alma" - -#: pisi/cli/commands.py:319 -msgid "" -"Build a PISI package using a pspec.xml file\n" -"\n" -"Usage: build \n" -"\n" -"You can give a URI of the pspec.xml file. PISI will\n" -"fetch all necessary files and build the package for you.\n" -msgstr "" -"pspec.xml kullanarak bir PISI paketi inşa et\n" -"\n" -"Kullanım: build \n" -"\n" -"pspec.xml dosyasının URI'ını verebilirsiniz. PISI sizin\n" -"için gerekli tüm dosyaları çekip inşa edecektir.\n" - -#: pisi/cli/commands.py:337 -msgid "output directory for produced packages" -msgstr "üretilecek paketler için çıktı dizini" - -#: pisi/cli/commands.py:340 -msgid "bypass errors from ActionsAPI" -msgstr "ActionsAPI kaynaklı hataları es geç" - -#: pisi/cli/commands.py:356 -msgid "Abstract package operation command" -msgstr "" - -#: pisi/cli/commands.py:365 -msgid "bypass comar configuration agent" -msgstr "çomar yapılandırma aygıtını kullanma" - -#: pisi/cli/commands.py:367 -msgid "bypass safety switch" -msgstr "emniyet mandalını esgeç" - -#: pisi/cli/commands.py:379 -msgid "" -"Install PISI packages\n" -"\n" -"Usage: install ... \n" -"\n" -"You may use filenames, URIs or package names for packages. If you have\n" -"specified a package name, it should exist in a specified repository.\n" -"\n" -"You can also specify components instead of package names, which will be\n" -"expanded to package names.\n" -msgstr "" -"PISI paketlerini yükle\n" -"\n" -"Kullanım: install ... \n" -"\n" -"Paketler için dosya adları, URI'lar veya paket adları kullanabilirsiniz.\n" -"Eğer bir paket adı verdiyseniz, paket deposunda bulunmalı.\n" -"Paket adları yerine bileşenler de verebilirsiniz.\n" - -#: pisi/cli/commands.py:400 pisi/cli/commands.py:444 -msgid "Bypass ldconfig phase" -msgstr "ldconfig safhasını esgeç" - -#: pisi/cli/commands.py:414 -msgid "" -"Upgrade PISI packages\n" -"\n" -"Usage: Upgrade [ ... ]\n" -"\n" -": package name\n" -"\n" -"Upgrades the entire system if no package names are given\n" -"\n" -"You may use only package names to specify packages because\n" -"the package upgrade operation is defined only with respect \n" -"to repositories. If you have specified a package name, it\n" -"should exist in the package repositories. If you just want to\n" -"reinstall a package from a pisi file, use the install command.\n" -"\n" -"You can also specify components instead of package names, which will be\n" -"expanded to package names.\n" -msgstr "" -"PISI paketlerini yükselt\n" -"\n" -"Kullanım: Upgrade ... \n" -"\n" -"Paketleri belirtmek için şimdilik sadece paket adları kullanabilirsiniz\n" -"Verdiğiniz paket adları depolarda yer almalıdır. Eğer sadece\n" -"bir dosyayı yeniden kurmak istiyorsanız install komutunu kullanın. \n" -"Paket adları yerine bileşenler de verebilirsiniz.\n" - -#: pisi/cli/commands.py:446 -msgid "eager upgrades" -msgstr "istekli yükseltmeler" - -#: pisi/cli/commands.py:461 -msgid "" -"Remove PISI packages\n" -"\n" -"Usage: remove ... \n" -"\n" -"Remove package(s) from your system. Just give the package names to remove.\n" -"\n" -"You can also specify components instead of package names, which will be\n" -"expanded to package names.\n" -msgstr "" -"PISI paketlerini kaldır\n" -"\n" -"Kullanım: remove ... \n" -"\n" -"Paket(leri) sisteminizden kaldırır. Sadece kaldırılacak paketlerin adlarını " -"verin.\n" -"Paket adları yerine bileşenler de verebilirsiniz.\n" - -#: pisi/cli/commands.py:488 -msgid "" -"configure pending packages\n" -" " -msgstr "" -"bekleyen paketleri yapılandır\n" -" " - -#: pisi/cli/commands.py:506 -msgid "" -"Display package information\n" -"\n" -"Usage: info ... \n" -"\n" -msgstr "" -"Paket bilgisini göster\n" -"\n" -"Kullanım: info ... \n" -"\n" - -#: pisi/cli/commands.py:521 -msgid "show a list of package files." -msgstr "paketteki dosyaların bir listesini göster" - -#: pisi/cli/commands.py:524 -msgid "Show only paths." -msgstr "Sadece yolları göster" - -#: pisi/cli/commands.py:547 -msgid "Reverse Dependencies:" -msgstr "Ters bağımlılıklar:" - -#: pisi/cli/commands.py:550 -msgid "" -"\n" -"Files:" -msgstr "" -"\n" -"Dosyalar:" - -#: pisi/cli/commands.py:557 -msgid "File information not available" -msgstr "Dosya bilgisi bulunamadı" - -#: pisi/cli/commands.py:561 -msgid "" -"Index PISI files in a given directory\n" -"\n" -"Usage: index \n" -"\n" -"This command searches for all PiSi files in a directory, collects PiSi\n" -"tags from them and accumulates the information in an output XML file,\n" -"named by default 'pisi-index.xml'. In particular, it indexes both\n" -"source and binary packages.\n" -msgstr "" -"Verilen bir dizindeki PISI dosyalarının endeksle\n" -"\n" -"Kullanım: index \n" -"\n" -"Bu komut bir dizindeki bütüm PİSİ dosyalarını arastırır, PIS\n" -"etiketlerini toplar ve bilgiyi çıktı, varsayılan adı 'pisi-index.xml',olan " -"XML dosyasında birleştirir. Özellikle, hem ikili hem kaynak\n" -"paketlerini endeksler.\n" - -#: pisi/cli/commands.py:580 -msgid "store absolute links for indexed files." -msgstr "indekslenmiş dosyalar için mutlak bağlar sakla" - -#: pisi/cli/commands.py:583 -msgid "index output file" -msgstr "index çıktı dosyası" - -#: pisi/cli/commands.py:592 -msgid "Indexing current directory." -msgstr "Şu andaki dizini indeksliyor." - -#: pisi/cli/commands.py:598 -msgid "" -"Print the list of all installed packages \n" -"\n" -"Usage: list-installed\n" -"\n" -msgstr "" -"Kurulu paketlerin bir listesini yaz \n" -"\n" -"Kullanım: list-installed\n" -"\n" - -# pisi/cli/commands.py:542 :729 -#: pisi/cli/commands.py:622 pisi/cli/commands.py:900 -msgid "" -"Package Name |St| Version| Rel.| Build| Distro| Date" -msgstr "" -"Paket Adı |Dm| Versiyon| Sürüm| İnşa| Dağıt.| Tarih" - -#: pisi/cli/commands.py:637 -msgid "" -"Rebuild Databases\n" -"\n" -"Usage: rebuilddb [ ... ]\n" -"\n" -"Rebuilds the PiSi databases\n" -"\n" -"If package specs are given, they should be the names of package dirs under /" -"var/lib/pisi\n" -msgstr "" -"Veritabanlarını yeniden inşa et\n" -"\n" -"Kullanım: rebuilddb [ ... ]\n" -"\n" -"PİSİ veritabanlarını yeniden inşa eder\n" -"\n" -"Eğer paket tanımları verildiyse /var/lib/pisi altındaki paket dizinlerinin " -"adları olmalılar\n" - -#: pisi/cli/commands.py:661 -msgid "Rebuild PISI databases?" -msgstr "PİSİ veritabanlarını güncelle?" - -#: pisi/cli/commands.py:678 -msgid "" -"Update repository databases\n" -"\n" -"Usage: update-repo [ ... ]\n" -"\n" -": repository name\n" -"Synchronizes the PiSi databases with the current repository.\n" -"If no repository is given, all repositories are updated.\n" -msgstr "" -"Depo veritabanlarını günceller\n" -"\n" -"Kullanım: update-repo ... \n" -"\n" -": depo adı\n" -"PİSİ veritabanlarını depo ile eşzamanlı hale getirir.\n" - -#: pisi/cli/commands.py:707 -msgid "" -"Add a repository\n" -"\n" -"Usage: add-repo \n" -"\n" -": name of repository to add\n" -": URI of index file\n" -"\n" -"NB: We support only local files (e.g., /a/b/c) and http:// URIs at the " -"moment\n" -msgstr "" -"Bir depo ekle\n" -"\n" -"Kullanım: add-repo \n" -"\n" -": eklenecek deponun adı\n" -": endeks dosyasının URI'ı\n" -"\n" -"Not: Şimdilik sadece lokal dosyaları (e.g., /a/b/c) ve http:// URI'larını\n" -"destekliyoruz\n" - -#: pisi/cli/commands.py:730 -msgid "Update PISI database for repository %s?" -msgstr "Depo %s için PİSİ veritabanını güncellensin mi?" - -#: pisi/cli/commands.py:739 -msgid "" -"Remove repositories\n" -"\n" -"Usage: remove-repo ... \n" -"\n" -"Remove all repository information from the system.\n" -msgstr "" -"Depoları kaldır\n" -"\n" -"Kullanım: remove-repo ... \n" -"\n" -"Sistemden ilgili bütün depo bilgisini kaldır.\n" - -#: pisi/cli/commands.py:765 -msgid "" -"List repositories\n" -"\n" -"Usage: list-repo\n" -"\n" -"Lists currently tracked repositories.\n" -msgstr "" -"Depoları listele\n" -"\n" -"Kullanım: list-repo\n" -"\n" -"Şu anda izlenen bütün depoları gösterir.\n" - -#: pisi/cli/commands.py:788 -msgid "" -"List available packages in the repositories\n" -"\n" -"Usage: list-available [ ... repon ]\n" -"\n" -"Gives a brief list of PiSi packages published in the repository.\n" -msgstr "" -"Depolardaki paketleri gösterir\n" -"\n" -"Kullanım: list-available [ ... depon ]\n" -"\n" -"Depoda yayımlanmış olan PİSİ bileşenlerinin kısa bir listesini verir.\n" - -#: pisi/cli/commands.py:815 -msgid "Repository : %s\n" -msgstr "Depo: %s\n" - -#: pisi/cli/commands.py:839 -msgid "" -"List available components\n" -"\n" -"Usage: list-components\n" -"\n" -"Gives a brief list of PiSi components published in the repositories.\n" -msgstr "" -"Depolardaki bileşenleri gösterir\n" -"\n" -"Kullanım: list-components [ ... depon ]\n" -"\n" -"Depoda yayımlanmış olan PİSİ bileşenlerinin kısa bir listesini verir.\n" - -#: pisi/cli/commands.py:876 -msgid "" -"List packages to be upgraded\n" -"\n" -"Usage: list-upgrades [ ... repon ]\n" -"\n" -msgstr "" -"Yükseltilecek paketleri listele\n" -"\n" -"Kullanım: list-upgrades [ ... depon ]\n" -"\n" - -#: pisi/cli/commands.py:892 -msgid "show detailed install info" -msgstr "detaylı yükleme bilgisi göster" - -#: pisi/cli/commands.py:916 -msgid "List pending packages" -msgstr "Yapılandırma bekleyen paketleri listele" - -#: pisi/cli/commands.py:936 -msgid "" -"Search packages\n" -"\n" -"Usage: search \n" -"\n" -"#FIXME: fill this later\n" -msgstr "" -"Paketleri ara\n" -"\n" -"Kullanım: search \n" -"\n" -"#FIXME: fill this later\n" - -#: pisi/cli/commands.py:945 -msgid "" -"Search for a file\n" -"\n" -"Usage: search-file ... \n" -"\n" -"Finds the installed package which contains the specified file.\n" -msgstr "" -"Dosya araştır\n" -"\n" -"Kullanım: search-file ... \n" -"\n" -"Belirtilen dosyayı içeren paketi bulur.\n" - -#: pisi/cli/commands.py:962 -msgid "fuzzy search" -msgstr "yaklaşık arama" - -#: pisi/cli/commands.py:980 -msgid "Package %s has file %s" -msgstr "Paket %s içinde dosya %s var" - -#: pisi/cli/commands.py:982 -msgid "Type: %s, Hash: %s" -msgstr "Tip: %s, Hash: %s" - -#: pisi/cli/commands.py:985 -msgid "Path '%s' does not belong to an installed package" -msgstr "Yol '%s' yerleştirilmiş bir pakete ait değil" - -#: pisi/cli/commands.py:997 -msgid "Searching for %s" -msgstr "%s'i arıyor" - -#: pisi/cli/commands.py:1010 -msgid "" -"Run the build process partially\n" -"\n" -"Usage: -sStateName build-until \n" -"\n" -"where states are:\n" -"unpack, setupaction, buildaction, installaction, buildpackages\n" -"\n" -"You can give an URI of the pspec.xml file. PISI will fetch all\n" -"necessary files and unpack the source and prepare a source directory\n" -"for you.\n" -msgstr "" -"İnşa işlevini kısmen çalıştır\n" -"\n" -"Kullanım: -s build-until \n" -"\n" -"Adım aşağıdakilerden birisi olabilir:\n" -"unpack, setupaction, buildaction, installaction, buildpackages\n" -"\n" - -#: pisi/cli/commands.py:1047 -msgid "" -"Unpack the source archive\n" -"\n" -"Usage: build-unpack \n" -"\n" -"TODO: desc.\n" -msgstr "" -"Kaynak arşivini açar\n" -"\n" -"Kullanım: build-unpack \n" -"\n" - -#: pisi/cli/commands.py:1072 -msgid "" -"Setup the source\n" -"\n" -"Usage: build-setup \n" -"\n" -"TODO: desc.\n" -msgstr "" -"Kaynağı kurar\n" -"\n" -"Kullanım: build-setup \n" -"\n" - -# pisi/cli/commands.py:866 :917 -#: pisi/cli/commands.py:1098 pisi/cli/commands.py:1149 -msgid "" -"Setup the source\n" -"\n" -"Usage: build-build \n" -"\n" -"TODO: desc.\n" -msgstr "" -"Kaynağı inşa eder\n" -"\n" -"Kullanım: build-build \n" -"\n" -"TODO: desc.\n" - -#: pisi/cli/commands.py:1123 -msgid "" -"Install to the sandbox\n" -"\n" -"Usage: build-install \n" -"\n" -"TODO: desc.\n" -msgstr "" -"Kaynağı sandbox'a kurar\n" -"\n" -"Kullanım: build-install \n" -"\n" - -#: pisi/cli/commands.py:1173 -msgid "" -"%prog [options] [arguments]\n" -"\n" -"where is one of:\n" -"\n" -msgstr "" -"%prog [seçenekler] [argümanlar]\n" -"\n" -" aşağıdakilerden birisi olabilir:\n" -"\n" - -#: pisi/cli/commands.py:1179 -msgid "" -"\n" -"Use \"%prog help \" for help on a specific command.\n" -msgstr "" -"\n" -"Belli bir komut hakkında yardım için \"%prog help \"'i kullanın.\n" - -#: pisi/cli/pisicli.py:92 -msgid "No command given" -msgstr "Komut verilmedi" - -#: pisi/cli/pisicli.py:96 -msgid "Command line parsing error" -msgstr "Komut satırı ayrıştırma hatası" - -#: pisi/comariface.py:35 -msgid "COMAR: comard not running or defunct" -msgstr "COMAR: comard calışmıyor ya da bozuk" - -#: pisi/comariface.py:38 -msgid "Registering COMAR script %s" -msgstr "COMAR betiği %s kayıt ediliyor" - -#: pisi/comariface.py:48 -msgid "COMAR.register ERROR!" -msgstr "COMAR kayıt hatası!" - -#: pisi/comariface.py:55 -msgid "Running post-install script for %s" -msgstr "%s için yerleştirme-sonrası betiği çalıştırılıyor." - -#: pisi/comariface.py:64 -msgid "COMAR.call_package(System.Package.postInstall, %s) failed!: %s" -msgstr "COMAR: call_package(System.Package.postInstall, %s) başarısız!: %s" - -# pisi/comariface.py:45 :65 -#: pisi/comariface.py:68 pisi/comariface.py:89 -msgid "COMAR.call_package ERROR: %d" -msgstr "COMAR.call_package hata: %d" - -#: pisi/comariface.py:76 -msgid "Running pre-remove script for %s" -msgstr "%s için kaldırma-öncesi betiği çalıştırılıyor." - -#: pisi/comariface.py:85 -msgid "COMAR.call_package(System.Package.preRemove, %s) failed!: %s" -msgstr "COMAR.call_package(System.Package.preRemove, %s) başarısız!: %s" - -#: pisi/comariface.py:92 -msgid "Unregistering COMAR scripts for %s" -msgstr "%s'in COMAR betikleri kayıttan siliniyor." - -#: pisi/component.py:117 -msgid "Information for component %s not available" -msgstr "Bileşen %s için bilgi bulunamadı" - -#: pisi/config.py:66 -msgid "Destination directory %s does not exist. Creating it." -msgstr "Hedef dizini %s bulunamadı. Yaratılıyor." - -#: pisi/configfile.py:89 -msgid "No section by name '%s'" -msgstr "'%s' diye bir bölüm yok." - -#: pisi/constants.py:32 -msgid "Can't rebind constant: %s" -msgstr "Sabit %s değiştirilemez" - -#: pisi/constants.py:38 -msgid "Can't unbind constant: %s" -msgstr "Sabit %s kaldırılamaz" - -#: pisi/dependency.py:98 -msgid "Package %s does not satisfy dependency %s" -msgstr "Paket %s %s bağımlılığını sağlamıyor." - -#: pisi/dependency.py:111 -msgid "Package %s is not present in the package database" -msgstr "Paket %s paket veritabanında bulunmamakta." - -#: pisi/fetcher.py:75 -msgid "Filename error" -msgstr "Dosya adı hatası" - -#: pisi/fetcher.py:78 -msgid "Access denied to write to dest dir" -msgstr "Hedef dizine yazmaya izin verilmedi." - -#: pisi/fetcher.py:131 -msgid "No such file or no permission to read" -msgstr "Öyle bir dosya yok ya da okuma izni yok." - -#: pisi/fetcher.py:154 -msgid "Cannot fetch %s; value error: %s" -msgstr "%s indirilemiyor, hata: %s" - -#: pisi/fetcher.py:156 pisi/fetcher.py:158 -msgid "Cannot fetch %s; %s" -msgstr "%s indirilemiyor; %s" - -#: pisi/fetcher.py:160 -msgid "Cannot fetch %s; (%s): %s" -msgstr "%s indirilemiyor; (%s): %s" - -#: pisi/fetcher.py:202 -msgid "Requested range not satisfiable" -msgstr "İstenen aralık sağlanamıyor." - -#: pisi/fetcher.py:241 pisi/fetcher.py:245 -msgid "Requested Range Not Satisfiable" -msgstr "İstenen aralık sağlanamıyor." - -#: pisi/fetcher.py:261 pisi/fetcher.py:282 pisi/fetcher.py:295 -msgid "ftp error" -msgstr "ftp hatası" - -#: pisi/index.py:71 -msgid "Adding %s to package index" -msgstr "%s paket indexine ekleniyor" - -#: pisi/index.py:74 -msgid "Adding %s to component index" -msgstr "%s bileşen dizinine ekleniyor" - -#: pisi/index.py:105 -msgid "Package %s: metadata corrupt" -msgstr "Paket %s: metadata bozuk" - -#: pisi/index.py:116 -msgid "Component in %s is corrupt" -msgstr "Bileşen: %s bozuk" - -#: pisi/index.py:120 -msgid "Adding %s to source index" -msgstr "%s kaynak dizinine ekleniyor" - -#: pisi/index.py:125 -msgid "SpecFile in %s is corrupt" -msgstr "SpecFile %s bozuk" - -#: pisi/installdb.py:60 -msgid "installed" -msgstr "yerleşik" - -#: pisi/installdb.py:60 -msgid "installed-pending" -msgstr "yerleşik-beklemede" - -#: pisi/installdb.py:61 -msgid "purged" -msgstr "temizlenmiş" - -#: pisi/installdb.py:61 -msgid "removed" -msgstr "kaldırılmış" - -#: pisi/installdb.py:64 -msgid "" -"State: %s\n" -"Version: %s, Release: %s, Build: %s\n" -msgstr "" -"Durum: %s\n" -"Versiyon: %s, Sürüm: %s, İnşa: %s\n" - -#: pisi/installdb.py:69 -msgid "Distribution: %s, Install Time: %s\n" -msgstr "Dağıtım: %s, Yerleştime Zamanı: %s\n" - -#: pisi/installdb.py:146 -msgid "Already installed" -msgstr "Halihazırda yerleştirilmiş." - -#: pisi/lockeddbshelve.py:42 -msgid "Cannot attain read or write access to database %s" -msgstr "Veritabanı %s için okuma ya da yazma erişimi edinilemedi" - -#: pisi/lockeddbshelve.py:66 -msgid "" -"Flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags" -msgstr "" -"Bayraklar 'r', 'w', 'c' or 'n'den birisi olmalı ya da bsddb.db.DB_* " -"bayraklarını kullanmalı" - -#: pisi/lockeddbshelve.py:78 -msgid "Another instance of PISI is running. Try later!" -msgstr "PISI bir yerde daha çalışıyor. Yine deneyin!" - -#: pisi/metadata.py:58 -msgid "Build: % s, Distribution: %s, Dist. Release: %s\n" -msgstr "İnşa: %s, Dağıtım: %s, Dağıtım Sürümü: %s\n" - -#: pisi/metadata.py:60 -msgid "Architecture: %s, Installed Size: %s\n" -msgstr "Mimari: %s, Yerleşik boyut: %s\n" - -#: pisi/operations.py:64 -msgid "Mixing file names and package names not supported yet." -msgstr "Dosya ve paket adlarını karıştırma henüz desteklenmiyor." - -#: pisi/operations.py:106 -msgid "" -"The following packages will be installed\n" -"in the respective order to satisfy extra dependencies:\n" -msgstr "" -"Bağımlılıkları sağlamak için bu minimal paket listesi\n" -" verilen sırada yerleştirilecek:\n" - -#: pisi/operations.py:109 pisi/operations.py:238 pisi/operations.py:372 -#: pisi/operations.py:434 -msgid "Do you want to continue?" -msgstr "Devam etmek istiyor musunuz?" - -#: pisi/operations.py:110 -msgid "External dependencies not satisfied" -msgstr "Dış bağımlılıklar sağlanmadı." - -# pisi/api.py:168 :215 -#: pisi/operations.py:122 pisi/operations.py:196 -msgid "No packages to install." -msgstr "Yerleştirilecek paket yok." - -#: pisi/operations.py:149 -msgid "Installation order: " -msgstr "Yerleştirme sırası: " - -#: pisi/operations.py:171 -msgid "Selected packages %s and %s are in conflict." -msgstr "Seçili paketler %s ve %s çakışıyorlar." - -#: pisi/operations.py:173 -msgid "Remove the following conflicting packages?" -msgstr "Bu çatışan paketleri kaldırayım mı?" - -#: pisi/operations.py:175 -msgid "Conflicts remain" -msgstr "Çakışmalar var" - -#: pisi/operations.py:234 -msgid "" -"The following minimal list of packages will be installed\n" -"in the respective order to satisfy dependencies:\n" -msgstr "" -"Bağımlılıkları sağlamak için bu minimal paket listesi verilen sırada\n" -"yerleştirilecek:\n" - -#: pisi/operations.py:261 -msgid "Warning: package *name* ends with '.pisi'" -msgstr "Uyarı: paket *adı* '.pisi' ile bitiyor." - -#: pisi/operations.py:263 -msgid "Package %s is not installed." -msgstr "Paket %s yerleştirilmemis." - -#: pisi/operations.py:281 -msgid "Package %s is already at its latest version %s, release %s, build %s." -msgstr "Paket %s zaten en son versiyon %s, sürüm %s, inşa %s'de." - -#: pisi/operations.py:287 -msgid "No packages to upgrade." -msgstr "Yükseltilecek paket yok." - -#: pisi/operations.py:338 pisi/operations.py:354 -msgid "Reverse dependency %s cannot be satisfied" -msgstr "Ters bağımlılık %s sağlanamadı" - -#: pisi/operations.py:369 -msgid "The following packages will be upgraded:\n" -msgstr "Bu paketler yükseltilecek: \n" - -#: pisi/operations.py:386 -msgid "Safety switch: cannot remove the following packages in system.base: " -msgstr "" -"Emniyet mandalı: taban sistem system.base deki izleyen paketleri " -"kaldırılamıyor" - -#: pisi/operations.py:390 -msgid "Safety switch: the component system.base cannot be found" -msgstr "Emniyet mandalı: taban sistem bileşeni system.base bulunamadı" - -#: pisi/operations.py:397 -msgid "Package %s does not exist. Cannot remove." -msgstr "Olmayan paket %s kaldırılamıyor." - -#: pisi/operations.py:401 -msgid "No packages to remove." -msgstr "Kaldıracak paket yok." - -#: pisi/operations.py:430 -msgid "" -"The following minimal list of packages will be removed\n" -"in the respective order to satisfy dependencies:\n" -msgstr "" -"İzleyen (en az sayıdaki) paketler bağımlılıkları sağlamak amacıyla\n" -"kaldırılacak:\n" - -#: pisi/operations.py:435 -msgid "Package removal declined" -msgstr "Paket kaldırmaya izin verilmedi." - -#: pisi/operations.py:441 -msgid "Package %s is not installed. Cannot remove." -msgstr "Paket %s kurulu değil. Kaldırılamıyor." - -#: pisi/package.py:53 pisi/sourcearchive.py:59 -msgid "%s [cached]" -msgstr "%s [önbellekte]" - -#: pisi/package.py:106 -msgid "MetaData format wrong" -msgstr "MetaData biçimi yanlış" - -#: pisi/packagedb.py:127 -msgid "get_package: package %s not found" -msgstr "get_package: paket %s bulunamadı" - -#: pisi/pxml/autoxml.py:85 -msgid "At least one '%s' tag should have local text" -msgstr "En azından bir tane '%s' etiketi yerel metne sahip olmalı" - -#: pisi/pxml/autoxml.py:93 -msgid "'%s' language of tag '%s' is empty" -msgstr "'%s' dili metni, etiket %s içerisinde, boş" - -#: pisi/pxml/autoxml.py:117 -msgid "LocalText: unable to get either current or default locale" -msgstr "" -"LocalText: şu andaki ya da ön tanımlı yerelleştirme seçenekleri (locale) " -"bulunamıyor" - -#: pisi/pxml/autoxml.py:123 pisi/pxml/autoxml.py:138 -msgid "" -"Tag should have at least the current locale, or failing that an English or " -"Turkish version" -msgstr "" -"Etiket en azından şu andaki yerel (locale) için bir girdiye, o olmazsa bir " -"Türkçe ya da İngilizce versiyona sahip olmalı" - -#: pisi/pxml/autoxml.py:356 -msgid "autoxml.check: '%s' errors" -msgstr "autoxml.check: %s hata" - -#: pisi/pxml/autoxml.py:408 pisi/pxml/autoxml.py:416 -msgid "autoxml.read: File '%s' has errors" -msgstr "autoxml.read: Dosya '%s' hatalara sahip" - -#: pisi/pxml/autoxml.py:423 -msgid "autoxml.write: object validation has failed" -msgstr "autoxml.write: nesne doğrulaması başarısızlığa uğradı" - -#: pisi/pxml/autoxml.py:431 -msgid "autoxml.write: File encoding '%s' has errors" -msgstr "autoxml.write: Dosya biçimlendirmesi '%s' hatalara sahip" - -#: pisi/pxml/autoxml.py:481 -msgid "gen_tag: unrecognized tag type %s in spec" -msgstr "gen_tag: tanınmayan tag tipi %s" - -#: pisi/pxml/autoxml.py:528 pisi/pxml/autoxml.py:539 -msgid "Mandatory variable %s not available" -msgstr "Gerekli değişken %s bulunamadı" - -#: pisi/pxml/autoxml.py:607 -msgid "Type mismatch: read text cannot be decoded" -msgstr "Tip uyumsuzluğu: okunan metin deşifre edilemedi" - -#: pisi/pxml/autoxml.py:611 pisi/pxml/autoxml.py:620 -msgid "Mandatory token %s not available" -msgstr "Gerekli im %s bulunamadı." - -#: pisi/pxml/autoxml.py:625 -msgid "Type mismatch. Expected %s, got %s" -msgstr "Tip uyumsuzluğu. %s beklerken, %s bulundu" - -# pisi/xmlfile.py:420 :521 -#: pisi/pxml/autoxml.py:655 pisi/pxml/autoxml.py:777 -msgid "Type mismatch: DOM cannot be decoded" -msgstr "Tip uyumsuzluğu: DOM deşifre edilemiyor" - -# pisi/xmlfile.py:392 :423 :439 :446 :524 :538 :545 -#: pisi/pxml/autoxml.py:658 pisi/pxml/autoxml.py:674 pisi/pxml/autoxml.py:684 -#: pisi/pxml/autoxml.py:780 pisi/pxml/autoxml.py:794 pisi/pxml/autoxml.py:804 -msgid "Mandatory argument not available" -msgstr "Gerekli argüman bulunamadı" - -# pisi/xmlfile.py:436 :535 -#: pisi/pxml/autoxml.py:671 pisi/pxml/autoxml.py:791 -msgid "Object cannot be encoded" -msgstr "Nesne kodlanamadı" - -#: pisi/pxml/autoxml.py:696 -msgid "List type must contain only one element" -msgstr "'List' tipi sadece bir eleman içermeli" - -# pisi/xmlfile.py:470 :485 -#: pisi/pxml/autoxml.py:709 pisi/pxml/autoxml.py:731 -msgid "Mandatory list empty" -msgstr "Zorunlu (mandatory) liste boş" - -#: pisi/pxml/xmlextcdom.py:58 pisi/pxml/xmlfilecdom.py:74 -msgid "File '%s' has invalid XML: %s" -msgstr "'%s' dosyasının XML sözdizimi geçersiz: %s" - -#: pisi/pxml/xmlextcdom.py:97 pisi/pxml/xmlextmdom.py:92 -#: pisi/pxml/xmlextpiks.py:61 -msgid "getNodeText: Expected text node, got something else!" -msgstr "getNodeText: metin bekliyorken başka birşey aldık!" - -#: pisi/pxml/xmlextmdom.py:53 pisi/pxml/xmlfilemdom.py:66 -#: pisi/pxml/xmlfilepiks.py:56 -msgid "File '%s' has invalid XML: %s\n" -msgstr "'%s' dosyasının XML sözdizimi geçersiz: %s\n" - -#: pisi/pxml/xmlfilecdom.py:76 -msgid "File '%s' not found" -msgstr "Dosya '%s' bulunamadı" - -#: pisi/pxml/xmlfilecdom.py:86 pisi/pxml/xmlfilemdom.py:77 -#: pisi/pxml/xmlfilepiks.py:67 -msgid "Root tagname %s not identical to %s as expected" -msgstr "Kök tag adı %s beklendiği gibi %s'le aynı değil." - -#: pisi/repodb.py:82 -msgid "Repository %s already exists" -msgstr "Depo %s halihazırda var" - -#: pisi/sourcearchive.py:68 -msgid "unpack: check_file_hash failed" -msgstr "unpack: check_file_hash başarısızlığa uğradı" - -#: pisi/sourcefetcher.py:87 -msgid "Fetching %s" -msgstr "%s'i indiriyor" - -#: pisi/specfile.py:139 -msgid "URI: %s, type: %s, sha1sum: %s" -msgstr "URI: %s, tip: %s, sha1sum: %s" - -#: pisi/specfile.py:197 -msgid "Name: %s, version: %s, release: %s, build %s\n" -msgstr "Ad: %s, versiyon %s, sürüm %s, inşa %s\n" - -#: pisi/specfile.py:199 -msgid "Summary: %s\n" -msgstr "Özet: %s\n" - -#: pisi/specfile.py:200 -msgid "Description: %s\n" -msgstr "Tanım: %s\n" - -#: pisi/specfile.py:201 -msgid "Component: %s\n" -msgstr "Bileşen: %s\n" - -#: pisi/specfile.py:202 -msgid "Provides: " -msgstr "Sağladıkları: " - -#: pisi/uri.py:78 -msgid "setAuthInfo needs a tuple (user, pass)" -msgstr "setAuthInfo bir (kullanıcı, parola) ikilisi ister. Sen ne yapıyorsun? " - -#: pisi/util.py:60 -msgid "%s section should have a '%s' tag" -msgstr "%s bölümünün bir '%s' etiketi olmalı" - -#: pisi/util.py:130 -msgid "running " -msgstr "çalıştırıyor " - -#: pisi/util.py:134 -msgid "return value %s" -msgstr "dönüş değeri %s" - -#: pisi/util.py:137 -msgid "Failed command: %s" -msgstr "Başarısız komut: %s" - -#: pisi/util.py:293 -msgid "Including external link '%s'" -msgstr "Harici bağ %s içeriliyor" - -#: pisi/util.py:295 -msgid "Including directory '%s'" -msgstr "%s dizini içeriliyor" - -#: pisi/util.py:367 -msgid "I/O Error: Cannot calculate SHA1 hash of %s" -msgstr "Girdi/Çıktı hatası: %s'in SHA1 hash'i hesaplanamıyor" - -#: pisi/util.py:376 -msgid "Cannot calculate SHA1 hash of given data" -msgstr "Verinin SHA1 hash'i hesaplanamıyor" - -#: pisi/util.py:412 -msgid "ERROR: patch (%s) failed: %s" -msgstr "Yama (%s) başarısız: %s" - -#: pisi/util.py:455 -msgid "strip command failed for file '%s'!" -msgstr "strip komutu '%s' dosyası için çalışmadı!" - -#: pisi/util.py:482 -msgid "Removing lock %s" -msgstr "Kilit %s kaldırılıyor." - -#: pisi/util.py:515 -msgid "Updating environment..." -msgstr "Çevre güncelleniyor..." - -#: tools/repostats.py:337 -msgid "" -"Duplicate binary packages:\n" -"%s\n" -"%s\n" -msgstr "" -"Kopyalanmış ikili paketler:\n" -"%s\n" -"%s\n" - -#: tools/repostats.py:342 -msgid "Unknown file type '%s' in package '%s'" -msgstr "Bilinmeyen dosya tiği '%s', '%s' paketi içinde bulundu. " - -#: tools/repostats.py:398 -msgid "" -"Duplicate source packages:\n" -"%s\n" -"%s\n" -msgstr "" -"Kopyalanmış kaynak paketleri:\n" -"%s\n" -"%s\n" - -#: tools/repostats.py:418 -msgid "Source package '%s' has wrong date format '%s'" -msgstr "Kaynak paketi '%s' yanlış tarih biçimlendirmesine sahip: '%s'" - -#: tools/repostats.py:431 -msgid "Source package '%s' has wrong release numbers" -msgstr "" - -#: tools/repostats.py:435 -msgid "Source package '%s' lacks release %d" -msgstr "" - -#: tools/repostats.py:443 -msgid "Source package '%s' has no first release" -msgstr "" - -#: tools/repostats.py:478 -msgid "" -"Developer '%s <%s>' has another mail address '%s' in source package '%s'" -msgstr "" - -#: tools/repostats.py:561 -#, fuzzy -msgid "" -"Cannot parse '%s':\n" -"%s\n" -msgstr "%s indirilemiyor; %s" - -#: tools/repostats.py:639 -msgid "Usage: repostats.py [OPTIONS] source-repo-path [binary-repo-path]\n" -msgstr "" - -#: tools/repostats.py:640 -msgid "Dont generate the web site.\n" -msgstr "" - -#: tools/repostats.py:661 -msgid "Scanning source repository...\n" -msgstr "" - -#: tools/repostats.py:665 -msgid "Scanning binary packages...\n" -msgstr "" - -#: tools/repostats.py:670 -msgid "Encountered %d errors! Fix them immediately!\n" -msgstr "" - -#: tools/repostats.py:678 -msgid "These dependencies are not available in repository:\n" -msgstr "" diff --git a/tags/pisi-1.0_beta2/setup.py b/tags/pisi-1.0_beta2/setup.py deleted file mode 100755 index 8ce9de2d..00000000 --- a/tags/pisi-1.0_beta2/setup.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Authors: {eray,gurer}@uludag.org.tr - -import os -import shutil -import glob -import sys -from distutils.core import setup -from distutils.command.install import install - -sys.path.insert(0, '.') -import pisi - -i18n_domain = "pisi" -i18n_languages = "tr" - -class Install(install): - def run(self): - install.run(self) - self.installi18n() - self.installdoc() - - def installi18n(self): - for lang in i18n_languages.split(' '): - print "Installing '%s' translations..." % lang - os.popen("msgfmt po/%s.po -o po/%s.mo" % (lang, lang)) - if not self.root: - self.root = "/" - destpath = os.path.join(self.root, "usr/share/locale/%s/LC_MESSAGES" % lang) - try: - os.makedirs(destpath) - except: - pass - shutil.copy("po/%s.mo" % lang, os.path.join(destpath, "%s.mo" % i18n_domain)) - - def installdoc(self): - destpath = os.path.join(self.root, "usr/share/doc/pisi") - try: - os.makedirs(destpath) - except: - pass - os.chdir('doc') - for pdf in glob.glob('*.pdf'): - print 'Installing', pdf - shutil.copy(pdf, os.path.join(destpath, pdf)) - os.chdir('..') - -setup(name="pisi", - version= pisi.__version__, - description="PISI (Packages Installed Successfully as Intended)", - long_description="PISI is the package management system of Pardus Linux.", - license="GNU GPL2", - author="Pardus Developers", - author_email="pisi@uludag.org.tr", - url="http://www.uludag.org.tr/eng/pisi/", - package_dir = {'': ''}, - packages = ['pisi', 'pisi.cli', 'pisi.actionsapi', 'pisi.pxml'], - scripts = ['pisi-cli', 'tools/ebuild2pisi.py', 'tools/repostats.py', - 'tools/find-lib-deps.py', 'tools/update-environ.py', - 'tools/lspisi'], - cmdclass = { - 'install' : Install - } - ) - -# the below stuff is really nice but we already have a version -# we can use this stuff for svn snapshots in a separate -# script -- exa - -PISI_VERSION = pisi.__version__ - -def getRevision(): - import os - try: - p = os.popen("svn info 2> /dev/null") - for line in p.readlines(): - line = line.strip() - if line.startswith("Revision:"): - return line.split(":")[1].strip() - except: - pass - - # doesn't working in a Subversion directory - return None - -def getVersion(): - rev = getRevision() - if rev: - return "-r".join([PISI_VERSION, rev]) - else: - return PISI_VERSION diff --git a/tags/pisi-1.0_beta2/tests/README b/tags/pisi-1.0_beta2/tests/README deleted file mode 100644 index 4ab7e004..00000000 --- a/tags/pisi-1.0_beta2/tests/README +++ /dev/null @@ -1,10 +0,0 @@ -PISI test suite ---------------- - - -There are python unit tests and shell scripts in this directory. - -Shell scripts use the CLIs to perform package operations. - -For this there must be a symlink "packages" to the PISI package repository -until we can find a few sample packages to put here. diff --git a/tags/pisi-1.0_beta2/tests/a.xml b/tags/pisi-1.0_beta2/tests/a.xml deleted file mode 100644 index ee6a6e29..00000000 --- a/tags/pisi-1.0_beta2/tests/a.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - cıvık mantardır bu - Eray Ozkural - 868 - Lazy Tin - Tembel Teneke - pisi - noatun - kdevelop - - 18071976 - AI - - Baris - Gurer - Caglar - Meren - - - diff --git a/tags/pisi-1.0_beta2/tests/actionsapitests.py b/tags/pisi-1.0_beta2/tests/actionsapitests.py deleted file mode 100644 index 30cf65af..00000000 --- a/tags/pisi-1.0_beta2/tests/actionsapitests.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -import unittest -import zipfile - -import testcase - -class ActionsAPITestCase(testcase.TestCase): - def setUp(self): - testcase.TestCase.setUp(self) - #FIXME: test incomplete - return - self.f = zipfile.ZipFile("helloworld-0.1-1.pisi", "r") - self.filelist = [] - - for file in self.f.namelist(): - self.filelist.append(file) - - def testFileList(self): - #FIXME: test incomplete - return - fileContent = ["files.xml", \ - "install/bin/helloworld", \ - "install/opt/PARDUS", \ - "install/opt/helloworld/helloworld", \ - "install/opt/uludag", \ - "install/sbin/helloworld", \ - "install/sys/PARDUS", \ - "install/sys/uludag", \ - "install/usr/bin/goodbye", \ - "install/usr/bin/helloworld", \ - "install/usr/lib/helloworld.o", \ - "install/usr/sbin/goodbye", \ - "install/usr/sbin/helloworld", \ - "install/usr/share/doc/helloworld-0.1-1/Makefile.am", \ - "install/usr/share/doc/helloworld-0.1-1/goodbyeworld.cpp", \ - "install/usr/share/info/Makefile.am", \ - "install/usr/share/info/Makefile.cvs", \ - "install/usr/share/info/Makefile.in", \ - "install/var/goodbye", \ - "install/var/hello", \ - "metadata.xml"] - - '''check number of files in package''' - self.assertEqual(fileContent.__len__(), self.filelist.__len__()) - - '''check file content''' - for file in self.filelist: - self.assert_(fileContent.__contains__(file)) - -suite = unittest.makeSuite(ActionsAPITestCase) diff --git a/tags/pisi-1.0_beta2/tests/archivetests.py b/tags/pisi-1.0_beta2/tests/archivetests.py deleted file mode 100644 index c292f893..00000000 --- a/tags/pisi-1.0_beta2/tests/archivetests.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os -from os.path import exists as pathexists -from os.path import basename, islink, join - -import pisi.context as ctx -import pisi.api -from pisi import archive -from pisi import sourcearchive -from pisi import fetcher -from pisi import util -from pisi.build import BuildContext -from pisi import uri - -import testcase - -class ArchiveFileTestCase(testcase.TestCase): - - def testUnpackTar(self): - bctx = BuildContext("tests/popt/pspec.xml") - - achv = sourcearchive.SourceArchive(bctx) - - assert bctx.spec.source.archive.type == "targz" - - # skip fetching and directly unpack the previously fetched (by - # fetchertests) archive - if not achv.is_cached(interactive=False): - achv.fetch(interactive=False) - achv.unpack() - - targetDir = bctx.pkg_work_dir() - # but testing is hard - # "var/tmp/pisi/popt-1.7-3/work" (targetDir) - assert pathexists(targetDir + "/popt-1.7") - - testfile = targetDir + "/popt-1.7/Makefile.am" - assert pathexists(testfile) - - # check file integrity - self.assertEqual(util.sha1_file(testfile), - "5af9dd7d754f788cf511c57ce0af3d555fed009d") - - def testUnpackZip(self): - bctx = BuildContext("tests/pccts/pspec.xml") - - assert bctx.spec.source.archive.type == "zip" - - achv = sourcearchive.SourceArchive(bctx) - achv.fetch(interactive=False) - achv.unpack(clean_dir=True) - - targetDir = bctx.pkg_work_dir() - assert pathexists(targetDir + "/pccts") - - testfile = targetDir + "/pccts/history.txt" - assert pathexists(testfile) - - # check file integrity - self.assertEqual(util.sha1_file(testfile), - "f2be0f9783e84e98fe4e2b8201a8f506fcc07a4d") - -# TODO: no link file in pccts package. Need to find a ZIP file -# containing a symlink - # check for symbolic links -# testfile = targetDir + "/sandbox/testdir/link1" -# assert islink(testfile) - - def testMakeZip(self): - # first unpack our dear sandbox.zip - bctx = BuildContext("tests/pccts/pspec.xml") - targetDir = bctx.pkg_work_dir() - achv = sourcearchive.SourceArchive(bctx) - achv.fetch(interactive=False) - achv.unpack(clean_dir=True) - del achv - - newZip = targetDir + "/new.zip" - zip = archive.ArchiveZip(newZip, 'zip', 'w') - sourceDir = targetDir + "/pccts" - zip.add_to_archive(sourceDir) - zip.close() - - #TODO: do some more work to test the integrity of new zip file - - def testUnpackZipCond(self): - bctx = BuildContext("tests/pccts/pspec.xml") - url = uri.URI(bctx.spec.source.archive.uri) - targetDir = bctx.pkg_work_dir() - filePath = join(ctx.config.archives_dir(), url.filename()) - - # check cached - if util.sha1_file(filePath) != bctx.spec.source.archive.sha1sum: - fetch = fetcher.Fetcher(bctx.spec.source.archive.uri, targetDir) - fetch.fetch() - assert bctx.spec.source.archive.type == "zip" - - achv = archive.Archive(filePath, bctx.spec.source.archive.type) - achv.unpack_files(["pccts/history.txt"], targetDir) - assert pathexists(targetDir + "/pccts") - testfile = targetDir + "/pccts/history.txt" - assert pathexists(testfile) - -suite = unittest.makeSuite(ArchiveFileTestCase) diff --git a/tags/pisi-1.0_beta2/tests/autoxmltests.py b/tags/pisi-1.0_beta2/tests/autoxmltests.py deleted file mode 100644 index c24400f5..00000000 --- a/tags/pisi-1.0_beta2/tests/autoxmltests.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os -import xml.dom.minidom as mdom -from xml.parsers.expat import ExpatError -import types - -import pisi -import pisi.api -from pisi.pxml import xmlfile -from pisi.pxml import autoxml -import pisi.util as util - -class AutoXmlTestCase(unittest.TestCase): - - def setUp(self): - - class OtherInfo: - __metaclass__ = autoxml.autoxml - t_BirthDate = [types.StringType, autoxml.mandatory] - t_Interest = [types.StringType, autoxml.optional] - t_CodesWith = [ [types.StringType], autoxml.optional, 'CodesWith/Person'] - - class A(xmlfile.XmlFile): - __metaclass__ = autoxml.autoxml - t_Name = [types.StringType, autoxml.mandatory] - t_Description = [autoxml.LocalText, autoxml.mandatory] - t_Number = [types.IntType, autoxml.optional] - t_Email = [types.StringType, autoxml.optional] - a_href = [types.StringType, autoxml.mandatory] - t_Projects = [ [types.StringType], autoxml.mandatory, 'Project'] - t_OtherInfo = [ OtherInfo, autoxml.optional ] - s_Comment = [ autoxml.Text, autoxml.mandatory] - - self.A = A - - def testDeclaration(self): - self.assertEqual(len(self.A.decoders), 8) # how many fields in A? - self.assert_(hasattr(self.A, 'encode')) - - def testReadWrite(self): - a = self.A() - - # test initializer - self.assertEqual(a.href, None) - - # test read - a.read('tests/a.xml') - self.assert_(a.href.startswith('http')) - self.assertEqual(a.number, 868) - self.assertEqual(a.name, 'Eray Ozkural') - self.assertEqual(len(a.projects), 3) - self.assertEqual(len(a.otherInfo.codesWith), 4) - - self.assert_(not a.errors()) - - a.print_text(file('/tmp/a', 'w')) - la = file('/tmp/a').readlines() - self.assert_( util.any(lambda x:x.find('18071976')!=-1, la) ) - a.write('/tmp/a.xml') - - def testWriteRead(self): - a = self.A() - a.name = "Baris Metin" - a.email = "baris@uludag.org.tr" - a.description['tr'] = u'Melek, melek' - a.comment = u'Bu da zibidi aslinda ama caktirmiyor' - a.href = 'http://cekirdek.uludag.org.tr/~baris' - a.otherInfo.birthDate = '30101979' - a.projects = [ 'pisi', 'tasma', 'plasma' ] - errs = a.errors() - if errs: - self.fail( 'We got a bunch of errors: ' + str(errs)) - a.write('/tmp/a2.xml') - a2 = self.A() - a2.read('/tmp/a2.xml') - self.assertEqual(a, a2) - -class LocalTextTestCase(unittest.TestCase): - - def setUp(self): - a = autoxml.LocalText() - a['tr'] = u'Zibidi' - a['en'] = u'ingiliz hiyarlari ne anlar zibididen' - self.a = a - - def testStr(self): - s = str(self.a) - self.assert_(s!= None and len(s)>=6) - -suite1 = unittest.makeSuite(AutoXmlTestCase) -suite2 = unittest.makeSuite(LocalTextTestCase) -suite = unittest.TestSuite((suite1, suite2)) diff --git a/tags/pisi-1.0_beta2/tests/beta-build.sh b/tags/pisi-1.0_beta2/tests/beta-build.sh deleted file mode 100755 index baea18d0..00000000 --- a/tags/pisi-1.0_beta2/tests/beta-build.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -echo "beta functionality test script" -echo "working directory:" `pwd` -echo "cleaning destination dir: tmp" -PATH=$PATH:. -set -x # xtrace -set -e # errexit -rm -rf tmp -#echo "*** build tests" -pisi-cli -Dtmp build http://svn.uludag.org.tr/pardus/pardus-devel/system/base/zip/pspec.xml http://svn.uludag.org.tr/pardus/pardus-devel/system/base/unzip/pspec.xml - -#partial-builds -pisi-cli -Dtmp build-setup http://svn.uludag.org.tr/pardus/pardus-devel/system/base/hdparm/pspec.xml -pisi-cli -Dtmp build-build http://svn.uludag.org.tr/pardus/pardus-devel/system/base/hdparm/pspec.xml -pisi-cli -Dtmp build-install http://svn.uludag.org.tr/pardus/pardus-devel/system/base/hdparm/pspec.xml -pisi-cli -Dtmp build-package http://svn.uludag.org.tr/pardus/pardus-devel/system/base/hdparm/pspec.xml - -#echo "*** repository tests" - -pisi-cli -Dtmp index . -pisi-cli -Dtmp add-repo repo1 pisi-index.xml -pisi-cli -Dtmp update-repo repo1 -pisi-cli -Dtmp list-repo - -#echo "*** package ops" -pisi-cli -Dtmp info *.pisi -# pisi-cli list-available -pisi-cli -Dtmp install --ignore-comar zip -pisi-cli -Dtmp list-installed -pisi-cli -Dtmp remove --ignore-comar unzip -pisi-cli -Dtmp install --ignore-comar zip*.pisi -pisi-cli -Dtmp install --ignore-comar hdparm*.pisi flex*.pisi grep*.pisi -pisi-cli -Dtmp remove-repo repo1 -# pisi-cli list-available - -echo "*** database contents" -for x in `find tmp -iname '*.bdb'`; do - echo "contents of database " $x; - tools/cat-db.py $x; -done diff --git a/tags/pisi-1.0_beta2/tests/beta-light.sh b/tags/pisi-1.0_beta2/tests/beta-light.sh deleted file mode 100755 index a5cff0a2..00000000 --- a/tags/pisi-1.0_beta2/tests/beta-light.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -pwd -PATH=$PATH:. -set -x -mkdir tmp -pisi-cli -Dtmp clean -pisi-cli -B -Dtmp remove unzip -pisi-cli -Dtmp remove-repo repo1 -set -e -pisi-cli -Dtmp -E --ignore-build-no build tests/zip/pspec.xml tests/unzip/pspec.xml -pisi-cli -Dtmp index . -pisi-cli -Dtmp -d add-repo repo1 pisi-index.xml -pisi-cli -Dtmp list-repo -pisi-cli -Dtmp update-repo repo1 -pisi-cli -Dtmp list-available -pisi-cli -Dtmp --ignore-comar -y install zip -pisi-cli -Dtmp list-installed -pisi-cli -Dtmp --ignore-comar -y remove unzip -pisi-cli -Dtmp info zip*.pisi -pisi-cli -d -Dtmp --ignore-comar -y install zip*.pisi -pisi-cli -Dtmp list-pending -pisi-cli -Dtmp configure-pending diff --git a/tags/pisi-1.0_beta2/tests/beta-remoterepo.sh b/tags/pisi-1.0_beta2/tests/beta-remoterepo.sh deleted file mode 100755 index 4bee52df..00000000 --- a/tags/pisi-1.0_beta2/tests/beta-remoterepo.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -export PATH=$PATH:. -set -x # xtrace -set -e # errexit - -echo "beta functionality test script for testing remote repos" -echo "working directory:" `pwd` -echo "cleaning destination dir: tmp" -rm -rf tmp -#echo "*** repository tests" -pisi-cli -Dtmp add-repo pardus http://paketler.uludag.org.tr/pardus-devel/pisi-index.xml -pisi-cli -Dtmp update-repo pardus -pisi-cli -Dtmp list-repo - -#echo "*** package ops" -pisi-cli -Dtmp list-available -pisi-cli -Dtmp info python -pisi-cli -Dtmp -By install python - -echo "*** database contents" -for x in `find tmp -iname '*.bdb'`; do - echo "contents of database " $x; - tools/cat-db.py $x; -done diff --git a/tags/pisi-1.0_beta2/tests/beta-upgrade.sh b/tags/pisi-1.0_beta2/tests/beta-upgrade.sh deleted file mode 100755 index 6241c301..00000000 --- a/tags/pisi-1.0_beta2/tests/beta-upgrade.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -pwd -PATH=$PATH:. -set -x -e - -pisi-cli -Dtmp -E --ignore-build-no build tests/zip/pspec.xml tests/unzip/pspec.xml -pisi-cli -Dtmp --yes-all --ignore-comar install unzip-5.50-1.pisi zip-2.3-1.pisi - -mkdir -p myrepo -cd myrepo -mkdir -p tmp -../pisi-cli -Dtmp -E --ignore-build-no build ../tests/zip2/pspec.xml ../tests/unzip2/pspec.xml -cd .. -pisi-cli -Dtmp --absolute-uris index myrepo -pisi-cli -Dtmp remove-repo repo1 -pisi-cli -Dtmp add-repo repo1 pisi-index.xml -pisi-cli -Dtmp list-repo -pisi-cli -Dtmp update-repo repo1 -pisi-cli -Dtmp list-available -pisi-cli -Dtmp --install-info list-installed -pisi-cli -Dtmp list-upgrades -pisi-cli -Dtmp --ignore-comar upgrade zip -pisi-cli -Dtmp --install-info list-installed diff --git a/tags/pisi-1.0_beta2/tests/configfiletests.py b/tags/pisi-1.0_beta2/tests/configfiletests.py deleted file mode 100644 index 70722aa3..00000000 --- a/tags/pisi-1.0_beta2/tests/configfiletests.py +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest - -from pisi.configfile import ConfigurationFile - -# NB: no need for pisi testcase in these things that do well without pisi init -class ConfigFileTestCase(unittest.TestCase): - - def setUp(self): - self.cf = ConfigurationFile("tests/pisi.conf") - - def testSections(self): - cf = self.cf - if not cf.general: - self.fail("No 'general' section found in ConfigurationFile") - if not cf.build: - self.fail("No 'build' section found in ConfigurationFile") - if not cf.dirs: - self.fail("No 'dirs' section found in ConfigurationFile") - - def testValues(self): - cf = self.cf - - # test values from pisi.conf file - self.assertEqual(cf.general.destinationdirectory, "/testing") - self.assertEqual(cf.dirs.archives_dir, "/disk2/pisi/archives") - - # test default values - self.assertEqual(cf.dirs.tmp_dir, "/var/tmp/pisi") - - def testAccessMethods(self): - cf = self.cf - - self.assertEqual(cf.build.host, cf.build["host"]) - self.assertEqual(cf.dirs.index_dir, cf.dirs["index_dir"]) - - def testFlagsExists(self): - cf = self.cf - - #build - self.assert_(cf.build.CFLAGS) - self.assert_(cf.build.CXXFLAGS) - - #general - self.assert_(cf.general.destinationdirectory) - - #dirs - self.assert_(cf.dirs.index_dir) - self.assert_(cf.dirs.tmp_dir) - self.assert_(cf.dirs.packages_dir) - -suite = unittest.makeSuite(ConfigFileTestCase) diff --git a/tags/pisi-1.0_beta2/tests/constantstests.py b/tags/pisi-1.0_beta2/tests/constantstests.py deleted file mode 100644 index 45a61b1c..00000000 --- a/tags/pisi-1.0_beta2/tests/constantstests.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest - -import pisi.context as ctx - -class ContextTestCase(unittest.TestCase): - - def testConstness(self): - const = ctx.const - - # test if we can get a const attribute? - try: - test = const.package_suffix - self.assertNotEqual(test, "") - except AttributeError: - self.fail("Couldn't get const attribute") - - # test binding a new constant - const.test = "test binding" - - # test re-binding (which is illegal) - try: - const.test = "test rebinding" - # we shouldn't reach here - self.fail("Rebinding a constant works. Something is wrong!") - except: - # we achived our goal with this error. infact, this is a - # ConstError but we can't catch it directly here - pass - - # test unbinding (which is also illegal) - try: - del const.test - # we shouldn't reach here - self.fail("Unbinding a constant works. Something is wrong!") - except: - # we achived our goal with this error. infact, this is a - # ConstError but we can't catch it directly here - pass - - def testConstValues(self): - const = ctx.const - - constDict = { - "actions_file": "actions.py", - "setup_func": "setup", - "metadata_xml": "metadata.xml" - } - - for k in constDict.keys(): - if hasattr(const, k): - value = getattr(const, k) - self.assertEqual(value, constDict[k]) - else: - self.fail("Constants does not have an attribute named %s" % k) - - -suite = unittest.makeSuite(ContextTestCase) diff --git a/tags/pisi-1.0_beta2/tests/dependencytests.py b/tags/pisi-1.0_beta2/tests/dependencytests.py deleted file mode 100644 index 23c7e54f..00000000 --- a/tags/pisi-1.0_beta2/tests/dependencytests.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Author: Eray Ozkural - -import unittest -import os - -from pisi.dependency import * - -class DependencyTestCase(unittest.TestCase): - def setUp(self): - pass - - def testDep(self): - # a real life story bug #603 - gtkmmdep = Dependency() - gtkmmdep.versionFrom = '1.9.1' - gtkmmdep.package = 'atk' - self.assert_( not gtkmmdep.satisfies('atk', '1.8.0', 1) ) - -suite = unittest.makeSuite(DependencyTestCase) diff --git a/tags/pisi-1.0_beta2/tests/fetchertests.py b/tags/pisi-1.0_beta2/tests/fetchertests.py deleted file mode 100644 index ed7b2f47..00000000 --- a/tags/pisi-1.0_beta2/tests/fetchertests.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import shutil -import os - -import pisi.context as ctx -import pisi.api -from pisi.specfile import SpecFile -from pisi import fetcher -from pisi import util -from pisi import uri - -import testcase -class FetcherTestCase(testcase.TestCase): - def setUp(self): - testcase.TestCase.setUp(self, database = False) - - self.spec = SpecFile() - self.spec.read("tests/helloworld/pspec.xml") - self.url = uri.URI(self.spec.source.archive.uri) - self.destpath = ctx.config.archives_dir() - self.fetch = fetcher.Fetcher(self.url, self.destpath) - - def testFetch(self): - self.fetch.fetch() - fetchedFile = os.path.join(self.destpath, self.url.filename()) - if os.access(fetchedFile, os.R_OK): - self.assertEqual(util.sha1_file(fetchedFile), - self.spec.source.archive.sha1sum) - os.remove(fetchedFile) - - def testResume(self): - resume_test_file = "tests/helloworld/hello-1.3.tar.gz.part" - shutil.copy(resume_test_file, ctx.config.archives_dir()) - self.fetch.fetch() - fetchedFile = os.path.join(self.destpath, self.url.filename()) - if os.access(fetchedFile, os.R_OK): - self.assertEqual(util.sha1_file(fetchedFile), - self.spec.source.archive.sha1sum) - os.remove(fetchedFile) - -suite = unittest.makeSuite(FetcherTestCase) diff --git a/tags/pisi-1.0_beta2/tests/filestests.py b/tags/pisi-1.0_beta2/tests/filestests.py deleted file mode 100644 index 0779883b..00000000 --- a/tags/pisi-1.0_beta2/tests/filestests.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi.context as ctx -import pisi.api -import pisi.installdb -import pisi.files as files -from pisi import util - -import testcase - -class FilesTestCase(testcase.TestCase): - - def setUp(self): - testcase.TestCase.setUp(self, database=False) - - def testFileInfo(self): - f1 = files.File(path = '/usr/bin/zibidi') - f2 = files.File(path = '/usr/bin/kopus', type='exec', size=13, hash="abugubu") - -suite = unittest.makeSuite(FilesTestCase) diff --git a/tags/pisi-1.0_beta2/tests/graphtests.py b/tags/pisi-1.0_beta2/tests/graphtests.py deleted file mode 100644 index 6249fd31..00000000 --- a/tags/pisi-1.0_beta2/tests/graphtests.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -from pisi import graph - -class GraphTestCase(unittest.TestCase): - def setUp(self): - self.g0 = graph.Digraph() - self.g0.from_list([ (1,2), (1,3), (2,3), (3,4), (4, 5), (4,1)]) - - self.g1 = graph.Digraph() - self.g1.from_list([ (0,2), (0,3), (3,4), (2,4), (0,5), (5,4) ]) - - def testCycle(self): - self.assert_(not self.g0.cycle_free()) - self.assert_(self.g1.cycle_free()) - - def testTopologicalSort(self): - order = self.g1.topological_sort() - self.assertEqual(order[0], 0) - self.assertEqual(order[len(order)-1], 4) - -suite = unittest.makeSuite(GraphTestCase) diff --git a/tags/pisi-1.0_beta2/tests/helloworld/actions.py b/tags/pisi-1.0_beta2/tests/helloworld/actions.py deleted file mode 100644 index da6b1f5c..00000000 --- a/tags/pisi-1.0_beta2/tests/helloworld/actions.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -from pisi.actionsapi import autotools -from pisi.actionsapi import pisitools -from pisi.actionsapi import shelltools -from pisi.actionsapi import libtools -from pisi.actionsapi import get - -WorkDir = "helloworld" - -def setup(): - autotools.configure() - -def build(): - autotools.make() - -def install(): - autotools.install() - - '''/opt/helloworld/''' - pisitools.dodir("/opt/helloworld") - - '''/usr/share/doc/helloworld-0.1-1/Makefile.am''' - pisitools.dodoc("Makefile.am") - - '''/opt/helloworld/helloworld''' - pisitools.doexe("src/helloworld", "/opt/helloworld") - - '''/usr/share/info/Makefile.am''' - '''/usr/share/info/Makefile.cvs''' - '''/usr/share/info/Makefile.in''' - pisitools.doinfo("Makefile.*") - - '''/usr/lib/helloworld.o''' - pisitools.dolib("src/helloworld.o") - - '''/opt/hello''' - pisitools.insinto("/opt/", "src/helloworld", "hello") - '''/opt/hi''' - pisitools.insinto("/opt/", "src/helloworld", "hi") - - '''/opt/hello -> /var/hello''' - pisitools.domove("/opt/hello", "/var/") - '''/opt/hi -> /var/goodbye''' - pisitools.domove("/opt/hi", "/var/", "goodbye") - - '''/usr/bin/helloworld''' - pisitools.dobin("src/helloworld") - '''/bin/helloworld''' - pisitools.dobin("src/helloworld", "/bin") - - '''/usr/sbin/helloworld''' - pisitools.dosbin("src/helloworld") - '''/sbin/helloworld''' - pisitools.dosbin("src/helloworld", "/sbin") - - '''Hello, world! -> Goodbye, world!''' - pisitools.dosed("src/helloworld.cpp", "Hello, world!", "Goodbye, world!") - - '''/usr/sbin/goodbye --> helloworld''' - pisitools.dosym("helloworld", "/usr/sbin/goodbye") - '''/usr/bin/goodbye --> helloworld''' - pisitools.dosym("helloworld", "/usr/bin/goodbye") - - '''/home/pardus/''' - pisitools.dodir("/home/pardus") - '''delete pardus''' - pisitools.removeDir("/home/pardus") - '''delete home''' - pisitools.removeDir("/home") - - '''src/helloworld.cpp --> /usr/share/doc/helloworld-0.1-1/goodbyeworld.cpp''' - pisitools.newdoc("src/helloworld.cpp", "goodbyeworld.cpp") - - '''/opt/pardus''' - shelltools.touch("%s/opt/pardus" % get.installDIR()) - - '''/opt/pardus --> /opt/uludag''' - shelltools.copy("%s/opt/pardus" % get.installDIR(), "%s/opt/uludag" % get.installDIR()) - '''/opt/pardus --> /opt/Pardus''' - shelltools.move("%s/opt/pardus" % get.installDIR(), "%s/opt/PARDUS" % get.installDIR()) - - '''/opt/ --> /sys/''' - shelltools.copytree("%s/opt/" % get.installDIR(), "%s/sys/" % get.installDIR()) - - '''delete /sys/helloworld/helloworld''' - shelltools.unlink("%s/sys/helloworld/helloworld" % get.installDIR()) - '''delete /sys/helloworld''' - shelltools.unlinkDir("%s/sys/helloworld" % get.installDIR()) - - '''generate /usr/lib/helloworld.o''' - libtools.gen_usr_ldscript("helloworld.o") diff --git a/tags/pisi-1.0_beta2/tests/helloworld/hello-1.3.tar.gz.part b/tags/pisi-1.0_beta2/tests/helloworld/hello-1.3.tar.gz.part deleted file mode 100644 index 0ecf0493b3b99450f4595dff4a6ea5d129b87d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11520 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 diff --git a/tags/pisi-1.0_beta2/tests/helloworld/pspec.xml b/tags/pisi-1.0_beta2/tests/helloworld/pspec.xml deleted file mode 100644 index 936871f2..00000000 --- a/tags/pisi-1.0_beta2/tests/helloworld/pspec.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - helloworld - http://www.uludag.org.tr - - S.Çağlar Onur - caglar@uludag.org.tr - - GPL-2 - category - component - Dummy HelloWorld for testing ActionsAPI - Dummy HelloWorld for testing ActionsAPI - http://cekirdek.uludag.org.tr/~eray/hello-1.3.tar.gz - - - - helloworld - - / - - - - - - 2005-08-21 - 0.1 - - - - diff --git a/tags/pisi-1.0_beta2/tests/installdbtests.py b/tags/pisi-1.0_beta2/tests/installdbtests.py deleted file mode 100644 index 7d4f9eee..00000000 --- a/tags/pisi-1.0_beta2/tests/installdbtests.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi.context as ctx -import pisi.api -import pisi.installdb -from pisi import util - -import testcase -class InstallDBTestCase(testcase.TestCase): - - def testRemoveDummy(self): - ctx.installdb.remove('installtest') - self.assert_(not ctx.installdb.is_installed('installtest')) - - def testInstall(self): - ctx.installdb.purge('installtest') - ctx.installdb.install('installtest', '0.1', '2', '3') - - def testRemovePurge(self): - ctx.installdb.install('installtest', '0.1', '2', '3') - self.assert_(ctx.installdb.is_installed('installtest')) - ctx.installdb.remove('installtest') - self.assert_(ctx.installdb.is_removed('installtest')) - ctx.installdb.purge('installtest') - self.assert_(not ctx.installdb.is_recorded('installtest')) - -suite = unittest.makeSuite(InstallDBTestCase) diff --git a/tags/pisi-1.0_beta2/tests/metadatatests.py b/tags/pisi-1.0_beta2/tests/metadatatests.py deleted file mode 100644 index b5514f5c..00000000 --- a/tags/pisi-1.0_beta2/tests/metadatatests.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -from pisi import metadata -from pisi import util - -class MetaDataTestCase(unittest.TestCase): - - def testRead(self): - md = metadata.MetaData() - md.read('tests/popt/metadata.xml') - - self.assertEqual(md.package.license, ["As-Is"]) - - self.assertEqual(md.package.version, "1.7") - - self.assertEqual(md.package.installedSize, 149691) - return md - - def testWrite(self): - md = self.testRead() - md.write('/tmp/metadata-test.xml') - - def testVerify(self): - md = self.testRead() - if md.errors(): - self.fail("Couldn't verify!") - - -suite = unittest.makeSuite(MetaDataTestCase) diff --git a/tags/pisi-1.0_beta2/tests/ootests.py b/tags/pisi-1.0_beta2/tests/ootests.py deleted file mode 100644 index 8bbbde3a..00000000 --- a/tags/pisi-1.0_beta2/tests/ootests.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -from pisi import version -from pisi.oo import * - -class OOTestCase(unittest.TestCase): - def setUp(self): - pass - - def testautosuper(self): - class A: - __metaclass__ = autosuper - def meth(self): - return "A" - class B(A): - def meth(self): - return "B" + self.__super.meth() - class C(A): - def meth(self): - return "C" + self.__super.meth() - class D(C, B): - def meth(self): - return "D" + self.__super.meth() - - self.assert_( D().meth() == "DCBA" ) - -suite = unittest.makeSuite(OOTestCase) - diff --git a/tags/pisi-1.0_beta2/tests/packagedbtests.py b/tags/pisi-1.0_beta2/tests/packagedbtests.py deleted file mode 100644 index 7d3acf54..00000000 --- a/tags/pisi-1.0_beta2/tests/packagedbtests.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi.context as ctx -import pisi.api -from pisi.packagedb import PackageDB -from pisi import util -from pisi.specfile import SpecFile - -import testcase -class PackageDBTestCase(testcase.TestCase): - - def setUp(self): - testcase.TestCase.setUp(self) - self.spec = SpecFile() - self.spec.read('tests/popt/pspec.xml') - - self.pdb = PackageDB('testdb') - - def testAdd(self): - self.pdb.add_package(self.spec.packages[0]) - self.assert_(self.pdb.has_package('popt-libs')) - # close the database and remove lock - self.pdb.close() - - def testRemove(self): - self.pdb.remove_package('popt-libs') - self.assert_(not self.pdb.has_package('popt-libs')) - self.pdb.close() - -suite = unittest.makeSuite(PackageDBTestCase) diff --git a/tags/pisi-1.0_beta2/tests/packagetests.py b/tags/pisi-1.0_beta2/tests/packagetests.py deleted file mode 100644 index 638223c8..00000000 --- a/tags/pisi-1.0_beta2/tests/packagetests.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -from pisi import util -import pisi.context as ctx -from pisi import package - -import testcase -class PackageTestCase(testcase.TestCase): - - def setUp(self): - testcase.TestCase.setUp(self) - self.pkgName = util.package_name("testing", - "5.1", - "2", 3) - - def testAddExtract(self): - cur = os.getcwd() - tmpdir = ctx.config.tmp_dir() - testdir = os.path.join(cur, "tests/popt") - - pkg_path = os.path.join(tmpdir, self.pkgName) - pkg = package.Package(pkg_path, "w") - - os.chdir(testdir) - pkg.add_to_package("files.xml") - pkg.add_to_package("metadata.xml") - os.chdir(cur) - - pkg.close() - - pkg = package.Package(pkg_path) - pkg.extract_file("files.xml", cur) - if not os.path.exists("files.xml"): - self.fail("Package extract error") - - os.remove("files.xml") - os.remove(pkg_path) - -suite = unittest.makeSuite(PackageTestCase) diff --git a/tags/pisi-1.0_beta2/tests/pccts/actions.py b/tags/pisi-1.0_beta2/tests/pccts/actions.py deleted file mode 100644 index 50add5ca..00000000 --- a/tags/pisi-1.0_beta2/tests/pccts/actions.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# Timu EREN - -from pisi.actionsapi import autotools -from pisi.actionsapi import get -from pisi.actionsapi import pisitools -from pisi.actionsapi import shelltools - -WorkDir = "pccts" - -def setup(): - shelltools.export("COPT", get.CFLAGS()) - -def build(): -# autotools.make("COPT=%s" % (get.CFLAGS())) - autotools.make() - -def install(): - #autotools.install("") - - pisitools.dobin("bin/antlr") - pisitools.dobin("bin/dlg") - pisitools.dobin("bin/genmk") - pisitools.dobin("bin/sor") - - pisitools.insinto("/usr/include/pccts","h/*.h") - pisitools.insinto("/usr/include/pccts","h/*.c") - pisitools.insinto("/usr/include/pccts","h/*.cpp") - - - pisitools.insinto("/usr/include/pccts/sorcerer","sorcerer/h/*.h") - pisitools.insinto("/usr/include/pccts/sorcerer","sorcerer/h/*.c") - pisitools.insinto("/usr/include/pccts/sorcerer","sorcerer/h/*.cpp") - - - pisitools.insinto("/usr/include/pccts/sorcerer/lib","sorcerer/lib/*.h") - pisitools.insinto("/usr/include/pccts/sorcerer/lib","sorcerer/lib/*.c") - pisitools.insinto("/usr/include/pccts/sorcerer/lib","sorcerer/lib/*.cpp") - - pisitools.dodoc("CHANGES*", "KNOWN_PROBLEMS*", "README", "RIGHTS", "history.txt", "history.ps") - pisitools.dodoc("sorcerer/README", "sorcerer/UPDATES") - - pisitools.doman("dlg/dlg.1", "antlr/antlr.1") diff --git a/tags/pisi-1.0_beta2/tests/pccts/files/pccts-1.33.33-gentoo.diff b/tags/pisi-1.0_beta2/tests/pccts/files/pccts-1.33.33-gentoo.diff deleted file mode 100644 index 1594cd96..00000000 --- a/tags/pisi-1.0_beta2/tests/pccts/files/pccts-1.33.33-gentoo.diff +++ /dev/null @@ -1,69 +0,0 @@ ---- pccts-1.33.33/support/genmk/genmk.c Fri Aug 3 17:12:51 2001 -+++ pccts-1.33.33/support/genmk/genmk-gentoo.c Fri Aug 3 17:12:14 2001 -@@ -7,6 +7,11 @@ - * U of MN - */ - -+/* modified 20010803 by Peter Kadau -+ * for better fhs-compliance -+ * i.e. from "none" to "hmmm soso" ;-) -+ */ -+ - #include - #include - #include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */ -@@ -65,7 +70,7 @@ - static int nondef_comp = 0; /* 1=compiler is non default */ - static char *compilerCCC="CC"; - static char *compilerCC="cc"; --static char *pccts_path="/usr/local/pccts"; -+static char *pccts_path="/usr/include/pccts"; - - #ifdef __STDC__ - void help(void); -@@ -356,7 +361,7 @@ - { "-cfiles",1,pCFiles, "Additional files in C or C++ to compile"}, - { "-sor",0,pSor, "Start of sorcerer group"}, - { "-pccts_path",1,ppccts_path, -- "Path for $PCCTS directory (default is /usr/local/pccts)"}, -+ "Path for $PCCTS directory (default is /usr/include/pccts)"}, - { "-compiler",1,pCompiler, - "Default compiler (default is CC/cc)"}, - { "*", 0,pFile, "" }, /* anything else is a file */ -@@ -495,13 +500,13 @@ - else printf("SCAN = %s%s\n", DIR(), dlg_class); - - printf("PCCTS = %s\n",pccts_path); -- printf("ANTLR_H = $(PCCTS)%sh\n", DirectorySymbol); -+ printf("ANTLR_H = $(PCCTS)\n"); - if (num_sors>0) { -- printf("SOR_H = $(PCCTS)%ssorcerer%sh\n", DirectorySymbol, DirectorySymbol); -+ printf("SOR_H = $(PCCTS)%ssorcerer\n", DirectorySymbol); - printf("SOR_LIB = $(PCCTS)%ssorcerer%slib\n", - DirectorySymbol, DirectorySymbol); - } -- printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol); -+ printf("BIN = %susr%sbin\n", DirectorySymbol, DirectorySymbol); - printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol); - printf("DLG = $(BIN)%sdlg\n", DirectorySymbol); - if (num_sors>0) printf("SOR = $(BIN)%ssor\n", DirectorySymbol); ---- pccts-1.33.33/sorcerer/lib/sorlist.c 1999-06-30 03:15:56.000000000 +0200 -+++ pccts-1.33.33/sorcerer/lib/sorlist.c.new 2003-05-23 11:11:09.000000000 +0200 -@@ -28,6 +28,7 @@ - */ - #include - #include -+#include "pcctscfg.h" - - #ifdef PCCTS_USE_STDARG - #include ---- pccts-1.33.33/sorcerer/lib/sintstack.c 1999-06-30 15:08:06.000000000 +0200 -+++ pccts-1.33.33/sorcerer/lib/sintstack.c.new 2003-05-23 12:54:26.000000000 +0200 -@@ -28,6 +28,7 @@ - */ - #include - #include -+#include "pcctscfg.h" - - #ifdef PCCTS_USE_STDARG - #include diff --git a/tags/pisi-1.0_beta2/tests/pccts/pspec.xml b/tags/pisi-1.0_beta2/tests/pccts/pspec.xml deleted file mode 100644 index 7bbc03eb..00000000 --- a/tags/pisi-1.0_beta2/tests/pccts/pspec.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - pccts - http://www.polhode.com - - Timu EREN - selamtux@gmail.com - - BSD - category - component - Purdue Compiler Construction Tool Set is an embedded C/C++ parser generator - Purdue Compiler Construction Tool Set is an embedded C/C++ parser generator - http://www.polhode.com/pccts133mr33.zip - - pccts-1.33.33-gentoo.diff - - - unzip - patch - - - - pccts - - /usr/include - /usr/share/doc - /usr/bin - /usr/share/man - - - - - - 2005-09-16 - 1.33.33 - - - - diff --git a/tags/pisi-1.0_beta2/tests/pisi.conf b/tags/pisi-1.0_beta2/tests/pisi.conf deleted file mode 100644 index 560e8567..00000000 --- a/tags/pisi-1.0_beta2/tests/pisi.conf +++ /dev/null @@ -1,6 +0,0 @@ -[general] -destinationdirectory = /testing - -[directories] -archives_dir = /disk2/pisi/archives - diff --git a/tags/pisi-1.0_beta2/tests/popt/actions.py b/tags/pisi-1.0_beta2/tests/popt/actions.py deleted file mode 100644 index c8fc6046..00000000 --- a/tags/pisi-1.0_beta2/tests/popt/actions.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -from pisi.actionsapi import autotools - -WorkDir='popt-1.7' - -def setup(): - autotools.configure( '--with-nls' ) - -def build(): - autotools.make() - -def install(): - autotools.install() diff --git a/tags/pisi-1.0_beta2/tests/popt/files.xml b/tags/pisi-1.0_beta2/tests/popt/files.xml deleted file mode 100644 index 34564b0c..00000000 --- a/tags/pisi-1.0_beta2/tests/popt/files.xml +++ /dev/null @@ -1,507 +0,0 @@ - - - - - usr/share/locale/es/LC_MESSAGES/popt.mo - - - localedata - - - 1593 - - - 29481dbd4051e5c6a0f000436664ba00e47572ae - - - - - usr/share/locale/de/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/is/LC_MESSAGES/popt.mo - - - localedata - - - 1793 - - - edbcbb430b122626216ea9f6bba268d5de8454b6 - - - - - usr/lib/libpopt.la - - - sharedLib - - - 699 - - - 04bac6fce89f2c84d4bb1c5adced729f7d312980 - - - - - usr/share/locale/sl/LC_MESSAGES/popt.mo - - - localedata - - - 514 - - - 2031bdefffcf57121e46f3f68f0747fe6b7f1fcc - - - - - usr/share/locale/fr/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/it/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/eu_ES/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/da/LC_MESSAGES/popt.mo - - - localedata - - - 1599 - - - 3ae14880a8bc2cddd9dd0a03861a55d663ac8b0d - - - - - usr/share/locale/ko/LC_MESSAGES/popt.mo - - - localedata - - - 1916 - - - 2079233b9e3284c866e5d17e5aca001f678d4c23 - - - - - usr/share/locale/ja/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/pt/LC_MESSAGES/popt.mo - - - localedata - - - 1870 - - - 7db5d457fa3cc169fea2f747f25ba0353ed5fb69 - - - - - usr/lib/libpopt.so - - - sharedLib - - - 38532 - - - 617c2afa4e79faee954cb95715470f875c044e5a - - - - - usr/share/locale/no/LC_MESSAGES/popt.mo - - - localedata - - - 1800 - - - b33d41a1fbde6b879f0cce06cf2d8395012cc0ec - - - - - usr/lib/libpopt.a - - - sharedLib - - - 36100 - - - f067421ebdb9a68f89c90526feb64a70763c95cf - - - - - usr/share/locale/wa/LC_MESSAGES/popt.mo - - - localedata - - - 517 - - - 92f1f582ae24dbf5631fee1ace8bfc99cb5c1b66 - - - - - usr/share/locale/tr/LC_MESSAGES/popt.mo - - - localedata - - - 1601 - - - 16e3e8e12af497102c75ccbb52edf8d1783545c3 - - - - - usr/share/locale/zh/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/id/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/ro/LC_MESSAGES/popt.mo - - - localedata - - - 1150 - - - 914729e4200d68e5c55d114e6a083c74e692707b - - - - - usr/share/locale/sr/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/hu/LC_MESSAGES/popt.mo - - - localedata - - - 496 - - - 236bf8c1fea44a5a93c6e18e0c88b3dae1762264 - - - - - usr/share/locale/pt_BR/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/sv/LC_MESSAGES/popt.mo - - - localedata - - - 1844 - - - 63517df43bd74c84496441d8894f2b67533c6060 - - - - - usr/lib/libpopt.so.0.0.0 - - - sharedLib - - - 38532 - - - 1f2d3c41ba8e4d6b1c4979225cdf2dd97d4a0aea - - - - - usr/share/locale/ru/LC_MESSAGES/popt.mo - - - localedata - - - 1955 - - - 4742785bd5235eb437922f76a9faa30ec314d09b - - - - - usr/share/locale/zh_CN.GB2312/LC_MESSAGES/popt.mo - - - localedata - - - 468 - - - 5e0a688794619278a452c851a3fc86b50b7f781e - - - - - usr/lib/libpopt.so.0 - - - sharedLib - - - 38532 - - - 617c2afa4e79faee954cb95715470f875c044e5a - - - - - usr/include/popt.h - - - header - - - 15982 - - - 091692391fd1c539b19298f30e8ae074e3210459 - - - - - usr/share/locale/sk/LC_MESSAGES/popt.mo - - - localedata - - - 510 - - - f7e081a22577eb5429809b7ce999b8b1e2b1f9b3 - - - - - usr/share/locale/pl/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - - - usr/share/locale/uk/LC_MESSAGES/popt.mo - - - localedata - - - 504 - - - f91c695161926679401201fdaf3edcef4664f6ca - - - - - usr/share/locale/cs/LC_MESSAGES/popt.mo - - - localedata - - - 1806 - - - 920f5b99199361f1d169430bf13d2bfac1a02fab - - - - - usr/share/man/man3/popt.3 - - - doc - - - 31011 - - - 5c0014442b4ef38d71733c952884573071978328 - - - - - usr/share/locale/gl/LC_MESSAGES/popt.mo - - - localedata - - - 1636 - - - 8486430a6ecbb006b5d374cbcb109e8303c7d5f8 - - - - - usr/share/locale/fi/LC_MESSAGES/popt.mo - - - localedata - - - 345 - - - 6ceb513b02af4f612a20b49e5d615c158fdcee31 - - - diff --git a/tags/pisi-1.0_beta2/tests/popt/files/popt-1.7-uclibc.patch.gz b/tags/pisi-1.0_beta2/tests/popt/files/popt-1.7-uclibc.patch.gz deleted file mode 100644 index 83bbae58fcb13d6d70a3f408cf7ee02484e4e350..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 891 zcmV->1BCn^iwFqvtfoQ$18{F}bS*J1H!XEzY-wU+E^uLVV`u>FR&8(FHW2zerCsUIZ}hwCI-FQRW;pF9CSNtUP6Q}EmxMS!|e$o9RzlkH?Y003?%vuoK9c1?0o za#GQqV5H%uadP^OvqC|DN!vf088tab{siTB7UAq{-~kN0EjGhU<05LR$@ zMJnDDDobl>454LtFnd4>?S;d3fjt)(1|WH}HCb1b$iX=f^6c_ALf|6|FD}4;20ni7 zG_UV=et{t4*MV%y@(h}SOV_r=JpOsQ1aC2)C%B?27dFO^@J3Txn1xvScJYg z4h_pQJcE%5{@VOBoA|Rnv(4CwoAEH%L>6=t2O~VR?(kj7r>j+HnS$$L8YlNKCEH6{ z;i;hditBXr`-`{1r8R*v!=o7W9JrSO*IXN+Bx&|FPu;fFO3pKc+mc%IT)a=Ey3_U! zy$WqK)q8>oa6?SZSvneiK&@4L8h+5cZ&)2Hrp!to`S8yZB61LoR99e_BMR#=r$nPV>&U4FA&+(EVFr(5sa%qvX z9{Po9_!{Y63k1uxstydA0+kt5bdSk4)|1w?R<#zi=@Kib#(rfSLpI8C!lZj{I^1(( zT1>h%LhkGxh3@{}5)wK>I+(9GdeU1uf}ZrV!aJT7N7OW}RK{xWp{D=kG^eaojFz)1 z`TjT$SN}fF4;T-g=h1SpvV*B#{||#{9z{z#nB4j}m>vhy<6!!Vn(m=D54(rnJWd`T RdJlT&{R522x}2U1004y>xIO>? diff --git a/tags/pisi-1.0_beta2/tests/popt/metadata.xml b/tags/pisi-1.0_beta2/tests/popt/metadata.xml deleted file mode 100644 index 286dfe84..00000000 --- a/tags/pisi-1.0_beta2/tests/popt/metadata.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - popt - - - - Kırmızı kafalar - - - hotmail@redhat.com - - - - - - popt-libs - - - Command line option parsing library - - - library files for popt - - - As-Is - - - library:util:optparser - - - rpm:archive - - - - gettext - - - - - /usr/lib - - - /usr/share/doc - - - /usr/share/man - - - /usr/share/locale - - - /usr/include/popt.h - - - - - 2005-06-14 - 1.7 - - - 2005-06-10 - 1.7 - - - 2005-05-05 - 1.7 - - - - 0 - - - Pardus - - - 0.1 - - - Any - - - 149691 - - - diff --git a/tags/pisi-1.0_beta2/tests/popt/pspec.xml b/tags/pisi-1.0_beta2/tests/popt/pspec.xml deleted file mode 100644 index fe2782ea..00000000 --- a/tags/pisi-1.0_beta2/tests/popt/pspec.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - popt - http://www.rpm.org/ - - Kırmızı kafalar - hotmail@redhat.com - - As-Is - library:util:optparser - rpm:archive - Popt command line option parser - Command line option parsing library. - While it is similiar to getopt(3), it contains a number of enhancements, including: - - 1) popt is fully reentrant - 2) popt can parse arbitrary argv[] style arrays while - getopt(2) makes this quite difficult - 3) popt allows users to alias command line arguments - 4) popt provides convience functions for parsing strings - into argv[] style arrays - - - ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.1.x/popt-1.7.tar.gz - - - popt-1.7-uclibc.patch.gz - - - make - - - - - popt-libs - Command line option parsing library - Komut satırı seçenekleri işleme kütüphanesi - - gettext - - library files for popt - - /usr/lib - /usr/share/doc - /usr/share/man - /usr/share/locale - /usr/include/popt.h - - - acpid.rc6 - - - - - - 06/14/2005 - 1.7 - - - 06/10/2005 - 1.7 - - - 05/05/2005 - 1.7 - 1 - - - diff --git a/tags/pisi-1.0_beta2/tests/run.py b/tags/pisi-1.0_beta2/tests/run.py deleted file mode 100755 index 65ca4207..00000000 --- a/tags/pisi-1.0_beta2/tests/run.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import sys -import os -import locale - -sys.path.insert(0, '.') -sys.path.insert(0, '..') - -import pisi.api -import pisi.context as ctx - -def run_test_suite(testsuite): - unittest.TextTestRunner(verbosity=2).run(testsuite) - if ctx.initialized: - pisi.api.finalize() - -def run_all(): - - print '** Running all tests' - #testsuite = unittest.TestSuite() - for root, dirs, files in os.walk('tests'): - testsources = filter(lambda x:x.endswith('tests.py'), files) - for testsource in testsources: - module = __import__(testsource[:len(testsource)-3]) - print '\n* Running tests in', testsource - run_test_suite(module.suite) - -if __name__ == "__main__": - - locale.setlocale(locale.LC_ALL, '') - args = sys.argv - if len(args) > 1: # run modules given from the command line - tests = sys.argv[1:] - for test in tests: - test += 'tests' - module = __import__(test) - print "* Running tests in", test - run_test_suite(module.suite) - else: # run all tests - run_all() diff --git a/tags/pisi-1.0_beta2/tests/sourcedbtests.py b/tags/pisi-1.0_beta2/tests/sourcedbtests.py deleted file mode 100644 index f11fac67..00000000 --- a/tags/pisi-1.0_beta2/tests/sourcedbtests.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi.context as ctx -import pisi.api -import pisi.sourcedb -from pisi import util -from pisi.specfile import SpecFile - -import testcase -class SourceDBTestCase(testcase.TestCase): - - def setUp(self): - testcase.TestCase.setUp(self) - - self.sourcedb = pisi.sourcedb.init() - self.spec = SpecFile() - self.spec.read("tests/popt/pspec.xml") - - def testAdd(self): - self.sourcedb.add_source(self.spec.source) - self.assert_(self.sourcedb.has_source("popt")) - - def testRemove(self): - self.testAdd() - self.sourcedb.remove_source("popt") - self.assert_(not self.sourcedb.has_source("popt")) - -suite = unittest.makeSuite(SourceDBTestCase) diff --git a/tags/pisi-1.0_beta2/tests/specfiletests.py b/tags/pisi-1.0_beta2/tests/specfiletests.py deleted file mode 100644 index f67c80b4..00000000 --- a/tags/pisi-1.0_beta2/tests/specfiletests.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi.specfile as specfile -import pisi.util as util - -class SpecFileNewTestCase(unittest.TestCase): - - def setUp(self): - self.spec = specfile.SpecFile() - self.spec.read("tests/popt/pspec.xml") - - def testFields(self): - self.assertEqual(self.spec.source.name, "popt") - - self.assertEqual(self.spec.source.version, "1.7") - - self.assertEqual(self.spec.source.release, "3") - - self.assertEqual(self.spec.source.archive.sha1sum, - "66f3c77b87a160951b180447f4a6dce68ad2f71b") - - patches = self.spec.source.patches - self.assertEqual(len(patches), 1) - patch = patches[0] #get first and the only patch - self.assertEqual(patch.filename, "popt-1.7-uclibc.patch.gz") - self.assertEqual(patch.compressionType, "gz") - - packages = self.spec.packages - self.assertEqual(len(packages), 1) - package = packages[0] # get the first and the only package - self.assertEqual(package.name, "popt-libs") - - # search for a path in package.paths - pn = "/usr/lib" - matched = [p for p in package.files if p.path == pn] - if not matched: - self.fail("Failed to match pathname: %s" %pn) - - def testIsAPartOf(self): - # test existence in Source - if not "library:util:optparser" in self.spec.source.isA: - self.fail("Failed to match IsA in Source") - if not isinstance(self.spec.source.isA, list): - self.fail("source.isA is not a list, but it must be...") - - if "rpm:archive" != self.spec.source.partOf: - self.fail("Failed to match PartOf in Source") - - # test existence in Package - pkg = self.spec.packages[0] - if not "library:util:optparser" in pkg.isA: - self.fail("Failed to match IsA in Package") - if not isinstance(pkg.isA, list): - self.fail("source.isA is not a list, but it must be...") - - if "rpm:archive" != pkg.partOf: - self.fail("Failed to match PartOf in Package") - - def testVerify(self): - if self.spec.errors(): - self.fail("Failed to verify specfile") - - def testCopy(self): - self.spec.read("tests/popt/pspec.xml") - self.spec.write('/tmp/popt-copy.pspec.xml') - -suite = unittest.makeSuite(SpecFileNewTestCase) diff --git a/tags/pisi-1.0_beta2/tests/testcase.py b/tags/pisi-1.0_beta2/tests/testcase.py deleted file mode 100644 index 08d5b6ac..00000000 --- a/tags/pisi-1.0_beta2/tests/testcase.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi -import pisi.api -import pisi.util -import pisi.config - -class TestCase(unittest.TestCase): - - def setUp(self, comar = False, database = True): - options = pisi.config.Options() - options.destdir = 'tmp' - pisi.api.init(options = options, comar = comar, database = database) - - def tearDown(self, ): - pisi.api.finalize() diff --git a/tags/pisi-1.0_beta2/tests/unzip/actions.py b/tags/pisi-1.0_beta2/tests/unzip/actions.py deleted file mode 100644 index ed12a90d..00000000 --- a/tags/pisi-1.0_beta2/tests/unzip/actions.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -from pisi.actionsapi import autotools -from pisi.actionsapi import get -from pisi.actionsapi import pisitools - -def setup(): - pisitools.dosed("unix/Makefile", "-O3", get.CFLAGS()) - pisitools.dosed("unix/Makefile", "CC=gcc LD=gcc", "CC=${CC:-gcc} LD=${CC:-gcc}") - pisitools.dosed("unix/Makefile", "-O ", get.CFLAGS()) - pass - -def build(): - autotools.make("-f unix/Makefile linux") - -def install(): - pisitools.insinto("/usr/bin/", "unzip") - pisitools.insinto("/usr/bin/", "funzip") - pisitools.insinto("/usr/bin/", "unzipsfx") - pisitools.insinto("/usr/bin/", "unix/zipgrep") - - pisitools.dosym("/usr/bin/unzip", "/usr/bin/zipinfo") - pisitools.doman("man/*.1") - pisitools.dodoc("BUGS", "History*", "README", "ToDo", "WHERE") diff --git a/tags/pisi-1.0_beta2/tests/unzip/files/unzip-5.50-dotdot.patch b/tags/pisi-1.0_beta2/tests/unzip/files/unzip-5.50-dotdot.patch deleted file mode 100644 index 73441f7b..00000000 --- a/tags/pisi-1.0_beta2/tests/unzip/files/unzip-5.50-dotdot.patch +++ /dev/null @@ -1,85 +0,0 @@ -Only in unzip-5.50-lhh/: cscope.files -Only in unzip-5.50-lhh/: cscope.out -diff -ur unzip-5.50/unix/unix.c unzip-5.50-lhh/unix/unix.c ---- unzip-5.50/unix/unix.c 2002-01-21 17:54:42.000000000 -0500 -+++ unzip-5.50-lhh/unix/unix.c 2003-06-11 18:35:38.000000000 -0400 -@@ -421,7 +421,8 @@ - */ - { - char pathcomp[FILNAMSIZ]; /* path-component buffer */ -- char *pp, *cp=(char *)NULL; /* character pointers */ -+ char *pp, *cp=(char *)NULL, /* character pointers */ -+ *dp=(char *)NULL; - char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ - #ifdef ACORN_FTYPE_NFS - char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ -@@ -429,6 +430,7 @@ - #endif - int quote = FALSE; /* flags */ - int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ -+ int snarf_ddot = FALSE; /* Is set while scanning for "../" */ - int error = MPN_OK; - register unsigned workch; /* hold the character being tested */ - -@@ -467,6 +469,9 @@ - while ((workch = (uch)*cp++) != 0) { - - if (quote) { /* if character quoted, */ -+ if ((pp == pathcomp) && (workch == '.')) -+ /* Oh no you don't... */ -+ goto ddot_hack; - *pp++ = (char)workch; /* include it literally */ - quote = FALSE; - } else -@@ -481,15 +486,44 @@ - break; - - case '.': -- if (pp == pathcomp) { /* nothing appended yet... */ -+ if (pp == pathcomp) { -+ddot_hack: -+ /* nothing appended yet... */ - if (*cp == '/') { /* don't bother appending "./" to */ - ++cp; /* the path: skip behind the '/' */ - break; -- } else if (!uO.ddotflag && *cp == '.' && cp[1] == '/') { -- /* "../" dir traversal detected */ -- cp += 2; /* skip over behind the '/' */ -- killed_ddot = TRUE; /* set "show message" flag */ -- break; -+ } else if (!uO.ddotflag) { -+ -+ /* -+ * SECURITY: Skip past control characters if the user -+ * didn't OK use of absolute pathnames. lhh - this is -+ * a very quick, ugly, inefficient fix. -+ */ -+ dp = cp; -+ do { -+ workch = (uch)(*dp); -+ if (workch == '/' && snarf_ddot) { -+ /* "../" dir traversal detected */ -+ cp = dp + 1; /* skip past the '/' */ -+ killed_ddot = TRUE; /* set "show msg" flag */ -+ break; -+ } else if (workch == '.' && !snarf_ddot) { -+ snarf_ddot = TRUE; -+ } else if (isprint(workch) || -+ ((workch > 127) && (workch <= 254))) { -+ /* -+ * Since we found a printable, non-ctrl char, -+ * we can stop looking for '../', the amount -+ * in ../! -+ */ -+ break; -+ } -+ -+ dp++; -+ } while (*dp != 0); -+ -+ if (killed_ddot) -+ break; - } - } - *pp++ = '.'; -Only in unzip-5.50-lhh/unix: .unix.c.swp diff --git a/tags/pisi-1.0_beta2/tests/unzip/pspec.xml b/tags/pisi-1.0_beta2/tests/unzip/pspec.xml deleted file mode 100644 index ed4188a0..00000000 --- a/tags/pisi-1.0_beta2/tests/unzip/pspec.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - unzip - ftp://ftp.info-zip.org/pub/infozip/UnZip.html - - A. Murat Eren - meren@uludag.org.tr - - Info-ZIP - category - component - Unzipper for pkzip-compressed files - Unzipper for pkzip-compressed files - ftp://ftp.linux.org.tr/pub/mirrors/gentoo/distfiles/unzip550.tar.gz - - unzip-5.50-dotdot.patch - - - libc - sed - patch - - - - - unzip - - - - - /usr/bin - /usr/share/doc - /usr/share/man - - - - - 2005-07-15 - 5.50 - - - - - diff --git a/tags/pisi-1.0_beta2/tests/unzip2/actions.py b/tags/pisi-1.0_beta2/tests/unzip2/actions.py deleted file mode 100644 index 09b91126..00000000 --- a/tags/pisi-1.0_beta2/tests/unzip2/actions.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -from pisi.actionsapi import autotools -from pisi.actionsapi import get -from pisi.actionsapi import pisitools - -WorkDir="unzip-5.50" - -def setup(): - pisitools.dosed("unix/Makefile", "-O3", get.CFLAGS()) - pisitools.dosed("unix/Makefile", "CC=gcc LD=gcc", "CC=${CC:-gcc} LD=${CC:-gcc}") - pisitools.dosed("unix/Makefile", "-O ", get.CFLAGS()) - pass - -def build(): - autotools.make("-f unix/Makefile linux") - -def install(): - pisitools.insinto("/usr/bin/", "unzip") - pisitools.insinto("/usr/bin/", "funzip") - pisitools.insinto("/usr/bin/", "unzipsfx") - pisitools.insinto("/usr/bin/", "unix/zipgrep") - - pisitools.dosym("/usr/bin/unzip", "/usr/bin/zipinfo") - pisitools.doman("man/*.1") - pisitools.dodoc("BUGS", "History*", "README", "ToDo", "WHERE") diff --git a/tags/pisi-1.0_beta2/tests/unzip2/files/unzip-5.50-dotdot.patch b/tags/pisi-1.0_beta2/tests/unzip2/files/unzip-5.50-dotdot.patch deleted file mode 100644 index 73441f7b..00000000 --- a/tags/pisi-1.0_beta2/tests/unzip2/files/unzip-5.50-dotdot.patch +++ /dev/null @@ -1,85 +0,0 @@ -Only in unzip-5.50-lhh/: cscope.files -Only in unzip-5.50-lhh/: cscope.out -diff -ur unzip-5.50/unix/unix.c unzip-5.50-lhh/unix/unix.c ---- unzip-5.50/unix/unix.c 2002-01-21 17:54:42.000000000 -0500 -+++ unzip-5.50-lhh/unix/unix.c 2003-06-11 18:35:38.000000000 -0400 -@@ -421,7 +421,8 @@ - */ - { - char pathcomp[FILNAMSIZ]; /* path-component buffer */ -- char *pp, *cp=(char *)NULL; /* character pointers */ -+ char *pp, *cp=(char *)NULL, /* character pointers */ -+ *dp=(char *)NULL; - char *lastsemi=(char *)NULL; /* pointer to last semi-colon in pathcomp */ - #ifdef ACORN_FTYPE_NFS - char *lastcomma=(char *)NULL; /* pointer to last comma in pathcomp */ -@@ -429,6 +430,7 @@ - #endif - int quote = FALSE; /* flags */ - int killed_ddot = FALSE; /* is set when skipping "../" pathcomp */ -+ int snarf_ddot = FALSE; /* Is set while scanning for "../" */ - int error = MPN_OK; - register unsigned workch; /* hold the character being tested */ - -@@ -467,6 +469,9 @@ - while ((workch = (uch)*cp++) != 0) { - - if (quote) { /* if character quoted, */ -+ if ((pp == pathcomp) && (workch == '.')) -+ /* Oh no you don't... */ -+ goto ddot_hack; - *pp++ = (char)workch; /* include it literally */ - quote = FALSE; - } else -@@ -481,15 +486,44 @@ - break; - - case '.': -- if (pp == pathcomp) { /* nothing appended yet... */ -+ if (pp == pathcomp) { -+ddot_hack: -+ /* nothing appended yet... */ - if (*cp == '/') { /* don't bother appending "./" to */ - ++cp; /* the path: skip behind the '/' */ - break; -- } else if (!uO.ddotflag && *cp == '.' && cp[1] == '/') { -- /* "../" dir traversal detected */ -- cp += 2; /* skip over behind the '/' */ -- killed_ddot = TRUE; /* set "show message" flag */ -- break; -+ } else if (!uO.ddotflag) { -+ -+ /* -+ * SECURITY: Skip past control characters if the user -+ * didn't OK use of absolute pathnames. lhh - this is -+ * a very quick, ugly, inefficient fix. -+ */ -+ dp = cp; -+ do { -+ workch = (uch)(*dp); -+ if (workch == '/' && snarf_ddot) { -+ /* "../" dir traversal detected */ -+ cp = dp + 1; /* skip past the '/' */ -+ killed_ddot = TRUE; /* set "show msg" flag */ -+ break; -+ } else if (workch == '.' && !snarf_ddot) { -+ snarf_ddot = TRUE; -+ } else if (isprint(workch) || -+ ((workch > 127) && (workch <= 254))) { -+ /* -+ * Since we found a printable, non-ctrl char, -+ * we can stop looking for '../', the amount -+ * in ../! -+ */ -+ break; -+ } -+ -+ dp++; -+ } while (*dp != 0); -+ -+ if (killed_ddot) -+ break; - } - } - *pp++ = '.'; -Only in unzip-5.50-lhh/unix: .unix.c.swp diff --git a/tags/pisi-1.0_beta2/tests/unzip2/pspec.xml b/tags/pisi-1.0_beta2/tests/unzip2/pspec.xml deleted file mode 100644 index b8841dcb..00000000 --- a/tags/pisi-1.0_beta2/tests/unzip2/pspec.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - unzip - ftp://ftp.info-zip.org/pub/infozip/UnZip.html - - A. Murat Eren - meren@uludag.org.tr - - Info-ZIP - category - component - Unzipper for pkzip-compressed files - Unzipper for pkzip-compressed files - ftp://ftp.linux.org.tr/pub/mirrors/gentoo/distfiles/unzip550.tar.gz - - unzip-5.50-dotdot.patch - - - libc - sed - patch - - - - - unzip - - - - - /usr/bin - /usr/share/doc - /usr/share/man - - - - - 2005-08-10 - 5.52 - - - - - diff --git a/tags/pisi-1.0_beta2/tests/utiltests.py b/tags/pisi-1.0_beta2/tests/utiltests.py deleted file mode 100644 index 6cd4927f..00000000 --- a/tags/pisi-1.0_beta2/tests/utiltests.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -from pisi import version -from pisi.util import * - -class UtilTestCase(unittest.TestCase): - - def setUp(self): - pass - - def testSubPath(self): - self.assert_(subpath('usr', 'usr')) - self.assert_(subpath('usr', 'usr/local/src')) - self.assert_(not subpath('usr/local', 'usr')) - - def testRemovePathPrefix(self): - a = removepathprefix('usr/local', 'usr/local/lib') - self.assertEqual(a, 'lib') - - a = removepathprefix('usr/local/', 'usr/local/lib') - self.assertEqual(a, 'lib') - - -suite = unittest.makeSuite(UtilTestCase) diff --git a/tags/pisi-1.0_beta2/tests/versiontests.py b/tags/pisi-1.0_beta2/tests/versiontests.py deleted file mode 100644 index b13915ab..00000000 --- a/tags/pisi-1.0_beta2/tests/versiontests.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -from pisi.version import Version - -class VersionTestCase(unittest.TestCase): - def setUp(self): - pass - - def testSingle(self): - v1 = Version("103") - v2 = Version("90") - self.assert_(v1 > v2) - - def testOpsNumerical(self): - v1 = Version("0.3.1") - v2 = Version("0.3.5") - v3 = Version("1.5.2-4") - v4 = Version("0.3.1-1") - v5 = Version("2.07") - self.assert_(v1 < v2) - self.assert_(v3 > v2) - self.assert_(v1 <= v3) - self.assert_(v4 >= v4) - self.assert_(v5 > v3) - - def testOpsKeywords(self): - # with keywords - v1 = Version("2.23_pre10") - v2 = Version("2.23") - v3 = Version("2.21") - v4 = Version("2.23_p1") - v5 = Version("2.23_beta1") - self.assert_(v1 < v2) - self.assert_(v1 > v3) - self.assert_(v1 < v4) - self.assert_(v1 > v5) - self.assert_(v2 < v4) - self.assert_(v2 > v5) - - v1 = Version("1.0_alpha1") - v2 = Version("1.0_alpha2") - self.assert_(v2 > v1) - - def testOpsCharacters(self): - # with character - v1 = Version("2.10a") - v2 = Version("2.10") - v3 = Version("2.10d") - self.assert_(v1 > v2) - self.assert_(v1 < v3) - self.assert_(v2 < v3) - - def testGeBug(self): - # bug 603 - v1 = Version('1.8.0') - v2 = Version('1.9.1') - self.assert_( not v1 > v2 ) - self.assert_( not v1 >= v2 ) - -suite = unittest.makeSuite(VersionTestCase) diff --git a/tags/pisi-1.0_beta2/tests/xmlexttests.py b/tags/pisi-1.0_beta2/tests/xmlexttests.py deleted file mode 100644 index 0d5ccb7d..00000000 --- a/tags/pisi-1.0_beta2/tests/xmlexttests.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import unittest -import os - -import pisi -import pisi.api -import pisi.context as ctx -import pisi.util as util -from pisi.pxml import xmlext - -import testcase - -class XmlExtTestCase(testcase.TestCase): - - def setUp(self): - testcase.TestCase.setUp(self, database=False) - - def testGet(self): - self.doc = xmlext.parse('tests/a.xml') - #self.doc = self.a.documentElement - self.assertEqual(xmlext.getNodeText(self.doc, 'Number'), '868') - self.assertEqual(xmlext.getNodeText(self.doc, 'OtherInfo/BirthDate'), '18071976') - codeswith = xmlext.getAllNodes(self.doc, 'OtherInfo/CodesWith/Person') - self.assertEqual(len(codeswith), 4) - self.assertEqual(xmlext.getNodeText(codeswith[2]), 'Caglar') - - def testAdd(self): - node = xmlext.newDocument('pardus') - #node = a.documentElement - xmlext.addText(node, 'team/coder', 'zibidi1') - xmlext.addText(node, 'team/coder', 'zibidi2') - xmlext.addText(node, 'team/coder', 'zibidi3') - reada = xmlext.getAllNodes(node, 'team/coder') - self.assertEqual(len(reada), 3) - -suite = unittest.makeSuite(XmlExtTestCase) diff --git a/tags/pisi-1.0_beta2/tests/zip/actions.py b/tags/pisi-1.0_beta2/tests/zip/actions.py deleted file mode 100644 index 730924b4..00000000 --- a/tags/pisi-1.0_beta2/tests/zip/actions.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -from pisi.actionsapi import autotools -from pisi.actionsapi import get -from pisi.actionsapi import pisitools - -def setup(): - pisitools.dosed("unix/Makefile", "-O2", get.CFLAGS()) - -def build(): - autotools.make("-f unix/Makefile CC=%s CPP=%s generic" % (get.CC(), get.CXX())) - -def install(): - pisitools.dobin("zip") - pisitools.dobin("zipcloak") - pisitools.dobin("zipnote") - pisitools.dobin("zipsplit") - - pisitools.doman("man/*.1") - pisitools.dodoc("BUGS", "CHANGES", "MANUAL", "README", "TODO", "WHATSNEW", "WHERE") - diff --git a/tags/pisi-1.0_beta2/tests/zip/files/zcrypt.patch b/tags/pisi-1.0_beta2/tests/zip/files/zcrypt.patch deleted file mode 100644 index 6b696af5..00000000 --- a/tags/pisi-1.0_beta2/tests/zip/files/zcrypt.patch +++ /dev/null @@ -1,752 +0,0 @@ -diff -ur zip-2.3.orig/crypt.c zip-2.3/crypt.c ---- zip-2.3.orig/crypt.c 1999-10-09 23:09:26.000000000 +0300 -+++ zip-2.3/crypt.c 2005-07-15 16:19:00.000000000 +0300 -@@ -1,20 +1,577 @@ - /* -- Copyright (c) 1990-1999 Info-ZIP. All rights reserved. -+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - -- See the accompanying file LICENSE, version 1999-Oct-05 or later -+ See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. -- If, for some reason, both of these files are missing, the Info-ZIP license -- also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html -+ If, for some reason, all these files are missing, the Info-ZIP license -+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - */ - /* -- crypt.c (dummy version) by Info-ZIP. Last revised: 15 Aug 98 -+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - -- This is a non-functional version of Info-ZIP's crypt.c encryption/ -- decryption code for Zip, ZipCloak, UnZip and fUnZip. This file is -- not copyrighted and may be distributed freely. :-) See the "WHERE" -- file for sites from which to obtain the full encryption/decryption -- sources (zcrypt28.zip or later). -+ The encryption/decryption parts of this source code (as opposed to the -+ non-echoing password parts) were originally written in Europe. The -+ whole source package can be freely distributed, including from the USA. -+ (Prior to January 2000, re-export from the US was a violation of US law.) - */ - -+/* -+ This encryption code is a direct transcription of the algorithm from -+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This -+ file (appnote.txt) is distributed with the PKZIP program (even in the -+ version without encryption capabilities). -+ */ -+ -+#define ZCRYPT_INTERNAL -+#include "zip.h" -+#include "crypt.h" -+#include "ttyio.h" -+ -+#if CRYPT -+ -+#ifndef FALSE -+# define FALSE 0 -+#endif -+ -+#ifdef ZIP -+ /* For the encoding task used in Zip (and ZipCloak), we want to initialize -+ the crypt algorithm with some reasonably unpredictable bytes, see -+ the crypthead() function. The standard rand() library function is -+ used to supply these `random' bytes, which in turn is initialized by -+ a srand() call. The srand() function takes an "unsigned" (at least 16bit) -+ seed value as argument to determine the starting point of the rand() -+ pseudo-random number generator. -+ This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with -+ Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 -+ as some (hopefully) nondeterministic bitmask. On many (most) systems, -+ we use some "process specific" number, as the PID or something similar, -+ but when nothing unpredictable is available, a fixed number may be -+ sufficient. -+ NOTE: -+ 1.) This implementation requires the availability of the following -+ standard UNIX C runtime library functions: time(), rand(), srand(). -+ On systems where some of them are missing, the environment that -+ incorporates the crypt routines must supply suitable replacement -+ functions. -+ 2.) It is a very bad idea to use a second call to time() to set the -+ "Seed2" number! In this case, both "Seed1" and "Seed2" would be -+ (almost) identical, resulting in a (mostly) "zero" constant seed -+ number passed to srand(). -+ -+ The implementation environment defined in the "zip.h" header should -+ supply a reasonable definition for ZCR_SEED2 (an unsigned number; for -+ most implementations of rand() and srand(), only the lower 16 bits are -+ significant!). An example that works on many systems would be -+ "#define ZCR_SEED2 (unsigned)getpid()". -+ The default definition for ZCR_SEED2 supplied below should be regarded -+ as a fallback to allow successful compilation in "beta state" -+ environments. -+ */ -+# include /* time() function supplies first part of crypt seed */ -+ /* "last resort" source for second part of crypt seed pattern */ -+# ifndef ZCR_SEED2 -+# define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ -+# endif -+# ifdef GLOBAL /* used in Amiga system headers, maybe others too */ -+# undef GLOBAL -+# endif -+# define GLOBAL(g) g -+#else /* !ZIP */ -+# define GLOBAL(g) G.g -+#endif /* ?ZIP */ -+ -+ -+#ifdef UNZIP -+ /* char *key = (char *)NULL; moved to globals.h */ -+# ifndef FUNZIP -+ local int testp OF((__GPRO__ ZCONST uch *h)); -+ local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); -+# endif -+#endif /* UNZIP */ -+ -+#ifndef UNZIP /* moved to globals.h for UnZip */ -+ local ulg keys[3]; /* keys defining the pseudo-random sequence */ -+#endif /* !UNZIP */ -+ -+#ifndef Trace -+# ifdef CRYPT_DEBUG -+# define Trace(x) fprintf x -+# else -+# define Trace(x) -+# endif -+#endif -+ -+#ifndef CRC_32_TAB -+# define CRC_32_TAB crc_32_tab -+#endif -+ -+#define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) -+ -+/*********************************************************************** -+ * Return the next byte in the pseudo-random sequence -+ */ -+int decrypt_byte(__G) -+ __GDEF -+{ -+ unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an -+ * unpredictable manner on 16-bit systems; not a problem -+ * with any known compiler so far, though */ -+ -+ temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; -+ return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -+} -+ -+/*********************************************************************** -+ * Update the encryption keys with the next byte of plain text -+ */ -+int update_keys(__G__ c) -+ __GDEF -+ int c; /* byte of plain text */ -+{ -+ GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c); -+ GLOBAL(keys[1]) += GLOBAL(keys[0]) & 0xff; -+ GLOBAL(keys[1]) = GLOBAL(keys[1]) * 134775813L + 1; -+ { -+ register int keyshift = (int)(GLOBAL(keys[1]) >> 24); -+ GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift); -+ } -+ return c; -+} -+ -+ -+/*********************************************************************** -+ * Initialize the encryption keys and the random header according to -+ * the given password. -+ */ -+void init_keys(__G__ passwd) -+ __GDEF -+ ZCONST char *passwd; /* password string with which to modify keys */ -+{ -+ GLOBAL(keys[0]) = 305419896L; -+ GLOBAL(keys[1]) = 591751049L; -+ GLOBAL(keys[2]) = 878082192L; -+ while (*passwd != '\0') { -+ update_keys(__G__ (int)*passwd); -+ passwd++; -+ } -+} -+ -+ -+#ifdef ZIP -+ -+/*********************************************************************** -+ * Write encryption header to file zfile using the password passwd -+ * and the cyclic redundancy check crc. -+ */ -+void crypthead(passwd, crc, zfile) -+ ZCONST char *passwd; /* password string */ -+ ulg crc; /* crc of file being encrypted */ -+ FILE *zfile; /* where to write header */ -+{ -+ int n; /* index in random header */ -+ int t; /* temporary */ -+ int c; /* random byte */ -+ int ztemp; /* temporary for zencoded value */ -+ uch header[RAND_HEAD_LEN-2]; /* random header */ -+ static unsigned calls = 0; /* ensure different random header each time */ -+ -+ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the -+ * output of rand() to get less predictability, since rand() is -+ * often poorly implemented. -+ */ -+ if (++calls == 1) { -+ srand((unsigned)time(NULL) ^ ZCR_SEED2); -+ } -+ init_keys(passwd); -+ for (n = 0; n < RAND_HEAD_LEN-2; n++) { -+ c = (rand() >> 7) & 0xff; -+ header[n] = (uch)zencode(c, t); -+ } -+ /* Encrypt random header (last two bytes is high word of crc) */ -+ init_keys(passwd); -+ for (n = 0; n < RAND_HEAD_LEN-2; n++) { -+ ztemp = zencode(header[n], t); -+ putc(ztemp, zfile); -+ } -+ ztemp = zencode((int)(crc >> 16) & 0xff, t); -+ putc(ztemp, zfile); -+ ztemp = zencode((int)(crc >> 24) & 0xff, t); -+ putc(ztemp, zfile); -+} -+ -+ -+#ifdef UTIL -+ -+/*********************************************************************** -+ * Encrypt the zip entry described by z from file source to file dest -+ * using the password passwd. Return an error code in the ZE_ class. -+ */ -+int zipcloak(z, source, dest, passwd) -+ struct zlist far *z; /* zip entry to encrypt */ -+ FILE *source, *dest; /* source and destination files */ -+ ZCONST char *passwd; /* password string */ -+{ -+ int c; /* input byte */ -+ int res; /* result code */ -+ ulg n; /* holds offset and counts size */ -+ ush flag; /* previous flags */ -+ int t; /* temporary */ -+ int ztemp; /* temporary storage for zencode value */ -+ -+ /* Set encrypted bit, clear extended local header bit and write local -+ header to output file */ -+ if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; -+ z->off = n; -+ flag = z->flg; -+ z->flg |= 1, z->flg &= ~8; -+ z->lflg |= 1, z->lflg &= ~8; -+ z->siz += RAND_HEAD_LEN; -+ if ((res = putlocal(z, dest)) != ZE_OK) return res; -+ -+ /* Initialize keys with password and write random header */ -+ crypthead(passwd, z->crc, dest); -+ -+ /* Skip local header in input file */ -+ if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), -+ SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ -+ /* Encrypt data */ -+ for (n = z->siz - RAND_HEAD_LEN; n; n--) { -+ if ((c = getc(source)) == EOF) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ ztemp = zencode(c, t); -+ putc(ztemp, dest); -+ } -+ /* Skip extended local header in input file if there is one */ -+ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ if (fflush(dest) == EOF) return ZE_TEMP; -+ return ZE_OK; -+} -+ -+/*********************************************************************** -+ * Decrypt the zip entry described by z from file source to file dest -+ * using the password passwd. Return an error code in the ZE_ class. -+ */ -+int zipbare(z, source, dest, passwd) -+ struct zlist far *z; /* zip entry to encrypt */ -+ FILE *source, *dest; /* source and destination files */ -+ ZCONST char *passwd; /* password string */ -+{ -+ int c0, c1; /* last two input bytes */ -+ ulg offset; /* used for file offsets */ -+ ulg size; /* size of input data */ -+ int r; /* size of encryption header */ -+ int res; /* return code */ -+ ush flag; /* previous flags */ -+ -+ /* Save position and skip local header in input file */ -+ if ((offset = (ulg)ftell(source)) == (ulg)-1L || -+ fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), -+ SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ /* Initialize keys with password */ -+ init_keys(passwd); -+ -+ /* Decrypt encryption header, save last two bytes */ -+ c1 = 0; -+ for (r = RAND_HEAD_LEN; r; r--) { -+ c0 = c1; -+ if ((c1 = getc(source)) == EOF) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ Trace((stdout, " (%02x)", c1)); -+ zdecode(c1); -+ Trace((stdout, " %02x", c1)); -+ } -+ Trace((stdout, "\n")); -+ -+ /* If last two bytes of header don't match crc (or file time in the -+ * case of an extended local header), back up and just copy. For -+ * pkzip 2.0, the check has been reduced to one byte only. -+ */ -+#ifdef ZIP10 -+ if ((ush)(c0 | (c1<<8)) != -+ (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { -+#else -+ c0++; /* avoid warning on unused variable */ -+ if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { -+#endif -+ if (fseek(source, offset, SEEK_SET)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; -+ return ZE_MISS; -+ } -+ -+ /* Clear encrypted bit and local header bit, and write local header to -+ output file */ -+ if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; -+ z->off = offset; -+ flag = z->flg; -+ z->flg &= ~9; -+ z->lflg &= ~9; -+ z->siz -= RAND_HEAD_LEN; -+ if ((res = putlocal(z, dest)) != ZE_OK) return res; -+ -+ /* Decrypt data */ -+ for (size = z->siz; size; size--) { -+ if ((c1 = getc(source)) == EOF) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ zdecode(c1); -+ putc(c1, dest); -+ } -+ /* Skip extended local header in input file if there is one */ -+ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ if (fflush(dest) == EOF) return ZE_TEMP; -+ -+ return ZE_OK; -+} -+ -+ -+#else /* !UTIL */ -+ -+/*********************************************************************** -+ * If requested, encrypt the data in buf, and in any case call fwrite() -+ * with the arguments to zfwrite(). Return what fwrite() returns. -+ */ -+unsigned zfwrite(buf, item_size, nb, f) -+ zvoid *buf; /* data buffer */ -+ extent item_size; /* size of each item in bytes */ -+ extent nb; /* number of items */ -+ FILE *f; /* file to write to */ -+{ -+ int t; /* temporary */ -+ -+ if (key != (char *)NULL) { /* key is the global password pointer */ -+ ulg size; /* buffer size */ -+ char *p = (char*)buf; /* steps through buffer */ -+ -+ /* Encrypt data in buffer */ -+ for (size = item_size*(ulg)nb; size != 0; p++, size--) { -+ *p = (char)zencode(*p, t); -+ } -+ } -+ /* Write the buffer out */ -+ return fwrite(buf, item_size, nb, f); -+} -+ -+#endif /* ?UTIL */ -+#endif /* ZIP */ -+ -+ -+#if (defined(UNZIP) && !defined(FUNZIP)) -+ -+/*********************************************************************** -+ * Get the password and set up keys for current zipfile member. -+ * Return PK_ class error. -+ */ -+int decrypt(__G__ passwrd) -+ __GDEF -+ ZCONST char *passwrd; -+{ -+ ush b; -+ int n, r; -+ uch h[RAND_HEAD_LEN]; -+ -+ Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); -+ -+ /* get header once (turn off "encrypted" flag temporarily so we don't -+ * try to decrypt the same data twice) */ -+ GLOBAL(pInfo->encrypted) = FALSE; -+ defer_leftover_input(__G); -+ for (n = 0; n < RAND_HEAD_LEN; n++) { -+ b = NEXTBYTE; -+ h[n] = (uch)b; -+ Trace((stdout, " (%02x)", h[n])); -+ } -+ undefer_input(__G); -+ GLOBAL(pInfo->encrypted) = TRUE; -+ -+ if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ -+ GLOBAL(newzip) = FALSE; -+ if (passwrd != (char *)NULL) { /* user gave password on command line */ -+ if (!GLOBAL(key)) { -+ if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == -+ (char *)NULL) -+ return PK_MEM2; -+ strcpy(GLOBAL(key), passwrd); -+ GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ -+ } -+ } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ -+ free(GLOBAL(key)); -+ GLOBAL(key) = (char *)NULL; -+ } -+ } -+ -+ /* if have key already, test it; else allocate memory for it */ -+ if (GLOBAL(key)) { -+ if (!testp(__G__ h)) -+ return PK_COOL; /* existing password OK (else prompt for new) */ -+ else if (GLOBAL(nopwd)) -+ return PK_WARN; /* user indicated no more prompting */ -+ } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) -+ return PK_MEM2; -+ -+ /* try a few keys */ -+ n = 0; -+ do { -+ r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, -+ GLOBAL(zipfn), GLOBAL(filename)); -+ if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ -+ free (GLOBAL(key)); -+ GLOBAL(key) = NULL; -+ return PK_MEM2; -+ } -+ if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ -+ *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ -+ n = 0; /* and cancel fetch for this item. */ -+ } -+ if (!testp(__G__ h)) -+ return PK_COOL; -+ if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ -+ GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ -+ } while (n > 0); -+ -+ return PK_WARN; -+ -+} /* end function decrypt() */ -+ -+ -+ -+/*********************************************************************** -+ * Test the password. Return -1 if bad, 0 if OK. -+ */ -+local int testp(__G__ h) -+ __GDEF -+ ZCONST uch *h; -+{ -+ int r; -+ char *key_translated; -+ -+ /* On systems with "obscure" native character coding (e.g., EBCDIC), -+ * the first test translates the password to the "main standard" -+ * character coding. */ -+ -+#ifdef STR_TO_CP1 -+ /* allocate buffer for translated password */ -+ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) -+ return -1; -+ /* first try, test password translated "standard" charset */ -+ r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); -+#else /* !STR_TO_CP1 */ -+ /* first try, test password as supplied on the extractor's host */ -+ r = testkey(__G__ h, GLOBAL(key)); -+#endif /* ?STR_TO_CP1 */ -+ -+#ifdef STR_TO_CP2 -+ if (r != 0) { -+#ifndef STR_TO_CP1 -+ /* now prepare for second (and maybe third) test with translated pwd */ -+ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) -+ return -1; -+#endif -+ /* second try, password translated to alternate ("standard") charset */ -+ r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); -+#ifdef STR_TO_CP3 -+ if (r != 0) -+ /* third try, password translated to another "standard" charset */ -+ r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); -+#endif -+#ifndef STR_TO_CP1 -+ free(key_translated); -+#endif -+ } -+#endif /* STR_TO_CP2 */ -+ -+#ifdef STR_TO_CP1 -+ free(key_translated); -+ if (r != 0) { -+ /* last resort, test password as supplied on the extractor's host */ -+ r = testkey(__G__ h, GLOBAL(key)); -+ } -+#endif /* STR_TO_CP1 */ -+ -+ return r; -+ -+} /* end function testp() */ -+ -+ -+local int testkey(__G__ h, key) -+ __GDEF -+ ZCONST uch *h; /* decrypted header */ -+ ZCONST char *key; /* decryption password to test */ -+{ -+ ush b; -+#ifdef ZIP10 -+ ush c; -+#endif -+ int n; -+ uch *p; -+ uch hh[RAND_HEAD_LEN]; /* decrypted header */ -+ -+ /* set keys and save the encrypted header */ -+ init_keys(__G__ key); -+ memcpy(hh, h, RAND_HEAD_LEN); -+ -+ /* check password */ -+ for (n = 0; n < RAND_HEAD_LEN; n++) { -+ zdecode(hh[n]); -+ Trace((stdout, " %02x", hh[n])); -+ } -+ -+ Trace((stdout, -+ "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", -+ GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), -+ GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); -+ Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", -+ GLOBAL(incnt), -+ GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); -+ -+ /* same test as in zipbare(): */ -+ -+#ifdef ZIP10 /* check two bytes */ -+ c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; -+ Trace((stdout, -+ " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", -+ (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); -+ if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : -+ (ush)(GLOBAL(lrec.crc32) >> 16))) -+ return -1; /* bad */ -+#else -+ b = hh[RAND_HEAD_LEN-1]; -+ Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", -+ b, (ush)(GLOBAL(lrec.crc32) >> 24), -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); -+ if (b != (GLOBAL(pInfo->ExtLocHdr) ? -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : -+ (ush)(GLOBAL(lrec.crc32) >> 24))) -+ return -1; /* bad */ -+#endif -+ /* password OK: decrypt current buffer contents before leaving */ -+ for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? -+ (int)GLOBAL(csize) : GLOBAL(incnt), -+ p = GLOBAL(inptr); n--; p++) -+ zdecode(*p); -+ return 0; /* OK */ -+ -+} /* end function testkey() */ -+ -+#endif /* UNZIP && !FUNZIP */ -+ -+#else /* !CRYPT */ -+ - /* something "externally visible" to shut up compiler/linker warnings */ - int zcr_dummy; -+ -+#endif /* ?CRYPT */ -diff -ur zip-2.3.orig/crypt.h zip-2.3/crypt.h ---- zip-2.3.orig/crypt.h 1999-10-09 23:10:00.000000000 +0300 -+++ zip-2.3/crypt.h 2005-07-15 16:19:00.000000000 +0300 -@@ -1,19 +1,13 @@ - /* -- Copyright (c) 1990-1999 Info-ZIP. All rights reserved. -+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - -- See the accompanying file LICENSE, version 1999-Oct-05 or later -+ See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. -- If, for some reason, both of these files are missing, the Info-ZIP license -- also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html -+ If, for some reason, all these files are missing, the Info-ZIP license -+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - */ - /* -- crypt.h (dummy version) by Info-ZIP. Last revised: 15 Aug 98 -- -- This is a non-functional version of Info-ZIP's crypt.h encryption/ -- decryption header file for Zip, ZipCloak, UnZip and fUnZip. This -- file is not copyrighted and may be distributed without restriction. -- See the "WHERE" file for sites from which to obtain the full crypt -- sources (zcrypt28.zip or later). -+ crypt.h (full version) by Info-ZIP. Last revised: [see CR_VERSION_DATE] - */ - - #ifndef __crypt_h /* don't include more than once */ -@@ -22,11 +16,131 @@ - #ifdef CRYPT - # undef CRYPT - #endif --#define CRYPT 0 /* dummy version */ -+ -+#if !defined(NO_CRYPT) -+# define CRYPT 1 /* full version */ -+#else -+# define CRYPT 0 /* dummy version */ -+#endif -+ -+#if CRYPT -+/* full version */ -+ -+#ifdef CR_BETA -+# undef CR_BETA /* this is not a beta release */ -+#endif -+ -+#define CR_MAJORVER 2 -+#define CR_MINORVER 9 -+#ifdef CR_BETA -+# define CR_BETA_VER "a BETA" -+# define CR_VERSION_DATE "9 April 2000" /* last real code change */ -+#else -+# define CR_BETA_VER "" -+# define CR_VERSION_DATE "22 April 2000" /* last public release date */ -+# define CR_RELEASE -+#endif -+ -+#ifndef __G /* UnZip only, for now (DLL stuff) */ -+# define __G -+# define __G__ -+# define __GDEF -+# define __GPRO void -+# define __GPRO__ -+#endif -+ -+#if defined(MSDOS) || defined(OS2) || defined(WIN32) -+# ifndef DOS_OS2_W32 -+# define DOS_OS2_W32 -+# endif -+#endif -+ -+#if defined(DOS_OS2_W32) || defined(__human68k__) -+# ifndef DOS_H68_OS2_W32 -+# define DOS_H68_OS2_W32 -+# endif -+#endif -+ -+#if defined(VM_CMS) || defined(MVS) -+# ifndef CMS_MVS -+# define CMS_MVS -+# endif -+#endif -+ -+/* To allow combining of Zip and UnZip static libraries in a single binary, -+ * the Zip and UnZip versions of the crypt core functions have to be named -+ * differently. -+ */ -+#ifdef ZIP -+# ifdef REALLY_SHORT_SYMS -+# define decrypt_byte zdcrby -+# else -+# define decrypt_byte zp_decrypt_byte -+# endif -+# define update_keys zp_update_keys -+# define init_keys zp_init_keys -+#else /* !ZIP */ -+# ifdef REALLY_SHORT_SYMS -+# define decrypt_byte dcrbyt -+# endif -+#endif /* ?ZIP */ -+ -+#define IZ_PWLEN 80 /* input buffer size for reading encryption key */ -+#ifndef PWLEN /* for compatibility with previous zcrypt release... */ -+# define PWLEN IZ_PWLEN -+#endif -+#define RAND_HEAD_LEN 12 /* length of encryption random header */ -+ -+/* the crc_32_tab array has to be provided externally for the crypt calculus */ -+#ifndef CRC_32_TAB /* UnZip provides this in globals.h */ -+# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) -+ extern ZCONST ulg near *crc_32_tab; -+# else -+ extern ZCONST ulg Far *crc_32_tab; -+# endif -+#endif /* !CRC_32_TAB */ -+ -+/* encode byte c, using temp t. Warning: c must not have side effects. */ -+#define zencode(c,t) (t=decrypt_byte(__G), update_keys(c), t^(c)) -+ -+/* decode byte c in place */ -+#define zdecode(c) update_keys(__G__ c ^= decrypt_byte(__G)) -+ -+int decrypt_byte OF((__GPRO)); -+int update_keys OF((__GPRO__ int c)); -+void init_keys OF((__GPRO__ ZCONST char *passwd)); -+ -+#ifdef ZIP -+ void crypthead OF((ZCONST char *, ulg, FILE *)); -+# ifdef UTIL -+ int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); -+ int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); -+# else -+ unsigned zfwrite OF((zvoid *, extent, extent, FILE *)); -+ extern char *key; -+# endif -+#endif /* ZIP */ -+ -+#if (defined(UNZIP) && !defined(FUNZIP)) -+ int decrypt OF((__GPRO__ ZCONST char *passwrd)); -+#endif -+ -+#ifdef FUNZIP -+ extern int encrypted; -+# ifdef NEXTBYTE -+# undef NEXTBYTE -+# endif -+# define NEXTBYTE \ -+ (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in)) -+#endif /* FUNZIP */ -+ -+#else /* !CRYPT */ -+/* dummy version */ - - #define zencode - #define zdecode - - #define zfwrite fwrite - -+#endif /* ?CRYPT */ - #endif /* !__crypt_h */ diff --git a/tags/pisi-1.0_beta2/tests/zip/files/zip-2.3-unix_configure-pic.patch b/tags/pisi-1.0_beta2/tests/zip/files/zip-2.3-unix_configure-pic.patch deleted file mode 100644 index 45b137b0..00000000 --- a/tags/pisi-1.0_beta2/tests/zip/files/zip-2.3-unix_configure-pic.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- unix/configure.orig 2004-09-28 06:45:33.000000000 +0000 -+++ unix/configure 2004-09-28 06:54:53.000000000 +0000 -@@ -29,6 +29,9 @@ - - echo Check if we can use asm code - OBJA="" -+piclib="$(echo | $CPP -dM $CFLAGS - | grep -i __pic__)" -+echo "Checking if compiler wants to create pic code" -+[ "$piclib" == "" ] && \ - if eval "$CPP match.S > _match.s 2>/dev/null"; then - if test ! -s _match.s || grep error < _match.s > /dev/null; then - : diff --git a/tags/pisi-1.0_beta2/tests/zip/files/zip-CAN-2004-1010.patch b/tags/pisi-1.0_beta2/tests/zip/files/zip-CAN-2004-1010.patch deleted file mode 100644 index 150d6407..00000000 --- a/tags/pisi-1.0_beta2/tests/zip/files/zip-CAN-2004-1010.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- zip-2.3/unix/unix.c.orig 2004-11-05 15:44:41.000000000 -0500 -+++ zip-2.3/unix/unix.c 2004-11-05 15:50:28.000000000 -0500 -@@ -319,8 +319,8 @@ iztimes *t; /* return value: - a file size of -1 */ - { - struct stat s; /* results of stat() */ -- char name[FNMAX]; -- int len = strlen(f); -+ char *name; -+ size_t len = strlen(f); - - if (f == label) { - if (a != NULL) -@@ -331,6 +331,11 @@ iztimes *t; /* return value: - t->atime = t->mtime = t->ctime = label_utim; - return label_time; - } -+ -+ name = malloc(len+1); -+ if (!name) -+ return 0; -+ - strcpy(name, f); - if (name[len - 1] == '/') - name[len - 1] = '\0'; diff --git a/tags/pisi-1.0_beta2/tests/zip/pspec.xml b/tags/pisi-1.0_beta2/tests/zip/pspec.xml deleted file mode 100644 index 3ec0bc40..00000000 --- a/tags/pisi-1.0_beta2/tests/zip/pspec.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - zip - ftp://ftp.freesoftware.com/pub/infozip/Zip.html - - zibidi - himini@gmail.com - - Info-ZIP - category - component - Info ZIP (encryption support) - Info ZIP (encryption support) - ftp://ftp.linux.org.tr/pub/mirrors/gentoo/distfiles/zip23.tar.gz - - zip-2.3-unix_configure-pic.patch - zip-CAN-2004-1010.patch - zcrypt.patch - - - patch - - - - - zip - - unzip - - - /usr/bin - /usr/share/doc - /usr/share/man - - - - - 2005-07-15 - 2.3 - - - - - diff --git a/tags/pisi-1.0_beta2/tests/zip2/actions.py b/tags/pisi-1.0_beta2/tests/zip2/actions.py deleted file mode 100644 index a2c1b060..00000000 --- a/tags/pisi-1.0_beta2/tests/zip2/actions.py +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -from pisi.actionsapi import autotools -from pisi.actionsapi import get -from pisi.actionsapi import pisitools - -WorkDir="zip-2.3" - -def setup(): - pisitools.dosed("unix/Makefile", "-O2", get.CFLAGS()) - -def build(): - autotools.make("-f unix/Makefile CC=%s CPP=%s generic" % (get.CC(), get.CXX())) - -def install(): - pisitools.dobin("zip") - pisitools.dobin("zipcloak") - pisitools.dobin("zipnote") - pisitools.dobin("zipsplit") - - pisitools.doman("man/*.1") - pisitools.dodoc("BUGS", "CHANGES", "MANUAL", "README", "TODO", "WHATSNEW", "WHERE") - diff --git a/tags/pisi-1.0_beta2/tests/zip2/files/zcrypt.patch b/tags/pisi-1.0_beta2/tests/zip2/files/zcrypt.patch deleted file mode 100644 index 6b696af5..00000000 --- a/tags/pisi-1.0_beta2/tests/zip2/files/zcrypt.patch +++ /dev/null @@ -1,752 +0,0 @@ -diff -ur zip-2.3.orig/crypt.c zip-2.3/crypt.c ---- zip-2.3.orig/crypt.c 1999-10-09 23:09:26.000000000 +0300 -+++ zip-2.3/crypt.c 2005-07-15 16:19:00.000000000 +0300 -@@ -1,20 +1,577 @@ - /* -- Copyright (c) 1990-1999 Info-ZIP. All rights reserved. -+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - -- See the accompanying file LICENSE, version 1999-Oct-05 or later -+ See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. -- If, for some reason, both of these files are missing, the Info-ZIP license -- also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html -+ If, for some reason, all these files are missing, the Info-ZIP license -+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - */ - /* -- crypt.c (dummy version) by Info-ZIP. Last revised: 15 Aug 98 -+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - -- This is a non-functional version of Info-ZIP's crypt.c encryption/ -- decryption code for Zip, ZipCloak, UnZip and fUnZip. This file is -- not copyrighted and may be distributed freely. :-) See the "WHERE" -- file for sites from which to obtain the full encryption/decryption -- sources (zcrypt28.zip or later). -+ The encryption/decryption parts of this source code (as opposed to the -+ non-echoing password parts) were originally written in Europe. The -+ whole source package can be freely distributed, including from the USA. -+ (Prior to January 2000, re-export from the US was a violation of US law.) - */ - -+/* -+ This encryption code is a direct transcription of the algorithm from -+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This -+ file (appnote.txt) is distributed with the PKZIP program (even in the -+ version without encryption capabilities). -+ */ -+ -+#define ZCRYPT_INTERNAL -+#include "zip.h" -+#include "crypt.h" -+#include "ttyio.h" -+ -+#if CRYPT -+ -+#ifndef FALSE -+# define FALSE 0 -+#endif -+ -+#ifdef ZIP -+ /* For the encoding task used in Zip (and ZipCloak), we want to initialize -+ the crypt algorithm with some reasonably unpredictable bytes, see -+ the crypthead() function. The standard rand() library function is -+ used to supply these `random' bytes, which in turn is initialized by -+ a srand() call. The srand() function takes an "unsigned" (at least 16bit) -+ seed value as argument to determine the starting point of the rand() -+ pseudo-random number generator. -+ This seed number is constructed as "Seed = Seed1 .XOR. Seed2" with -+ Seed1 supplied by the current time (= "(unsigned)time()") and Seed2 -+ as some (hopefully) nondeterministic bitmask. On many (most) systems, -+ we use some "process specific" number, as the PID or something similar, -+ but when nothing unpredictable is available, a fixed number may be -+ sufficient. -+ NOTE: -+ 1.) This implementation requires the availability of the following -+ standard UNIX C runtime library functions: time(), rand(), srand(). -+ On systems where some of them are missing, the environment that -+ incorporates the crypt routines must supply suitable replacement -+ functions. -+ 2.) It is a very bad idea to use a second call to time() to set the -+ "Seed2" number! In this case, both "Seed1" and "Seed2" would be -+ (almost) identical, resulting in a (mostly) "zero" constant seed -+ number passed to srand(). -+ -+ The implementation environment defined in the "zip.h" header should -+ supply a reasonable definition for ZCR_SEED2 (an unsigned number; for -+ most implementations of rand() and srand(), only the lower 16 bits are -+ significant!). An example that works on many systems would be -+ "#define ZCR_SEED2 (unsigned)getpid()". -+ The default definition for ZCR_SEED2 supplied below should be regarded -+ as a fallback to allow successful compilation in "beta state" -+ environments. -+ */ -+# include /* time() function supplies first part of crypt seed */ -+ /* "last resort" source for second part of crypt seed pattern */ -+# ifndef ZCR_SEED2 -+# define ZCR_SEED2 (unsigned)3141592654L /* use PI as default pattern */ -+# endif -+# ifdef GLOBAL /* used in Amiga system headers, maybe others too */ -+# undef GLOBAL -+# endif -+# define GLOBAL(g) g -+#else /* !ZIP */ -+# define GLOBAL(g) G.g -+#endif /* ?ZIP */ -+ -+ -+#ifdef UNZIP -+ /* char *key = (char *)NULL; moved to globals.h */ -+# ifndef FUNZIP -+ local int testp OF((__GPRO__ ZCONST uch *h)); -+ local int testkey OF((__GPRO__ ZCONST uch *h, ZCONST char *key)); -+# endif -+#endif /* UNZIP */ -+ -+#ifndef UNZIP /* moved to globals.h for UnZip */ -+ local ulg keys[3]; /* keys defining the pseudo-random sequence */ -+#endif /* !UNZIP */ -+ -+#ifndef Trace -+# ifdef CRYPT_DEBUG -+# define Trace(x) fprintf x -+# else -+# define Trace(x) -+# endif -+#endif -+ -+#ifndef CRC_32_TAB -+# define CRC_32_TAB crc_32_tab -+#endif -+ -+#define CRC32(c, b) (CRC_32_TAB[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8)) -+ -+/*********************************************************************** -+ * Return the next byte in the pseudo-random sequence -+ */ -+int decrypt_byte(__G) -+ __GDEF -+{ -+ unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an -+ * unpredictable manner on 16-bit systems; not a problem -+ * with any known compiler so far, though */ -+ -+ temp = ((unsigned)GLOBAL(keys[2]) & 0xffff) | 2; -+ return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -+} -+ -+/*********************************************************************** -+ * Update the encryption keys with the next byte of plain text -+ */ -+int update_keys(__G__ c) -+ __GDEF -+ int c; /* byte of plain text */ -+{ -+ GLOBAL(keys[0]) = CRC32(GLOBAL(keys[0]), c); -+ GLOBAL(keys[1]) += GLOBAL(keys[0]) & 0xff; -+ GLOBAL(keys[1]) = GLOBAL(keys[1]) * 134775813L + 1; -+ { -+ register int keyshift = (int)(GLOBAL(keys[1]) >> 24); -+ GLOBAL(keys[2]) = CRC32(GLOBAL(keys[2]), keyshift); -+ } -+ return c; -+} -+ -+ -+/*********************************************************************** -+ * Initialize the encryption keys and the random header according to -+ * the given password. -+ */ -+void init_keys(__G__ passwd) -+ __GDEF -+ ZCONST char *passwd; /* password string with which to modify keys */ -+{ -+ GLOBAL(keys[0]) = 305419896L; -+ GLOBAL(keys[1]) = 591751049L; -+ GLOBAL(keys[2]) = 878082192L; -+ while (*passwd != '\0') { -+ update_keys(__G__ (int)*passwd); -+ passwd++; -+ } -+} -+ -+ -+#ifdef ZIP -+ -+/*********************************************************************** -+ * Write encryption header to file zfile using the password passwd -+ * and the cyclic redundancy check crc. -+ */ -+void crypthead(passwd, crc, zfile) -+ ZCONST char *passwd; /* password string */ -+ ulg crc; /* crc of file being encrypted */ -+ FILE *zfile; /* where to write header */ -+{ -+ int n; /* index in random header */ -+ int t; /* temporary */ -+ int c; /* random byte */ -+ int ztemp; /* temporary for zencoded value */ -+ uch header[RAND_HEAD_LEN-2]; /* random header */ -+ static unsigned calls = 0; /* ensure different random header each time */ -+ -+ /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the -+ * output of rand() to get less predictability, since rand() is -+ * often poorly implemented. -+ */ -+ if (++calls == 1) { -+ srand((unsigned)time(NULL) ^ ZCR_SEED2); -+ } -+ init_keys(passwd); -+ for (n = 0; n < RAND_HEAD_LEN-2; n++) { -+ c = (rand() >> 7) & 0xff; -+ header[n] = (uch)zencode(c, t); -+ } -+ /* Encrypt random header (last two bytes is high word of crc) */ -+ init_keys(passwd); -+ for (n = 0; n < RAND_HEAD_LEN-2; n++) { -+ ztemp = zencode(header[n], t); -+ putc(ztemp, zfile); -+ } -+ ztemp = zencode((int)(crc >> 16) & 0xff, t); -+ putc(ztemp, zfile); -+ ztemp = zencode((int)(crc >> 24) & 0xff, t); -+ putc(ztemp, zfile); -+} -+ -+ -+#ifdef UTIL -+ -+/*********************************************************************** -+ * Encrypt the zip entry described by z from file source to file dest -+ * using the password passwd. Return an error code in the ZE_ class. -+ */ -+int zipcloak(z, source, dest, passwd) -+ struct zlist far *z; /* zip entry to encrypt */ -+ FILE *source, *dest; /* source and destination files */ -+ ZCONST char *passwd; /* password string */ -+{ -+ int c; /* input byte */ -+ int res; /* result code */ -+ ulg n; /* holds offset and counts size */ -+ ush flag; /* previous flags */ -+ int t; /* temporary */ -+ int ztemp; /* temporary storage for zencode value */ -+ -+ /* Set encrypted bit, clear extended local header bit and write local -+ header to output file */ -+ if ((n = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; -+ z->off = n; -+ flag = z->flg; -+ z->flg |= 1, z->flg &= ~8; -+ z->lflg |= 1, z->lflg &= ~8; -+ z->siz += RAND_HEAD_LEN; -+ if ((res = putlocal(z, dest)) != ZE_OK) return res; -+ -+ /* Initialize keys with password and write random header */ -+ crypthead(passwd, z->crc, dest); -+ -+ /* Skip local header in input file */ -+ if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), -+ SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ -+ /* Encrypt data */ -+ for (n = z->siz - RAND_HEAD_LEN; n; n--) { -+ if ((c = getc(source)) == EOF) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ ztemp = zencode(c, t); -+ putc(ztemp, dest); -+ } -+ /* Skip extended local header in input file if there is one */ -+ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ if (fflush(dest) == EOF) return ZE_TEMP; -+ return ZE_OK; -+} -+ -+/*********************************************************************** -+ * Decrypt the zip entry described by z from file source to file dest -+ * using the password passwd. Return an error code in the ZE_ class. -+ */ -+int zipbare(z, source, dest, passwd) -+ struct zlist far *z; /* zip entry to encrypt */ -+ FILE *source, *dest; /* source and destination files */ -+ ZCONST char *passwd; /* password string */ -+{ -+ int c0, c1; /* last two input bytes */ -+ ulg offset; /* used for file offsets */ -+ ulg size; /* size of input data */ -+ int r; /* size of encryption header */ -+ int res; /* return code */ -+ ush flag; /* previous flags */ -+ -+ /* Save position and skip local header in input file */ -+ if ((offset = (ulg)ftell(source)) == (ulg)-1L || -+ fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext), -+ SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ /* Initialize keys with password */ -+ init_keys(passwd); -+ -+ /* Decrypt encryption header, save last two bytes */ -+ c1 = 0; -+ for (r = RAND_HEAD_LEN; r; r--) { -+ c0 = c1; -+ if ((c1 = getc(source)) == EOF) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ Trace((stdout, " (%02x)", c1)); -+ zdecode(c1); -+ Trace((stdout, " %02x", c1)); -+ } -+ Trace((stdout, "\n")); -+ -+ /* If last two bytes of header don't match crc (or file time in the -+ * case of an extended local header), back up and just copy. For -+ * pkzip 2.0, the check has been reduced to one byte only. -+ */ -+#ifdef ZIP10 -+ if ((ush)(c0 | (c1<<8)) != -+ (z->flg & 8 ? (ush) z->tim & 0xffff : (ush)(z->crc >> 16))) { -+#else -+ c0++; /* avoid warning on unused variable */ -+ if ((ush)c1 != (z->flg & 8 ? (ush) z->tim >> 8 : (ush)(z->crc >> 24))) { -+#endif -+ if (fseek(source, offset, SEEK_SET)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ if ((res = zipcopy(z, source, dest)) != ZE_OK) return res; -+ return ZE_MISS; -+ } -+ -+ /* Clear encrypted bit and local header bit, and write local header to -+ output file */ -+ if ((offset = (ulg)ftell(dest)) == (ulg)-1L) return ZE_TEMP; -+ z->off = offset; -+ flag = z->flg; -+ z->flg &= ~9; -+ z->lflg &= ~9; -+ z->siz -= RAND_HEAD_LEN; -+ if ((res = putlocal(z, dest)) != ZE_OK) return res; -+ -+ /* Decrypt data */ -+ for (size = z->siz; size; size--) { -+ if ((c1 = getc(source)) == EOF) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ zdecode(c1); -+ putc(c1, dest); -+ } -+ /* Skip extended local header in input file if there is one */ -+ if ((flag & 8) != 0 && fseek(source, 16L, SEEK_CUR)) { -+ return ferror(source) ? ZE_READ : ZE_EOF; -+ } -+ if (fflush(dest) == EOF) return ZE_TEMP; -+ -+ return ZE_OK; -+} -+ -+ -+#else /* !UTIL */ -+ -+/*********************************************************************** -+ * If requested, encrypt the data in buf, and in any case call fwrite() -+ * with the arguments to zfwrite(). Return what fwrite() returns. -+ */ -+unsigned zfwrite(buf, item_size, nb, f) -+ zvoid *buf; /* data buffer */ -+ extent item_size; /* size of each item in bytes */ -+ extent nb; /* number of items */ -+ FILE *f; /* file to write to */ -+{ -+ int t; /* temporary */ -+ -+ if (key != (char *)NULL) { /* key is the global password pointer */ -+ ulg size; /* buffer size */ -+ char *p = (char*)buf; /* steps through buffer */ -+ -+ /* Encrypt data in buffer */ -+ for (size = item_size*(ulg)nb; size != 0; p++, size--) { -+ *p = (char)zencode(*p, t); -+ } -+ } -+ /* Write the buffer out */ -+ return fwrite(buf, item_size, nb, f); -+} -+ -+#endif /* ?UTIL */ -+#endif /* ZIP */ -+ -+ -+#if (defined(UNZIP) && !defined(FUNZIP)) -+ -+/*********************************************************************** -+ * Get the password and set up keys for current zipfile member. -+ * Return PK_ class error. -+ */ -+int decrypt(__G__ passwrd) -+ __GDEF -+ ZCONST char *passwrd; -+{ -+ ush b; -+ int n, r; -+ uch h[RAND_HEAD_LEN]; -+ -+ Trace((stdout, "\n[incnt = %d]: ", GLOBAL(incnt))); -+ -+ /* get header once (turn off "encrypted" flag temporarily so we don't -+ * try to decrypt the same data twice) */ -+ GLOBAL(pInfo->encrypted) = FALSE; -+ defer_leftover_input(__G); -+ for (n = 0; n < RAND_HEAD_LEN; n++) { -+ b = NEXTBYTE; -+ h[n] = (uch)b; -+ Trace((stdout, " (%02x)", h[n])); -+ } -+ undefer_input(__G); -+ GLOBAL(pInfo->encrypted) = TRUE; -+ -+ if (GLOBAL(newzip)) { /* this is first encrypted member in this zipfile */ -+ GLOBAL(newzip) = FALSE; -+ if (passwrd != (char *)NULL) { /* user gave password on command line */ -+ if (!GLOBAL(key)) { -+ if ((GLOBAL(key) = (char *)malloc(strlen(passwrd)+1)) == -+ (char *)NULL) -+ return PK_MEM2; -+ strcpy(GLOBAL(key), passwrd); -+ GLOBAL(nopwd) = TRUE; /* inhibit password prompting! */ -+ } -+ } else if (GLOBAL(key)) { /* get rid of previous zipfile's key */ -+ free(GLOBAL(key)); -+ GLOBAL(key) = (char *)NULL; -+ } -+ } -+ -+ /* if have key already, test it; else allocate memory for it */ -+ if (GLOBAL(key)) { -+ if (!testp(__G__ h)) -+ return PK_COOL; /* existing password OK (else prompt for new) */ -+ else if (GLOBAL(nopwd)) -+ return PK_WARN; /* user indicated no more prompting */ -+ } else if ((GLOBAL(key) = (char *)malloc(IZ_PWLEN+1)) == (char *)NULL) -+ return PK_MEM2; -+ -+ /* try a few keys */ -+ n = 0; -+ do { -+ r = (*G.decr_passwd)((zvoid *)&G, &n, GLOBAL(key), IZ_PWLEN+1, -+ GLOBAL(zipfn), GLOBAL(filename)); -+ if (r == IZ_PW_ERROR) { /* internal error in fetch of PW */ -+ free (GLOBAL(key)); -+ GLOBAL(key) = NULL; -+ return PK_MEM2; -+ } -+ if (r != IZ_PW_ENTERED) { /* user replied "skip" or "skip all" */ -+ *GLOBAL(key) = '\0'; /* We try the NIL password, ... */ -+ n = 0; /* and cancel fetch for this item. */ -+ } -+ if (!testp(__G__ h)) -+ return PK_COOL; -+ if (r == IZ_PW_CANCELALL) /* User replied "Skip all" */ -+ GLOBAL(nopwd) = TRUE; /* inhibit any further PW prompt! */ -+ } while (n > 0); -+ -+ return PK_WARN; -+ -+} /* end function decrypt() */ -+ -+ -+ -+/*********************************************************************** -+ * Test the password. Return -1 if bad, 0 if OK. -+ */ -+local int testp(__G__ h) -+ __GDEF -+ ZCONST uch *h; -+{ -+ int r; -+ char *key_translated; -+ -+ /* On systems with "obscure" native character coding (e.g., EBCDIC), -+ * the first test translates the password to the "main standard" -+ * character coding. */ -+ -+#ifdef STR_TO_CP1 -+ /* allocate buffer for translated password */ -+ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) -+ return -1; -+ /* first try, test password translated "standard" charset */ -+ r = testkey(__G__ h, STR_TO_CP1(key_translated, GLOBAL(key))); -+#else /* !STR_TO_CP1 */ -+ /* first try, test password as supplied on the extractor's host */ -+ r = testkey(__G__ h, GLOBAL(key)); -+#endif /* ?STR_TO_CP1 */ -+ -+#ifdef STR_TO_CP2 -+ if (r != 0) { -+#ifndef STR_TO_CP1 -+ /* now prepare for second (and maybe third) test with translated pwd */ -+ if ((key_translated = malloc(strlen(GLOBAL(key)) + 1)) == (char *)NULL) -+ return -1; -+#endif -+ /* second try, password translated to alternate ("standard") charset */ -+ r = testkey(__G__ h, STR_TO_CP2(key_translated, GLOBAL(key))); -+#ifdef STR_TO_CP3 -+ if (r != 0) -+ /* third try, password translated to another "standard" charset */ -+ r = testkey(__G__ h, STR_TO_CP3(key_translated, GLOBAL(key))); -+#endif -+#ifndef STR_TO_CP1 -+ free(key_translated); -+#endif -+ } -+#endif /* STR_TO_CP2 */ -+ -+#ifdef STR_TO_CP1 -+ free(key_translated); -+ if (r != 0) { -+ /* last resort, test password as supplied on the extractor's host */ -+ r = testkey(__G__ h, GLOBAL(key)); -+ } -+#endif /* STR_TO_CP1 */ -+ -+ return r; -+ -+} /* end function testp() */ -+ -+ -+local int testkey(__G__ h, key) -+ __GDEF -+ ZCONST uch *h; /* decrypted header */ -+ ZCONST char *key; /* decryption password to test */ -+{ -+ ush b; -+#ifdef ZIP10 -+ ush c; -+#endif -+ int n; -+ uch *p; -+ uch hh[RAND_HEAD_LEN]; /* decrypted header */ -+ -+ /* set keys and save the encrypted header */ -+ init_keys(__G__ key); -+ memcpy(hh, h, RAND_HEAD_LEN); -+ -+ /* check password */ -+ for (n = 0; n < RAND_HEAD_LEN; n++) { -+ zdecode(hh[n]); -+ Trace((stdout, " %02x", hh[n])); -+ } -+ -+ Trace((stdout, -+ "\n lrec.crc= %08lx crec.crc= %08lx pInfo->ExtLocHdr= %s\n", -+ GLOBAL(lrec.crc32), GLOBAL(pInfo->crc), -+ GLOBAL(pInfo->ExtLocHdr) ? "true":"false")); -+ Trace((stdout, " incnt = %d unzip offset into zipfile = %ld\n", -+ GLOBAL(incnt), -+ GLOBAL(cur_zipfile_bufstart)+(GLOBAL(inptr)-GLOBAL(inbuf)))); -+ -+ /* same test as in zipbare(): */ -+ -+#ifdef ZIP10 /* check two bytes */ -+ c = hh[RAND_HEAD_LEN-2], b = hh[RAND_HEAD_LEN-1]; -+ Trace((stdout, -+ " (c | (b<<8)) = %04x (crc >> 16) = %04x lrec.time = %04x\n", -+ (ush)(c | (b<<8)), (ush)(GLOBAL(lrec.crc32) >> 16), -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff)))); -+ if ((ush)(c | (b<<8)) != (GLOBAL(pInfo->ExtLocHdr) ? -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) & 0xffff) : -+ (ush)(GLOBAL(lrec.crc32) >> 16))) -+ return -1; /* bad */ -+#else -+ b = hh[RAND_HEAD_LEN-1]; -+ Trace((stdout, " b = %02x (crc >> 24) = %02x (lrec.time >> 8) = %02x\n", -+ b, (ush)(GLOBAL(lrec.crc32) >> 24), -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff)); -+ if (b != (GLOBAL(pInfo->ExtLocHdr) ? -+ ((ush)GLOBAL(lrec.last_mod_dos_datetime) >> 8) & 0xff : -+ (ush)(GLOBAL(lrec.crc32) >> 24))) -+ return -1; /* bad */ -+#endif -+ /* password OK: decrypt current buffer contents before leaving */ -+ for (n = (long)GLOBAL(incnt) > GLOBAL(csize) ? -+ (int)GLOBAL(csize) : GLOBAL(incnt), -+ p = GLOBAL(inptr); n--; p++) -+ zdecode(*p); -+ return 0; /* OK */ -+ -+} /* end function testkey() */ -+ -+#endif /* UNZIP && !FUNZIP */ -+ -+#else /* !CRYPT */ -+ - /* something "externally visible" to shut up compiler/linker warnings */ - int zcr_dummy; -+ -+#endif /* ?CRYPT */ -diff -ur zip-2.3.orig/crypt.h zip-2.3/crypt.h ---- zip-2.3.orig/crypt.h 1999-10-09 23:10:00.000000000 +0300 -+++ zip-2.3/crypt.h 2005-07-15 16:19:00.000000000 +0300 -@@ -1,19 +1,13 @@ - /* -- Copyright (c) 1990-1999 Info-ZIP. All rights reserved. -+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - -- See the accompanying file LICENSE, version 1999-Oct-05 or later -+ See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. -- If, for some reason, both of these files are missing, the Info-ZIP license -- also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html -+ If, for some reason, all these files are missing, the Info-ZIP license -+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - */ - /* -- crypt.h (dummy version) by Info-ZIP. Last revised: 15 Aug 98 -- -- This is a non-functional version of Info-ZIP's crypt.h encryption/ -- decryption header file for Zip, ZipCloak, UnZip and fUnZip. This -- file is not copyrighted and may be distributed without restriction. -- See the "WHERE" file for sites from which to obtain the full crypt -- sources (zcrypt28.zip or later). -+ crypt.h (full version) by Info-ZIP. Last revised: [see CR_VERSION_DATE] - */ - - #ifndef __crypt_h /* don't include more than once */ -@@ -22,11 +16,131 @@ - #ifdef CRYPT - # undef CRYPT - #endif --#define CRYPT 0 /* dummy version */ -+ -+#if !defined(NO_CRYPT) -+# define CRYPT 1 /* full version */ -+#else -+# define CRYPT 0 /* dummy version */ -+#endif -+ -+#if CRYPT -+/* full version */ -+ -+#ifdef CR_BETA -+# undef CR_BETA /* this is not a beta release */ -+#endif -+ -+#define CR_MAJORVER 2 -+#define CR_MINORVER 9 -+#ifdef CR_BETA -+# define CR_BETA_VER "a BETA" -+# define CR_VERSION_DATE "9 April 2000" /* last real code change */ -+#else -+# define CR_BETA_VER "" -+# define CR_VERSION_DATE "22 April 2000" /* last public release date */ -+# define CR_RELEASE -+#endif -+ -+#ifndef __G /* UnZip only, for now (DLL stuff) */ -+# define __G -+# define __G__ -+# define __GDEF -+# define __GPRO void -+# define __GPRO__ -+#endif -+ -+#if defined(MSDOS) || defined(OS2) || defined(WIN32) -+# ifndef DOS_OS2_W32 -+# define DOS_OS2_W32 -+# endif -+#endif -+ -+#if defined(DOS_OS2_W32) || defined(__human68k__) -+# ifndef DOS_H68_OS2_W32 -+# define DOS_H68_OS2_W32 -+# endif -+#endif -+ -+#if defined(VM_CMS) || defined(MVS) -+# ifndef CMS_MVS -+# define CMS_MVS -+# endif -+#endif -+ -+/* To allow combining of Zip and UnZip static libraries in a single binary, -+ * the Zip and UnZip versions of the crypt core functions have to be named -+ * differently. -+ */ -+#ifdef ZIP -+# ifdef REALLY_SHORT_SYMS -+# define decrypt_byte zdcrby -+# else -+# define decrypt_byte zp_decrypt_byte -+# endif -+# define update_keys zp_update_keys -+# define init_keys zp_init_keys -+#else /* !ZIP */ -+# ifdef REALLY_SHORT_SYMS -+# define decrypt_byte dcrbyt -+# endif -+#endif /* ?ZIP */ -+ -+#define IZ_PWLEN 80 /* input buffer size for reading encryption key */ -+#ifndef PWLEN /* for compatibility with previous zcrypt release... */ -+# define PWLEN IZ_PWLEN -+#endif -+#define RAND_HEAD_LEN 12 /* length of encryption random header */ -+ -+/* the crc_32_tab array has to be provided externally for the crypt calculus */ -+#ifndef CRC_32_TAB /* UnZip provides this in globals.h */ -+# if (!defined(USE_ZLIB) || defined(USE_OWN_CRCTAB)) -+ extern ZCONST ulg near *crc_32_tab; -+# else -+ extern ZCONST ulg Far *crc_32_tab; -+# endif -+#endif /* !CRC_32_TAB */ -+ -+/* encode byte c, using temp t. Warning: c must not have side effects. */ -+#define zencode(c,t) (t=decrypt_byte(__G), update_keys(c), t^(c)) -+ -+/* decode byte c in place */ -+#define zdecode(c) update_keys(__G__ c ^= decrypt_byte(__G)) -+ -+int decrypt_byte OF((__GPRO)); -+int update_keys OF((__GPRO__ int c)); -+void init_keys OF((__GPRO__ ZCONST char *passwd)); -+ -+#ifdef ZIP -+ void crypthead OF((ZCONST char *, ulg, FILE *)); -+# ifdef UTIL -+ int zipcloak OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); -+ int zipbare OF((struct zlist far *, FILE *, FILE *, ZCONST char *)); -+# else -+ unsigned zfwrite OF((zvoid *, extent, extent, FILE *)); -+ extern char *key; -+# endif -+#endif /* ZIP */ -+ -+#if (defined(UNZIP) && !defined(FUNZIP)) -+ int decrypt OF((__GPRO__ ZCONST char *passwrd)); -+#endif -+ -+#ifdef FUNZIP -+ extern int encrypted; -+# ifdef NEXTBYTE -+# undef NEXTBYTE -+# endif -+# define NEXTBYTE \ -+ (encrypted? update_keys(__G__ getc(G.in)^decrypt_byte(__G)) : getc(G.in)) -+#endif /* FUNZIP */ -+ -+#else /* !CRYPT */ -+/* dummy version */ - - #define zencode - #define zdecode - - #define zfwrite fwrite - -+#endif /* ?CRYPT */ - #endif /* !__crypt_h */ diff --git a/tags/pisi-1.0_beta2/tests/zip2/files/zip-2.3-unix_configure-pic.patch b/tags/pisi-1.0_beta2/tests/zip2/files/zip-2.3-unix_configure-pic.patch deleted file mode 100644 index 45b137b0..00000000 --- a/tags/pisi-1.0_beta2/tests/zip2/files/zip-2.3-unix_configure-pic.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- unix/configure.orig 2004-09-28 06:45:33.000000000 +0000 -+++ unix/configure 2004-09-28 06:54:53.000000000 +0000 -@@ -29,6 +29,9 @@ - - echo Check if we can use asm code - OBJA="" -+piclib="$(echo | $CPP -dM $CFLAGS - | grep -i __pic__)" -+echo "Checking if compiler wants to create pic code" -+[ "$piclib" == "" ] && \ - if eval "$CPP match.S > _match.s 2>/dev/null"; then - if test ! -s _match.s || grep error < _match.s > /dev/null; then - : diff --git a/tags/pisi-1.0_beta2/tests/zip2/files/zip-CAN-2004-1010.patch b/tags/pisi-1.0_beta2/tests/zip2/files/zip-CAN-2004-1010.patch deleted file mode 100644 index 150d6407..00000000 --- a/tags/pisi-1.0_beta2/tests/zip2/files/zip-CAN-2004-1010.patch +++ /dev/null @@ -1,25 +0,0 @@ ---- zip-2.3/unix/unix.c.orig 2004-11-05 15:44:41.000000000 -0500 -+++ zip-2.3/unix/unix.c 2004-11-05 15:50:28.000000000 -0500 -@@ -319,8 +319,8 @@ iztimes *t; /* return value: - a file size of -1 */ - { - struct stat s; /* results of stat() */ -- char name[FNMAX]; -- int len = strlen(f); -+ char *name; -+ size_t len = strlen(f); - - if (f == label) { - if (a != NULL) -@@ -331,6 +331,11 @@ iztimes *t; /* return value: - t->atime = t->mtime = t->ctime = label_utim; - return label_time; - } -+ -+ name = malloc(len+1); -+ if (!name) -+ return 0; -+ - strcpy(name, f); - if (name[len - 1] == '/') - name[len - 1] = '\0'; diff --git a/tags/pisi-1.0_beta2/tests/zip2/pspec.xml b/tags/pisi-1.0_beta2/tests/zip2/pspec.xml deleted file mode 100644 index 5c439849..00000000 --- a/tags/pisi-1.0_beta2/tests/zip2/pspec.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - zip - ftp://ftp.freesoftware.com/pub/infozip/Zip.html - - PACKAGER - PACKAGER_EMAIL - - Info-ZIP - category - component - Info ZIP (encryption support) - Info ZIP (encryption support) - ftp://ftp.linux.org.tr/pub/mirrors/gentoo/distfiles/zip23.tar.gz - - zip-2.3-unix_configure-pic.patch - - zcrypt.patch - - - unzip - patch - - - - - zip - - unzip - - - /usr/bin - /usr/share/doc - /usr/share/man - - - - - - 2005-08-11 - 2.4 - - - - - diff --git a/tags/pisi-1.0_beta2/tools/cat-db.py b/tags/pisi-1.0_beta2/tools/cat-db.py deleted file mode 100755 index c7574085..00000000 --- a/tags/pisi-1.0_beta2/tools/cat-db.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# -# Author: Eray Ozkural - -import sys -import bsddb.dbshelve as shelve - -sys.path.append('.') - -import pisi - -d = shelve.open( sys.argv[1], flags='r' ) - -for (k, data) in d.iteritems(): - print k, data - -d.close() diff --git a/tags/pisi-1.0_beta2/tools/check-source-repo.py b/tags/pisi-1.0_beta2/tools/check-source-repo.py deleted file mode 100755 index 15cc9ac7..00000000 --- a/tags/pisi-1.0_beta2/tools/check-source-repo.py +++ /dev/null @@ -1,32 +0,0 @@ -#! /usr/bin/python -# a simple tool to list stuff in source repository -# author: exa - -import sys -import os - -import pisi -import pisi.api -import pisi.config -import pisi.specfile as specfile -import pisi.context as ctx -import pisi.util - -options = pisi.config.Options() -if len(sys.argv) > 2: - options.destdir=sys.argv[2] -else: - options.destdir = '/' -pisi.api.init(database=False, options=options) -repo_uri = sys.argv[1] - -for root, dirs, files in os.walk(repo_uri): - for fn in files: - if fn == 'pspec.xml': - #ctx.ui.info(_('Adding %s to package index') % fn) - sf = specfile.SpecFile() - sf.read(pisi.util.join_path(root, fn)) - sf.check() - print sf.source.name - -pisi.api.finalize() diff --git a/tags/pisi-1.0_beta2/tools/convert_history.py b/tags/pisi-1.0_beta2/tools/convert_history.py deleted file mode 100755 index d4a64380..00000000 --- a/tags/pisi-1.0_beta2/tools/convert_history.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/python - -import sys -import os -import codecs -import xml.dom.minidom as mdom - -def find_pspecs(folder): - paks = [] - for root, dirs, files in os.walk(folder): - if "pspec.xml" in files: - paks.append(root) - # dont walk into the versioned stuff - if ".svn" in dirs: - dirs.remove(".svn") - return paks - -def addText(doc, parent, text): - cdata =doc.createTextNode(text) - parent.appendChild(cdata) - -def getTags(parent, childName): - return [x for x in parent.childNodes if x.nodeType == x.ELEMENT_NODE if x.tagName == childName] - -def getNodeText(node, tag, default=None): - try: - c = getTags(node, tag)[0].firstChild.data - except: - c = default - return c - -def newNode(doc, tag, text): - node = doc.createElement(tag) - cdata = doc.createTextNode(text) - node.appendChild(cdata) - return node - -def fixIndent(doc, node): - for x in node.childNodes: - if x.nodeType == x.ELEMENT_NODE: - if x.tagName == "Update": - fixIndent(doc, x) - else: - x.data = "\n" + x.data[5:] - -def fixTags(doc, hist): - for update in hist.childNodes: - if update.nodeType == update.ELEMENT_NODE: - rno = getNodeText(update, "Release") - update.setAttribute("release", rno) - if rno == "1": - comment = newNode(doc, "Comment", "First release.") - paker = getTags(getTags(doc.documentElement, "Source")[0], "Packager")[0] - name = newNode(doc, "Name", getNodeText(paker, "Name")) - email = newNode(doc, "Email", getNodeText(paker, "Email")) - else: - comment = newNode(doc, "Comment", "FIXHISTORY") - name = newNode(doc, "Name", "FIXHISTORY") - email = newNode(doc, "Email", "FIXHISTORY") - update.replaceChild(comment, getTags(update, "Release")[0]) - addText(doc, update, " ") - update.appendChild(name) - addText(doc, update, "\n ") - update.appendChild(email) - addText(doc, update, "\n ") - -def fixPspec(path): - doc = mdom.parse(path) - pisi = doc.documentElement - source = getTags(pisi, "Source")[0] - history = getTags(source, "History")[0] - item = source.removeChild(history) - addText(doc, pisi, "\n ") - fixIndent(doc, item) - fixTags(doc, item) - pisi.appendChild(item) - addText(doc, pisi, "\n") - f = codecs.open(path,'w', "utf-8") - f.write(doc.toxml()) - f.close() - -pakages = find_pspecs(sys.argv[1]) -for pak in pakages: - fixPspec(os.path.join(pak, "pspec.xml")) diff --git a/tags/pisi-1.0_beta2/tools/ebuild2pisi.py b/tags/pisi-1.0_beta2/tools/ebuild2pisi.py deleted file mode 100755 index e30b9004..00000000 --- a/tags/pisi-1.0_beta2/tools/ebuild2pisi.py +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. -# - -import sys -import re -import datetime - -sys.path.insert(0, "/usr/lib/portage/pym") -import portage - -PSPEC_TEMPLATE=''' - - - - - - %(packagename)s - %(homepage)s - - PACKAGER - PACKAGER_EMAIL - - %(license)s - - - %(description)s - %(description)s - %(archiveUri)s - -%(patches)s - - -%(buildDep)s - - - - - %(packagename)s - -%(runDep)s - - -FILES - - - - - - - %(updateDate)s - %(updateVersion)s - First release. - PACKAGER - PACKAGER_EMAIL - - - -''' - -def packageVersion(pkg): - if len(pkg) > 1: - parts = portage.catpkgsplit(pkg) - if parts == None: - return "" - - if parts[3] != 'r0': - version = parts[2] + "-" + parts[3] - else: - version = parts[2] - return version - else: - return False - -def getArchiveType(uri): - if uri.endswith("gz"): - return "targz" - elif uri.endswith("bz2"): - return "tarbz2" - elif uri.endswith("tar"): - return "tar" - elif uri.endswith("zip"): - return "zip" - return "UNKNOWN_TYPE" - -def getDepString(deps): - depString = "Dependencies should be reformated and check for correctness" - for dep in portage.flatten(portage.tokenize(deps)): - depString += "\n "+dep+"" - - return depString - - -def getPatches(filename, pkgName, version): - fileObj = open(filename) - patchList=[] - - # ebuild variables - rc = re.compile - dispatcher = { - rc("\$\{FILESDIR\}"): "", - rc('"'): "", - rc('^/'): "", - rc("\$\{P\}|\$\{PF\}"): "-".join([pkgName,version]), - rc("\$\{PN\}"): pkgName - } - - patched = False - for line in fileObj: - line = line.strip() - if line.startswith('#'): - continue - - p = rc("\Aepatch ").search(line) - if not p: - p = rc("\Apatch ").search(line) - if p: - patched = True - line = line[p.end():] - for r in dispatcher.keys(): - m = r.search(line) - while m: - line = line[:m.start()] + dispatcher[r] + line[m.end():] - m = r.search(line) - - patchList.append(line) - - patchString = "Patches should be checked for correctness" - for patch in patchList: - patchString += "\n "+patch+"" - - return patchString - -def main(ebuild): - dict = {} - db = portage.portdb - getKeys = lambda x: db.aux_get(ebuild, [x]) - getKey = lambda x: getKeys(x)[0] - - dict["homepage"] = getKey("HOMEPAGE") - dict["archiveUri"] = getKey("SRC_URI").split()[0] - dict["archiveType"] = getArchiveType(dict["archiveUri"]) - dict["packagename"] = portage.catpkgsplit(ebuild)[1] - dict["license"] = getKey("LICENSE") - dict["description"] = getKey("DESCRIPTION") - dict["updateDate"] = datetime.date.today() - - # version & release - if '-' in packageVersion(ebuild): - (version, release) = packageVersion(ebuild).split("-") - release = release.replace("r","") - else: - version = packageVersion(ebuild) - release = '' - dict["updateVersion"] = version - dict["updateRelease"] = release - - # buildDep & runDep - deps = getKeys("DEPEND") - dict["buildDep"] = getDepString(deps) - dict["runDep"] = getDepString(getKeys("RDEPEND")) - - # patches - dict["patches"] = getPatches(db.findname(ebuild), - dict["packagename"], - dict["updateVersion"]) - - print PSPEC_TEMPLATE % dict - -if __name__ == "__main__": - usage = """Usage: -PORTDIR=/path/to/portage/overlay %s category/ebuild - -Example: -PORTDIR=/trunk/ %s app-admin/fam-2.7.0-r2 - -You don't have to define PORTDIR if you are converting a package from -the main portage repository. -""" - try: - ebuild = sys.argv[1] - except: - print usage - sys.exit(1) - - main(ebuild) diff --git a/tags/pisi-1.0_beta2/tools/fetchAll.py b/tags/pisi-1.0_beta2/tools/fetchAll.py deleted file mode 100755 index a522b01d..00000000 --- a/tags/pisi-1.0_beta2/tools/fetchAll.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -import os -import sys - -sys.path.append('.') - -import pisi.uri -import pisi.specfile -import pisi.util as util -from pisi.fetcher import fetch_url - -def scanPSPEC(folder): - packages = [] - for root, dirs, files in os.walk(folder): - if "pspec.xml" in files: - packages.append(root) - # dont walk into the versioned stuff - if ".svn" in dirs: - dirs.remove(".svn") - return packages - -def isCached(file, sha1sum): - return util.check_file_hash(os.path.join(config.archives_dir(), file), sha1sum) - -if __name__ == "__main__": - try: - packages = scanPSPEC(sys.argv[1]) - except: - print "Usage: fetchAll.py path2repo" - sys.exit(1) - - for package in packages: - spec = pisi.specfile.SpecFile() - spec.read(os.path.join(package, "pspec.xml")) - - URI = pisi.uri.URI(spec.source.archiveUri) - - if not isCached(URI.filename(), spec.source.archiveSHA1): - print URI, " -> " , os.path.join(config.archives_dir(), URI.filename()) - try: - fetch_url(URI, config.archives_dir()) - except pisi.fetcher.FetchError, e: - print e - pass - else: - print URI, "already downloaded..." diff --git a/tags/pisi-1.0_beta2/tools/find-lib-deps.py b/tags/pisi-1.0_beta2/tools/find-lib-deps.py deleted file mode 100755 index dd624f49..00000000 --- a/tags/pisi-1.0_beta2/tools/find-lib-deps.py +++ /dev/null @@ -1,64 +0,0 @@ -#! /usr/bin/python -# -*- coding: utf-8 -*- -# -# find library dependencies of a package -# author: exa (Eray Özkural) - -import locale -import sys -import os -import fnmatch - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -import pisi -import pisi.api -import pisi.config -import pisi.specfile as specfile -import pisi.context as ctx -import pisi.util as util -from pisi.package import Package - -locale.setlocale(locale.LC_ALL, '') -options = pisi.config.Options() -if len(sys.argv) > 2: - options.destdir=sys.argv[2] -else: - options.destdir = '/' -pisi.api.init(database=True, comar=False, options=options) - -filename = sys.argv[1] -package = Package(filename) -package.read() -util.clean_dir('/tmp/install') -package.extract_dir_flat('install', '/tmp/install') -deps = set() -needed = set() -for file in package.files.list: - #print file.path, file.type - if file.type == 'executable': - (ret, lines) = util.run_batch('objdump -p %s' % util.join_path('/tmp/install', file.path)) - for x in lines: - if x.startswith(' NEEDED'): - needed.add(x[8:].strip()) - -#print 'needed guys', needed - -for lib in needed: - - (ret, out) = util.run_batch('locate %s' % lib) - path = out[0].strip().lstrip('/') - try: - (pkg_name, file_info) = ctx.filesdb.get_file(path) - ctx.ui.info("Library dependency: '%s' due to library '%s'" % (pkg_name, file_info.path)) - deps.add(pkg_name) - except: - ctx.ui.warning('Cannot find an installed package for library %s' % lib) - -ctx.ui.info('Found deps:') -for x in deps: - ctx.ui.info(x) - -pisi.api.finalize() diff --git a/tags/pisi-1.0_beta2/tools/fix_old_metadata_files.py b/tags/pisi-1.0_beta2/tools/fix_old_metadata_files.py deleted file mode 100755 index ed1305d1..00000000 --- a/tags/pisi-1.0_beta2/tools/fix_old_metadata_files.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -import xml.dom.minidom as mdom -import codecs -import os - -folder = "/var/lib/pisi" - -def saveMetadata(data, file): - if data: - f = codecs.open(file, 'w', "utf-8") - f.write(data) - f.close() - return True - -def getNodeText(node, tag, default=None): - try : c = getTags(node, tag)[0].firstChild.data - except: c = default - return c - -def getTags(parent, childName): - return [x for x in parent.childNodes if x.nodeType == x.ELEMENT_NODE if x.tagName == childName] - -def addText(dom, parent, text): - cdata = dom.createTextNode(text) - parent.appendChild(cdata) - -def fixMetadata(metadata): - dom = mdom.parse(metadata) - pisi = dom.documentElement - - package = getTags(pisi, "Package")[0] - history = getTags(package, "History")[0] - item = package.removeChild(history) - - for update in history.childNodes: - if update.nodeType == update.ELEMENT_NODE: - try: - rno = getNodeText(update, "Release")[6:-5] - except TypeError: - return None - update.setAttribute("release", rno) - release = getTags(update, "Release")[0] - update.removeChild(release) - - addText(dom, package, " ") - package.appendChild(item) - addText(dom, package, "\n ") - return dom.toxml() - -def findMetadata(): - for root, dirs, files in os.walk(folder): - if "metadata.xml" in files: - yield (root + '/metadata.xml') - -for file in findMetadata(): - if saveMetadata(fixMetadata(file), file): - print "Güncellendi : ", file - else: - print "Hiç bir şey yapılmadı: ", file diff --git a/tags/pisi-1.0_beta2/tools/installAllAvailable.sh b/tags/pisi-1.0_beta2/tools/installAllAvailable.sh deleted file mode 100755 index f8b7a4b3..00000000 --- a/tags/pisi-1.0_beta2/tools/installAllAvailable.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -argNUM=${#} -if [ ${argNUM} -lt 1 ] ; then - echo "At least one repo name needed" - exit 1 -fi -./pisi-cli --ignore-comar install `./pisi-cli list-available $@ | tail -n+3 | xargs` diff --git a/tags/pisi-1.0_beta2/tools/lspisi b/tags/pisi-1.0_beta2/tools/lspisi deleted file mode 100755 index 351ec03f..00000000 --- a/tags/pisi-1.0_beta2/tools/lspisi +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# Please read the COPYING file. - -import os -import sys -import zipfile - -def openZip(fileName): - if not zipfile.is_zipfile(fileName): - print "ZIP file required..." - sys.exit() - else: - f = zipfile.ZipFile(fileName, "r") - return f - -def fillFileList(zipFile): - filelist = [] - - for file in zipFile.namelist(): - filelist.append(file) - - filelist.sort() - return filelist - -def uniq(alist): - set = {} - return [set.setdefault(e,e) for e in alist if e not in set] - -if __name__ == "__main__": - - if sys.argv[1] == "dirs": - f = openZip(sys.argv[2]) - dirlist =[] - for file in fillFileList(f): - dirlist.append(os.path.dirname(file)) - - for dir in uniq(dirlist): - print "" + dir.replace("install/", "/") + "" - elif sys.argv[1]: - f = openZip(sys.argv[1]) - for file in fillFileList(f): - if f.getinfo(file).external_attr == 2716663808: - print file + " --> " + f.read(file) - else: - print file - else: - print "pisi file name required..." - sys.exit() diff --git a/tags/pisi-1.0_beta2/tools/repostats.py b/tags/pisi-1.0_beta2/tools/repostats.py deleted file mode 100755 index 8eeb23db..00000000 --- a/tags/pisi-1.0_beta2/tools/repostats.py +++ /dev/null @@ -1,695 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2005, TUBITAK/UEKAE -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# - -import sys -import os -import codecs -import re -import getopt - -import gettext -__trans = gettext.translation('pisi', fallback=True) -_ = __trans.ugettext - -from svn import core, client - -sys.path.append('.') -import pisi.specfile -import pisi.uri -import pisi.package -import pisi.metadata -import pisi.files -from pisi.cli import printu - -# default html templates - -def_table_html = u""" -%s%s -""" - -def_repo_sizes_html = u""" -

Boyutlar

-

Toplam kurulu boyut %(total)s

-

Dosya tiplerine göre liste:

- -%(sizes)s -
-""" - -def_repo_html = u""" - - Depo istatistikleri - - - -

-Depoda toplam %(nr_source)d -kaynak paket, ve bu paketlerden oluşturulacak -%(nr_packages)d ikili paket bulunmaktadır. Toplam %(nr_patches)d yama mevcuttur. -

- -

-%(errors)s -

- -

En fazla yamalanmış 5 kaynak paket:

-%(most_patched)s -

- -

En uzun actions.py betikli 5 kaynak paket:

-%(longpy)s -

- -

Eksik ikili paketler

-%(missing)s -

- -%(sizes)s - -

Paketçiler:

-%(packagers)s -

- - - -""" - -def_packager_html = u""" - - Paketçi %(name)s - - - -

%(name)s <%(email)s>

- -

Paketler:

-

%(sources)s

- -

Güncellemeler:

-

%(updates)s

- - -""" - -def_package_html = u""" - - İkili paket %(name)s - - - -

İkili paket: %(name)s

-

Kaynak versiyon %(version)s, depo sürümü %(release)s

- -

Kaynak paket %(source)s

- -

Derlemek için gerekenler:

-

%(buildDeps)s

- -

Çalıştırmak için gerekenler:

-

%(runtimeDeps)s

- -

Bağımlı paketler (derlenmek için):

-

%(revBuildDeps)s

- -

Bağımlı paketler (çalışmak için):

-

%(revRuntimeDeps)s

- - -""" - -def_history_html= u""" -
Sürüm %s

-Tarih: %s
-Yapan: %s
-Açıklama: %s -

-""" - -def_source_html = u""" - - Kaynak paket %(name)s - - - -

Kaynak paket: %(name)s

-

Kaynak versiyon %(version)s, depo sürümü %(release)s

-

%(homepage)s

- -

Açıklama

-

%(summary)s

- -

Lisanslar:

-

%(license)s

- -

İşlemler:

-

Paket dosyalarına bak

-

-Hata kayıtlarına bak

- -

Bu kaynaktan derlenen ikili paketler:

-

%(packages)s

- -

Tarihçe

-%(history)s - -

Yamalar

-%(patches)s - - -""" - -def_sources_html = u""" - - Kaynak paketler listesi - - - -

Kaynak paketler listesi

-
- -

-%(source_list)s -

- - -""" - -def_missing_html = u""" - - Eksik ikili paket %(name)s - - - -

Eksik ikili paket: %(name)s

- -

Bağımlı paketler (derlenmek için):

-

%(revBuildDeps)s

- -

Bağımlı paketler (çalışmak için):

-

%(revRuntimeDeps)s

- - -""" - - -def svn_uri(path): - # init - core.apr_initialize() - pool = core.svn_pool_create(None) - core.svn_config_ensure(None, pool) - # get commit date - uri = client.svn_client_url_from_path(path, pool) - # cleanup - core.svn_pool_destroy(pool) - core.apr_terminate() - return uri - - -# FIXME: This check should be in specfile -valid_filetypes = [ - "executable", - "library", - "data", - "config", - "doc", - "man", - "info", - "localedata", - "header", - "all" -] - -def valuesort(x, y): - if x[1] > y[1]: - return -1 - elif x[1] == y[1]: - return 0 - else: - return 1 - -def find_pspecs(folder): - paks = [] - for root, dirs, files in os.walk(folder): - if "pspec.xml" in files: - paks.append(root) - # dont walk into the versioned stuff - if ".svn" in dirs: - dirs.remove(".svn") - return paks - -def template_get(tmpl_name): - try: - f = codecs.open(tmpl_name + ".html", "r", "utf-8") - data = f.read() - f.close() - return data - except: - return globals()["def_" + tmpl_name + "_html"] - -def template_write(filename, tmpl_name, dict): - f = codecs.open(filename, "w", "utf-8") - f.write(template_get(tmpl_name) % dict) - f.close() - -def template_table(tmpl_name, list): - tmpl = template_get(tmpl_name) - data = "" - for item in list: - data += (tmpl % item) - return data - -def mangle_email(email): - return re.sub("@", " [at] ", email) - - -class Histogram: - def __init__(self): - self.list = {} - - def add(self, name, value=None): - if value: - self.list[name] = value - else: - if self.list.has_key(name): - self.list[name] = self.list[name] + 1 - else: - self.list[name] = 1 - - def note(self, name): - if not self.list.has_key(name): - self.list[name] = 0 - - def get_list(self, max=0): - items = self.list.items() - items.sort(valuesort) - if max != 0: - return items[:max] - else: - return items - - -# Dictionary of all source packages keyed by the source name -sources = {} - -# Dictionary of all binary packages keyed by the package name -packages = {} - -# Dictionary of all packagers keyed by the packager name -packagers = {} - -# Dictionary of missing depended binary packages keyed by the package name -missing = {} - -# List of all repository problems -errors = [] - - -class Missing: - def __init__(self, name): - missing[name] = self - self.name = name - self.revBuildDeps = [] - self.revRuntimeDeps = [] - - def report_html(self): - bDeps = map(lambda x: "%s" % (x, x), self.revBuildDeps) - rDeps = map(lambda x: "%s" % (x, x), self.revRuntimeDeps) - dict = { - "name": self.name, - "revBuildDeps": ", ".join(bDeps), - "revRuntimeDeps": ", ".join(rDeps) - } - template_write("paksite/package-%s.html" % self.name, "missing", dict) - - -class Package: - def __init__(self, source, pakspec): - name = pakspec.name - if packages.has_key(name): - errors.append(_("Duplicate binary packages:\n%s\n%s\n") % ( - source.name, packages[name].source.name)) - return - for p in pakspec.paths: - if p.fileType not in valid_filetypes: - e = _("Unknown file type '%s' in package '%s'") % ( - p.fileType, source.name) - errors.append(e) - packages[name] = self - self.name = name - self.source = source - self.pakspec = pakspec - self.revBuildDeps = [] - self.revRuntimeDeps = [] - self.installedSize = 0 - - def markDeps(self): - # mark reverse build dependencies - for d in self.source.spec.source.buildDeps: - p = d.package - if packages.has_key(p): - packages[p].revBuildDeps.append(self.name) - else: - if not missing.has_key(p): - Missing(p) - missing[p].revBuildDeps.append(self.name) - # mark reverse runtime dependencies - for d in self.pakspec.runtimeDeps: - p = d.package - if packages.has_key(p): - packages[p].revRuntimeDeps.append(self.name) - else: - if not missing.has_key(p): - Missing(p) - missing[p].revRuntimeDeps.append(self.name) - - def report_html(self): - source = self.source.spec.source - bDeps = map(lambda x: "%s" % (x, x), - (map(lambda x: x.package, source.buildDeps))) - rDeps = map(lambda x: "%s" % (x, x), - (map(lambda x: x.package, self.pakspec.runtimeDeps))) - rbDeps = map(lambda x: "%s" % (x, x), self.revBuildDeps) - rrDeps = map(lambda x: "%s" % (x, x), self.revRuntimeDeps) - dict = { - "name": self.name, - "source": source.name, - "version": source.version, - "release": source.release, - "buildDeps": ", ".join(bDeps), - "runtimeDeps": ", ".join(rDeps), - "revBuildDeps": ", ".join(rbDeps), - "revRuntimeDeps": ", ".join(rrDeps) - } - template_write("paksite/package-%s.html" % self.name, "package", dict) - - -class Source: - def __init__(self, path, spec): - name = spec.source.name - if sources.has_key(name): - errors.append(_("Duplicate source packages:\n%s\n%s\n") % ( - path, sources[name].path)) - return - sources[name] = self - self.spec = spec - self.name = name - self.path = path - self.uri = svn_uri(path) - for p in spec.packages: - Package(self, p) - self.checkRelease() - - def validDate(self, date): - # yyyy-mm-dd - err = 0 - if len(date) != 10: - err = 1 - if date[4] != '-' or date[7] != '-': - err = 1 - if err: - e = _("Source package '%s' has wrong date format '%s'") % (self.name, date) - errors.append(e) - # more checks can be added, i.e. valid day month ranges, etc - - def checkRelease(self): - # FIXME: this check also belongs to specfile - prev = None - prevDate = None - for h in self.spec.source.history: - if prev: - prev -= 1 - self.validDate(h.date) - if prev <= 0: - e = _("Source package '%s' has wrong release numbers") % self.name - errors.append(e) - return - if int(h.release) != prev: - e = _("Source package '%s' lacks release %d") % (self.name, prev) - errors.append(e) - return - else: - prev = int(h.release) - prevDate = h.date - self.validDate(prevDate) - if prev != 1: - e = _("Source package '%s' has no first release") % self.name - errors.append(e) - - def report_html(self): - source = self.spec.source - paks = map(lambda x: "%s" % (x, x), - (map(lambda x: x.name, self.spec.packages))) - histdata = map(lambda x: (x.release, x.date, x.name, x.name, x.comment), self.spec.history) - ptch = map(lambda x: "%s" % (self.uri, - x.filename, x.filename), source.patches) - dict = { - "name": self.name, - "homepage": source.homepage, - "license": ", ".join(source.license), - "version": source.version, - "release": source.release, - "history": template_table("history", histdata), - "packages": "
".join(paks), - "summary": source.summary, - "patches": "
".join(ptch), - "uri": self.uri - } - template_write("paksite/source-%s.html" % self.name, "source", dict) - - -class Packager: - def __init__(self, spec, update=None): - if update: - name = update.name - email = update.email - else: - name = spec.source.packager.name - email = spec.source.packager.email - if packagers.has_key(name): - if email != packagers[name].email: - e = _("Developer '%s <%s>' has another mail address '%s' in source package '%s'") % ( - name, packagers[name].email, email, spec.source.name) - packagers[name].errors.append(e) - errors.append(e) - if update: - packagers[name].updates.append((spec.source.name, update.release, update.comment)) - else: - packagers[name].sources.append(spec.source.name) - else: - packagers[name] = self - self.name = name - self.email = email - if update: - self.sources = [] - self.updates = [(spec.source.name, update.release, update.comment)] - else: - self.sources = [spec.source.name] - self.updates = [] - self.errors = [] - if not update: - for update in spec.history: - Packager(spec, update) - - def report_html(self): - srcs = map(lambda x: "%s" % (x, x), self.sources) - srcs.sort() - upds = map(lambda x: "%s (%s)
%s
" % ( - x[0], x[0], x[1], x[2]), self.updates) - dict = { - "name": self.name, - "email": mangle_email(self.email), - "sources": "
".join(srcs), - "updates": " ".join(upds) - } - template_write("paksite/%s.html" % self.name, "packager", dict) - - -class Repository: - def __init__(self, path): - self.path = path - self.nr_sources = 0 - self.nr_packages = 0 - self.nr_patches = 0 - self.people = Histogram() - self.licenses = Histogram() - self.mostpatched = Histogram() - self.longpy = Histogram() - self.cscripts = Histogram() - self.total_installed_size = 0 - self.installed_sizes = {} - - def processPspec(self, path, spec): - # new classes - Packager(spec) - Source(path, spec) - # update global stats - self.nr_sources += 1 - self.nr_packages += len(spec.packages) - self.nr_patches += len(spec.source.patches) - # update top fives - self.people.add(spec.source.packager.name) - for u in spec.history: - self.people.note(u.name) - for p in spec.packages: - for cs in p.providesComar: - self.cscripts.add(cs.om) - for L in spec.source.license: - self.licenses.add(L) - self.mostpatched.add(spec.source.name, len(spec.source.patches)) - try: - f = file(os.path.join(path, "actions.py")) - L = len(f.readlines()) - self.longpy.add(spec.source.name, L) - f.close() - except: - pass - - def scan(self): - for pak in find_pspecs(self.path): - spec = pisi.specfile.SpecFile() - try: - spec.read(os.path.join(pak, "pspec.xml")) - except Exception, inst: - errors.append(_("Cannot parse '%s':\n%s\n") % (pak, inst.args[0])) - continue - self.processPspec(pak, spec) - for p in packages.values(): - p.markDeps() - - def processPisi(self, path): - p = pisi.package.Package(path) - p.extract_files(["metadata.xml", "files.xml"], ".") - md = pisi.metadata.MetaData() - md.read("metadata.xml") - self.total_installed_size += md.package.installedSize - if packages.has_key(md.package.name): - # FIXME: check version/release match too? - packages[md.package.name].installed_size = md.package.installedSize - else: - printu("Binary package '%s' has no source package in repository %s\n" % (path, self.path)) - fd = pisi.files.Files() - fd.read("files.xml") - for f in fd.list: - if self.installed_sizes.has_key(f.type): - # Emtpy directories and symlinks has None size - if not f.size is None: - self.installed_sizes[f.type] += int(f.size) - else: - self.installed_sizes[f.type] = int(f.size) - - def scan_bins(self, binpath): - for root, dirs, files in os.walk(binpath): - for fn in files: - if fn.endswith(".pisi"): - self.processPisi(os.path.join(root, fn)) - - def report_html(self): - miss = map(lambda x: "%s" % (x, x), missing.keys()) - upeople = [] - for p in self.people.get_list(): - upeople.append(("%s" % (p[0], p[0]), p[1])) - if errors: - e = "
".join(errors) - else: - e = "" - upatch = [] - for p in self.mostpatched.get_list(5): - upatch.append(("%s" % (p[0], p[0]), p[1])) - ulongpy = [] - for p in self.longpy.get_list(5): - ulongpy.append(("%s" % (p[0], p[0]), p[1])) - if self.total_installed_size: - items = self.installed_sizes.items() - items.sort(valuesort) - elts = "".join(map(lambda x: "%s%d" % (x[0], x[1]), items)) - sizes = template_get("repo_sizes") % { "total": self.total_installed_size, "sizes": elts } - else: - sizes = "" - dict = { - "nr_source": self.nr_sources, - "nr_packages": self.nr_packages, - "nr_patches": self.nr_patches, - "most_patched": template_table("table", upatch), - "longpy": template_table("table", ulongpy), - "packagers": template_table("table", upeople), - "missing": "\n".join(miss), - "sizes": sizes, - "errors": e - } - template_write("paksite/index.html", "repo", dict) - srclist = map(lambda x: "%s" % (x, x), sources) - srclist.sort() - dict = { - "source_list": "
".join(srclist) - } - template_write("paksite/sources.html", "sources", dict) - - -# command line driver - -def usage(): - printu(_("Usage: repostats.py [OPTIONS] source-repo-path [binary-repo-path]\n")) - printu(" -t, --test-only: %s" % _("Dont generate the web site.\n")) - sys.exit(0) - -if __name__ == "__main__": - try: - opts, args = getopt.gnu_getopt(sys.argv[1:], "ht", ["help", "test-only"]) - except: - usage() - - if args == []: - usage() - - do_web = True - - for o, v in opts: - if o in ("-h", "--help"): - usage() - if o in ("-t", "--test-only"): - do_web = False - - repo = Repository(args[0]) - printu(_("Scanning source repository...\n")) - repo.scan() - - if len(args) > 1: - printu(_("Scanning binary packages...\n")) - repo.scan_bins(args[1]) - - if errors: - printu("***\n") - printu(_("Encountered %d errors! Fix them immediately!\n") % len(errors)) - for e in errors: - printu(e) - printu("\n") - printu("\n") - printu("***\n") - - if missing: - printu(_("These dependencies are not available in repository:\n")) - for m in missing.keys(): - printu(" %s\n" % m) - - if do_web: - try: - os.mkdir("paksite") - except: - pass - repo.report_html() - for p in packagers.values(): - p.report_html() - for p in missing.values(): - p.report_html() - for p in packages.values(): - p.report_html() - for p in sources.values(): - p.report_html() diff --git a/tags/pisi-1.0_beta2/tools/rmcomp-source-repo.py b/tags/pisi-1.0_beta2/tools/rmcomp-source-repo.py deleted file mode 100755 index bd7a2ff0..00000000 --- a/tags/pisi-1.0_beta2/tools/rmcomp-source-repo.py +++ /dev/null @@ -1,46 +0,0 @@ -#! /usr/bin/python -# a simple tool to list stuff in source repository -# author: exa - -import sys -import os - -import pisi -import pisi.api -import pisi.config -import pisi.specfile as specfile -import pisi.context as ctx -import pisi.util -import pisi.pxml.xmlfilecdom as xmlfile - -options = pisi.config.Options() -if len(sys.argv) > 2: - options.destdir=sys.argv[2] -else: - options.destdir = '/' -pisi.api.init(database=False, options=options) -repo_uri = sys.argv[1] - -for root, dirs, files in os.walk(repo_uri): - for fn in files: - if fn == 'pspec.xml': - sf = xmlfile.XmlFile(tag = 'PISI') - path = pisi.util.join_path(root, fn) - ctx.ui.info('Looking at %s' % path) - ls = file(path).readlines() - ls = filter(lambda x:x.find('')==-1, ls) - f = file(path, 'w') - for x in ls: - f.write(x) - f.close() - #sf.readxml(path) - #src = sf.getNode('Source') - #comp = sf.getNode('Source/PartOf') - #print src, comp - #if comp: - # print 'removing partof tag' - # src.removeChild(comp) - #else: - # print 'no comp already' - #sf.writexml(path) -pisi.api.finalize() diff --git a/tags/pisi-1.0_beta2/tools/svndist.py b/tags/pisi-1.0_beta2/tools/svndist.py deleted file mode 100755 index dfc3896c..00000000 --- a/tags/pisi-1.0_beta2/tools/svndist.py +++ /dev/null @@ -1,31 +0,0 @@ -#! /usr/bin/python -# a script to preare PiSi source tarball from svn -# author: exa - -#TODO: arguments for svn snapshot with rev number, or a tag to override default - -import sys -import os -import shutil - -def run(cmd): - print 'running', cmd - os.system(cmd) - -sys.path.insert(0, '.') -import pisi -if not os.path.exists('svndist'): - os.makedirs('svndist') - -ver = pisi.__version__ - -if os.path.exists('svndist/pisi-%s' % ver): - shutil.rmtree('svndist/pisi-%s' % ver) - -print 'Exporting svn directory' -run('svn export http://svn.uludag.org.tr/uludag/trunk/pisi svndist/pisi-%s' % ver) - -os.chdir('svndist') -run('tar cjvf pisi-%s.tar.bz2 pisi-%s' % (ver, ver)) - -print 'Have a look at svndist directory' diff --git a/tags/pisi-1.0_beta2/tools/update-environ.py b/tags/pisi-1.0_beta2/tools/update-environ.py deleted file mode 100755 index 6d648134..00000000 --- a/tags/pisi-1.0_beta2/tools/update-environ.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Generates /etc/ld.so.conf and /etc/profile.env according to /etc/env.d directory - -import pisi -import pisi.api -import pisi.util -import pisi.config - -if __name__ == "__main__": - options = pisi.config.Options() - pisi.api.init(options = options, comar = False, database = False) - pisi.util.env_update() diff --git a/tags/pisi-1.0_beta2/tools/update-po.sh b/tags/pisi-1.0_beta2/tools/update-po.sh deleted file mode 100755 index 79db6bf0..00000000 --- a/tags/pisi-1.0_beta2/tools/update-po.sh +++ /dev/null @@ -1,4 +0,0 @@ -find pisi -iname '*.py' | grep -v pisi/cli/commands.py >exclude -pygettext.py -D -X exclude -o po/pisi.pot pisi pisi-cli tools -msgmerge -U po/tr.po po/pisi.pot -rm exclude