Bases: mini_buildd.misc.Status
Note
OBSOLETED SUDO WORKAROUND for http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=608840
The workaround has been removed, except for the “/etc/sudoers” cleanup (search below).
This is still there so that users who do not re-create their chroots for whatever reason at least keep the same level of security as before.
Since some version of sudo, upgrading the package with missing /etc/sudoers fails, so we now additionally touch this, so /etc/sudoers exist as empty file.
This left over will be removed for the 1.2.x version.
Bases: mini_buildd.misc.API
Subset of ‘Build’ for pickled statistics.
Close build. Just continue on errors, but log them; guarantee to remove it from the builds dict.
Bases: debian.deb822.Changes
Build buildrequest files for all architectures.
Gen any changes file name.
Always strip epoch from version, and handle special mini-buildd types.
>>> Changes.gen_changes_file_name("mypkg", "1.2.3-1", "mips")
u'mypkg_1.2.3-1_mips.changes'
>>> Changes.gen_changes_file_name("mypkg", "7:1.2.3-1", "mips")
u'mypkg_1.2.3-1_mips.changes'
>>> Changes.gen_changes_file_name("mypkg", "7:1.2.3-1", "mips", mbd_type=Changes.TYPE_BREQ)
u'mypkg_1.2.3-1_mini-buildd-buildrequest_mips.changes'
>>> Changes.gen_changes_file_name("mypkg", "7:1.2.3-1", "mips", mbd_type=Changes.TYPE_BRES)
u'mypkg_1.2.3-1_mini-buildd-buildresult_mips.changes'
Package log path for this changes file: REPOID/[_failed]/PACKAGE/VERSION/ARCH
In case the changes is bogus (i.e, cannot produce a valid path for us, like a wrong distribution), None is returned.
Write to file (optionally signed).
>>> import tempfile
>>> t = tempfile.NamedTemporaryFile()
>>> c = Changes(t.name)
>>> c["key"] = "ASCII value"
>>> c.save(None)
>>> c["key"] = "Ünicöde «value»"
>>> c.save(None)
Bases: debian.changelog.Changelog
Changelog class with some extra functions.
>>> cl = Changelog(mini_buildd.misc.open_utf8("./examples/doctests/changelog"), max_blocks=100)
>>> cl.find_first_not("mini-buildd@buildd.intra")
(u'Stephan S\xfcrken <absurd@debian.org>', u'1.0.0-2')
>>> cl = Changelog(mini_buildd.misc.open_utf8("./examples/doctests/changelog.ported"), max_blocks=100)
>>> cl.find_first_not("mini-buildd@buildd.intra")
(u'Stephan S\xfcrken <absurd@debian.org>', u'1.0.0-2')
>>> cl = Changelog(mini_buildd.misc.open_utf8("./examples/doctests/changelog.oneblock"), max_blocks=100)
>>> cl.find_first_not("mini-buildd@buildd.intra")
(u'Stephan S\xfcrken <absurd@debian.org>', u'1.0.1-1~')
>>> cl = Changelog(mini_buildd.misc.open_utf8("./examples/doctests/changelog.oneblock.ported"), max_blocks=100)
>>> cl.find_first_not("mini-buildd@buildd.intra")
(u'Mini Buildd <mini-buildd@buildd.intra>', u'1.0.1-1~')
Find (author,version+1) of the first changelog block not by given author.
Bases: mini_buildd.misc.TmpDir
Bases: object
Human-readable short title for this Daemon instance.
Get repository, distribution and suite model objects (plus rollback no) from distribtion string.
Bases: debian.debian_support.Version
Generate an ‘external port’ version.
This currently just appends the given default version appendix. For example:
1.2.3 -> 1.2.3~test60+1
Generate an ‘internal port’ version.
Tests for the (recommended) Default layout:
>>> sid_regex = r"~testSID\+[1-9]"
>>> sid_default = "~testSID+1"
>>> sid_exp_regex = r"~testSID\+0"
>>> sid_exp_default = "~testSID+0"
>>> wheezy_regex = r"~test70\+[1-9]"
>>> wheezy_default = "~test70+1"
>>> wheezy_exp_regex = r"~test70\+0"
>>> wheezy_exp_default = "~test70+0"
>>> squeeze_regex = r"~test60\+[1-9]"
>>> squeeze_default = "~test60+1"
>>> squeeze_exp_regex = r"~test60\+0"
>>> squeeze_exp_default = "~test60+0"
sid->wheezy ports:
>>> DebianVersion("1.2.3-1~testSID+1").gen_internal_port(sid_regex, wheezy_default)
u'1.2.3-1~test70+1'
>>> DebianVersion("1.2.3-1~testSID+4").gen_internal_port(sid_regex, wheezy_default)
u'1.2.3-1~test70+4'
>>> DebianVersion("1.2.3-1~testSID+4fud15").gen_internal_port(sid_regex, wheezy_default)
u'1.2.3-1~test70+4fud15'
>>> DebianVersion("1.2.3-1~testSID+0").gen_internal_port(sid_exp_regex, wheezy_exp_default)
u'1.2.3-1~test70+0'
>>> DebianVersion("1.2.3-1~testSID+0exp2").gen_internal_port(sid_exp_regex, wheezy_exp_default)
u'1.2.3-1~test70+0exp2'
wheezy->squeeze ports:
>>> DebianVersion("1.2.3-1~test70+1").gen_internal_port(wheezy_regex, squeeze_default)
u'1.2.3-1~test60+1'
>>> DebianVersion("1.2.3-1~test70+4").gen_internal_port(wheezy_regex, squeeze_default)
u'1.2.3-1~test60+4'
>>> DebianVersion("1.2.3-1~test70+4fud15").gen_internal_port(wheezy_regex, squeeze_default)
u'1.2.3-1~test60+4fud15'
>>> DebianVersion("1.2.3-1~test70+0").gen_internal_port(wheezy_exp_regex, squeeze_exp_default)
u'1.2.3-1~test60+0'
>>> DebianVersion("1.2.3-1~test70+0exp2").gen_internal_port(wheezy_exp_regex, squeeze_exp_default)
u'1.2.3-1~test60+0exp2'
No version restrictions: just add default version
>>> DebianVersion("1.2.3-1").gen_internal_port(".*", "~port+1")
u'1.2.3-1~port+1'
Generate an ‘internal rebuild’ version.
If the version is not already a rebuild version, just append the rebuild appendix, otherwise replace the old one. For example:
1.2.3 -> 1.2.3+rebuilt20130215100453
1.2.3+rebuilt20130215100453 -> 1.2.3+rebuilt20130217120517
Code samples:
>>> regex = r"^1\.2\.3\+rebuilt{s}$".format(s=DebianVersion.stamp_regex())
>>> bool(re.match(regex, DebianVersion("1.2.3").gen_internal_rebuild()))
True
>>> bool(re.match(regex, DebianVersion("1.2.3+rebuilt20130215100453").gen_internal_rebuild()))
True
Bases: mini_buildd.misc.TmpDir
Bases: object
Hold/manage all gnupg keyrings (for remotes and all repository uploaders).
mini-buildd ‘daemon engine’ run.
Bases: object
SMTP creds string parser. Format “USER:PASSWORD@smtp|ssmtp://HOST:PORT”.
>>> d = SMTPCreds(":@smtp://localhost:25")
>>> (d.user, d.password, d.protocol, d.host, d.port)
(u'', u'', u'smtp', u'localhost', 25)
>>> d = SMTPCreds("kuh:sa:ck@smtp://colahost:44")
>>> (d.user, d.password, d.protocol, d.host, d.port)
(u'kuh', u'sa:ck', u'smtp', u'colahost', 44)
Configure django.
This method creates once django’s SECRET_KEY and/or returns it.
Parameters: | home (string) – mini-buildd’s home directory. |
---|---|
Returns: | string – the (created) key. |
Pseudo-configure django. Use this where you need mini-buildd’s model classes, but no actual instance.
Example: Sphinx doc creation, API clients for unpickling model instances.
Bases: pyftpdlib.handlers.FTPHandler
Make any incoming file read-only as soon as it arrives; avoids overriding uploads of the same file.
Bases: object
Tool collection for some extra incoming directory handling.
Remove cruft files from incoming.
Remove all files from list of files not mentioned in a changes file.
Re-queue all existing changes in incoming.
We must feed the the user uploads first, so the daemon does not get any yet-unknown build results (hence the sorting).
Bases: object
Bases: object
Provide a colon->name mapping for the gpg script-parsable ‘–with-colons’ output.
See /usr/share/doc/gnupg/DETAILS.gz.
fingerprint for ‘fpr’ type
Bases: mini_buildd.gnupg.BaseGnuPG
Bases: mini_buildd.gnupg.BaseGnuPG, mini_buildd.misc.TmpDir
>>> gnupg = TmpGnuPG()
>>> gnupg.gen_secret_key("Key-Type: DSA\nKey-Length: 1024\nName-Real: Üdo Ümlaut\nName-Email: test@key.org")
>>> gnupg.get_first_sec_key().type
u'sec'
>>> gnupg.get_first_sec_key().user_id
u'\xdcdo \xdcmlaut <test@key.org>'
>>> gnupg.get_first_sec_key().key_id
u'...'
>>> gnupg.get_first_sec_key_fingerprint().user_id
u'...'
>>> t = tempfile.NamedTemporaryFile()
>>> t.write("A test file\n")
>>> t.flush()
>>> gnupg.sign(file_name=t.name, identity="test@key.org")
>>> gnupg.verify(t.name)
>>> pub_key = gnupg.get_pub_key(identity="test@key.org")
>>> gnupg.close()
>>> tgnupg = TmpGnuPG()
>>> tgnupg.add_pub_key(pub_key)
>>> tgnupg.verify(t.name)
>>> tgnupg.close()
Bases: cherrypy._cptools.HandlerTool
Run the CherryPy WSGI Web Server.
Parameters: |
|
---|
Bases: object
Helper class to implement an API check.
Inheriting classes must define an __API__ class attribute that should be increased on incompatible changes, and may then check via api_check() method.
Bases: Queue.Queue
Wrapper around Queue to get put() block until <= maxsize tasks are actually done. In Queue.Queue, task_done() is only used together with join().
This way can use the Queue directly to limit the number of actually worked-on items for incoming and builds.
Bases: object
ConfFile generation helper.
>>> ConfFile("/tmp/mini_buildd_test_conf_file", "my_option=7").add("my_2nd_option=42").save()
Bases: object
A mini-buildd distribution string.
>>> d = Distribution("squeeze-test-stable")
>>> d.codename, d.repository, d.suite
(u'squeeze', u'test', u'stable')
>>> d.get()
u'squeeze-test-stable'
>>> d = Distribution("squeeze-test-stable-rollback5")
>>> d.is_rollback
True
>>> d.codename, d.repository, d.suite, d.rollback
(u'squeeze', u'test', u'stable', u'rollback5')
>>> d.get()
u'squeeze-test-stable-rollback5'
>>> d.rollback_no
5
Rollback (int) number: ‘rollback0’ -> 0
Bases: object
Convenience class to parse bind string “hostname:port”
Check that we can bind to the first found addrinfo (not already bound, permissions).
Bases: object
Bases: object
Bases: object
Helper class to implement an internal status.
Inheriting classes must give a stati dict to init.
Get raw (integer) status.
Set status with optional description.
Bases: object
Use with contextlib.closing() to guarantee tmpdir is purged afterwards.
Bases: object
URL with a username attached.
>>> U = UserURL("http://admin@localhost:8066")
>>> (U.username, U.plain, U.full)
(u'admin', u'http://localhost:8066', u'http://admin@localhost:8066')
>>> U = UserURL("http://example.org:8066", "admin")
>>> (U.username, U.plain, U.full)
(u'admin', u'http://example.org:8066', u'http://admin@example.org:8066')
>>> UserURL("http://localhost:8066")
Traceback (most recent call last):
...
Exception: UserURL: No username given
Traceback (most recent call last):
...
Exception: UserURL: No username given
>>> UserURL("http://admin@localhost:8066", "root")
Traceback (most recent call last):
...
Exception: UserURL: Username given in twice, in URL and parameter
Traceback (most recent call last):
...
Exception: UserURL: Username given in twice, in URL and parameter
URL string with username.
URL string without username.
Convert base46 string to unicode.
>>> u = b642u('w5xuaWNvZGUgc3Ryw7xuZw==')
>>> u.__class__.__name__
'unicode'
>>> print(u)
Ünicode strüng
Wrapper around subprocess.call().
>>> call(["echo", "-n", "hallo"])
u'hallo'
>>> call(["id", "-syntax-error"], value_on_error="Kapott")
u'Kapott'
Run sequences of calls with rollback support.
>>> call_sequence([(["echo", "-n", "cmd0"], ["echo", "-n", "rollback cmd0"])])
>>> call_sequence([(["echo", "cmd0"], ["echo", "rollback cmd0"])], rollback_only=True)
Multiprocessing needs shared memory. This may be use to check for misconfigured shm early for better error handling.
Setup logger named ‘dst’ with the same handlers and loglevel as the logger named ‘src’.
Test if the distribution (identified by the codename) has a recent lintian with the ‘–suppress-tags’ option.
Guess the ‘codeversion’ aka the first two digits of a Debian release version; for releases without version, this falls back to the uppercase codename.
Ubuntu just uses YY.MM which we can use as-is.
>>> guess_codeversion({"Origin": "Debian", "Version": "3.1r8", "Codename": "sarge"})
u'31'
>>> guess_codeversion({"Origin": "Debian", "Version": "4.0r9", "Codename": "etch"})
u'40'
>>> guess_codeversion({"Origin": "Debian", "Version": "6.0.6", "Codename": "squeeze"})
u'60'
>>> guess_codeversion({"Origin": "Debian", "Version": "7.0", "Codename": "wheezy"})
u'70'
>>> guess_codeversion({"Origin": "Debian", "Version": "7.1", "Codename": "wheezy"})
u'70'
>>> guess_codeversion({"Origin": "Debian", "Codename": "jessie"})
u'JESSIE'
>>> guess_codeversion({"Origin": "Debian", "Codename": "sid"})
u'SID'
>>> guess_codeversion({"Origin": "Ubuntu", "Version": "12.10", "Codename": "quantal"})
u'1210'
Helper to get any hash from file contents.
Note
Needed for python 2.x only. For 3.x, just use ‘exist_ok’ parameter.
Generate a package status line.
Create sbuild’s internal key if needed (sbuild needs this one-time call, but does not handle it itself).
>>> sose_call(["echo", "-n", "hallo"])
u'hallo'
>>> sose_call(["ls", "__no_such_file__"])
Traceback (most recent call last):
...
Exception: SoSe call failed (ret=2): ls __no_such_file__
Traceback (most recent call last):
...
Exception: SoSe call failed (ret=2): ls __no_such_file__
Strip the epoch from a version string.
Substitue placeholders in string from a dict.
>>> subst_placeholders("Repoversionstring: %IDENTITY%%CODEVERSION%", { "IDENTITY": "test", "CODEVERSION": "60" })
u'Repoversionstring: test60'
python 2.6 compat for timedelta.total_seconds() from python >= 2.7.
Convert unicode string to base46.
>>> b64 = u2b64("Ünicode strüng")
>>> b64.__class__.__name__
'str'
>>> b64
'w5xuaWNvZGUgc3Ryw7xuZw=='
Bases: mini_buildd.misc.API
Subset of ‘Package’ for pickled statistics.
Bases: mini_buildd.misc.Status
Install package to repository.
This may throw on error, and if so, no changes should be done to the repo.
Close package. Just continue on errors, but log them; guarantee to remove it from the packages dict.
Run reprepro commands.
Bases: object
Abstraction to reprepro repository commands.
Locking
This implicitly provides a locking mechanism to avoid parallel calls to the same repository from mini-buildd itself. This rules out any failed call due to reprepro locking errors in the first place.
For the case that someone else is using reprepro manually, we also always run it with ‘–waitforlock’.
Bases: django.views.generic.base.TemplateView
This just adds repositories to context.
Bases: django.core.handlers.wsgi.WSGIHandler
This class represents mini-buildd’s web application.
Bulk-remove all model instances that might have produced cruft on the system (i.e., outside mini-buildd’s home).
This method sets the password for the administrator.
Parameters: | password (string) – The password to use. |
---|