Gentoo Archives: gentoo-portage-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-portage-dev@l.g.o
Cc: "Michał Górny" <mgorny@g.o>
Subject: [gentoo-portage-dev] [PATCH v2] Install Portage using setup.py
Date: Sat, 23 Aug 2014 20:31:10
Message-Id: 1408825856-12510-1-git-send-email-mgorny@gentoo.org
In Reply to: Re: [gentoo-portage-dev] [PATCH 5/6] Install Python modules using setup.py by Brian Dolbec
1 ---
2 .gitignore | 1 +
3 MANIFEST.in | 19 ++
4 Makefile | 215 -------------------
5 doc/Makefile | 11 -
6 mkrelease.sh | 141 -------------
7 pym/portage/const.py | 4 +-
8 setup.py | 578 +++++++++++++++++++++++++++++++++++++++++++++++++++
9 7 files changed, 600 insertions(+), 369 deletions(-)
10 create mode 100644 MANIFEST.in
11 delete mode 100644 Makefile
12 delete mode 100644 doc/Makefile
13 delete mode 100755 mkrelease.sh
14 create mode 100755 setup.py
15
16 diff --git a/.gitignore b/.gitignore
17 index 074bb86..c2dd534 100644
18 --- a/.gitignore
19 +++ b/.gitignore
20 @@ -1,4 +1,5 @@
21 *.py[co]
22 __pycache__/
23 *.class
24 +/build
25 /tags
26 diff --git a/MANIFEST.in b/MANIFEST.in
27 new file mode 100644
28 index 0000000..a005ab9
29 --- /dev/null
30 +++ b/MANIFEST.in
31 @@ -0,0 +1,19 @@
32 +# docs
33 +include DEVELOPING
34 +include LICENSE
35 +include TEST-NOTES
36 +
37 +# docbook sources
38 +include doc/custom.xsl
39 +include doc/fragment/*
40 +recursive-include doc *.docbook
41 +
42 +# extra conf files used in ebuild
43 +include cnf/make.conf.example.*
44 +
45 +# extra files for tests
46 +include .portage_not_installed
47 +include cnf/metadata.dtd
48 +
49 +# extra scripts
50 +include misc/*
51 diff --git a/Makefile b/Makefile
52 deleted file mode 100644
53 index 9eb6e66..0000000
54 --- a/Makefile
55 +++ /dev/null
56 @@ -1,215 +0,0 @@
57 -SHELL = /bin/sh
58 -PN ?= portage
59 -PF ?= portage
60 -HOMEPAGE ?= http://www.gentoo.org/proj/en/portage/index.xml
61 -PWD ?= $(shell pwd)
62 -S ?= $(PWD)
63 -WORKDIR ?= $(PWD)
64 -DESTDIR = $(PWD)/image/
65 -srcdir = $(S)
66 -prefix = /usr
67 -sysconfdir = /etc
68 -exec_prefix = $(prefix)
69 -bindir = $(exec_prefix)/bin
70 -sbindir = $(exec_prefix)/sbin
71 -libdir = $(exec_prefix)/lib
72 -datarootdir = $(prefix)/share
73 -datadir = $(datarootdir)
74 -mandir = $(datarootdir)/man
75 -docdir = $(datarootdir)/doc/$(PF)
76 -htmldir = $(docdir)/html
77 -portage_datadir = $(datarootdir)/$(PN)
78 -portage_confdir = $(portage_datadir)/config
79 -portage_setsdir = $(portage_confdir)/sets
80 -portage_base = $(libdir)/$(PN)
81 -EPYDOC_OPTS = -qqqqq --no-frames --show-imports
82 -INSMODE = 0644
83 -EXEMODE = 0755
84 -DIRMODE = 0755
85 -SYSCONFDIR_FILES = etc-update.conf dispatch-conf.conf
86 -PORTAGE_CONFDIR_FILES = make.conf.example make.globals repos.conf
87 -LOGROTATE_FILES = elog-save-summary
88 -BINDIR_FILES = ebuild egencache emerge emerge-webrsync \
89 - emirrordist portageq quickpkg repoman
90 -SBINDIR_FILES = archive-conf dispatch-conf emaint \
91 - env-update etc-update fixpackages regenworld
92 -DOCS = ChangeLog NEWS RELEASE-NOTES
93 -LINGUAS ?= $(shell cd "$(srcdir)/man" && find -mindepth 1 -type d)
94 -
95 -ifdef PYTHONPATH
96 - PYTHONPATH := $(srcdir)/pym:$(PYTHONPATH)
97 -else
98 - PYTHONPATH := $(srcdir)/pym
99 -endif
100 -
101 -all: docbook epydoc
102 -
103 -docbook:
104 - set -e; \
105 - touch "$(srcdir)/doc/fragment/date"; \
106 - $(MAKE) -C "$(srcdir)/doc" xhtml xhtml-nochunks
107 -
108 -epydoc:
109 - set -e; \
110 - env PYTHONPATH="$(PYTHONPATH)" epydoc \
111 - -o "$(WORKDIR)/epydoc" \
112 - --name $(PN) \
113 - --url "$(HOMEPAGE)" \
114 - $(EPYDOC_OPTS) \
115 - $$(cd "$(srcdir)" && find pym -name '*.py' | sed \
116 - -e s:/__init__.py$$:: \
117 - -e s:\.py$$:: \
118 - -e s:^pym/:: \
119 - -e s:/:.:g \
120 - | sort); \
121 - rm -f "$(WORKDIR)/epydoc/api-objects.txt"; \
122 -
123 -test:
124 - set -e; \
125 - "$(srcdir)/pym/portage/tests/runTests.py"; \
126 -
127 -install:
128 - set -e; \
129 - cd "$(srcdir)/cnf"; \
130 - install -d -m$(DIRMODE) "$(DESTDIR)$(sysconfdir)"; \
131 - install -m$(INSMODE) $(SYSCONFDIR_FILES) "$(DESTDIR)$(sysconfdir)"; \
132 - \
133 - install -d -m$(DIRMODE) "$(DESTDIR)$(portage_confdir)"; \
134 - cd "$(srcdir)/cnf"; \
135 - install -m$(INSMODE) $(PORTAGE_CONFDIR_FILES) \
136 - "$(DESTDIR)$(portage_confdir)"; \
137 - install -d -m$(DIRMODE) "$(DESTDIR)$(portage_setsdir)"; \
138 - cd "$(S)/cnf/sets"; \
139 - install -m$(INSMODE) *.conf "$(DESTDIR)$(portage_setsdir)"; \
140 - \
141 - install -d -m$(DIRMODE) "$(DESTDIR)$(sysconfdir)/logrotate.d"; \
142 - cd "$(srcdir)/cnf/logrotate.d"; \
143 - install -m$(INSMODE) $(LOGROTATE_FILES) \
144 - "$(DESTDIR)$(sysconfdir)/logrotate.d"; \
145 - \
146 - for x in $$(cd "$(srcdir)" && find bin -type d) ; do \
147 - cd "$(srcdir)/$$x"; \
148 - install -d -m$(DIRMODE) "$(DESTDIR)$(portage_base)/$$x"; \
149 - files=$$(find . -mindepth 1 -maxdepth 1 -type f ! -type l); \
150 - if [ -n "$$files" ] ; then \
151 - install -m$(EXEMODE) $$files \
152 - "$(DESTDIR)$(portage_base)/$$x"; \
153 - fi; \
154 - symlinks=$$(find . -mindepth 1 -maxdepth 1 -type l); \
155 - if [ -n "$$symlinks" ] ; then \
156 - cp -P $$symlinks "$(DESTDIR)$(portage_base)/$$x"; \
157 - fi; \
158 - done; \
159 - \
160 - for x in $$(cd "$(srcdir)" && find pym/* -type d \
161 - ! -path "pym/portage/tests*") ; do \
162 - cd "$(srcdir)/$$x"; \
163 - files=$$(echo *.py); \
164 - if [ -z "$$files" ] || [ "$$files" = "*.py" ]; then \
165 - # __pycache__ directories contain no py files \
166 - continue; \
167 - fi; \
168 - install -d -m$(DIRMODE) "$(DESTDIR)$(portage_base)/$$x"; \
169 - install -m$(INSMODE) $$files "$(DESTDIR)$(portage_base)/$$x"; \
170 - done; \
171 - \
172 - install -d -m$(DIRMODE) "$(DESTDIR)$(bindir)"; \
173 - relative_path=".."; \
174 - x=$(bindir) ; \
175 - y="$(portage_base)"; \
176 - if [ "$${x#$(prefix)}" != "$$x" ] && \
177 - [ "$${y#$(prefix)}" != "$$y" ]; then \
178 - x=$${x#$(prefix)}; \
179 - y=$${y#$(prefix)}; \
180 - fi; \
181 - x=$${x%/*}; \
182 - while [ -n "$$x" ] ; do \
183 - relative_path=$${relative_path}/..; \
184 - x=$${x%/*}; \
185 - done; \
186 - relative_path=$$relative_path$$y; \
187 - for x in $(BINDIR_FILES) ; do \
188 - ln -sf "$$relative_path/bin/$$x" \
189 - "$(DESTDIR)$(bindir)/$$x"; \
190 - done; \
191 - \
192 - install -d -m$(DIRMODE) "$(DESTDIR)$(sbindir)"; \
193 - relative_path=".."; \
194 - x=$(sbindir) ; \
195 - y="$(portage_base)"; \
196 - if [ "$${x#$(prefix)}" != "$$x" ] && \
197 - [ "$${y#$(prefix)}" != "$$y" ]; then \
198 - x=$${x#$(prefix)}; \
199 - y=$${y#$(prefix)}; \
200 - fi; \
201 - x=$${x%/*}; \
202 - while [ -n "$$x" ] ; do \
203 - relative_path=$${relative_path}/..; \
204 - x=$${x%/*}; \
205 - done; \
206 - relative_path=$$relative_path$$y; \
207 - for x in $(SBINDIR_FILES) ; do \
208 - ln -sf "$$relative_path/bin/$$x" \
209 - "$(DESTDIR)$(sbindir)/$$x"; \
210 - done; \
211 - \
212 - ln -sf "$$relative_path/bin/env-update" \
213 - "$(DESTDIR)$(sbindir)/update-env"; \
214 - ln -sf "$$relative_path/bin/etc-update" \
215 - "$(DESTDIR)$(sbindir)/update-etc"; \
216 - \
217 - # We install some minimal tests for use as a preinst sanity check. \
218 - # These tests must be able to run without a full source tree and \
219 - # without relying on a previous portage instance being installed. \
220 - install -d -m$(DIRMODE) \
221 - "$(DESTDIR)$(portage_base)/pym/portage/tests"; \
222 - install -m$(EXEMODE) "$(srcdir)/pym/portage/tests/runTests" \
223 - "$(DESTDIR)$(portage_base)/pym/portage/tests"; \
224 - cd "$(srcdir)/pym/portage/tests"; \
225 - install -m$(INSMODE) *.py \
226 - "$(DESTDIR)$(portage_base)/pym/portage/tests"; \
227 - install -d -m$(DIRMODE) \
228 - "$(DESTDIR)$(portage_base)/pym/portage/tests/lint"; \
229 - cd "$(srcdir)/pym/portage/tests/lint"; \
230 - install -m$(INSMODE) *.py __test__ \
231 - "$(DESTDIR)$(portage_base)/pym/portage/tests/lint"; \
232 - \
233 - install -d -m$(DIRMODE) "$(DESTDIR)$(docdir)"; \
234 - cd "$(srcdir)"; \
235 - install -m $(INSMODE) $(DOCS) "$(DESTDIR)$(docdir)"; \
236 - \
237 - for x in "" $(LINGUAS); do \
238 - for y in 1 5 ; do \
239 - if [ -d "$(srcdir)/man/$$x" ]; then \
240 - cd "$(srcdir)/man/$$x"; \
241 - files=$$(echo *.$$y); \
242 - if [ -z "$$files" ] || [ "$$files" = "*.$$y" ]; then \
243 - continue; \
244 - fi; \
245 - install -d -m$(DIRMODE) "$(DESTDIR)$(mandir)/$$x/man$$y"; \
246 - install -m$(INSMODE) *.$$y "$(DESTDIR)$(mandir)/$$x/man$$y"; \
247 - fi; \
248 - done; \
249 - done; \
250 - \
251 - if [ -f "$(srcdir)/doc/portage.html" ] ; then \
252 - install -d -m$(DIRMODE) "$(DESTDIR)$(htmldir)"; \
253 - cd "$(srcdir)/doc"; \
254 - install -m$(INSMODE) *.html "$(DESTDIR)$(htmldir)"; \
255 - fi; \
256 - \
257 - if [ -d "$(WORKDIR)/epydoc" ] ; then \
258 - install -d -m$(DIRMODE) "$(DESTDIR)$(htmldir)"; \
259 - cp -pPR "$(WORKDIR)/epydoc" \
260 - "$(DESTDIR)$(htmldir)/api"; \
261 - cd "$(DESTDIR)$(htmldir)/api"; \
262 - find . -type d | xargs chmod $(DIRMODE); \
263 - find . -type f | xargs chmod $(INSMODE); \
264 - fi; \
265 -
266 -clean:
267 - set -e; \
268 - $(MAKE) -C "$(srcdir)/doc" clean; \
269 - rm -rf "$(WORKDIR)/epydoc"; \
270 -
271 -.PHONY: all clean docbook epydoc install test
272 diff --git a/doc/Makefile b/doc/Makefile
273 deleted file mode 100644
274 index 261a0b4..0000000
275 --- a/doc/Makefile
276 +++ /dev/null
277 @@ -1,11 +0,0 @@
278 -all: xhtml xhtml-nochunks
279 -
280 -XMLTO_FLAGS = -m custom.xsl
281 -man pdf txt xhtml xhtml-nochunks:
282 - xmlto $@ $(XMLTO_FLAGS) portage.docbook
283 -
284 -clean distclean:
285 - rm -f *.1 *.html portage.txt
286 -
287 -.PHONY: all clean distclean \
288 - man pdf txt xhtml xhtml-nochunks
289 diff --git a/mkrelease.sh b/mkrelease.sh
290 deleted file mode 100755
291 index f9f7564..0000000
292 --- a/mkrelease.sh
293 +++ /dev/null
294 @@ -1,141 +0,0 @@
295 -#!/bin/bash
296 -# Copyright 2008-2014 Gentoo Foundation
297 -# Distributed under the terms of the GNU General Public License v2
298 -
299 -RELEASE_BUILDDIR=${RELEASE_BUILDDIR:-/var/tmp/portage-release}
300 -SOURCE_DIR=${RELEASE_BUILDDIR}/checkout
301 -BRANCH=${BRANCH:-master}
302 -USE_TAG=false
303 -CHANGELOG_REVISION=
304 -UPLOAD_LOCATION=
305 -RUNTESTS=false
306 -USER=
307 -
308 -usage() {
309 - echo "Usage: ${0##*/} [--changelog-rev <tree-ish>] [-t|--tag] [-u|--upload <location>] [--user <username>] [--runtests] <version>"
310 - exit ${1:-0}
311 -}
312 -
313 -die() {
314 - printf 'error: %s\n' "$*"
315 - usage 1
316 -}
317 -
318 -ARGS=$(getopt -o htu: --long help,changelog-rev:,runtests,tag,upload:,user: \
319 - -n "${0##*/}" -- "$@")
320 -[ $? != 0 ] && die "initialization error"
321 -
322 -eval set -- "${ARGS}"
323 -
324 -while true; do
325 - case $1 in
326 - --changelog-rev)
327 - CHANGELOG_REVISION=$2
328 - shift 2
329 - ;;
330 - -t|--tag)
331 - USE_TAG=true
332 - shift
333 - ;;
334 - -u|--upload)
335 - UPLOAD_LOCATION=$2
336 - shift 2
337 - ;;
338 - --user)
339 - USER=$2"@"
340 - shift 2
341 - ;;
342 - -h|--help)
343 - usage
344 - ;;
345 - --runtests)
346 - RUNTESTS=true
347 - shift
348 - ;;
349 - --)
350 - shift
351 - break
352 - ;;
353 - *)
354 - die "unknown option: $1"
355 - ;;
356 - esac
357 -done
358 -
359 -[ $# != 1 ] && die "Need version argument"
360 -[[ -n ${1/[0-9]*} ]] && die "Invalid version argument"
361 -
362 -VERSION=$1
363 -RELEASE=portage-${VERSION}
364 -RELEASE_DIR=${RELEASE_BUILDDIR}/${RELEASE}
365 -RELEASE_TARBALL="${RELEASE_BUILDDIR}/${RELEASE}.tar.bz2"
366 -TREE_ISH=${BRANCH}
367 -if [[ ${USE_TAG} == "true" ]] ; then
368 - TREE_ISH="v${VERSION}"
369 -fi
370 -
371 -echo ">>> Cleaning working directories ${RELEASE_DIR} ${SOURCE_DIR}"
372 -rm -rf "${RELEASE_DIR}" "${SOURCE_DIR}" || die "directory cleanup failed"
373 -mkdir -p "${RELEASE_DIR}" || die "directory creation failed"
374 -mkdir -p "${SOURCE_DIR}" || die "mkdir failed"
375 -
376 -echo ">>> Starting GIT archive"
377 -git archive --format=tar ${TREE_ISH} | \
378 - tar -xf - -C "${SOURCE_DIR}" || die "git archive failed"
379 -
380 -echo ">>> Building release tree"
381 -cp -a "${SOURCE_DIR}/"{bin,cnf,doc,man,misc,pym} "${RELEASE_DIR}/" || die "directory copy failed"
382 -cp "${SOURCE_DIR}/"{.portage_not_installed,DEVELOPING,LICENSE,Makefile,NEWS,README,RELEASE-NOTES,TEST-NOTES} \
383 - "${RELEASE_DIR}/" || die "file copy failed"
384 -
385 -if [[ ${RUNTESTS} == "true" ]] ; then
386 - pushd "${SOURCE_DIR}" >/dev/null
387 - ./runtests.sh --python-versions=supported || die "tests failed"
388 - popd >/dev/null
389 -fi
390 -
391 -rm -rf "${SOURCE_DIR}" || die "directory cleanup failed"
392 -
393 -echo ">>> Setting portage.VERSION"
394 -sed -e "s/^VERSION = .*/VERSION = \"${VERSION}\"/" \
395 - -i "${RELEASE_DIR}/pym/portage/__init__.py" || \
396 - die "Failed to patch portage.VERSION"
397 -
398 -echo ">>> Creating Changelog"
399 -git_log_opts=""
400 -if [[ -n ${CHANGELOG_REVISION} ]] ; then
401 - git_log_opts+=" ${CHANGELOG_REVISION}^..${TREE_ISH}"
402 -else
403 - git_log_opts+=" ${TREE_ISH}"
404 -fi
405 -skip_next=false
406 -git log ${git_log_opts} | fmt -w 80 -p " " | while read -r ; do
407 - if [[ ${skip_next} == "true" ]] ; then
408 - skip_next=false
409 - elif [[ ${REPLY} == " svn path="* ]] ; then
410 - skip_next=true
411 - else
412 - echo "${REPLY}"
413 - fi
414 -done > "${RELEASE_DIR}/ChangeLog" || die "ChangeLog creation failed"
415 -
416 -cd "${RELEASE_BUILDDIR}"
417 -
418 -echo ">>> Creating release tarball ${RELEASE_TARBALL}"
419 -tar --owner portage --group portage -cjf "${RELEASE_TARBALL}" "${RELEASE}" || \
420 - die "tarball creation failed"
421 -
422 -DISTDIR=$(portageq distdir)
423 -if [[ -n ${DISTDIR} && -d ${DISTDIR} && -w ${DISTDIR} ]] ; then
424 - echo ">>> Copying release tarball into ${DISTDIR}"
425 - cp "${RELEASE_TARBALL}" "${DISTDIR}"/ || echo "!!! tarball copy failed"
426 -fi
427 -
428 -if [[ -n ${UPLOAD_LOCATION} ]] ; then
429 - echo ">>> Uploading ${RELEASE_TARBALL} to ${USER}dev.gentoo.org:${UPLOAD_LOCATION}"
430 - scp "${RELEASE_TARBALL}" "${USER}dev.gentoo.org:${UPLOAD_LOCATION}" || die "upload failed"
431 -else
432 - du -h "${RELEASE_TARBALL}"
433 -fi
434 -
435 -exit 0
436 diff --git a/pym/portage/const.py b/pym/portage/const.py
437 index f518b47..acb90f9 100644
438 --- a/pym/portage/const.py
439 +++ b/pym/portage/const.py
440 @@ -60,8 +60,8 @@ GLOBAL_CONFIG_PATH = "/usr/share/portage/config"
441 # these variables are not used with target_root or config_root
442 # NOTE: Use realpath(__file__) so that python module symlinks in site-packages
443 # are followed back to the real location of the whole portage installation.
444 -PORTAGE_BASE_PATH = os.path.join(os.sep, os.sep.join(os.path.realpath(
445 - __file__.rstrip("co")).split(os.sep)[:-3]))
446 +# NOTE: Please keep PORTAGE_BASE_PATH in one line to help substitutions.
447 +PORTAGE_BASE_PATH = os.path.join(os.sep, os.sep.join(os.path.realpath(__file__.rstrip("co")).split(os.sep)[:-3]))
448 PORTAGE_BIN_PATH = PORTAGE_BASE_PATH + "/bin"
449 PORTAGE_PYM_PATH = os.path.realpath(os.path.join(__file__, '../..'))
450 LOCALE_DATA_PATH = PORTAGE_BASE_PATH + "/locale" # FIXME: not used
451 diff --git a/setup.py b/setup.py
452 new file mode 100755
453 index 0000000..7ffe7f0
454 --- /dev/null
455 +++ b/setup.py
456 @@ -0,0 +1,578 @@
457 +#!/usr/bin/env python
458 +# vim:fileencoding=utf-8
459 +# (c) 2010 Michał Górny <mgorny@g.o>
460 +# Released under the terms of the 2-clause BSD license.
461 +
462 +from distutils.core import setup, Command
463 +from distutils.command.build_scripts import build_scripts
464 +from distutils.command.clean import clean
465 +from distutils.command.install import install
466 +from distutils.command.install_data import install_data
467 +from distutils.command.install_lib import install_lib
468 +from distutils.command.install_scripts import install_scripts
469 +from distutils.command.sdist import sdist
470 +from distutils.dir_util import remove_tree
471 +from distutils.util import change_root, subst_vars
472 +
473 +import codecs, collections, glob, os, os.path, re, subprocess, sys
474 +
475 +# TODO:
476 +# - smarter rebuilds of docs w/ 'install_docbook' and 'install_epydoc'.
477 +
478 +x_scripts = {
479 + 'bin': [
480 + 'bin/ebuild', 'bin/egencache', 'bin/emerge', 'bin/emerge-webrsync',
481 + 'bin/emirrordist', 'bin/portageq', 'bin/quickpkg', 'bin/repoman'
482 + ],
483 + 'sbin': [
484 + 'bin/archive-conf', 'bin/dispatch-conf', 'bin/emaint', 'bin/env-update',
485 + 'bin/etc-update', 'bin/fixpackages', 'bin/regenworld'
486 + ],
487 +}
488 +
489 +
490 +class docbook(Command):
491 + """ Build docs using docbook. """
492 +
493 + user_options = [
494 + ('doc-formats=', None, 'Documentation formats to build (all xmlto formats for docbook are allowed, comma-separated'),
495 + ]
496 +
497 + def initialize_options(self):
498 + self.doc_formats = 'xhtml,xhtml-nochunks'
499 +
500 + def finalize_options(self):
501 + self.doc_formats = self.doc_formats.replace(',', ' ').split()
502 +
503 + def run(self):
504 + with open('doc/fragment/date', 'w'):
505 + pass
506 +
507 + for f in self.doc_formats:
508 + print('Building docs in %s format...' % f)
509 + subprocess.check_call(['xmlto', '-o', 'doc',
510 + '-m', 'doc/custom.xsl', f, 'doc/portage.docbook'])
511 +
512 +
513 +class epydoc(Command):
514 + """ Build API docs using epydoc. """
515 +
516 + user_options = [
517 + ]
518 +
519 + def initialize_options(self):
520 + self.build_lib = None
521 +
522 + def finalize_options(self):
523 + self.set_undefined_options('build_py', ('build_lib', 'build_lib'))
524 +
525 + def run(self):
526 + self.run_command('build_py')
527 +
528 + print('Building API documentation...')
529 +
530 + process_env = os.environ.copy()
531 + pythonpath = self.build_lib
532 + try:
533 + pythonpath += ':' + process_env['PYTHONPATH']
534 + except KeyError:
535 + pass
536 + process_env['PYTHONPATH'] = pythonpath
537 +
538 + subprocess.check_call(['epydoc', '-o', 'epydoc',
539 + '--name', self.distribution.get_name(),
540 + '--url', self.distribution.get_url(),
541 + '-qq', '--no-frames', '--show-imports',
542 + '--exclude', 'portage.tests',
543 + '_emerge', 'portage', 'repoman'],
544 + env = process_env)
545 + os.remove('epydoc/api-objects.txt')
546 +
547 +
548 +class install_docbook(install_data):
549 + """ install_data for docbook docs """
550 +
551 + user_options = install_data.user_options
552 +
553 + def initialize_options(self):
554 + install_data.initialize_options(self)
555 + self.htmldir = None
556 +
557 + def finalize_options(self):
558 + self.set_undefined_options('install', ('htmldir', 'htmldir'))
559 + install_data.finalize_options(self)
560 +
561 + def run(self):
562 + if not os.path.exists('doc/portage.html'):
563 + self.run_command('docbook')
564 + self.data_files = [
565 + (self.htmldir, glob.glob('doc/*.html')),
566 + ]
567 + install_data.run(self)
568 +
569 +
570 +class install_epydoc(install_data):
571 + """ install_data for epydoc docs """
572 +
573 + user_options = install_data.user_options
574 +
575 + def initialize_options(self):
576 + install_data.initialize_options(self)
577 + self.htmldir = None
578 +
579 + def finalize_options(self):
580 + self.set_undefined_options('install', ('htmldir', 'htmldir'))
581 + install_data.finalize_options(self)
582 +
583 + def run(self):
584 + if not os.path.exists('epydoc/index.html'):
585 + self.run_command('epydoc')
586 + self.data_files = [
587 + (os.path.join(self.htmldir, 'api'), glob.glob('epydoc/*')),
588 + ]
589 + install_data.run(self)
590 +
591 +
592 +class x_build_scripts_custom(build_scripts):
593 + def finalize_options(self):
594 + build_scripts.finalize_options(self)
595 + if 'dir_name' in dir(self):
596 + self.build_dir = os.path.join(self.build_dir, self.dir_name)
597 + if self.dir_name in x_scripts:
598 + self.scripts = x_scripts[self.dir_name]
599 + else:
600 + self.scripts = set(self.scripts)
601 + for other_files in x_scripts.values():
602 + self.scripts.difference_update(other_files)
603 +
604 + def run(self):
605 + # group scripts by subdirectory
606 + split_scripts = collections.defaultdict(list)
607 + for f in self.scripts:
608 + dir_name = os.path.dirname(f[len('bin/'):])
609 + split_scripts[dir_name].append(f)
610 +
611 + base_dir = self.build_dir
612 + base_scripts = self.scripts
613 + for d, files in split_scripts.items():
614 + self.build_dir = os.path.join(base_dir, d)
615 + self.scripts = files
616 + self.copy_scripts()
617 +
618 + # restore previous values
619 + self.build_dir = base_dir
620 + self.scripts = base_scripts
621 +
622 +
623 +class x_build_scripts_bin(x_build_scripts_custom):
624 + dir_name = 'bin'
625 +
626 +
627 +class x_build_scripts_sbin(x_build_scripts_custom):
628 + dir_name = 'sbin'
629 +
630 +
631 +class x_build_scripts_portagebin(x_build_scripts_custom):
632 + dir_name = 'portage'
633 +
634 +
635 +class x_build_scripts(build_scripts):
636 + def initialize_option(self):
637 + build_scripts.initialize_options(self)
638 +
639 + def finalize_options(self):
640 + build_scripts.finalize_options(self)
641 +
642 + def run(self):
643 + self.run_command('build_scripts_bin')
644 + self.run_command('build_scripts_portagebin')
645 + self.run_command('build_scripts_sbin')
646 +
647 +
648 +class x_clean(clean):
649 + """ clean extended for doc & post-test cleaning """
650 +
651 + def clean_docs(self):
652 + def get_doc_outfiles():
653 + for dirpath, dirnames, filenames in os.walk('doc'):
654 + for f in filenames:
655 + if f.endswith('.docbook') or f == 'custom.xsl':
656 + pass
657 + else:
658 + yield os.path.join(dirpath, f)
659 +
660 + # do not recurse
661 + break
662 +
663 +
664 + for f in get_doc_outfiles():
665 + print('removing %s' % repr(f))
666 + os.remove(f)
667 +
668 + if os.path.isdir('epydoc'):
669 + remove_tree('epydoc')
670 +
671 + def clean_tests(self):
672 + # do not remove incorrect dirs accidentally
673 + top_dir = os.path.normpath(os.path.join(self.build_lib, '..'))
674 + cprefix = os.path.commonprefix((self.build_base, top_dir))
675 + if cprefix != self.build_base:
676 + return
677 +
678 + bin_dir = os.path.join(top_dir, 'bin')
679 + if os.path.exists(bin_dir):
680 + remove_tree(bin_dir)
681 +
682 + conf_dir = os.path.join(top_dir, 'cnf')
683 + if os.path.islink(conf_dir):
684 + print('removing %s symlink' % repr(conf_dir))
685 + os.unlink(conf_dir)
686 +
687 + pni_file = os.path.join(top_dir, '.portage_not_installed')
688 + if os.path.exists(pni_file):
689 + print('removing %s' % repr(pni_file))
690 + os.unlink(pni_file)
691 +
692 + def run(self):
693 + if self.all:
694 + self.clean_tests()
695 + self.clean_docs()
696 +
697 + clean.run(self)
698 +
699 +
700 +class x_install(install):
701 + """ install command with extra Portage paths """
702 +
703 + user_options = install.user_options + [
704 + # note: $prefix and $exec_prefix are reserved for Python install
705 + ('system-prefix=', None, "Prefix for architecture-independent data"),
706 + ('system-exec-prefix=', None, "Prefix for architecture-specific data"),
707 +
708 + ('bindir=', None, "Install directory for main executables"),
709 + ('datarootdir=', None, "Data install root directory"),
710 + ('docdir=', None, "Documentation install directory"),
711 + ('htmldir=', None, "HTML documentation install directory"),
712 + ('mandir=', None, "Manpage root install directory"),
713 + ('portage-base=', 'b', "Portage install base"),
714 + ('portage-bindir=', None, "Install directory for Portage internal-use executables"),
715 + ('portage-datadir=', None, 'Install directory for data files'),
716 + ('sbindir=', None, "Install directory for superuser-intended executables"),
717 + ('sysconfdir=', None, 'System configuration path'),
718 + ]
719 +
720 + # note: the order is important for proper substitution
721 + paths = [
722 + ('system_prefix', '/usr'),
723 + ('system_exec_prefix', '$system_prefix'),
724 +
725 + ('bindir', '$system_exec_prefix/bin'),
726 + ('sbindir', '$system_exec_prefix/sbin'),
727 + ('sysconfdir', '/etc'),
728 +
729 + ('datarootdir', '$system_prefix/share'),
730 + ('docdir', '$datarootdir/doc/$package-$version'),
731 + ('htmldir', '$docdir/html'),
732 + ('mandir', '$datarootdir/man'),
733 +
734 + ('portage_base', '$system_exec_prefix/lib/portage'),
735 + ('portage_bindir', '$portage_base/bin'),
736 + ('portage_datadir', '$datarootdir/portage'),
737 +
738 + # not customized at the moment
739 + ('logrotatedir', '$sysconfdir/logrotate'),
740 + ('portage_confdir', '$portage_datadir/config'),
741 + ('portage_setsdir', '$portage_confdir/sets'),
742 + ]
743 +
744 + def initialize_options(self):
745 + install.initialize_options(self)
746 +
747 + for key, default in self.paths:
748 + setattr(self, key, default)
749 + self.subst_paths = {}
750 +
751 + def finalize_options(self):
752 + install.finalize_options(self)
753 +
754 + # substitute variables
755 + new_paths = {
756 + 'package': self.distribution.get_name(),
757 + 'version': self.distribution.get_version(),
758 + }
759 + for key, default in self.paths:
760 + new_paths[key] = subst_vars(getattr(self, key), new_paths)
761 + setattr(self, key, new_paths[key])
762 + self.subst_paths = new_paths
763 +
764 +
765 +class x_install_data(install_data):
766 + """ install_data with customized path support """
767 +
768 + user_options = install_data.user_options
769 +
770 + def initialize_options(self):
771 + install_data.initialize_options(self)
772 + self.paths = None
773 +
774 + def finalize_options(self):
775 + install_data.finalize_options(self)
776 + self.set_undefined_options('install',
777 + ('subst_paths', 'paths'))
778 +
779 + # substitute variables in data_files
780 + for f in self.data_files:
781 + f[0] = subst_vars(f[0], self.paths)
782 +
783 +
784 +class x_install_lib(install_lib):
785 + """ install_lib command with Portage path substitution """
786 +
787 + user_options = install_lib.user_options
788 +
789 + def initialize_options(self):
790 + install_lib.initialize_options(self)
791 + self.portage_base = None
792 + self.portage_bindir = None
793 + self.portage_confdir = None
794 +
795 + def finalize_options(self):
796 + install_lib.finalize_options(self)
797 + self.set_undefined_options('install',
798 + ('portage_base', 'portage_base'),
799 + ('portage_bindir', 'portage_bindir'),
800 + ('portage_confdir', 'portage_confdir'))
801 +
802 + def install(self):
803 + ret = install_lib.install(self)
804 +
805 + def rewrite_file(path, val_dict):
806 + path = os.path.join(self.install_dir, path)
807 + print('Rewriting %s' % path)
808 + with codecs.open(path, 'r', 'utf-8') as f:
809 + data = f.read()
810 +
811 + for varname, val in val_dict.items():
812 + regexp = r'^(%s\s*=).*$' % varname
813 + repl = r'\1 %s' % repr(val)
814 +
815 + data = re.sub(regexp, repl, data, 0, re.MULTILINE)
816 +
817 + with codecs.open(path, 'w', 'utf-8') as f:
818 + f.write(data)
819 +
820 + rewrite_file('portage/__init__.py', {
821 + 'VERSION': self.distribution.get_version(),
822 + })
823 + rewrite_file('portage/const.py', {
824 + 'PORTAGE_BASE_PATH': self.portage_base,
825 + 'PORTAGE_BIN_PATH': self.portage_bindir,
826 + 'PORTAGE_CONFIG_PATH': self.portage_confdir,
827 + })
828 +
829 + return ret
830 +
831 +
832 +class x_install_scripts_custom(install_scripts):
833 + def initialize_options(self):
834 + install_scripts.initialize_options(self)
835 + self.root = None
836 +
837 + def finalize_options(self):
838 + self.set_undefined_options('install',
839 + ('root', 'root'),
840 + (self.var_name, 'install_dir'))
841 + install_scripts.finalize_options(self)
842 + self.build_dir = os.path.join(self.build_dir, self.dir_name)
843 +
844 + # prepend root
845 + if self.root is not None:
846 + self.install_dir = change_root(self.root, self.install_dir)
847 +
848 +
849 +class x_install_scripts_bin(x_install_scripts_custom):
850 + dir_name = 'bin'
851 + var_name = 'bindir'
852 +
853 +
854 +class x_install_scripts_sbin(x_install_scripts_custom):
855 + dir_name = 'sbin'
856 + var_name = 'sbindir'
857 +
858 +
859 +class x_install_scripts_portagebin(x_install_scripts_custom):
860 + dir_name = 'portage'
861 + var_name = 'portage_bindir'
862 +
863 +
864 +class x_install_scripts(install_scripts):
865 + def initialize_option(self):
866 + pass
867 +
868 + def finalize_options(self):
869 + pass
870 +
871 + def run(self):
872 + self.run_command('install_scripts_bin')
873 + self.run_command('install_scripts_portagebin')
874 + self.run_command('install_scripts_sbin')
875 +
876 +
877 +class x_sdist(sdist):
878 + """ sdist defaulting to .tar.bz2 format """
879 +
880 + def finalize_options(self):
881 + if self.formats is None:
882 + self.formats = ['bztar']
883 +
884 + sdist.finalize_options(self)
885 +
886 +
887 +class build_tests(x_build_scripts_custom):
888 + """ Prepare build dir for running tests. """
889 +
890 + def initialize_options(self):
891 + x_build_scripts_custom.initialize_options(self)
892 + self.build_base = None
893 + self.build_lib = None
894 +
895 + def finalize_options(self):
896 + x_build_scripts_custom.finalize_options(self)
897 + self.set_undefined_options('build',
898 + ('build_base', 'build_base'),
899 + ('build_lib', 'build_lib'))
900 +
901 + # since we will be writing to $build_lib/.., it is important
902 + # that we do not leave $build_base
903 + self.top_dir = os.path.normpath(os.path.join(self.build_lib, '..'))
904 + cprefix = os.path.commonprefix((self.build_base, self.top_dir))
905 + if cprefix != self.build_base:
906 + raise SystemError('build_lib must be a subdirectory of build_base')
907 +
908 + self.build_dir = os.path.join(self.top_dir, 'bin')
909 +
910 + def run(self):
911 + self.run_command('build_py')
912 +
913 + # install all scripts $build_lib/../bin
914 + # (we can't do a symlink since we want shebangs corrected)
915 + x_build_scripts_custom.run(self)
916 +
917 + # symlink 'cnf' directory
918 + conf_dir = os.path.join(self.top_dir, 'cnf')
919 + if os.path.exists(conf_dir):
920 + if not os.path.islink(conf_dir):
921 + raise SystemError('%s exists and is not a symlink (collision)'
922 + % repr(conf_dir))
923 + os.unlink(conf_dir)
924 + conf_src = os.path.relpath('cnf', self.top_dir)
925 + print('Symlinking %s -> %s' % (conf_dir, conf_src))
926 + os.symlink(conf_src, conf_dir)
927 +
928 + # create $build_lib/../.portage_not_installed
929 + # to enable proper paths in tests
930 + with open(os.path.join(self.top_dir, '.portage_not_installed'), 'w') as f:
931 + pass
932 +
933 +
934 +class test(Command):
935 + """ run tests """
936 +
937 + user_options = []
938 +
939 + def initialize_options(self):
940 + self.build_lib = None
941 +
942 + def finalize_options(self):
943 + self.set_undefined_options('build',
944 + ('build_lib', 'build_lib'))
945 +
946 + def run(self):
947 + self.run_command('build_tests')
948 + subprocess.check_call([
949 + sys.executable, '-bWd',
950 + os.path.join(self.build_lib, 'portage/tests/runTests.py')
951 + ])
952 +
953 +
954 +def find_packages():
955 + for dirpath, dirnames, filenames in os.walk('pym'):
956 + if '__init__.py' in filenames:
957 + yield os.path.relpath(dirpath, 'pym')
958 +
959 +
960 +def find_scripts():
961 + for dirpath, dirnames, filenames in os.walk('bin'):
962 + for f in filenames:
963 + yield os.path.join(dirpath, f)
964 +
965 +
966 +def get_manpages():
967 + linguas = os.environ.get('LINGUAS')
968 + if linguas is not None:
969 + linguas = linguas.split()
970 +
971 + for dirpath, dirnames, filenames in os.walk('man'):
972 + groups = collections.defaultdict(list)
973 + for f in filenames:
974 + fn, suffix = f.rsplit('.', 1)
975 + groups[suffix].append(os.path.join(dirpath, f))
976 +
977 + topdir = dirpath[len('man/'):]
978 + if not topdir or linguas is None or topdir in linguas:
979 + for g, mans in groups.items():
980 + yield [os.path.join('$mandir', topdir, 'man%s' % g), mans]
981 +
982 +setup(
983 + name = 'portage',
984 + version = '2.2.12',
985 + url = 'https://wiki.gentoo.org/wiki/Project:Portage',
986 + author = 'Gentoo Portage Development Team',
987 + author_email = 'dev-portage@g.o',
988 +
989 + package_dir = {'': 'pym'},
990 + packages = list(find_packages()),
991 + # something to cheat build & install commands
992 + scripts = list(find_scripts()),
993 +
994 + data_files = list(get_manpages()) + [
995 + ['$sysconfdir', ['cnf/etc-update.conf', 'cnf/dispatch-conf.conf']],
996 + ['$logrotatedir', ['cnf/logrotate.d/elog-save-summary']],
997 + ['$portage_confdir', [
998 + 'cnf/make.conf.example', 'cnf/make.globals', 'cnf/repos.conf']],
999 + ['$portage_setsdir', ['cnf/sets/portage.conf']],
1000 + ['$docdir', ['NEWS', 'RELEASE-NOTES']],
1001 + ],
1002 +
1003 + cmdclass = {
1004 + 'build_scripts': x_build_scripts,
1005 + 'build_scripts_bin': x_build_scripts_bin,
1006 + 'build_scripts_portagebin': x_build_scripts_portagebin,
1007 + 'build_scripts_sbin': x_build_scripts_sbin,
1008 + 'build_tests': build_tests,
1009 + 'clean': x_clean,
1010 + 'docbook': docbook,
1011 + 'epydoc': epydoc,
1012 + 'install': x_install,
1013 + 'install_data': x_install_data,
1014 + 'install_docbook': install_docbook,
1015 + 'install_epydoc': install_epydoc,
1016 + 'install_lib': x_install_lib,
1017 + 'install_scripts': x_install_scripts,
1018 + 'install_scripts_bin': x_install_scripts_bin,
1019 + 'install_scripts_portagebin': x_install_scripts_portagebin,
1020 + 'install_scripts_sbin': x_install_scripts_sbin,
1021 + 'sdist': x_sdist,
1022 + 'test': test,
1023 + },
1024 +
1025 + classifiers = [
1026 + 'Development Status :: 5 - Production/Stable',
1027 + 'Environment :: Console',
1028 + 'Intended Audience :: System Administrators',
1029 + 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
1030 + 'Operating System :: POSIX',
1031 + 'Programming Language :: Python',
1032 + 'Topic :: System :: Installation/Setup'
1033 + ]
1034 +)
1035 --
1036 2.0.4

Replies