Gentoo Archives: gentoo-portage-dev

From: Brian Dolbec <dolsen@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH v2] Install Portage using setup.py
Date: Sat, 23 Aug 2014 21:58:06
Message-Id: 20140823145649.30ab06e1.dolsen@gentoo.org
In Reply to: [gentoo-portage-dev] [PATCH v2] Install Portage using setup.py by "Michał Górny"
1 On Sat, 23 Aug 2014 22:30:56 +0200
2 Michał Górny <mgorny@g.o> wrote:
3
4
5 What about adding to the commit message that v2 also includes "setup.py
6 sdist" capability?
7
8
9
10 > diff --git a/mkrelease.sh b/mkrelease.sh
11 > deleted file mode 100755
12 > index f9f7564..0000000
13 > --- a/mkrelease.sh
14 > +++ /dev/null
15 > @@ -1,141 +0,0 @@
16 > -#!/bin/bash
17 > -# Copyright 2008-2014 Gentoo Foundation
18 > -# Distributed under the terms of the GNU General Public License v2
19 > -
20 > -RELEASE_BUILDDIR=${RELEASE_BUILDDIR:-/var/tmp/portage-release}
21 > -SOURCE_DIR=${RELEASE_BUILDDIR}/checkout
22 > -BRANCH=${BRANCH:-master}
23 > -USE_TAG=false
24 > -CHANGELOG_REVISION=
25 > -UPLOAD_LOCATION=
26 > -RUNTESTS=false
27 > -USER=
28 > -
29 > -usage() {
30 > - echo "Usage: ${0##*/} [--changelog-rev <tree-ish>]
31 > [-t|--tag] [-u|--upload <location>] [--user <username>] [--runtests]
32 > <version>"
33 > - exit ${1:-0}
34 > -}
35 > -
36 > -die() {
37 > - printf 'error: %s\n' "$*"
38 > - usage 1
39 > -}
40 > -
41 > -ARGS=$(getopt -o htu: --long
42 > help,changelog-rev:,runtests,tag,upload:,user: \
43 > - -n "${0##*/}" -- "$@")
44 > -[ $? != 0 ] && die "initialization error"
45 > -
46 > -eval set -- "${ARGS}"
47 > -
48 > -while true; do
49 > - case $1 in
50 > - --changelog-rev)
51 > - CHANGELOG_REVISION=$2
52 > - shift 2
53 > - ;;
54 > - -t|--tag)
55 > - USE_TAG=true
56 > - shift
57 > - ;;
58 > - -u|--upload)
59 > - UPLOAD_LOCATION=$2
60 > - shift 2
61 > - ;;
62 > - --user)
63 > - USER=$2"@"
64 > - shift 2
65 > - ;;
66 > - -h|--help)
67 > - usage
68 > - ;;
69 > - --runtests)
70 > - RUNTESTS=true
71 > - shift
72 > - ;;
73 > - --)
74 > - shift
75 > - break
76 > - ;;
77 > - *)
78 > - die "unknown option: $1"
79 > - ;;
80 > - esac
81 > -done
82 > -
83 > -[ $# != 1 ] && die "Need version argument"
84 > -[[ -n ${1/[0-9]*} ]] && die "Invalid version argument"
85 > -
86 > -VERSION=$1
87 > -RELEASE=portage-${VERSION}
88 > -RELEASE_DIR=${RELEASE_BUILDDIR}/${RELEASE}
89 > -RELEASE_TARBALL="${RELEASE_BUILDDIR}/${RELEASE}.tar.bz2"
90 > -TREE_ISH=${BRANCH}
91 > -if [[ ${USE_TAG} == "true" ]] ; then
92 > - TREE_ISH="v${VERSION}"
93 > -fi
94 > -
95 > -echo ">>> Cleaning working directories ${RELEASE_DIR} ${SOURCE_DIR}"
96 > -rm -rf "${RELEASE_DIR}" "${SOURCE_DIR}" || die "directory cleanup
97 > failed" -mkdir -p "${RELEASE_DIR}" || die "directory creation failed"
98 > -mkdir -p "${SOURCE_DIR}" || die "mkdir failed"
99 > -
100 > -echo ">>> Starting GIT archive"
101 > -git archive --format=tar ${TREE_ISH} | \
102 > - tar -xf - -C "${SOURCE_DIR}" || die "git archive failed"
103 > -
104 > -echo ">>> Building release tree"
105 > -cp -a "${SOURCE_DIR}/"{bin,cnf,doc,man,misc,pym} "${RELEASE_DIR}/"
106 > || die "directory copy failed" -cp
107 > "${SOURCE_DIR}/"{.portage_not_installed,DEVELOPING,LICENSE,Makefile,NEWS,README,RELEASE-NOTES,TEST-NOTES}
108 > \
109 > - "${RELEASE_DIR}/" || die "file copy failed"
110 > -
111 > -if [[ ${RUNTESTS} == "true" ]] ; then
112 > - pushd "${SOURCE_DIR}" >/dev/null
113 > - ./runtests.sh --python-versions=supported || die "tests
114 > failed"
115 > - popd >/dev/null
116 > -fi
117 > -
118 > -rm -rf "${SOURCE_DIR}" || die "directory cleanup failed"
119 > -
120 > -echo ">>> Setting portage.VERSION"
121 > -sed -e "s/^VERSION = .*/VERSION = \"${VERSION}\"/" \
122 > - -i "${RELEASE_DIR}/pym/portage/__init__.py" || \
123 > - die "Failed to patch portage.VERSION"
124 > -
125 > -echo ">>> Creating Changelog"
126 > -git_log_opts=""
127 > -if [[ -n ${CHANGELOG_REVISION} ]] ; then
128 > - git_log_opts+=" ${CHANGELOG_REVISION}^..${TREE_ISH}"
129 > -else
130 > - git_log_opts+=" ${TREE_ISH}"
131 > -fi
132 > -skip_next=false
133 > -git log ${git_log_opts} | fmt -w 80 -p " " | while read -r ; do
134 > - if [[ ${skip_next} == "true" ]] ; then
135 > - skip_next=false
136 > - elif [[ ${REPLY} == " svn path="* ]] ; then
137 > - skip_next=true
138 > - else
139 > - echo "${REPLY}"
140 > - fi
141 > -done > "${RELEASE_DIR}/ChangeLog" || die "ChangeLog creation failed"
142 > -
143 > -cd "${RELEASE_BUILDDIR}"
144 > -
145 > -echo ">>> Creating release tarball ${RELEASE_TARBALL}"
146 > -tar --owner portage --group portage -cjf "${RELEASE_TARBALL}"
147 > "${RELEASE}" || \
148 > - die "tarball creation failed"
149 > -
150 > -DISTDIR=$(portageq distdir)
151 > -if [[ -n ${DISTDIR} && -d ${DISTDIR} && -w ${DISTDIR} ]] ; then
152 > - echo ">>> Copying release tarball into ${DISTDIR}"
153 > - cp "${RELEASE_TARBALL}" "${DISTDIR}"/ || echo "!!! tarball
154 > copy failed" -fi
155 > -
156 > -if [[ -n ${UPLOAD_LOCATION} ]] ; then
157 > - echo ">>> Uploading ${RELEASE_TARBALL} to
158 > ${USER}dev.gentoo.org:${UPLOAD_LOCATION}"
159 > - scp "${RELEASE_TARBALL}"
160 > "${USER}dev.gentoo.org:${UPLOAD_LOCATION}" || die "upload failed"
161 > -else
162 > - du -h "${RELEASE_TARBALL}"
163 > -fi
164 > -
165 > -exit 0
166 >
167
168 Why are you removing everything from mkrelease.sh?
169
170 It does do some other useful things other than just make the release
171 tarball.
172 We have not decided to drop the Changelog as a team yet, only a few
173 words on irc. Instead mkrelease could be modified to work with
174 setup.py for the tarball creation, but it still creates the Changelog,
175 copies the tarball to distfiles, uploads the file...
176
177 I did not see any of that functionality added to setup.py below.
178
179
180 > FIXME: not used diff --git a/setup.py b/setup.py new file mode 100755
181 > index 0000000..7ffe7f0 --- /dev/null
182 > +++ b/setup.py
183 > @@ -0,0 +1,578 @@
184 > +#!/usr/bin/env python
185 > +# vim:fileencoding=utf-8
186 > +# (c) 2010 Michał Górny <mgorny@g.o>
187 > +# Released under the terms of the 2-clause BSD license.
188 > +
189 > +from distutils.core import setup, Command
190 > +from distutils.command.build_scripts import build_scripts
191 > +from distutils.command.clean import clean
192 > +from distutils.command.install import install
193 > +from distutils.command.install_data import install_data
194 > +from distutils.command.install_lib import install_lib
195 > +from distutils.command.install_scripts import install_scripts
196 > +from distutils.command.sdist import sdist
197 > +from distutils.dir_util import remove_tree
198 > +from distutils.util import change_root, subst_vars
199 > +
200 > +import codecs, collections, glob, os, os.path, re, subprocess, sys
201 > +
202 > +# TODO:
203 > +# - smarter rebuilds of docs w/ 'install_docbook' and
204 > 'install_epydoc'. +
205 > +x_scripts = {
206 > + 'bin': [
207 > + 'bin/ebuild', 'bin/egencache', 'bin/emerge',
208 > 'bin/emerge-webrsync',
209 > + 'bin/emirrordist', 'bin/portageq', 'bin/quickpkg',
210 > 'bin/repoman'
211 > + ],
212 > + 'sbin': [
213 > + 'bin/archive-conf', 'bin/dispatch-conf',
214 > 'bin/emaint', 'bin/env-update',
215 > + 'bin/etc-update', 'bin/fixpackages', 'bin/regenworld'
216 > + ],
217 > +}
218 > +
219 > +
220 > +class docbook(Command):
221 > + """ Build docs using docbook. """
222 > +
223 > + user_options = [
224 > + ('doc-formats=', None, 'Documentation formats to
225 > build (all xmlto formats for docbook are allowed, comma-separated'),
226 > + ]
227 > +
228 > + def initialize_options(self):
229 > + self.doc_formats = 'xhtml,xhtml-nochunks'
230 > +
231 > + def finalize_options(self):
232 > + self.doc_formats = self.doc_formats.replace(',', '
233 > ').split() +
234 > + def run(self):
235 > + with open('doc/fragment/date', 'w'):
236 > + pass
237 > +
238 > + for f in self.doc_formats:
239 > + print('Building docs in %s format...' % f)
240 > + subprocess.check_call(['xmlto', '-o', 'doc',
241 > + '-m', 'doc/custom.xsl', f,
242 > 'doc/portage.docbook']) +
243 > +
244 > +class epydoc(Command):
245 > + """ Build API docs using epydoc. """
246 > +
247 > + user_options = [
248 > + ]
249 > +
250 > + def initialize_options(self):
251 > + self.build_lib = None
252 > +
253 > + def finalize_options(self):
254 > + self.set_undefined_options('build_py', ('build_lib',
255 > 'build_lib')) +
256 > + def run(self):
257 > + self.run_command('build_py')
258 > +
259 > + print('Building API documentation...')
260 > +
261 > + process_env = os.environ.copy()
262 > + pythonpath = self.build_lib
263 > + try:
264 > + pythonpath += ':' + process_env['PYTHONPATH']
265 > + except KeyError:
266 > + pass
267 > + process_env['PYTHONPATH'] = pythonpath
268 > +
269 > + subprocess.check_call(['epydoc', '-o', 'epydoc',
270 > + '--name', self.distribution.get_name(),
271 > + '--url', self.distribution.get_url(),
272 > + '-qq', '--no-frames', '--show-imports',
273 > + '--exclude', 'portage.tests',
274 > + '_emerge', 'portage', 'repoman'],
275 > + env = process_env)
276 > + os.remove('epydoc/api-objects.txt')
277 > +
278 > +
279 > +class install_docbook(install_data):
280 > + """ install_data for docbook docs """
281 > +
282 > + user_options = install_data.user_options
283 > +
284 > + def initialize_options(self):
285 > + install_data.initialize_options(self)
286 > + self.htmldir = None
287 > +
288 > + def finalize_options(self):
289 > + self.set_undefined_options('install', ('htmldir',
290 > 'htmldir'))
291 > + install_data.finalize_options(self)
292 > +
293 > + def run(self):
294 > + if not os.path.exists('doc/portage.html'):
295 > + self.run_command('docbook')
296 > + self.data_files = [
297 > + (self.htmldir, glob.glob('doc/*.html')),
298 > + ]
299 > + install_data.run(self)
300 > +
301 > +
302 > +class install_epydoc(install_data):
303 > + """ install_data for epydoc docs """
304 > +
305 > + user_options = install_data.user_options
306 > +
307 > + def initialize_options(self):
308 > + install_data.initialize_options(self)
309 > + self.htmldir = None
310 > +
311 > + def finalize_options(self):
312 > + self.set_undefined_options('install', ('htmldir',
313 > 'htmldir'))
314 > + install_data.finalize_options(self)
315 > +
316 > + def run(self):
317 > + if not os.path.exists('epydoc/index.html'):
318 > + self.run_command('epydoc')
319 > + self.data_files = [
320 > + (os.path.join(self.htmldir, 'api'),
321 > glob.glob('epydoc/*')),
322 > + ]
323 > + install_data.run(self)
324 > +
325 > +
326 > +class x_build_scripts_custom(build_scripts):
327 > + def finalize_options(self):
328 > + build_scripts.finalize_options(self)
329 > + if 'dir_name' in dir(self):
330 > + self.build_dir =
331 > os.path.join(self.build_dir, self.dir_name)
332 > + if self.dir_name in x_scripts:
333 > + self.scripts =
334 > x_scripts[self.dir_name]
335 > + else:
336 > + self.scripts = set(self.scripts)
337 > + for other_files in
338 > x_scripts.values():
339 > +
340 > self.scripts.difference_update(other_files) +
341 > + def run(self):
342 > + # group scripts by subdirectory
343 > + split_scripts = collections.defaultdict(list)
344 > + for f in self.scripts:
345 > + dir_name = os.path.dirname(f[len('bin/'):])
346 > + split_scripts[dir_name].append(f)
347 > +
348 > + base_dir = self.build_dir
349 > + base_scripts = self.scripts
350 > + for d, files in split_scripts.items():
351 > + self.build_dir = os.path.join(base_dir, d)
352 > + self.scripts = files
353 > + self.copy_scripts()
354 > +
355 > + # restore previous values
356 > + self.build_dir = base_dir
357 > + self.scripts = base_scripts
358 > +
359 > +
360 > +class x_build_scripts_bin(x_build_scripts_custom):
361 > + dir_name = 'bin'
362 > +
363 > +
364 > +class x_build_scripts_sbin(x_build_scripts_custom):
365 > + dir_name = 'sbin'
366 > +
367 > +
368 > +class x_build_scripts_portagebin(x_build_scripts_custom):
369 > + dir_name = 'portage'
370 > +
371 > +
372 > +class x_build_scripts(build_scripts):
373 > + def initialize_option(self):
374 > + build_scripts.initialize_options(self)
375 > +
376 > + def finalize_options(self):
377 > + build_scripts.finalize_options(self)
378 > +
379 > + def run(self):
380 > + self.run_command('build_scripts_bin')
381 > + self.run_command('build_scripts_portagebin')
382 > + self.run_command('build_scripts_sbin')
383 > +
384 > +
385 > +class x_clean(clean):
386 > + """ clean extended for doc & post-test cleaning """
387 > +
388 > + def clean_docs(self):
389 > + def get_doc_outfiles():
390 > + for dirpath, dirnames, filenames in
391 > os.walk('doc'):
392 > + for f in filenames:
393 > + if f.endswith('.docbook') or
394 > f == 'custom.xsl':
395 > + pass
396 > + else:
397 > + yield
398 > os.path.join(dirpath, f) +
399 > + # do not recurse
400 > + break
401 > +
402 > +
403 > + for f in get_doc_outfiles():
404 > + print('removing %s' % repr(f))
405 > + os.remove(f)
406 > +
407 > + if os.path.isdir('epydoc'):
408 > + remove_tree('epydoc')
409 > +
410 > + def clean_tests(self):
411 > + # do not remove incorrect dirs accidentally
412 > + top_dir =
413 > os.path.normpath(os.path.join(self.build_lib, '..'))
414 > + cprefix = os.path.commonprefix((self.build_base,
415 > top_dir))
416 > + if cprefix != self.build_base:
417 > + return
418 > +
419 > + bin_dir = os.path.join(top_dir, 'bin')
420 > + if os.path.exists(bin_dir):
421 > + remove_tree(bin_dir)
422 > +
423 > + conf_dir = os.path.join(top_dir, 'cnf')
424 > + if os.path.islink(conf_dir):
425 > + print('removing %s symlink' % repr(conf_dir))
426 > + os.unlink(conf_dir)
427 > +
428 > + pni_file = os.path.join(top_dir,
429 > '.portage_not_installed')
430 > + if os.path.exists(pni_file):
431 > + print('removing %s' % repr(pni_file))
432 > + os.unlink(pni_file)
433 > +
434 > + def run(self):
435 > + if self.all:
436 > + self.clean_tests()
437 > + self.clean_docs()
438 > +
439 > + clean.run(self)
440 > +
441 > +
442 > +class x_install(install):
443 > + """ install command with extra Portage paths """
444 > +
445 > + user_options = install.user_options + [
446 > + # note: $prefix and $exec_prefix are reserved for
447 > Python install
448 > + ('system-prefix=', None, "Prefix for
449 > architecture-independent data"),
450 > + ('system-exec-prefix=', None, "Prefix for
451 > architecture-specific data"), +
452 > + ('bindir=', None, "Install directory for main
453 > executables"),
454 > + ('datarootdir=', None, "Data install root
455 > directory"),
456 > + ('docdir=', None, "Documentation install directory"),
457 > + ('htmldir=', None, "HTML documentation install
458 > directory"),
459 > + ('mandir=', None, "Manpage root install directory"),
460 > + ('portage-base=', 'b', "Portage install base"),
461 > + ('portage-bindir=', None, "Install directory for
462 > Portage internal-use executables"),
463 > + ('portage-datadir=', None, 'Install directory for
464 > data files'),
465 > + ('sbindir=', None, "Install directory for
466 > superuser-intended executables"),
467 > + ('sysconfdir=', None, 'System configuration path'),
468 > + ]
469 > +
470 > + # note: the order is important for proper substitution
471 > + paths = [
472 > + ('system_prefix', '/usr'),
473 > + ('system_exec_prefix', '$system_prefix'),
474 > +
475 > + ('bindir', '$system_exec_prefix/bin'),
476 > + ('sbindir', '$system_exec_prefix/sbin'),
477 > + ('sysconfdir', '/etc'),
478 > +
479 > + ('datarootdir', '$system_prefix/share'),
480 > + ('docdir', '$datarootdir/doc/$package-$version'),
481 > + ('htmldir', '$docdir/html'),
482 > + ('mandir', '$datarootdir/man'),
483 > +
484 > + ('portage_base', '$system_exec_prefix/lib/portage'),
485 > + ('portage_bindir', '$portage_base/bin'),
486 > + ('portage_datadir', '$datarootdir/portage'),
487 > +
488 > + # not customized at the moment
489 > + ('logrotatedir', '$sysconfdir/logrotate'),
490 > + ('portage_confdir', '$portage_datadir/config'),
491 > + ('portage_setsdir', '$portage_confdir/sets'),
492 > + ]
493 > +
494 > + def initialize_options(self):
495 > + install.initialize_options(self)
496 > +
497 > + for key, default in self.paths:
498 > + setattr(self, key, default)
499 > + self.subst_paths = {}
500 > +
501 > + def finalize_options(self):
502 > + install.finalize_options(self)
503 > +
504 > + # substitute variables
505 > + new_paths = {
506 > + 'package': self.distribution.get_name(),
507 > + 'version': self.distribution.get_version(),
508 > + }
509 > + for key, default in self.paths:
510 > + new_paths[key] = subst_vars(getattr(self,
511 > key), new_paths)
512 > + setattr(self, key, new_paths[key])
513 > + self.subst_paths = new_paths
514 > +
515 > +
516 > +class x_install_data(install_data):
517 > + """ install_data with customized path support """
518 > +
519 > + user_options = install_data.user_options
520 > +
521 > + def initialize_options(self):
522 > + install_data.initialize_options(self)
523 > + self.paths = None
524 > +
525 > + def finalize_options(self):
526 > + install_data.finalize_options(self)
527 > + self.set_undefined_options('install',
528 > + ('subst_paths', 'paths'))
529 > +
530 > + # substitute variables in data_files
531 > + for f in self.data_files:
532 > + f[0] = subst_vars(f[0], self.paths)
533 > +
534 > +
535 > +class x_install_lib(install_lib):
536 > + """ install_lib command with Portage path substitution """
537 > +
538 > + user_options = install_lib.user_options
539 > +
540 > + def initialize_options(self):
541 > + install_lib.initialize_options(self)
542 > + self.portage_base = None
543 > + self.portage_bindir = None
544 > + self.portage_confdir = None
545 > +
546 > + def finalize_options(self):
547 > + install_lib.finalize_options(self)
548 > + self.set_undefined_options('install',
549 > + ('portage_base', 'portage_base'),
550 > + ('portage_bindir', 'portage_bindir'),
551 > + ('portage_confdir', 'portage_confdir'))
552 > +
553 > + def install(self):
554 > + ret = install_lib.install(self)
555 > +
556 > + def rewrite_file(path, val_dict):
557 > + path = os.path.join(self.install_dir, path)
558 > + print('Rewriting %s' % path)
559 > + with codecs.open(path, 'r', 'utf-8') as f:
560 > + data = f.read()
561 > +
562 > + for varname, val in val_dict.items():
563 > + regexp = r'^(%s\s*=).*$' % varname
564 > + repl = r'\1 %s' % repr(val)
565 > +
566 > + data = re.sub(regexp, repl, data, 0,
567 > re.MULTILINE) +
568 > + with codecs.open(path, 'w', 'utf-8') as f:
569 > + f.write(data)
570 > +
571 > + rewrite_file('portage/__init__.py', {
572 > + 'VERSION': self.distribution.get_version(),
573 > + })
574 > + rewrite_file('portage/const.py', {
575 > + 'PORTAGE_BASE_PATH': self.portage_base,
576 > + 'PORTAGE_BIN_PATH': self.portage_bindir,
577 > + 'PORTAGE_CONFIG_PATH': self.portage_confdir,
578 > + })
579 > +
580 > + return ret
581 > +
582 > +
583 > +class x_install_scripts_custom(install_scripts):
584 > + def initialize_options(self):
585 > + install_scripts.initialize_options(self)
586 > + self.root = None
587 > +
588 > + def finalize_options(self):
589 > + self.set_undefined_options('install',
590 > + ('root', 'root'),
591 > + (self.var_name, 'install_dir'))
592 > + install_scripts.finalize_options(self)
593 > + self.build_dir = os.path.join(self.build_dir,
594 > self.dir_name) +
595 > + # prepend root
596 > + if self.root is not None:
597 > + self.install_dir = change_root(self.root,
598 > self.install_dir) +
599 > +
600 > +class x_install_scripts_bin(x_install_scripts_custom):
601 > + dir_name = 'bin'
602 > + var_name = 'bindir'
603 > +
604 > +
605 > +class x_install_scripts_sbin(x_install_scripts_custom):
606 > + dir_name = 'sbin'
607 > + var_name = 'sbindir'
608 > +
609 > +
610 > +class x_install_scripts_portagebin(x_install_scripts_custom):
611 > + dir_name = 'portage'
612 > + var_name = 'portage_bindir'
613 > +
614 > +
615 > +class x_install_scripts(install_scripts):
616 > + def initialize_option(self):
617 > + pass
618 > +
619 > + def finalize_options(self):
620 > + pass
621 > +
622 > + def run(self):
623 > + self.run_command('install_scripts_bin')
624 > + self.run_command('install_scripts_portagebin')
625 > + self.run_command('install_scripts_sbin')
626 > +
627 > +
628 > +class x_sdist(sdist):
629 > + """ sdist defaulting to .tar.bz2 format """
630 > +
631 > + def finalize_options(self):
632 > + if self.formats is None:
633 > + self.formats = ['bztar']
634 > +
635 > + sdist.finalize_options(self)
636 > +
637 > +
638 > +class build_tests(x_build_scripts_custom):
639 > + """ Prepare build dir for running tests. """
640 > +
641 > + def initialize_options(self):
642 > + x_build_scripts_custom.initialize_options(self)
643 > + self.build_base = None
644 > + self.build_lib = None
645 > +
646 > + def finalize_options(self):
647 > + x_build_scripts_custom.finalize_options(self)
648 > + self.set_undefined_options('build',
649 > + ('build_base', 'build_base'),
650 > + ('build_lib', 'build_lib'))
651 > +
652 > + # since we will be writing to $build_lib/.., it is
653 > important
654 > + # that we do not leave $build_base
655 > + self.top_dir =
656 > os.path.normpath(os.path.join(self.build_lib, '..'))
657 > + cprefix = os.path.commonprefix((self.build_base,
658 > self.top_dir))
659 > + if cprefix != self.build_base:
660 > + raise SystemError('build_lib must be a
661 > subdirectory of build_base') +
662 > + self.build_dir = os.path.join(self.top_dir, 'bin')
663 > +
664 > + def run(self):
665 > + self.run_command('build_py')
666 > +
667 > + # install all scripts $build_lib/../bin
668 > + # (we can't do a symlink since we want shebangs
669 > corrected)
670 > + x_build_scripts_custom.run(self)
671 > +
672 > + # symlink 'cnf' directory
673 > + conf_dir = os.path.join(self.top_dir, 'cnf')
674 > + if os.path.exists(conf_dir):
675 > + if not os.path.islink(conf_dir):
676 > + raise SystemError('%s exists and is
677 > not a symlink (collision)'
678 > + % repr(conf_dir))
679 > + os.unlink(conf_dir)
680 > + conf_src = os.path.relpath('cnf', self.top_dir)
681 > + print('Symlinking %s -> %s' % (conf_dir, conf_src))
682 > + os.symlink(conf_src, conf_dir)
683 > +
684 > + # create $build_lib/../.portage_not_installed
685 > + # to enable proper paths in tests
686 > + with open(os.path.join(self.top_dir,
687 > '.portage_not_installed'), 'w') as f:
688 > + pass
689 > +
690 > +
691 > +class test(Command):
692 > + """ run tests """
693 > +
694 > + user_options = []
695 > +
696 > + def initialize_options(self):
697 > + self.build_lib = None
698 > +
699 > + def finalize_options(self):
700 > + self.set_undefined_options('build',
701 > + ('build_lib', 'build_lib'))
702 > +
703 > + def run(self):
704 > + self.run_command('build_tests')
705 > + subprocess.check_call([
706 > + sys.executable, '-bWd',
707 > + os.path.join(self.build_lib,
708 > 'portage/tests/runTests.py')
709 > + ])
710 > +
711 > +
712 > +def find_packages():
713 > + for dirpath, dirnames, filenames in os.walk('pym'):
714 > + if '__init__.py' in filenames:
715 > + yield os.path.relpath(dirpath, 'pym')
716 > +
717 > +
718 > +def find_scripts():
719 > + for dirpath, dirnames, filenames in os.walk('bin'):
720 > + for f in filenames:
721 > + yield os.path.join(dirpath, f)
722 > +
723 > +
724 > +def get_manpages():
725 > + linguas = os.environ.get('LINGUAS')
726 > + if linguas is not None:
727 > + linguas = linguas.split()
728 > +
729 > + for dirpath, dirnames, filenames in os.walk('man'):
730 > + groups = collections.defaultdict(list)
731 > + for f in filenames:
732 > + fn, suffix = f.rsplit('.', 1)
733 > + groups[suffix].append(os.path.join(dirpath,
734 > f)) +
735 > + topdir = dirpath[len('man/'):]
736 > + if not topdir or linguas is None or topdir in
737 > linguas:
738 > + for g, mans in groups.items():
739 > + yield [os.path.join('$mandir',
740 > topdir, 'man%s' % g), mans] +
741 > +setup(
742 > + name = 'portage',
743 > + version = '2.2.12',
744 > + url = 'https://wiki.gentoo.org/wiki/Project:Portage',
745 > + author = 'Gentoo Portage Development Team',
746 > + author_email = 'dev-portage@g.o',
747 > +
748 > + package_dir = {'': 'pym'},
749 > + packages = list(find_packages()),
750 > + # something to cheat build & install commands
751 > + scripts = list(find_scripts()),
752 > +
753 > + data_files = list(get_manpages()) + [
754 > + ['$sysconfdir', ['cnf/etc-update.conf',
755 > 'cnf/dispatch-conf.conf']],
756 > + ['$logrotatedir',
757 > ['cnf/logrotate.d/elog-save-summary']],
758 > + ['$portage_confdir', [
759 > + 'cnf/make.conf.example', 'cnf/make.globals',
760 > 'cnf/repos.conf']],
761 > + ['$portage_setsdir', ['cnf/sets/portage.conf']],
762 > + ['$docdir', ['NEWS', 'RELEASE-NOTES']],
763 > + ],
764 > +
765 > + cmdclass = {
766 > + 'build_scripts': x_build_scripts,
767 > + 'build_scripts_bin': x_build_scripts_bin,
768 > + 'build_scripts_portagebin':
769 > x_build_scripts_portagebin,
770 > + 'build_scripts_sbin': x_build_scripts_sbin,
771 > + 'build_tests': build_tests,
772 > + 'clean': x_clean,
773 > + 'docbook': docbook,
774 > + 'epydoc': epydoc,
775 > + 'install': x_install,
776 > + 'install_data': x_install_data,
777 > + 'install_docbook': install_docbook,
778 > + 'install_epydoc': install_epydoc,
779 > + 'install_lib': x_install_lib,
780 > + 'install_scripts': x_install_scripts,
781 > + 'install_scripts_bin': x_install_scripts_bin,
782 > + 'install_scripts_portagebin':
783 > x_install_scripts_portagebin,
784 > + 'install_scripts_sbin': x_install_scripts_sbin,
785 > + 'sdist': x_sdist,
786 > + 'test': test,
787 > + },
788 > +
789 > + classifiers = [
790 > + 'Development Status :: 5 - Production/Stable',
791 > + 'Environment :: Console',
792 > + 'Intended Audience :: System Administrators',
793 > + 'License :: OSI Approved :: GNU General Public
794 > License v2 (GPLv2)',
795 > + 'Operating System :: POSIX',
796 > + 'Programming Language :: Python',
797 > + 'Topic :: System :: Installation/Setup'
798 > + ]
799 > +)
800
801
802
803 --
804 Brian Dolbec <dolsen>