mirror of
https://git.launchpad.net/ubuntu-dev-tools
synced 2025-03-13 08:01:09 +00:00
Merge branch 'megamerge_request' of git+ssh://git.launchpad.net/~ddstreet/ubuntu-dev-tools/+git/ubuntu-dev-tools
MR: https://code.launchpad.net/~ddstreet/ubuntu-dev-tools/+git/ubuntu-dev-tools/+merge/375292 Signed-off-by: Mattia Rizzolo <mattia@debian.org>
This commit is contained in:
commit
87f226258a
@ -36,11 +36,13 @@ from ubuntutools.builder import get_builder
|
|||||||
from ubuntutools.lp.lpapicache import (Launchpad, Distribution,
|
from ubuntutools.lp.lpapicache import (Launchpad, Distribution,
|
||||||
SeriesNotFoundException,
|
SeriesNotFoundException,
|
||||||
PackageNotFoundException)
|
PackageNotFoundException)
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.misc import (system_distribution, vendor_to_distroinfo,
|
from ubuntutools.misc import (system_distribution, vendor_to_distroinfo,
|
||||||
codename_to_distribution)
|
codename_to_distribution)
|
||||||
from ubuntutools.question import YesNoQuestion
|
from ubuntutools.question import YesNoQuestion
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def error(msg):
|
def error(msg):
|
||||||
Logger.error(msg)
|
Logger.error(msg)
|
||||||
@ -48,7 +50,7 @@ def error(msg):
|
|||||||
|
|
||||||
|
|
||||||
def check_call(cmd, *args, **kwargs):
|
def check_call(cmd, *args, **kwargs):
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
ret = subprocess.call(cmd, *args, **kwargs)
|
ret = subprocess.call(cmd, *args, **kwargs)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
error('%s returned %d.' % (cmd[0], ret))
|
error('%s returned %d.' % (cmd[0], ret))
|
||||||
@ -302,7 +304,7 @@ def orig_needed(upload, workdir, pkg):
|
|||||||
not headers['content-location'].startswith('https://launchpadlibrarian.net')):
|
not headers['content-location'].startswith('https://launchpadlibrarian.net')):
|
||||||
return True
|
return True
|
||||||
except HttpLib2Error as e:
|
except HttpLib2Error as e:
|
||||||
Logger.info(e)
|
Logger.debug(e)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
4
bitesize
4
bitesize
@ -28,7 +28,9 @@ from launchpadlib.launchpad import Launchpad
|
|||||||
from launchpadlib.errors import HTTPError
|
from launchpadlib.errors import HTTPError
|
||||||
|
|
||||||
from ubuntutools.config import UDTConfig
|
from ubuntutools.config import UDTConfig
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def error_out(msg):
|
def error_out(msg):
|
||||||
|
5
debian/changelog
vendored
5
debian/changelog
vendored
@ -12,6 +12,11 @@ ubuntu-dev-tools (0.175) UNRELEASED; urgency=medium
|
|||||||
[ Dan Streetman ]
|
[ Dan Streetman ]
|
||||||
* tests/pylint.conf: use jobs=0 to speed up tests.
|
* tests/pylint.conf: use jobs=0 to speed up tests.
|
||||||
* submittodebian: use a context manager while opening a file.
|
* submittodebian: use a context manager while opening a file.
|
||||||
|
* d/control: add dependency on python3-lazr.restfulclient.
|
||||||
|
* Big refactor/rewrite of the whole archive.py module, together with a
|
||||||
|
restracturing of all the pull-pkg-* commands.
|
||||||
|
* Unify the logging using the standard python logging module, and remove the
|
||||||
|
local ubuntutools.logger module.
|
||||||
|
|
||||||
-- Mattia Rizzolo <mattia@debian.org> Mon, 28 Oct 2019 14:32:20 +0100
|
-- Mattia Rizzolo <mattia@debian.org> Mon, 28 Oct 2019 14:32:20 +0100
|
||||||
|
|
||||||
|
9
debian/control
vendored
9
debian/control
vendored
@ -104,7 +104,13 @@ Description: useful tools for Ubuntu developers
|
|||||||
a Debian package and its immediate parent to generate a debdiff.
|
a Debian package and its immediate parent to generate a debdiff.
|
||||||
- pull-debian-source - downloads the latest source package available in
|
- pull-debian-source - downloads the latest source package available in
|
||||||
Debian of a package.
|
Debian of a package.
|
||||||
- pull-lp-source - downloads latest source package from Launchpad.
|
- pull-lp-source - downloads source package from Launchpad.
|
||||||
|
- pull-lp-debs - downloads debs package(s) from Launchpad.
|
||||||
|
- pull-lp-ddebs - downloads dbgsym/ddebs package(s) from Launchpad.
|
||||||
|
- pull-lp-udebs - downloads udebs package(s) from Launchpad.
|
||||||
|
- pull-debian-* - same as pull-lp-* but for Debian packages.
|
||||||
|
- pull-uca-* - same as pull-lp-* but for Ubuntu Cloud Archive packages.
|
||||||
|
- pull-pkg - common script that provides above pull-* functionality.
|
||||||
- pull-revu-source - downloads the latest source package from REVU
|
- pull-revu-source - downloads the latest source package from REVU
|
||||||
- requestbackport - file a backporting request.
|
- requestbackport - file a backporting request.
|
||||||
- requestsync - files a sync request with Debian changelog and rationale.
|
- requestsync - files a sync request with Debian changelog and rationale.
|
||||||
@ -132,6 +138,7 @@ Depends:
|
|||||||
python3-distro-info,
|
python3-distro-info,
|
||||||
python3-httplib2,
|
python3-httplib2,
|
||||||
python3-launchpadlib,
|
python3-launchpadlib,
|
||||||
|
python3-lazr.restfulclient,
|
||||||
sensible-utils,
|
sensible-utils,
|
||||||
${misc:Depends},
|
${misc:Depends},
|
||||||
${python3:Depends},
|
${python3:Depends},
|
||||||
|
1
doc/pull-debian-ddebs.1
Symbolic link
1
doc/pull-debian-ddebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-debian-debs.1
Symbolic link
1
doc/pull-debian-debs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
@ -1,89 +0,0 @@
|
|||||||
.\" Copyright (C) 2010-2011, Stefano Rivera <stefanor@ubuntu.com>
|
|
||||||
.\"
|
|
||||||
.\" Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
.\" purpose with or without fee is hereby granted, provided that the above
|
|
||||||
.\" copyright notice and this permission notice appear in all copies.
|
|
||||||
.\"
|
|
||||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
.\" AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
.\" OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
.\" PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
.TH PULL\-DEBIAN\-SOURCE "1" "22 January 2011" "ubuntu\-dev\-tools"
|
|
||||||
|
|
||||||
.SH NAME
|
|
||||||
pull\-debian\-source \- download and extract a source package from Debian
|
|
||||||
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B pull\-debian\-source \fR[\fIoptions\fR] <\fIsource package\fR>
|
|
||||||
[\fIrelease\fR|\fIversion\fR]
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
\fBpull\-debian\-source\fR downloads and extracts the specified
|
|
||||||
\fIversion\fR of \fIsource package\fR, or the latest version in the
|
|
||||||
specified Debian \fIrelease\fR.
|
|
||||||
.P
|
|
||||||
\fBpull\-debian\-source\fR will try the preferred mirror, default
|
|
||||||
mirror, security mirror, and fall back to \fBLaunchpad\fR or
|
|
||||||
\fBsnapshot.debian.org\fR, in search of the requested version.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
.TP
|
|
||||||
.I source package
|
|
||||||
The source package to download from Debian.
|
|
||||||
.TP
|
|
||||||
.I release
|
|
||||||
The release to download the source package from. Defaults to
|
|
||||||
\fBunstable\fR.
|
|
||||||
.TP
|
|
||||||
.I version
|
|
||||||
The specific version of the package to download.
|
|
||||||
.TP
|
|
||||||
.BR \-d ", " \-\-download\-only
|
|
||||||
Do not extract the source package.
|
|
||||||
.TP
|
|
||||||
.B \-m \fIDEBIAN_MIRROR\fR, \fB\-\-mirror\fR=\fIDEBIAN_MIRROR\fR
|
|
||||||
Use the specified mirror.
|
|
||||||
Should be in the form \fBhttp://ftp.debian.org/debian\fR.
|
|
||||||
If the package isn't found on this mirror, \fBpull\-debian\-source\fR
|
|
||||||
will fall back to the default mirror.
|
|
||||||
.TP
|
|
||||||
.B \-s \fIDEBSEC_MIRROR\fR, \fB\-\-security\-mirror\fR=\fIDEBSEC_MIRROR\fR
|
|
||||||
Use the specified mirror.
|
|
||||||
Should be in the form \fBhttp://security.debian.org\fR.
|
|
||||||
If the package isn't found on this mirror, \fBpull\-debian\-source\fR
|
|
||||||
will fall back to the default mirror.
|
|
||||||
.TP
|
|
||||||
.B \-\-no\-conf
|
|
||||||
Do not read any configuration files, or configuration from environment
|
|
||||||
variables.
|
|
||||||
.TP
|
|
||||||
.BR \-h ", " \-\-help
|
|
||||||
Display the usage instructions and exit.
|
|
||||||
|
|
||||||
.SH ENVIRONMENT
|
|
||||||
All of the \fBCONFIGURATION VARIABLES\fR below are also supported as
|
|
||||||
environment variables.
|
|
||||||
Variables in the environment take precedence to those in configuration
|
|
||||||
files.
|
|
||||||
|
|
||||||
.SH CONFIGURATION VARIABLES
|
|
||||||
The following variables can be set in the environment or in
|
|
||||||
.BR ubuntu\-dev\-tools (5)
|
|
||||||
configuration files.
|
|
||||||
In each case, the script\-specific variable takes precedence over the
|
|
||||||
package\-wide variable.
|
|
||||||
.TP
|
|
||||||
.BR PULL_DEBIAN_SOURCE_DEBIAN_MIRROR ", " UBUNTUTOOLS_DEBIAN_MIRROR
|
|
||||||
The default value for \fB\-\-mirror\fR.
|
|
||||||
.TP
|
|
||||||
.BR PULL_DEBIAN_SOURCE_DEBSEC_MIRROR ", " UBUNTUTOOLS_DEBSEC_MIRROR
|
|
||||||
The default value for \fB\-\-security\-mirror\fR.
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR dget (1),
|
|
||||||
.BR pull\-debian\-debdiff (1),
|
|
||||||
.BR pull\-lp\-source (1),
|
|
||||||
.BR ubuntu\-dev\-tools (5)
|
|
1
doc/pull-debian-source.1
Symbolic link
1
doc/pull-debian-source.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-debian-udebs.1
Symbolic link
1
doc/pull-debian-udebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-lp-ddebs.1
Symbolic link
1
doc/pull-lp-ddebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-lp-debs.1
Symbolic link
1
doc/pull-lp-debs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
@ -1,79 +0,0 @@
|
|||||||
.TH PULL\-LP\-SOURCE "1" "4 August 2008" "ubuntu-dev-tools"
|
|
||||||
|
|
||||||
.SH NAME
|
|
||||||
pull\-lp\-source \- download a source package from Launchpad
|
|
||||||
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B pull\-lp\-source \fR[\fIoptions\fR]\fB \fBsource package\fR
|
|
||||||
[\fIrelease\fR|\fIversion\fR]
|
|
||||||
|
|
||||||
.SH DESCRIPTION
|
|
||||||
\fBpull\-lp\-source\fR downloads and extracts the specified
|
|
||||||
\fIversion\fR of <\fBsource package\fR> from Launchpad, or the latest
|
|
||||||
version of the specified \fIrelease\fR.
|
|
||||||
To request a version from a particular pocket say
|
|
||||||
\fIrelease\fB\-\fIpocket\fR (with a magic \fB\-release\fR for only the
|
|
||||||
release pocket).
|
|
||||||
If no \fIversion\fR or \fIrelease\fR is specified, the latest version in
|
|
||||||
the development release will be downloaded.
|
|
||||||
|
|
||||||
.SH OPTIONS
|
|
||||||
Listed below are the command line options for pull\-lp\-source:
|
|
||||||
.TP
|
|
||||||
.B source package
|
|
||||||
This is the source package that you would like to be downloaded from Launchpad.
|
|
||||||
.TP
|
|
||||||
.B version
|
|
||||||
This is the version of the source package to be downloaded.
|
|
||||||
.TP
|
|
||||||
.B release
|
|
||||||
This is the release that you would like the source package to be downloaded from.
|
|
||||||
This value defaults to the current development release.
|
|
||||||
.TP
|
|
||||||
.BR \-h ", " \-\-help
|
|
||||||
Display a help message and exit.
|
|
||||||
.TP
|
|
||||||
.BR \-d ", " \-\-download\-only
|
|
||||||
Do not extract the source package.
|
|
||||||
.TP
|
|
||||||
.B \-m \fIUBUNTU_MIRROR\fR, \fB\-\-mirror\fR=\fIUBUNTU_MIRROR\fR
|
|
||||||
Use the specified Ubuntu mirror.
|
|
||||||
Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR.
|
|
||||||
If the package isn't found on this mirror, \fBpull\-lp\-source\fR will
|
|
||||||
fall back to Launchpad, as its name implies.
|
|
||||||
.TP
|
|
||||||
.B \-\-no\-conf
|
|
||||||
Do not read any configuration files, or configuration from environment
|
|
||||||
variables.
|
|
||||||
|
|
||||||
.SH ENVIRONMENT
|
|
||||||
All of the \fBCONFIGURATION VARIABLES\fR below are also supported as
|
|
||||||
environment variables.
|
|
||||||
Variables in the environment take precedence to those in configuration
|
|
||||||
files.
|
|
||||||
.TP
|
|
||||||
.B
|
|
||||||
DIST
|
|
||||||
Specifies the default target.
|
|
||||||
|
|
||||||
.SH CONFIGURATION VARIABLES
|
|
||||||
The following variables can be set in the environment or in
|
|
||||||
.BR ubuntu\-dev\-tools (5)
|
|
||||||
configuration files.
|
|
||||||
In each case, the script\-specific variable takes precedence over the
|
|
||||||
package\-wide variable.
|
|
||||||
.TP
|
|
||||||
.BR PULL_LP_SOURCE_UBUNTU_MIRROR ", " UBUNTUTOOLS_UBUNTU_MIRROR
|
|
||||||
The default value for \fB\-\-mirror\fR.
|
|
||||||
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR dget (1),
|
|
||||||
.BR pull\-debian\-source (1),
|
|
||||||
.BR pull\-debian\-debdiff (1),
|
|
||||||
.BR ubuntu\-dev\-tools (5)
|
|
||||||
|
|
||||||
.SH AUTHOR
|
|
||||||
.PP
|
|
||||||
\fBpull\-lp\-source\fR and this manual page were written by Iain Lane
|
|
||||||
<iain@orangesquash.org.uk>.
|
|
||||||
Both are released under the GNU General Public License, version 3 or later.
|
|
1
doc/pull-lp-source.1
Symbolic link
1
doc/pull-lp-source.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-lp-udebs.1
Symbolic link
1
doc/pull-lp-udebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
146
doc/pull-pkg.1
Normal file
146
doc/pull-pkg.1
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
.TH PULL\-PKG "1" "28 August 2017" "ubuntu-dev-tools"
|
||||||
|
|
||||||
|
.SH NAME
|
||||||
|
pull\-pkg \- download a package for Debian, Ubuntu, UCA, or a PPA
|
||||||
|
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B pull\-pkg \fR[\fIoptions\fR]\fR <\fIpackage name\fR>
|
||||||
|
[\fIrelease\fR|\fIversion\fR]
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
\fBpull\-pkg\fR downloads the specified \fIversion\fR of
|
||||||
|
<\fIpackage name\fR>, or the latest version from the
|
||||||
|
specified \fIrelease\fR. To request a version from
|
||||||
|
a particular pocket say \fIrelease\fB\-\fIpocket\fR (with a magic
|
||||||
|
\fB\-release\fR for only the release pocket).
|
||||||
|
If no \fIversion\fR or \fIrelease\fR is specified, the latest version in
|
||||||
|
the development release will be downloaded.
|
||||||
|
|
||||||
|
There are convenience scripts that set pull type and distribution
|
||||||
|
appropriately: these are
|
||||||
|
\fBpull\-lp\-source\fR, \fBpull\-lp\-debs\fR, \fBpull\-lp\-ddebs\fR,
|
||||||
|
and \fBpull\-lp\-udebs\fR, which all pull Ubuntu packages;
|
||||||
|
\fBpull\-debian\-source\fR, \fBpull\-debian\-debs\fR, \fBpull\-debian\-ddebs\fR,
|
||||||
|
and \fBpull\-debian\-udebs\fR, which all pull Debian packages;
|
||||||
|
\fBpull\-uca\-source\fR, \fBpull\-uca\-debs\fR, \fBpull\-uca\-ddebs\fR,
|
||||||
|
and \fBpull\-uca\-udebs\fR, which all pull Ubuntu Cloud Archive packages;
|
||||||
|
and \fBpull\-ppa\-source\fR, \fBpull\-ppa\-debs\fR, \fBpull\-ppa\-ddebs\fR,
|
||||||
|
and \fBpull\-ppa\-udebs\fR, which all pull from a specified Personal Package
|
||||||
|
Archive on Launchpad. Each script pulls the file type in its name, i.e.
|
||||||
|
\fIsource\fR, \fIdebs\fR, \fIddebs\fR, or \fIudebs\fR.
|
||||||
|
|
||||||
|
.SH OPTIONS
|
||||||
|
Listed below are the command line options for pull\-pkg:
|
||||||
|
.TP
|
||||||
|
.I package name
|
||||||
|
This is name of the package to downloaded.
|
||||||
|
You can use either the source package name, or binary package name.
|
||||||
|
.TP
|
||||||
|
.I version
|
||||||
|
This is the version of the package to downloaded.
|
||||||
|
.TP
|
||||||
|
.I release
|
||||||
|
This is the release to downloaded from.
|
||||||
|
For debian, you can use either the release name like \fBjessie\fR
|
||||||
|
or \fBsid\fR, or you can use the special release names \fBunstable\fR,
|
||||||
|
\fBstable\fR, or \fBtesting\fR.
|
||||||
|
For ubuntu, you can use either the release name like \fBxenial\fR
|
||||||
|
or the release-pocket like \fBxenial-proposed\fR.
|
||||||
|
For ubuntu cloud archive (uca) you can use either the uca release
|
||||||
|
name like \fBmitaka\fR or the ubuntu and uca release names like
|
||||||
|
\fBtrusty-mitaka\fR. Defaults to the current development release.
|
||||||
|
.TP
|
||||||
|
.BR \-h ", " \-\-help
|
||||||
|
Display a help message and exit.
|
||||||
|
.TP
|
||||||
|
.BR \-v ", " \-\-verbose
|
||||||
|
Be verbose about what is being done.
|
||||||
|
.TP
|
||||||
|
.BR \-d ", " \-\-download\-only
|
||||||
|
Do not extract the source package (applies only to source packages).
|
||||||
|
.TP
|
||||||
|
.B \-m \fIMIRROR\fR, \fB\-\-mirror\fR=\fIMIRROR\fR
|
||||||
|
Use the specified mirror server.
|
||||||
|
Should be in the form \fBhttp://archive.ubuntu.com/ubuntu\fR or
|
||||||
|
\fBhttp://deb.debian.org/debian\fR. If not specified or if the
|
||||||
|
package is not found on the specified mirror, this will fall
|
||||||
|
back to the default mirror(s) and/or mirror(s) from environment
|
||||||
|
variables, and then will fall back to Launchpad or Debian Snapshot.
|
||||||
|
This can be specified multiple times to try multiple mirrors.
|
||||||
|
.TP
|
||||||
|
.B \-\-no\-conf
|
||||||
|
Do not use mirrors from the default configuration, or from
|
||||||
|
any environment variables.
|
||||||
|
.TP
|
||||||
|
.B \-a \fIARCH\fR, \fB\-\-arch\fR=\fIARCH\fR
|
||||||
|
Get binary packages from the \fIARCH\fR architecture.
|
||||||
|
Defaults to the local architecture, if it can be deteected.
|
||||||
|
.TP
|
||||||
|
.B \-p \fIPULL\fR, \fB\-\-pull\fR=\fIPULL\fR
|
||||||
|
What to pull: \fBsource\fR, \fBdebs\fR, \fBddebs\fR, \fBudebs\fR,
|
||||||
|
or \fBlist\fR. The \fBlist\fR action only lists all a package's
|
||||||
|
source and binary files, but does not actually download any.
|
||||||
|
Defaults to \fBsource\fR.
|
||||||
|
.TP
|
||||||
|
.B \-D \fIDISTRO\fR, \fB\-\-distro\fR=\fIDISTRO\fR
|
||||||
|
Pull from: \fBdebian\fR, \fBuca\fR, \fBubuntu\fR, or a \fBppa\fR.
|
||||||
|
\fBlp\fR can be used instead of \fBubuntu\fR.
|
||||||
|
Any string containing \fBcloud\fR can be used instead of \fBuca\fR.
|
||||||
|
If pulling from a ppa, you must specify the PPA. Deafults to \fBubuntu\fR.
|
||||||
|
.TP
|
||||||
|
.B \-\-ppa\fR=ppa:\fIUSER/NAME\fR
|
||||||
|
Applies only when \fBdistro\fR is \fIppa\fR. Can be provided either as
|
||||||
|
a value to the \fB\-\-ppa\fR option parameter, or as a plain option
|
||||||
|
(like \fIrelease\fR or \fIversion\fR). When specified as a plain option,
|
||||||
|
the form must be \fBppa:USER/NAME\fR; when specified as a value to the
|
||||||
|
\fB\-\-ppa\fR option parameter, the leading \fBppa:\fR is optional.
|
||||||
|
|
||||||
|
.SH ENVIRONMENT
|
||||||
|
All of the \fBCONFIGURATION VARIABLES\fR below are also supported as
|
||||||
|
environment variables.
|
||||||
|
Variables in the environment take precedence to those in configuration
|
||||||
|
files.
|
||||||
|
|
||||||
|
.SH CONFIGURATION VARIABLES
|
||||||
|
The following variables can be set in the environment or in
|
||||||
|
.BR ubuntu\-dev\-tools (5)
|
||||||
|
configuration files.
|
||||||
|
In each case, the script\-specific variable takes precedence over the
|
||||||
|
package\-wide variable.
|
||||||
|
.TP
|
||||||
|
.BR UBUNTUTOOLS_UBUNTU_MIRROR
|
||||||
|
The default mirror.
|
||||||
|
.TP
|
||||||
|
.BR PULL_PKG_UBUNTU_MIRROR
|
||||||
|
The default mirror when using the \fBpull\-pkg\fR script.
|
||||||
|
.TP
|
||||||
|
.BR PULL_[LP|DEBIAN|PPA|UCA]_[SOURCE|DEBS|DDEBS|UDEBS]_MIRROR
|
||||||
|
The default mirror when using the associated script.
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR dget (1),
|
||||||
|
.BR pull\-lp\-source (1),
|
||||||
|
.BR pull\-lp\-debs (1),
|
||||||
|
.BR pull\-lp\-ddebs (1),
|
||||||
|
.BR pull\-lp\-udebs (1),
|
||||||
|
.BR pull\-debian\-source (1),
|
||||||
|
.BR pull\-debian\-debs (1),
|
||||||
|
.BR pull\-debian\-ddebs (1),
|
||||||
|
.BR pull\-debian\-udebs (1),
|
||||||
|
.BR pull\-ppa\-source (1),
|
||||||
|
.BR pull\-ppa\-debs (1),
|
||||||
|
.BR pull\-ppa\-ddebs (1),
|
||||||
|
.BR pull\-ppa\-udebs (1),
|
||||||
|
.BR pull\-uca\-source (1),
|
||||||
|
.BR pull\-uca\-debs (1),
|
||||||
|
.BR pull\-uca\-ddebs (1),
|
||||||
|
.BR pull\-uca\-udebs (1),
|
||||||
|
.BR pull\-debian\-debdiff (1),
|
||||||
|
.BR ubuntu\-dev\-tools (5)
|
||||||
|
|
||||||
|
.SH AUTHOR
|
||||||
|
.PP
|
||||||
|
\fBpull\-pkg\fR was written by Dan Streetman <ddstreet@canonical.com>,
|
||||||
|
based on the original \fBpull\-lp\-source\fR; it and this manual page
|
||||||
|
were written by Iain Lane <iain@orangesquash.org.uk>.
|
||||||
|
All are released under the GNU General Public License, version 3 or later.
|
1
doc/pull-ppa-ddebs.1
Symbolic link
1
doc/pull-ppa-ddebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-ppa-debs.1
Symbolic link
1
doc/pull-ppa-debs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-ppa-source.1
Symbolic link
1
doc/pull-ppa-source.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-ppa-udebs.1
Symbolic link
1
doc/pull-ppa-udebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-uca-ddebs.1
Symbolic link
1
doc/pull-uca-ddebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-uca-debs.1
Symbolic link
1
doc/pull-uca-debs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-uca-source.1
Symbolic link
1
doc/pull-uca-source.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
1
doc/pull-uca-udebs.1
Symbolic link
1
doc/pull-uca-udebs.1
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
pull-pkg.1
|
11
grep-merges
11
grep-merges
@ -27,6 +27,9 @@ from httplib2 import Http, HttpLib2Error
|
|||||||
|
|
||||||
import ubuntutools.misc
|
import ubuntutools.misc
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = optparse.OptionParser(
|
parser = optparse.OptionParser(
|
||||||
@ -52,11 +55,11 @@ def main():
|
|||||||
try:
|
try:
|
||||||
headers, page = Http().request(url)
|
headers, page = Http().request(url)
|
||||||
except HttpLib2Error as e:
|
except HttpLib2Error as e:
|
||||||
print(str(e), file=sys.stderr)
|
Logger.exception(e)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if headers.status != 200:
|
if headers.status != 200:
|
||||||
print("%s: %s %s" % (url, headers.status, headers.reason),
|
Logger.error("%s: %s %s" % (url, headers.status,
|
||||||
file=sys.stderr)
|
headers.reason))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for merge in json.loads(page):
|
for merge in json.loads(page):
|
||||||
@ -71,7 +74,7 @@ def main():
|
|||||||
pretty_uploader = '{} {}'.format(author, uploader)
|
pretty_uploader = '{} {}'.format(author, uploader)
|
||||||
if (match is None or match in package or match in author
|
if (match is None or match in package or match in author
|
||||||
or match in uploader or match in teams):
|
or match in uploader or match in teams):
|
||||||
print('%s\t%s' % (package, pretty_uploader))
|
Logger.info('%s\t%s' % (package, pretty_uploader))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
25
hugdaylist
25
hugdaylist
@ -36,6 +36,9 @@ from launchpadlib.launchpad import Launchpad
|
|||||||
|
|
||||||
from ubuntutools.lp.libsupport import translate_web_api
|
from ubuntutools.lp.libsupport import translate_web_api
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def check_args():
|
def check_args():
|
||||||
howmany = -1
|
howmany = -1
|
||||||
@ -57,8 +60,7 @@ def check_args():
|
|||||||
|
|
||||||
# Check that we have an URL.
|
# Check that we have an URL.
|
||||||
if not args:
|
if not args:
|
||||||
print("An URL pointing to a Launchpad bug list is required.",
|
Logger.error("An URL pointing to a Launchpad bug list is required.")
|
||||||
file=sys.stderr)
|
|
||||||
opt_parser.print_help()
|
opt_parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
@ -87,15 +89,14 @@ def main():
|
|||||||
if len(url.split("?", 1)) == 2:
|
if len(url.split("?", 1)) == 2:
|
||||||
# search options not supported, because there is no mapping web ui
|
# search options not supported, because there is no mapping web ui
|
||||||
# options <-> API options
|
# options <-> API options
|
||||||
print("Options in url are not supported, url: %s" % url,
|
Logger.error("Options in url are not supported, url: %s" % url)
|
||||||
file=sys.stderr)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
launchpad = None
|
launchpad = None
|
||||||
try:
|
try:
|
||||||
launchpad = Launchpad.login_with("ubuntu-dev-tools", 'production')
|
launchpad = Launchpad.login_with("ubuntu-dev-tools", 'production')
|
||||||
except IOError as error:
|
except IOError as error:
|
||||||
print(error)
|
Logger.exception(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
api_url = translate_web_api(url, launchpad)
|
api_url = translate_web_api(url, launchpad)
|
||||||
@ -104,8 +105,8 @@ def main():
|
|||||||
except Exception as error:
|
except Exception as error:
|
||||||
response = getattr(error, "response", {})
|
response = getattr(error, "response", {})
|
||||||
if response.get("status", None) == "404":
|
if response.get("status", None) == "404":
|
||||||
print(("The URL at '%s' does not appear to be a valid url to a "
|
Logger.error("The URL at '%s' does not appear to be a "
|
||||||
"product") % url, file=sys.stderr)
|
"valid url to a product" % url)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
@ -113,12 +114,12 @@ def main():
|
|||||||
bug_list = [b for b in product.searchTasks() if filter_unsolved(b)]
|
bug_list = [b for b in product.searchTasks() if filter_unsolved(b)]
|
||||||
|
|
||||||
if not bug_list:
|
if not bug_list:
|
||||||
print("Bug list of %s is empty." % url)
|
Logger.info("Bug list of %s is empty." % url)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
if howmany == -1:
|
if howmany == -1:
|
||||||
howmany = len(bug_list)
|
howmany = len(bug_list)
|
||||||
|
|
||||||
print("""
|
Logger.info("""
|
||||||
## ||<rowbgcolor="#CCFFCC"> This task is done || somebody || ||
|
## ||<rowbgcolor="#CCFFCC"> This task is done || somebody || ||
|
||||||
## ||<rowbgcolor="#FFFFCC"> This task is assigned || somebody || <status> ||
|
## ||<rowbgcolor="#FFFFCC"> This task is assigned || somebody || <status> ||
|
||||||
## ||<rowbgcolor="#FFEBBB"> This task isn't || ... || ||
|
## ||<rowbgcolor="#FFEBBB"> This task isn't || ... || ||
|
||||||
@ -128,13 +129,13 @@ def main():
|
|||||||
|
|
||||||
for i in list(bug_list)[:howmany]:
|
for i in list(bug_list)[:howmany]:
|
||||||
bug = i.bug
|
bug = i.bug
|
||||||
print('||<rowbgcolor="#FFEBBB"> [%s %s] || %s || ||'
|
Logger.info('||<rowbgcolor="#FFEBBB"> [%s %s] || %s || ||' %
|
||||||
% (bug.web_link, bug.id, bug.title))
|
(bug.web_link, bug.id, bug.title))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Aborted.", file=sys.stderr)
|
Logger.error("Aborted.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -30,7 +30,9 @@ import webbrowser
|
|||||||
from launchpadlib.launchpad import Launchpad
|
from launchpadlib.launchpad import Launchpad
|
||||||
|
|
||||||
from ubuntutools.config import UDTConfig
|
from ubuntutools.config import UDTConfig
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import debianbts
|
import debianbts
|
||||||
@ -134,7 +136,7 @@ def main():
|
|||||||
d_watch = u_bug.addWatch(remote_bug=bug_num, bug_tracker=lp_debbugs)
|
d_watch = u_bug.addWatch(remote_bug=bug_num, bug_tracker=lp_debbugs)
|
||||||
d_task.bug_watch = d_watch
|
d_task.bug_watch = d_watch
|
||||||
d_task.lp_save()
|
d_task.lp_save()
|
||||||
Logger.normal("Opened %s", u_bug.web_link)
|
Logger.info("Opened %s", u_bug.web_link)
|
||||||
if not options.browserless:
|
if not options.browserless:
|
||||||
webbrowser.open(u_bug.web_link)
|
webbrowser.open(u_bug.web_link)
|
||||||
|
|
||||||
|
@ -22,9 +22,12 @@ import sys
|
|||||||
|
|
||||||
from debian.changelog import Changelog
|
from debian.changelog import Changelog
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def usage(exit_code=1):
|
def usage(exit_code=1):
|
||||||
print('''Usage: merge-changelog <left changelog> <right changelog>
|
Logger.info('''Usage: merge-changelog <left changelog> <right changelog>
|
||||||
|
|
||||||
merge-changelog takes two changelogs that once shared a common source,
|
merge-changelog takes two changelogs that once shared a common source,
|
||||||
merges them back together, and prints the merged result to stdout. This
|
merges them back together, and prints the merged result to stdout. This
|
||||||
@ -61,7 +64,7 @@ def merge_changelog(left_changelog, right_changelog):
|
|||||||
|
|
||||||
assert block.version == version
|
assert block.version == version
|
||||||
|
|
||||||
print(str(block).strip(), end='\n\n')
|
Logger.info(str(block).strip() + '\n\n')
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -39,9 +39,11 @@ from distro_info import DebianDistroInfo, UbuntuDistroInfo, DistroDataOutdated
|
|||||||
import ubuntutools.misc
|
import ubuntutools.misc
|
||||||
import ubuntutools.version
|
import ubuntutools.version
|
||||||
from ubuntutools.config import UDTConfig
|
from ubuntutools.config import UDTConfig
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.question import YesNoQuestion
|
from ubuntutools.question import YesNoQuestion
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PbuilderDist(object):
|
class PbuilderDist(object):
|
||||||
def __init__(self, builder):
|
def __init__(self, builder):
|
||||||
@ -103,9 +105,10 @@ class PbuilderDist(object):
|
|||||||
'~/pbuilder/'))
|
'~/pbuilder/'))
|
||||||
|
|
||||||
if 'SUDO_USER' in os.environ:
|
if 'SUDO_USER' in os.environ:
|
||||||
Logger.warn('Running under sudo. '
|
Logger.warning('Running under sudo. '
|
||||||
'This is probably not what you want. '
|
'This is probably not what you want. '
|
||||||
'pbuilder-dist will use sudo itself, when necessary.')
|
'pbuilder-dist will use sudo itself, '
|
||||||
|
'when necessary.')
|
||||||
if os.stat(os.environ['HOME']).st_uid != os.getuid():
|
if os.stat(os.environ['HOME']).st_uid != os.getuid():
|
||||||
Logger.error("You don't own $HOME")
|
Logger.error("You don't own $HOME")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -280,7 +283,7 @@ class PbuilderDist(object):
|
|||||||
codename = debian_info.codename(self.target_distro,
|
codename = debian_info.codename(self.target_distro,
|
||||||
default=self.target_distro)
|
default=self.target_distro)
|
||||||
except DistroDataOutdated as error:
|
except DistroDataOutdated as error:
|
||||||
Logger.warn(error)
|
Logger.warning(error)
|
||||||
if codename in (debian_info.devel(), 'experimental'):
|
if codename in (debian_info.devel(), 'experimental'):
|
||||||
self.enable_security = False
|
self.enable_security = False
|
||||||
self.enable_updates = False
|
self.enable_updates = False
|
||||||
@ -307,7 +310,7 @@ class PbuilderDist(object):
|
|||||||
try:
|
try:
|
||||||
dev_release = self.target_distro == UbuntuDistroInfo().devel()
|
dev_release = self.target_distro == UbuntuDistroInfo().devel()
|
||||||
except DistroDataOutdated as error:
|
except DistroDataOutdated as error:
|
||||||
Logger.warn(error)
|
Logger.warning(error)
|
||||||
dev_release = True
|
dev_release = True
|
||||||
|
|
||||||
if dev_release:
|
if dev_release:
|
||||||
@ -396,7 +399,7 @@ def show_help(exit_code=0):
|
|||||||
|
|
||||||
Print a help message for pbuilder-dist, and exit with the given code.
|
Print a help message for pbuilder-dist, and exit with the given code.
|
||||||
"""
|
"""
|
||||||
print('See man pbuilder-dist for more information.')
|
Logger.info('See man pbuilder-dist for more information.')
|
||||||
|
|
||||||
sys.exit(exit_code)
|
sys.exit(exit_code)
|
||||||
|
|
||||||
@ -498,7 +501,7 @@ def main():
|
|||||||
if '--debug-echo' not in args:
|
if '--debug-echo' not in args:
|
||||||
sys.exit(subprocess.call(app.get_command(args)))
|
sys.exit(subprocess.call(app.get_command(args)))
|
||||||
else:
|
else:
|
||||||
print(app.get_command([arg for arg in args if arg != '--debug-echo']))
|
Logger.info(app.get_command([arg for arg in args if arg != '--debug-echo']))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
11
pull-debian-ddebs
Executable file
11
pull-debian-ddebs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-debian-ddebs -- pull ddeb package files for debian
|
||||||
|
# Basic usage: pull-debian-ddebs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='debian', pull='ddebs')
|
@ -24,9 +24,11 @@ import debian.changelog
|
|||||||
|
|
||||||
from ubuntutools.archive import DebianSourcePackage, DownloadError
|
from ubuntutools.archive import DebianSourcePackage, DownloadError
|
||||||
from ubuntutools.config import UDTConfig
|
from ubuntutools.config import UDTConfig
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.version import Version
|
from ubuntutools.version import Version
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def previous_version(package, version, distance):
|
def previous_version(package, version, distance):
|
||||||
"Given an (extracted) package, determine the version distance versions ago"
|
"Given an (extracted) package, determine the version distance versions ago"
|
||||||
@ -79,7 +81,7 @@ def main():
|
|||||||
opts.debsec_mirror = config.get_value('DEBSEC_MIRROR')
|
opts.debsec_mirror = config.get_value('DEBSEC_MIRROR')
|
||||||
mirrors = [opts.debsec_mirror, opts.debian_mirror]
|
mirrors = [opts.debsec_mirror, opts.debian_mirror]
|
||||||
|
|
||||||
Logger.normal('Downloading %s %s', package, version)
|
Logger.info('Downloading %s %s', package, version)
|
||||||
|
|
||||||
newpkg = DebianSourcePackage(package, version, mirrors=mirrors)
|
newpkg = DebianSourcePackage(package, version, mirrors=mirrors)
|
||||||
try:
|
try:
|
||||||
@ -96,7 +98,7 @@ def main():
|
|||||||
if not oldversion:
|
if not oldversion:
|
||||||
Logger.error('No previous version could be found')
|
Logger.error('No previous version could be found')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
Logger.normal('Downloading %s %s', package, oldversion)
|
Logger.info('Downloading %s %s', package, oldversion)
|
||||||
|
|
||||||
oldpkg = DebianSourcePackage(package, oldversion, mirrors=mirrors)
|
oldpkg = DebianSourcePackage(package, oldversion, mirrors=mirrors)
|
||||||
try:
|
try:
|
||||||
@ -104,11 +106,11 @@ def main():
|
|||||||
except DownloadError as e:
|
except DownloadError as e:
|
||||||
Logger.error('Failed to download: %s', str(e))
|
Logger.error('Failed to download: %s', str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
print('file://' + oldpkg.debdiff(newpkg, diffstat=True))
|
Logger.info('file://' + oldpkg.debdiff(newpkg, diffstat=True))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
Logger.normal('User abort.')
|
Logger.info('User abort.')
|
||||||
|
11
pull-debian-debs
Executable file
11
pull-debian-debs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-debian-debs -- pull deb package files for debian
|
||||||
|
# Basic usage: pull-debian-debs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='debian', pull='debs')
|
@ -1,148 +1,11 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
#
|
#
|
||||||
# pull-debian-source -- pull a source package from Launchpad
|
# pull-debian-source -- pull source package files for debian
|
||||||
# Copyright (C) 2011, Stefano Rivera <stefanor@ubuntu.com>
|
# Basic usage: pull-debian-source <package name> [version|release]
|
||||||
# Inspired by a tool of the same name by Nathan Handler.
|
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for any
|
# See pull-pkg
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
|
||||||
# copyright notice and this permission notice appear in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
import json
|
|
||||||
import optparse
|
|
||||||
import sys
|
|
||||||
import urllib.request
|
|
||||||
import urllib.error
|
|
||||||
|
|
||||||
from distro_info import DebianDistroInfo, DistroDataOutdated
|
|
||||||
|
|
||||||
from ubuntutools.archive import DebianSourcePackage, DownloadError, rmadison
|
|
||||||
from ubuntutools.config import UDTConfig
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
|
|
||||||
|
|
||||||
def is_suite(version):
|
|
||||||
"""If version could be considered to be a Debian suite, return the
|
|
||||||
canonical suite name. Otherwise None
|
|
||||||
"""
|
|
||||||
debian_info = DebianDistroInfo()
|
|
||||||
debian_releases = debian_info.all + ['experimental']
|
|
||||||
|
|
||||||
if '-' in version:
|
|
||||||
release, pocket = version.split('-', 1)
|
|
||||||
release = debian_info.codename(release, default=release)
|
|
||||||
if release in debian_releases:
|
|
||||||
if pocket in ('proposed-updates', 'p-u'):
|
|
||||||
return (release + '-proposed-updates')
|
|
||||||
elif pocket == 'security':
|
|
||||||
return (release + '-security')
|
|
||||||
else:
|
|
||||||
release = debian_info.codename(version, default=version)
|
|
||||||
if release in debian_releases:
|
|
||||||
return release
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def source_package_for(binary, release):
|
|
||||||
"""Query DDE to find the source package for a particular binary"""
|
|
||||||
try:
|
|
||||||
release = DebianDistroInfo().codename(release, default=release)
|
|
||||||
except DistroDataOutdated as e:
|
|
||||||
Logger.warn(e)
|
|
||||||
url = ('http://dde.debian.net/dde/q/udd/dist/d:debian/r:%s/p:%s/?t=json'
|
|
||||||
% (release, binary))
|
|
||||||
data = None
|
|
||||||
try:
|
|
||||||
data = json.load(urllib.request.urlopen(url))['r']
|
|
||||||
except urllib.error.URLError as e:
|
|
||||||
Logger.error('Unable to retrieve package information from DDE: '
|
|
||||||
'%s (%s)', url, str(e))
|
|
||||||
except ValueError as e:
|
|
||||||
Logger.error('Unable to parse JSON response from DDE: '
|
|
||||||
'%s (%s)', url, str(e))
|
|
||||||
if not data:
|
|
||||||
return None
|
|
||||||
return data[0]['source']
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
usage = 'Usage: %prog <package> [release|version]'
|
|
||||||
parser = optparse.OptionParser(usage)
|
|
||||||
parser.add_option('-d', '--download-only',
|
|
||||||
dest='download_only', default=False, action='store_true',
|
|
||||||
help='Do not extract the source package')
|
|
||||||
parser.add_option('-m', '--mirror', metavar='DEBIAN_MIRROR',
|
|
||||||
dest='debian_mirror',
|
|
||||||
help='Preferred Debian mirror (default: %s)'
|
|
||||||
% UDTConfig.defaults['DEBIAN_MIRROR'])
|
|
||||||
parser.add_option('-s', '--security-mirror', metavar='DEBSEC_MIRROR',
|
|
||||||
dest='debsec_mirror',
|
|
||||||
help='Preferred Debian Security mirror (default: %s)'
|
|
||||||
% UDTConfig.defaults['DEBSEC_MIRROR'])
|
|
||||||
parser.add_option('--no-conf',
|
|
||||||
dest='no_conf', default=False, action='store_true',
|
|
||||||
help="Don't read config files or environment variables")
|
|
||||||
parser.add_option('--no-verify-signature',
|
|
||||||
dest='verify_signature', default=True,
|
|
||||||
action='store_false',
|
|
||||||
help="Allow signature verification failure")
|
|
||||||
(options, args) = parser.parse_args()
|
|
||||||
if not args:
|
|
||||||
parser.error('Must specify package name')
|
|
||||||
elif len(args) > 2:
|
|
||||||
parser.error('Too many arguments. '
|
|
||||||
'Must only specify package and (optionally) release.')
|
|
||||||
|
|
||||||
config = UDTConfig(options.no_conf)
|
|
||||||
if options.debian_mirror is None:
|
|
||||||
options.debian_mirror = config.get_value('DEBIAN_MIRROR')
|
|
||||||
if options.debsec_mirror is None:
|
|
||||||
options.debsec_mirror = config.get_value('DEBSEC_MIRROR')
|
|
||||||
|
|
||||||
package = args[0].lower()
|
|
||||||
|
|
||||||
version = args[1] if len(args) > 1 else 'unstable'
|
|
||||||
component = None
|
|
||||||
|
|
||||||
suite = is_suite(version)
|
|
||||||
if suite is not None:
|
|
||||||
line = list(rmadison('debian', package, suite, 'source'))
|
|
||||||
if not line:
|
|
||||||
source_package = source_package_for(package, suite)
|
|
||||||
if source_package is not None and package != source_package:
|
|
||||||
package = source_package
|
|
||||||
line = list(rmadison('debian', package, suite, 'source'))
|
|
||||||
if not line:
|
|
||||||
Logger.error('Unable to find %s in Debian suite "%s".', package,
|
|
||||||
suite)
|
|
||||||
sys.exit(1)
|
|
||||||
line = line[-1]
|
|
||||||
version = line['version']
|
|
||||||
component = line['component']
|
|
||||||
|
|
||||||
Logger.normal('Downloading %s version %s', package, version)
|
|
||||||
srcpkg = DebianSourcePackage(package, version, component=component,
|
|
||||||
mirrors=[options.debian_mirror,
|
|
||||||
options.debsec_mirror])
|
|
||||||
try:
|
|
||||||
srcpkg.pull(verify_signature=options.verify_signature)
|
|
||||||
except DownloadError as e:
|
|
||||||
Logger.error('Failed to download: %s', str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
if not options.download_only:
|
|
||||||
srcpkg.unpack()
|
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
PullPkg.main(distro='debian', pull='source')
|
||||||
main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
Logger.normal('User abort.')
|
|
||||||
|
11
pull-debian-udebs
Executable file
11
pull-debian-udebs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-debian-udebs -- pull udeb package files for debian
|
||||||
|
# Basic usage: pull-debian-udebs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='debian', pull='udebs')
|
11
pull-lp-ddebs
Executable file
11
pull-lp-ddebs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-lp-ddebs -- pull ddeb package files for ubuntu
|
||||||
|
# Basic usage: pull-lp-ddebs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ubuntu', pull='ddebs')
|
11
pull-lp-debs
Executable file
11
pull-lp-debs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-lp-debs -- pull deb package files for ubuntu
|
||||||
|
# Basic usage: pull-lp-debs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ubuntu', pull='debs')
|
149
pull-lp-source
149
pull-lp-source
@ -1,150 +1,11 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
#
|
#
|
||||||
# pull-lp-source -- pull a source package from Launchpad
|
# pull-lp-source -- pull source package files for ubuntu
|
||||||
# Basic usage: pull-lp-source <source package> [<release>]
|
# Basic usage: pull-lp-source <package name> [version|release]
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008, Iain Lane <iain@orangesquash.org.uk>,
|
# See pull-pkg
|
||||||
# 2010-2011, Stefano Rivera <stefanor@ubuntu.com>
|
|
||||||
#
|
|
||||||
# ##################################################################
|
|
||||||
#
|
|
||||||
# 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 3
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# See file /usr/share/common-licenses/GPL for more details.
|
|
||||||
#
|
|
||||||
# ##################################################################
|
|
||||||
|
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import urllib.error
|
|
||||||
import urllib.request
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
from distro_info import UbuntuDistroInfo, DistroDataOutdated
|
|
||||||
|
|
||||||
from ubuntutools.archive import UbuntuSourcePackage, DownloadError
|
|
||||||
from ubuntutools.config import UDTConfig
|
|
||||||
from ubuntutools.lp.lpapicache import Distribution, Launchpad
|
|
||||||
from ubuntutools.lp.udtexceptions import (SeriesNotFoundException,
|
|
||||||
PackageNotFoundException,
|
|
||||||
PocketDoesNotExistError)
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.misc import split_release_pocket
|
|
||||||
|
|
||||||
|
|
||||||
def source_package_for(binary, release):
|
|
||||||
"""Query DDE to find the source package for a particular binary
|
|
||||||
Should really do this with LP, but it's not possible LP: #597041
|
|
||||||
"""
|
|
||||||
url = ('http://dde.debian.net/dde/q/udd/dist/d:ubuntu/r:%s/p:%s/?t=json'
|
|
||||||
% (release, binary))
|
|
||||||
data = None
|
|
||||||
try:
|
|
||||||
data = json.load(urllib.request.urlopen(url))['r']
|
|
||||||
except urllib.error.URLError as e:
|
|
||||||
Logger.error('Unable to retrieve package information from DDE: '
|
|
||||||
'%s (%s)', url, str(e))
|
|
||||||
except ValueError as e:
|
|
||||||
Logger.error('Unable to parse JSON response from DDE: '
|
|
||||||
'%s (%s)', url, str(e))
|
|
||||||
if not data:
|
|
||||||
return None
|
|
||||||
return data[0]['source']
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
usage = "Usage: %prog <package> [release|version]"
|
|
||||||
opt_parser = OptionParser(usage)
|
|
||||||
opt_parser.add_option('-d', '--download-only',
|
|
||||||
dest='download_only', default=False,
|
|
||||||
action='store_true',
|
|
||||||
help="Do not extract the source package")
|
|
||||||
opt_parser.add_option('-m', '--mirror', metavar='UBUNTU_MIRROR',
|
|
||||||
dest='ubuntu_mirror',
|
|
||||||
help='Preferred Ubuntu mirror (default: Launchpad)')
|
|
||||||
opt_parser.add_option('--no-conf',
|
|
||||||
dest='no_conf', default=False, action='store_true',
|
|
||||||
help="Don't read config files or environment "
|
|
||||||
"variables")
|
|
||||||
(options, args) = opt_parser.parse_args()
|
|
||||||
if not args:
|
|
||||||
opt_parser.error("Must specify package name")
|
|
||||||
|
|
||||||
config = UDTConfig(options.no_conf)
|
|
||||||
if options.ubuntu_mirror is None:
|
|
||||||
options.ubuntu_mirror = config.get_value('UBUNTU_MIRROR')
|
|
||||||
|
|
||||||
# Login anonymously to LP
|
|
||||||
Launchpad.login_anonymously()
|
|
||||||
|
|
||||||
package = str(args[0]).lower()
|
|
||||||
|
|
||||||
ubuntu_info = UbuntuDistroInfo()
|
|
||||||
if len(args) > 1: # Custom distribution specified.
|
|
||||||
version = str(args[1])
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
version = os.getenv('DIST') or ubuntu_info.devel()
|
|
||||||
except DistroDataOutdated as e:
|
|
||||||
Logger.warn("%s\nOr specify a distribution.", e)
|
|
||||||
sys.exit(1)
|
|
||||||
component = None
|
|
||||||
|
|
||||||
# Release, not package version number:
|
|
||||||
release = None
|
|
||||||
pocket = None
|
|
||||||
try:
|
|
||||||
(release, pocket) = split_release_pocket(version, default=None)
|
|
||||||
except PocketDoesNotExistError:
|
|
||||||
pass
|
|
||||||
if release in ubuntu_info.all:
|
|
||||||
archive = Distribution('ubuntu').getArchive()
|
|
||||||
try:
|
|
||||||
spph = archive.getSourcePackage(package, release, pocket)
|
|
||||||
except SeriesNotFoundException as e:
|
|
||||||
Logger.error(str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
except PackageNotFoundException as e:
|
|
||||||
source_package = source_package_for(package, release)
|
|
||||||
if source_package is not None and source_package != package:
|
|
||||||
try:
|
|
||||||
spph = archive.getSourcePackage(source_package, release,
|
|
||||||
pocket)
|
|
||||||
package = source_package
|
|
||||||
except PackageNotFoundException:
|
|
||||||
Logger.error(str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
Logger.error(str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
version = spph.getVersion()
|
|
||||||
component = spph.getComponent()
|
|
||||||
|
|
||||||
Logger.normal('Downloading %s version %s', package, version)
|
|
||||||
srcpkg = UbuntuSourcePackage(package, version, component=component,
|
|
||||||
mirrors=[options.ubuntu_mirror])
|
|
||||||
try:
|
|
||||||
srcpkg.pull()
|
|
||||||
except DownloadError as e:
|
|
||||||
Logger.error('Failed to download: %s', str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
if not options.download_only:
|
|
||||||
srcpkg.unpack()
|
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
PullPkg.main(distro='ubuntu', pull='source')
|
||||||
main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
Logger.normal('User abort.')
|
|
||||||
|
11
pull-lp-udebs
Executable file
11
pull-lp-udebs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-lp-udebs -- pull udeb package files for ubuntu
|
||||||
|
# Basic usage: pull-lp-udebs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ubuntu', pull='udebs')
|
29
pull-pkg
Executable file
29
pull-pkg
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-pkg -- pull package files for debian/ubuntu/uca/ppa
|
||||||
|
# Basic usage: pull-pkg -D distro -p type <package name> [version|release]
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008, Iain Lane <iain@orangesquash.org.uk>,
|
||||||
|
# 2010-2011, Stefano Rivera <stefanor@ubuntu.com>
|
||||||
|
# 2017-2018, Dan Streetman <ddstreet@canonical.com>
|
||||||
|
#
|
||||||
|
# ##################################################################
|
||||||
|
#
|
||||||
|
# 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 3
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# See file /usr/share/common-licenses/GPL for more details.
|
||||||
|
#
|
||||||
|
# ##################################################################
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main()
|
12
pull-ppa-ddebs
Executable file
12
pull-ppa-ddebs
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-ppa-ddebs -- pull ddeb package files for a Launchpad Personal Package Archive
|
||||||
|
# Basic usage: pull-ppa-ddebs <package name> <ppa:USER/NAME> [version|release]
|
||||||
|
# pull-ppa-ddebs --ppa USER/NAME <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ppa', pull='ddebs')
|
12
pull-ppa-debs
Executable file
12
pull-ppa-debs
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-ppa-debs -- pull deb package files for a Launchpad Personal Package Archive
|
||||||
|
# Basic usage: pull-ppa-debs <package name> <ppa:USER/NAME> [version|release]
|
||||||
|
# pull-ppa-debs --ppa USER/NAME <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ppa', pull='debs')
|
12
pull-ppa-source
Executable file
12
pull-ppa-source
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-ppa-source -- pull source package files for a Launchpad Personal Package Archive
|
||||||
|
# Basic usage: pull-ppa-source <package name> <ppa:USER/NAME> [version|release]
|
||||||
|
# pull-ppa-source --ppa USER/NAME <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ppa', pull='source')
|
12
pull-ppa-udebs
Executable file
12
pull-ppa-udebs
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-ppa-udebs -- pull udeb package files for a Launchpad Personal Package Archive
|
||||||
|
# Basic usage: pull-ppa-udebs <package name> <ppa:USER/NAME> [version|release]
|
||||||
|
# pull-ppa-udebs --ppa USER/NAME <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='ppa', pull='udebs')
|
11
pull-uca-ddebs
Executable file
11
pull-uca-ddebs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-uca-ddebs -- pull ddeb package files for ubuntu cloud archive
|
||||||
|
# Basic usage: pull-uca-ddebs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='uca', pull='ddebs')
|
11
pull-uca-debs
Executable file
11
pull-uca-debs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-uca-debs -- pull deb package files for ubuntu cloud archive
|
||||||
|
# Basic usage: pull-uca-debs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='uca', pull='debs')
|
156
pull-uca-source
156
pull-uca-source
@ -1,157 +1,11 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
#
|
#
|
||||||
# pull-uca-source -- pull a source package from Ubuntu Cloud Archive
|
# pull-uca-source -- pull source package files for ubuntu cloud archive
|
||||||
# Basic usage: pull-uca-source <source package> <openstack release> [version]
|
# Basic usage: pull-uca-source <package name> [version|release]
|
||||||
#
|
#
|
||||||
# Copyright (C) 2008, Iain Lane <iain@orangesquash.org.uk>,
|
# See pull-pkg
|
||||||
# 2010-2011, Stefano Rivera <stefanor@ubuntu.com>
|
|
||||||
# 2016, Corey Bryant <corey.bryant@ubuntu.com>
|
|
||||||
# 2016, Dan Streetman <dan.streetman@canonical.com>
|
|
||||||
#
|
|
||||||
# ##################################################################
|
|
||||||
#
|
|
||||||
# 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 3
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# See file /usr/share/common-licenses/GPL for more details.
|
|
||||||
#
|
|
||||||
# ##################################################################
|
|
||||||
|
|
||||||
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
from ubuntutools.archive import UbuntuCloudArchiveSourcePackage, DownloadError
|
|
||||||
from ubuntutools.config import UDTConfig
|
|
||||||
from ubuntutools.lp.lpapicache import Launchpad
|
|
||||||
from ubuntutools.lp.udtexceptions import PocketDoesNotExistError
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.misc import split_release_pocket
|
|
||||||
|
|
||||||
from lazr.restfulclient.errors import NotFound
|
|
||||||
|
|
||||||
from launchpadlib.launchpad import Launchpad as LP
|
|
||||||
|
|
||||||
|
|
||||||
def showOpenstackReleases(uca):
|
|
||||||
releases = []
|
|
||||||
for p in uca.ppas:
|
|
||||||
if re.match(r"\w*-staging", p.name):
|
|
||||||
releases.append(re.sub("-staging", "", p.name))
|
|
||||||
Logger.error("Openstack releases are:\n\t%s", ", ".join(releases))
|
|
||||||
|
|
||||||
|
|
||||||
def getSPPH(lp, archive, package, version=None, series=None, pocket=None, try_binary=True):
|
|
||||||
params = {'exact_match': True, 'order_by_date': True}
|
|
||||||
if pocket:
|
|
||||||
params['pocket'] = pocket
|
|
||||||
if series:
|
|
||||||
params['distro_series'] = series()
|
|
||||||
elif version:
|
|
||||||
params['version'] = version
|
|
||||||
Logger.normal("checking %s version %s pocket %s", package, version, pocket)
|
|
||||||
spphs = archive.getPublishedSources(source_name=package, **params)
|
|
||||||
if spphs:
|
|
||||||
return spphs[0]
|
|
||||||
if not try_binary:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Didn't find any, maybe the package is a binary package name
|
|
||||||
if series:
|
|
||||||
del params['distro_series']
|
|
||||||
archs = lp.load(series().architectures_collection_link).entries
|
|
||||||
params['distro_arch_series'] = archs[0]['self_link']
|
|
||||||
bpphs = archive.getPublishedBinaries(binary_name=package, **params)
|
|
||||||
if bpphs:
|
|
||||||
bpph_build = lp.load(bpphs[0].build_link)
|
|
||||||
source_package = bpph_build.source_package_name
|
|
||||||
return getSPPH(lp, archive, source_package, version, series, pocket,
|
|
||||||
try_binary=False)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
usage = "Usage: %prog <package> <openstack release> [version]"
|
|
||||||
opt_parser = OptionParser(usage)
|
|
||||||
opt_parser.add_option('-d', '--download-only',
|
|
||||||
dest='download_only', default=False,
|
|
||||||
action='store_true',
|
|
||||||
help="Do not extract the source package")
|
|
||||||
opt_parser.add_option('-m', '--mirror', metavar='OPENSTACK_MIRROR',
|
|
||||||
dest='openstack_mirror',
|
|
||||||
help='Preferred Openstack mirror (default: Launchpad)')
|
|
||||||
opt_parser.add_option('--no-conf',
|
|
||||||
dest='no_conf', default=False, action='store_true',
|
|
||||||
help="Don't read config files or environment "
|
|
||||||
"variables")
|
|
||||||
(options, args) = opt_parser.parse_args()
|
|
||||||
if len(args) < 2:
|
|
||||||
opt_parser.error("Must specify package name and openstack release")
|
|
||||||
|
|
||||||
config = UDTConfig(options.no_conf)
|
|
||||||
if options.openstack_mirror is None:
|
|
||||||
options.openstack_mirror = config.get_value('OPENSTACK_MIRROR')
|
|
||||||
mirrors = []
|
|
||||||
if options.openstack_mirror:
|
|
||||||
mirrors.append(options.openstack_mirror)
|
|
||||||
|
|
||||||
# Login anonymously to LP
|
|
||||||
Launchpad.login_anonymously()
|
|
||||||
lp = LP.login_anonymously("pull-uca-source", "production")
|
|
||||||
uca = lp.people("ubuntu-cloud-archive")
|
|
||||||
|
|
||||||
package = str(args[0]).lower()
|
|
||||||
release = str(args[1]).lower()
|
|
||||||
version = None
|
|
||||||
if len(args) > 2:
|
|
||||||
version = str(args[2])
|
|
||||||
|
|
||||||
pocket = None
|
|
||||||
try:
|
|
||||||
(release, pocket) = split_release_pocket(release, default=None)
|
|
||||||
except PocketDoesNotExistError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
try:
|
|
||||||
archive = uca.getPPAByName(name="%s-staging" % release)
|
|
||||||
except NotFound:
|
|
||||||
Logger.error('Archive does not exist for Openstack release: %s',
|
|
||||||
release)
|
|
||||||
showOpenstackReleases(uca)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
spph = getSPPH(lp, archive, package, version, pocket=pocket)
|
|
||||||
if not spph:
|
|
||||||
Logger.error("Package %s in %s not found.", package, release)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
package = spph.source_package_name
|
|
||||||
version = spph.source_package_version
|
|
||||||
component = spph.component_name
|
|
||||||
Logger.normal('Downloading %s version %s component %s', package, version, component)
|
|
||||||
srcpkg = UbuntuCloudArchiveSourcePackage(release, package, version, component=component,
|
|
||||||
mirrors=mirrors)
|
|
||||||
|
|
||||||
try:
|
|
||||||
srcpkg.pull()
|
|
||||||
except DownloadError as e:
|
|
||||||
Logger.error('Failed to download: %s', str(e))
|
|
||||||
sys.exit(1)
|
|
||||||
if not options.download_only:
|
|
||||||
srcpkg.unpack()
|
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
try:
|
PullPkg.main(distro='uca', pull='source')
|
||||||
main()
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
Logger.normal('User abort.')
|
|
||||||
|
11
pull-uca-udebs
Executable file
11
pull-uca-udebs
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
#
|
||||||
|
# pull-uca-udebs -- pull udeb package files for ubuntu cloud archive
|
||||||
|
# Basic usage: pull-uca-udebs <package name> [version|release]
|
||||||
|
#
|
||||||
|
# See pull-pkg
|
||||||
|
|
||||||
|
from ubuntutools.pullpkg import PullPkg
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
PullPkg.main(distro='uca', pull='udebs')
|
@ -25,11 +25,13 @@ from distro_info import UbuntuDistroInfo
|
|||||||
from ubuntutools.config import UDTConfig
|
from ubuntutools.config import UDTConfig
|
||||||
from ubuntutools.lp.lpapicache import Launchpad, Distribution
|
from ubuntutools.lp.lpapicache import Launchpad, Distribution
|
||||||
from ubuntutools.lp.udtexceptions import PackageNotFoundException
|
from ubuntutools.lp.udtexceptions import PackageNotFoundException
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.question import (YesNoQuestion, EditBugReport,
|
from ubuntutools.question import (YesNoQuestion, EditBugReport,
|
||||||
confirmation_prompt)
|
confirmation_prompt)
|
||||||
from ubuntutools.rdepends import query_rdepends, RDependsException
|
from ubuntutools.rdepends import query_rdepends, RDependsException
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class DestinationException(Exception):
|
class DestinationException(Exception):
|
||||||
pass
|
pass
|
||||||
@ -106,16 +108,11 @@ def check_existing(package, destinations):
|
|||||||
if not bugs:
|
if not bugs:
|
||||||
return
|
return
|
||||||
|
|
||||||
Logger.normal("There are existing bug reports that look similar to your "
|
Logger.info("There are existing bug reports that look similar to your "
|
||||||
"request. Please check before continuing:")
|
"request. Please check before continuing:")
|
||||||
|
|
||||||
by_id = {}
|
for bug in sorted(set(bug_task.bug for bug_task in bugs)):
|
||||||
for bug_task in bugs:
|
Logger.info(" * LP: #%-7i: %s %s", bug.id, bug.title, bug.web_link)
|
||||||
bug = bug_task.bug
|
|
||||||
by_id[bug.id] = bug
|
|
||||||
|
|
||||||
for id_, bug in sorted(by_id.items()):
|
|
||||||
Logger.normal(" * LP: #%-7i: %s %s", bug.id, bug.title, bug.web_link)
|
|
||||||
|
|
||||||
confirmation_prompt()
|
confirmation_prompt()
|
||||||
|
|
||||||
@ -190,7 +187,7 @@ def locate_package(package, distribution):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
package = apt_pkg.candidate.source_name
|
package = apt_pkg.candidate.source_name
|
||||||
Logger.normal("Binary package specified, considering its source "
|
Logger.info("Binary package specified, considering its source "
|
||||||
"package instead: %s", package)
|
"package instead: %s", package)
|
||||||
|
|
||||||
|
|
||||||
@ -204,7 +201,7 @@ def request_backport(package_spph, source, destinations):
|
|||||||
Logger.error("%s (%s) has no published binaries in %s. ",
|
Logger.error("%s (%s) has no published binaries in %s. ",
|
||||||
package_spph.getPackageName(), package_spph.getVersion(),
|
package_spph.getPackageName(), package_spph.getVersion(),
|
||||||
source)
|
source)
|
||||||
Logger.normal("Is it stuck in bin-NEW? It can't be backported until "
|
Logger.info("Is it stuck in bin-NEW? It can't be backported until "
|
||||||
"the binaries have been accepted.")
|
"the binaries have been accepted.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@ -256,7 +253,7 @@ def request_backport(package_spph, source, destinations):
|
|||||||
editor.edit()
|
editor.edit()
|
||||||
subject, body = editor.get_report()
|
subject, body = editor.get_report()
|
||||||
|
|
||||||
Logger.normal('The final report is:\nSummary: %s\nDescription:\n%s\n',
|
Logger.info('The final report is:\nSummary: %s\nDescription:\n%s\n',
|
||||||
subject, body)
|
subject, body)
|
||||||
if YesNoQuestion().ask("Request this backport", "yes") == "no":
|
if YesNoQuestion().ask("Request this backport", "yes") == "no":
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -268,7 +265,7 @@ def request_backport(package_spph, source, destinations):
|
|||||||
for target in targets[1:]:
|
for target in targets[1:]:
|
||||||
bug.addTask(target=target)
|
bug.addTask(target=target)
|
||||||
|
|
||||||
Logger.normal("Backport request filed as %s", bug.web_link)
|
Logger.info("Backport request filed as %s", bug.web_link)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
72
requestsync
72
requestsync
@ -38,6 +38,9 @@ from ubuntutools.misc import require_utf8
|
|||||||
from ubuntutools.question import confirmation_prompt, EditBugReport
|
from ubuntutools.question import confirmation_prompt, EditBugReport
|
||||||
from ubuntutools.version import Version
|
from ubuntutools.version import Version
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
#
|
#
|
||||||
# entry point
|
# entry point
|
||||||
#
|
#
|
||||||
@ -97,7 +100,7 @@ def main():
|
|||||||
config = UDTConfig(options.no_conf)
|
config = UDTConfig(options.no_conf)
|
||||||
|
|
||||||
if options.deprecated_lp_flag:
|
if options.deprecated_lp_flag:
|
||||||
print("The --lp flag is now default, ignored.")
|
Logger.info("The --lp flag is now default, ignored.")
|
||||||
if options.email:
|
if options.email:
|
||||||
options.lpapi = False
|
options.lpapi = False
|
||||||
else:
|
else:
|
||||||
@ -115,8 +118,8 @@ def main():
|
|||||||
elif options.lpinstance == 'staging':
|
elif options.lpinstance == 'staging':
|
||||||
bug_mail_domain = 'bugs.staging.launchpad.net'
|
bug_mail_domain = 'bugs.staging.launchpad.net'
|
||||||
else:
|
else:
|
||||||
print('Error: Unknown launchpad instance: %s' % options.lpinstance,
|
Logger.error('Error: Unknown launchpad instance: %s'
|
||||||
file=sys.stderr)
|
% options.lpinstance)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
mailserver_host = config.get_value('SMTP_SERVER',
|
mailserver_host = config.get_value('SMTP_SERVER',
|
||||||
@ -130,8 +133,8 @@ def main():
|
|||||||
firstmx = mxlist[0]
|
firstmx = mxlist[0]
|
||||||
mailserver_host = firstmx[1]
|
mailserver_host = firstmx[1]
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print('Please install python3-dns to support Launchpad mail '
|
Logger.error('Please install python-dns to support '
|
||||||
'server lookup.', file=sys.stderr)
|
'Launchpad mail server lookup.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
mailserver_port = config.get_value('SMTP_PORT', default=25,
|
mailserver_port = config.get_value('SMTP_PORT', default=25,
|
||||||
@ -167,9 +170,8 @@ def main():
|
|||||||
get_ubuntu_delta_changelog,
|
get_ubuntu_delta_changelog,
|
||||||
mail_bug, need_sponsorship)
|
mail_bug, need_sponsorship)
|
||||||
if not any(x in os.environ for x in ('UBUMAIL', 'DEBEMAIL', 'EMAIL')):
|
if not any(x in os.environ for x in ('UBUMAIL', 'DEBEMAIL', 'EMAIL')):
|
||||||
print('E: The environment variable UBUMAIL, DEBEMAIL or EMAIL '
|
Logger.error('The environment variable UBUMAIL, DEBEMAIL or EMAIL needs '
|
||||||
'needs to be set to let this script mail the sync request.',
|
'to be set to let this script mail the sync request.')
|
||||||
file=sys.stderr)
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
newsource = options.newpkg
|
newsource = options.newpkg
|
||||||
@ -187,15 +189,14 @@ def main():
|
|||||||
else:
|
else:
|
||||||
ubu_info = UbuntuDistroInfo()
|
ubu_info = UbuntuDistroInfo()
|
||||||
release = ubu_info.devel()
|
release = ubu_info.devel()
|
||||||
print('W: Target release missing - assuming %s' % release,
|
Logger.warning('Target release missing - assuming %s' % release)
|
||||||
file=sys.stderr)
|
|
||||||
elif len(args) == 2:
|
elif len(args) == 2:
|
||||||
release = args[1]
|
release = args[1]
|
||||||
elif len(args) == 3:
|
elif len(args) == 3:
|
||||||
release = args[1]
|
release = args[1]
|
||||||
force_base_version = Version(args[2])
|
force_base_version = Version(args[2])
|
||||||
else:
|
else:
|
||||||
print('E: Too many arguments.', file=sys.stderr)
|
Logger.error('Too many arguments.')
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@ -210,13 +211,12 @@ def main():
|
|||||||
ubuntu_version = Version('~')
|
ubuntu_version = Version('~')
|
||||||
ubuntu_component = None # Set after getting the Debian info
|
ubuntu_component = None # Set after getting the Debian info
|
||||||
if not newsource:
|
if not newsource:
|
||||||
print(("'%s' doesn't exist in 'Ubuntu %s'.\n"
|
Logger.info("'%s' doesn't exist in 'Ubuntu %s'." % (srcpkg, release))
|
||||||
"Do you want to sync a new package?")
|
Logger.info("Do you want to sync a new package?")
|
||||||
% (srcpkg, release))
|
|
||||||
confirmation_prompt()
|
confirmation_prompt()
|
||||||
newsource = True
|
newsource = True
|
||||||
except udtexceptions.SeriesNotFoundException as error:
|
except udtexceptions.SeriesNotFoundException as error:
|
||||||
print("E: %s" % error, file=sys.stderr)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Get the requested Debian source package
|
# Get the requested Debian source package
|
||||||
@ -225,10 +225,10 @@ def main():
|
|||||||
debian_version = Version(debian_srcpkg.getVersion())
|
debian_version = Version(debian_srcpkg.getVersion())
|
||||||
debian_component = debian_srcpkg.getComponent()
|
debian_component = debian_srcpkg.getComponent()
|
||||||
except udtexceptions.PackageNotFoundException as error:
|
except udtexceptions.PackageNotFoundException as error:
|
||||||
print("E: %s" % error, file=sys.stderr)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except udtexceptions.SeriesNotFoundException as error:
|
except udtexceptions.SeriesNotFoundException as error:
|
||||||
print("E: %s" % error, file=sys.stderr)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if ubuntu_component is None:
|
if ubuntu_component is None:
|
||||||
@ -246,17 +246,17 @@ def main():
|
|||||||
debian_version = Version(debian_srcpkg.getVersion())
|
debian_version = Version(debian_srcpkg.getVersion())
|
||||||
debian_component = debian_srcpkg.getComponent()
|
debian_component = debian_srcpkg.getComponent()
|
||||||
except udtexceptions.PackageNotFoundException as error:
|
except udtexceptions.PackageNotFoundException as error:
|
||||||
print("E: %s" % error, file=sys.stderr)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if ubuntu_version == debian_version:
|
if ubuntu_version == debian_version:
|
||||||
print('E: The versions in Debian and Ubuntu are the same already '
|
Logger.error('The versions in Debian and Ubuntu are the '
|
||||||
'(%s). Aborting.' % ubuntu_version, file=sys.stderr)
|
'same already (%s). Aborting.' % ubuntu_version)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if ubuntu_version > debian_version:
|
if ubuntu_version > debian_version:
|
||||||
print(('E: The version in Ubuntu (%s) is newer than the version in '
|
Logger.error('The version in Ubuntu (%s) is newer than '
|
||||||
'Debian (%s). Aborting.')
|
'the version in Debian (%s). Aborting.'
|
||||||
% (ubuntu_version, debian_version), file=sys.stderr)
|
% (ubuntu_version, debian_version))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# -s flag not specified - check if we do need sponsorship
|
# -s flag not specified - check if we do need sponsorship
|
||||||
@ -264,8 +264,8 @@ def main():
|
|||||||
sponsorship = need_sponsorship(srcpkg, ubuntu_component, release)
|
sponsorship = need_sponsorship(srcpkg, ubuntu_component, release)
|
||||||
|
|
||||||
if not sponsorship and not ffe:
|
if not sponsorship and not ffe:
|
||||||
print('Consider using syncpackage(1) for syncs that do not require '
|
Logger.error('Consider using syncpackage(1) for syncs that '
|
||||||
'feature freeze exceptions.', file=sys.stderr)
|
'do not require feature freeze exceptions.')
|
||||||
|
|
||||||
# Check for existing package reports
|
# Check for existing package reports
|
||||||
if not newsource:
|
if not newsource:
|
||||||
@ -283,9 +283,9 @@ def main():
|
|||||||
if 'ubuntu' in str(ubuntu_version):
|
if 'ubuntu' in str(ubuntu_version):
|
||||||
need_interaction = True
|
need_interaction = True
|
||||||
|
|
||||||
print('Changes have been made to the package in Ubuntu.\n'
|
Logger.info('Changes have been made to the package in Ubuntu.')
|
||||||
'Please edit the report and give an explanation.\n'
|
Logger.info('Please edit the report and give an explanation.')
|
||||||
'Not saving the report file will abort the request.')
|
Logger.info('Not saving the report file will abort the request.')
|
||||||
report += ('Explanation of the Ubuntu delta and why it can be '
|
report += ('Explanation of the Ubuntu delta and why it can be '
|
||||||
'dropped:\n%s\n>>> ENTER_EXPLANATION_HERE <<<\n\n'
|
'dropped:\n%s\n>>> ENTER_EXPLANATION_HERE <<<\n\n'
|
||||||
% get_ubuntu_delta_changelog(ubuntu_srcpkg))
|
% get_ubuntu_delta_changelog(ubuntu_srcpkg))
|
||||||
@ -293,9 +293,9 @@ def main():
|
|||||||
if ffe:
|
if ffe:
|
||||||
need_interaction = True
|
need_interaction = True
|
||||||
|
|
||||||
print('To approve FeatureFreeze exception, you need to state\n'
|
Logger.info('To approve FeatureFreeze exception, you need to state')
|
||||||
'the reason why you feel it is necessary.\n'
|
Logger.info('the reason why you feel it is necessary.')
|
||||||
'Not saving the report file will abort the request.')
|
Logger.info('Not saving the report file will abort the request.')
|
||||||
report += ('Explanation of FeatureFreeze exception:\n'
|
report += ('Explanation of FeatureFreeze exception:\n'
|
||||||
'>>> ENTER_EXPLANATION_HERE <<<\n\n')
|
'>>> ENTER_EXPLANATION_HERE <<<\n\n')
|
||||||
|
|
||||||
@ -312,10 +312,10 @@ def main():
|
|||||||
changelog = debian_srcpkg.getChangelog(since_version=base_version)
|
changelog = debian_srcpkg.getChangelog(since_version=base_version)
|
||||||
if not changelog:
|
if not changelog:
|
||||||
if not options.missing_changelog_ok:
|
if not options.missing_changelog_ok:
|
||||||
print("E: Did not retrieve any changelog entries. "
|
Logger.error("Did not retrieve any changelog entries. "
|
||||||
"Do you need to specify '-C'? "
|
"Do you need to specify '-C'? "
|
||||||
"Was the package recently uploaded? (check "
|
"Was the package recently uploaded? (check "
|
||||||
"http://packages.debian.org/changelogs/)", file=sys.stderr)
|
"http://packages.debian.org/changelogs/)")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
need_interaction = True
|
need_interaction = True
|
||||||
@ -327,8 +327,8 @@ def main():
|
|||||||
title, report = editor.get_report()
|
title, report = editor.get_report()
|
||||||
|
|
||||||
if 'XXX FIXME' in report:
|
if 'XXX FIXME' in report:
|
||||||
print("E: changelog boilerplate found in report, please manually add "
|
Logger.error("changelog boilerplate found in report, "
|
||||||
"changelog when using '-C'", file=sys.stderr)
|
"please manually add changelog when using '-C'")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# bug status and bug subscriber
|
# bug status and bug subscriber
|
||||||
@ -359,5 +359,5 @@ if __name__ == '__main__':
|
|||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\nUser abort.")
|
Logger.error("User abort.")
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
@ -19,11 +19,13 @@ import sys
|
|||||||
|
|
||||||
from distro_info import DistroDataOutdated
|
from distro_info import DistroDataOutdated
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.misc import (system_distribution, vendor_to_distroinfo,
|
from ubuntutools.misc import (system_distribution, vendor_to_distroinfo,
|
||||||
codename_to_distribution)
|
codename_to_distribution)
|
||||||
from ubuntutools.rdepends import query_rdepends, RDependsException
|
from ubuntutools.rdepends import query_rdepends, RDependsException
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_MAX_DEPTH = 10 # We want avoid any infinite loop...
|
DEFAULT_MAX_DEPTH = 10 # We want avoid any infinite loop...
|
||||||
|
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ def main():
|
|||||||
try:
|
try:
|
||||||
default_release = system_distro_info.devel()
|
default_release = system_distro_info.devel()
|
||||||
except DistroDataOutdated as e:
|
except DistroDataOutdated as e:
|
||||||
Logger.warn(e)
|
Logger.warning(e)
|
||||||
default_release = 'unstable'
|
default_release = 'unstable'
|
||||||
|
|
||||||
description = ("List reverse-dependencies of package. "
|
description = ("List reverse-dependencies of package. "
|
||||||
@ -85,7 +87,7 @@ def main():
|
|||||||
options.release = distro_info.codename(options.release,
|
options.release = distro_info.codename(options.release,
|
||||||
default=options.release)
|
default=options.release)
|
||||||
except DistroDataOutdated:
|
except DistroDataOutdated:
|
||||||
# We already printed a warning
|
# We already logged a warning
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if options.build_depends:
|
if options.build_depends:
|
||||||
@ -143,14 +145,14 @@ def main():
|
|||||||
|
|
||||||
def display_verbose(package, values):
|
def display_verbose(package, values):
|
||||||
if not values:
|
if not values:
|
||||||
print("No reverse dependencies found")
|
Logger.info("No reverse dependencies found")
|
||||||
return
|
return
|
||||||
|
|
||||||
def print_field(field):
|
def log_field(field):
|
||||||
print(field)
|
Logger.info(field)
|
||||||
print('=' * len(field))
|
Logger.info('=' * len(field))
|
||||||
|
|
||||||
def print_package(values, package, arch, dependency, offset=0):
|
def log_package(values, package, arch, dependency, offset=0):
|
||||||
line = ' ' * offset + '* %s' % package
|
line = ' ' * offset + '* %s' % package
|
||||||
if all_archs and set(arch) != all_archs:
|
if all_archs and set(arch) != all_archs:
|
||||||
line += ' [%s]' % ' '.join(sorted(arch))
|
line += ' [%s]' % ' '.join(sorted(arch))
|
||||||
@ -158,13 +160,13 @@ def display_verbose(package, values):
|
|||||||
if len(line) < 30:
|
if len(line) < 30:
|
||||||
line += ' ' * (30 - len(line))
|
line += ' ' * (30 - len(line))
|
||||||
line += ' (for %s)' % dependency
|
line += ' (for %s)' % dependency
|
||||||
print(line)
|
Logger.info(line)
|
||||||
data = values.get(package)
|
data = values.get(package)
|
||||||
if data:
|
if data:
|
||||||
offset = offset + 1
|
offset = offset + 1
|
||||||
for rdeps in data.values():
|
for rdeps in data.values():
|
||||||
for rdep in rdeps:
|
for rdep in rdeps:
|
||||||
print_package(values,
|
log_package(values,
|
||||||
rdep['Package'],
|
rdep['Package'],
|
||||||
rdep.get('Architectures', all_archs),
|
rdep.get('Architectures', all_archs),
|
||||||
rdep.get('Dependency'),
|
rdep.get('Dependency'),
|
||||||
@ -179,17 +181,17 @@ def display_verbose(package, values):
|
|||||||
all_archs.update(rdep['Architectures'])
|
all_archs.update(rdep['Architectures'])
|
||||||
|
|
||||||
for field, rdeps in values[package].items():
|
for field, rdeps in values[package].items():
|
||||||
print_field(field)
|
Logger.info(field)
|
||||||
rdeps.sort(key=lambda x: x['Package'])
|
rdeps.sort(key=lambda x: x['Package'])
|
||||||
for rdep in rdeps:
|
for rdep in rdeps:
|
||||||
print_package(values,
|
log_package(values,
|
||||||
rdep['Package'],
|
rdep['Package'],
|
||||||
rdep.get('Architectures', all_archs),
|
rdep.get('Architectures', all_archs),
|
||||||
rdep.get('Dependency'))
|
rdep.get('Dependency'))
|
||||||
print()
|
Logger.info("")
|
||||||
|
|
||||||
if all_archs:
|
if all_archs:
|
||||||
print("Packages without architectures listed are "
|
Logger.info("Packages without architectures listed are "
|
||||||
"reverse-dependencies in: %s"
|
"reverse-dependencies in: %s"
|
||||||
% ', '.join(sorted(list(all_archs))))
|
% ', '.join(sorted(list(all_archs))))
|
||||||
|
|
||||||
@ -201,7 +203,7 @@ def display_consise(values):
|
|||||||
for rdep in rdeps:
|
for rdep in rdeps:
|
||||||
result.add(rdep['Package'])
|
result.add(rdep['Package'])
|
||||||
|
|
||||||
print('\n'.join(sorted(list(result))))
|
Logger.info('\n'.join(sorted(list(result))))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -24,7 +24,9 @@ import urllib.request
|
|||||||
|
|
||||||
from ubuntutools.lp.lpapicache import (Distribution, Launchpad,
|
from ubuntutools.lp.lpapicache import (Distribution, Launchpad,
|
||||||
PackageNotFoundException)
|
PackageNotFoundException)
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
DATA_URL = 'http://qa.ubuntuwire.org/ubuntu-seeded-packages/seeded.json.gz'
|
DATA_URL = 'http://qa.ubuntuwire.org/ubuntu-seeded-packages/seeded.json.gz'
|
||||||
|
|
||||||
@ -88,28 +90,28 @@ def output_binaries(index, binaries):
|
|||||||
'''Print binaries found in index'''
|
'''Print binaries found in index'''
|
||||||
for binary in binaries:
|
for binary in binaries:
|
||||||
if binary in index:
|
if binary in index:
|
||||||
print("%s is seeded in:" % binary)
|
Logger.info("%s is seeded in:" % binary)
|
||||||
print(present_on(index[binary]))
|
Logger.info(present_on(index[binary]))
|
||||||
else:
|
else:
|
||||||
print("%s is not seeded (and may not exist)." % binary)
|
Logger.info("%s is not seeded (and may not exist)." % binary)
|
||||||
|
|
||||||
|
|
||||||
def output_by_source(index, by_source):
|
def output_by_source(index, by_source):
|
||||||
'''Print binaries found in index. Grouped by source'''
|
'''Logger.Info(binaries found in index. Grouped by source'''
|
||||||
for source, binaries in by_source.items():
|
for source, binaries in by_source.items():
|
||||||
seen = False
|
seen = False
|
||||||
if not binaries:
|
if not binaries:
|
||||||
print("Status unknown: No binary packages built by the latest "
|
Logger.info("Status unknown: No binary packages built by the latest "
|
||||||
"%s.\nTry again using -b and the expected binary packages."
|
"%s.\nTry again using -b and the expected binary packages."
|
||||||
% source)
|
% source)
|
||||||
continue
|
continue
|
||||||
for binary in binaries:
|
for binary in binaries:
|
||||||
if binary in index:
|
if binary in index:
|
||||||
seen = True
|
seen = True
|
||||||
print("%s (from %s) is seeded in:" % (binary, source))
|
Logger.info("%s (from %s) is seeded in:" % (binary, source))
|
||||||
print(present_on(index[binary]))
|
Logger.info(present_on(index[binary]))
|
||||||
if not seen:
|
if not seen:
|
||||||
print("%s's binaries are not seeded." % source)
|
Logger.info("%s's binaries are not seeded." % source)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
14
setup.py
14
setup.py
@ -27,11 +27,25 @@ scripts = [
|
|||||||
'mk-sbuild',
|
'mk-sbuild',
|
||||||
'pbuilder-dist',
|
'pbuilder-dist',
|
||||||
'pbuilder-dist-simple',
|
'pbuilder-dist-simple',
|
||||||
|
'pull-pkg',
|
||||||
'pull-debian-debdiff',
|
'pull-debian-debdiff',
|
||||||
'pull-debian-source',
|
'pull-debian-source',
|
||||||
|
'pull-debian-debs',
|
||||||
|
'pull-debian-ddebs',
|
||||||
|
'pull-debian-udebs',
|
||||||
'pull-lp-source',
|
'pull-lp-source',
|
||||||
|
'pull-lp-debs',
|
||||||
|
'pull-lp-ddebs',
|
||||||
|
'pull-lp-udebs',
|
||||||
|
'pull-ppa-source',
|
||||||
|
'pull-ppa-debs',
|
||||||
|
'pull-ppa-ddebs',
|
||||||
|
'pull-ppa-udebs',
|
||||||
'pull-revu-source',
|
'pull-revu-source',
|
||||||
'pull-uca-source',
|
'pull-uca-source',
|
||||||
|
'pull-uca-debs',
|
||||||
|
'pull-uca-ddebs',
|
||||||
|
'pull-uca-udebs',
|
||||||
'requestbackport',
|
'requestbackport',
|
||||||
'requestsync',
|
'requestsync',
|
||||||
'reverse-build-depends',
|
'reverse-build-depends',
|
||||||
|
@ -19,12 +19,15 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import logging
|
||||||
|
|
||||||
from ubuntutools.builder import get_builder
|
from ubuntutools.builder import get_builder
|
||||||
from ubuntutools.config import UDTConfig
|
from ubuntutools.config import UDTConfig
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.sponsor_patch.sponsor_patch import sponsor_patch, check_dependencies
|
from ubuntutools.sponsor_patch.sponsor_patch import sponsor_patch, check_dependencies
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def parse(script_name):
|
def parse(script_name):
|
||||||
"""Parse the command line parameters."""
|
"""Parse the command line parameters."""
|
||||||
@ -64,7 +67,8 @@ def parse(script_name):
|
|||||||
"temporary directory, deleted afterwards).")
|
"temporary directory, deleted afterwards).")
|
||||||
|
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
Logger.set_verbosity(options.verbose)
|
if options.verbose:
|
||||||
|
Logger.setLevel(logging.DEBUG)
|
||||||
check_dependencies()
|
check_dependencies()
|
||||||
|
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
@ -123,7 +127,7 @@ def main():
|
|||||||
options.keyid, options.lpinstance, options.update,
|
options.keyid, options.lpinstance, options.update,
|
||||||
options.upload, workdir)
|
options.upload, workdir)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\nUser abort.")
|
Logger.error("User abort.")
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
finally:
|
finally:
|
||||||
if options.workdir is None:
|
if options.workdir is None:
|
||||||
|
@ -27,7 +27,9 @@ import os
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
from subprocess import call, check_call, Popen, PIPE
|
|
||||||
|
from subprocess import call, check_call, run, Popen, PIPE, DEVNULL
|
||||||
|
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
|
|
||||||
from debian.changelog import Changelog
|
from debian.changelog import Changelog
|
||||||
@ -37,6 +39,9 @@ from ubuntutools.config import ubu_email
|
|||||||
from ubuntutools.question import YesNoQuestion, EditFile
|
from ubuntutools.question import YesNoQuestion, EditFile
|
||||||
from ubuntutools.update_maintainer import update_maintainer, restore_maintainer
|
from ubuntutools.update_maintainer import update_maintainer, restore_maintainer
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_most_recent_debian_version(changelog):
|
def get_most_recent_debian_version(changelog):
|
||||||
for block in changelog:
|
for block in changelog:
|
||||||
@ -85,10 +90,9 @@ def gen_debdiff(tmpdir, changelog):
|
|||||||
|
|
||||||
debdiff = os.path.join(tmpdir, '%s_%s.debdiff' % (pkg, newver))
|
debdiff = os.path.join(tmpdir, '%s_%s.debdiff' % (pkg, newver))
|
||||||
|
|
||||||
devnull = open('/dev/null', 'w')
|
|
||||||
diff_cmd = ['bzr', 'diff', '-r', 'tag:' + str(oldver)]
|
diff_cmd = ['bzr', 'diff', '-r', 'tag:' + str(oldver)]
|
||||||
if call(diff_cmd, stdout=devnull, stderr=devnull) == 1:
|
if call(diff_cmd, stdout=DEVNULL, stderr=DEVNULL) == 1:
|
||||||
print("Extracting bzr diff between %s and %s" % (oldver, newver))
|
Logger.info("Extracting bzr diff between %s and %s" % (oldver, newver))
|
||||||
else:
|
else:
|
||||||
if oldver.epoch is not None:
|
if oldver.epoch is not None:
|
||||||
oldver = str(oldver)[str(oldver).index(":") + 1:]
|
oldver = str(oldver)[str(oldver).index(":") + 1:]
|
||||||
@ -101,17 +105,13 @@ def gen_debdiff(tmpdir, changelog):
|
|||||||
check_file(olddsc)
|
check_file(olddsc)
|
||||||
check_file(newdsc)
|
check_file(newdsc)
|
||||||
|
|
||||||
print("Generating debdiff between %s and %s" % (oldver, newver))
|
Logger.info("Generating debdiff between %s and %s" % (oldver, newver))
|
||||||
diff_cmd = ['debdiff', olddsc, newdsc]
|
diff_cmd = ['debdiff', olddsc, newdsc]
|
||||||
|
|
||||||
diff = Popen(diff_cmd, stdout=PIPE)
|
with Popen(diff_cmd, stdout=PIPE, encoding='utf-8') as diff:
|
||||||
debdiff_f = open(debdiff, 'w')
|
with open(debdiff, 'w', encoding='utf-8') as debdiff_f:
|
||||||
filterdiff = Popen(['filterdiff', '-x', '*changelog*'],
|
run(['filterdiff', '-x', '*changelog*'],
|
||||||
stdin=diff.stdout, stdout=debdiff_f)
|
stdin=diff.stdout, stdout=debdiff_f, encoding='utf-8')
|
||||||
diff.stdout.close()
|
|
||||||
filterdiff.wait()
|
|
||||||
debdiff_f.close()
|
|
||||||
devnull.close()
|
|
||||||
|
|
||||||
return debdiff
|
return debdiff
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ def check_file(fname, critical=True):
|
|||||||
else:
|
else:
|
||||||
if not critical:
|
if not critical:
|
||||||
return False
|
return False
|
||||||
print("Couldn't find «%s».\n" % fname)
|
Logger.info("Couldn't find «%s».\n" % fname)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ def submit_bugreport(body, debdiff, deb_version, changelog):
|
|||||||
try:
|
try:
|
||||||
devel = UbuntuDistroInfo().devel()
|
devel = UbuntuDistroInfo().devel()
|
||||||
except DistroDataOutdated as e:
|
except DistroDataOutdated as e:
|
||||||
print(str(e))
|
Logger.info(str(e))
|
||||||
devel = ''
|
devel = ''
|
||||||
|
|
||||||
if os.path.dirname(sys.argv[0]).startswith('/usr/bin'):
|
if os.path.dirname(sys.argv[0]).startswith('/usr/bin'):
|
||||||
@ -200,7 +200,7 @@ no-cc
|
|||||||
with open(fn, 'w') as f:
|
with open(fn, 'w') as f:
|
||||||
f.write(reportbugrc)
|
f.write(reportbugrc)
|
||||||
|
|
||||||
print("""\
|
Logger.info("""\
|
||||||
You have not configured reportbug. Assuming this is the first time you have
|
You have not configured reportbug. Assuming this is the first time you have
|
||||||
used it. Writing a ~/.reportbugrc that will use Debian's mail server, and CC
|
used it. Writing a ~/.reportbugrc that will use Debian's mail server, and CC
|
||||||
the bug to you at <%s>
|
the bug to you at <%s>
|
||||||
@ -224,7 +224,7 @@ def main():
|
|||||||
parser.parse_args()
|
parser.parse_args()
|
||||||
|
|
||||||
if not os.path.exists('/usr/bin/reportbug'):
|
if not os.path.exists('/usr/bin/reportbug'):
|
||||||
print("This utility requires the «reportbug» package, which isn't "
|
Logger.error("This utility requires the «reportbug» package, which isn't "
|
||||||
"currently installed.")
|
"currently installed.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
60
syncpackage
60
syncpackage
@ -21,6 +21,7 @@
|
|||||||
# ##################################################################
|
# ##################################################################
|
||||||
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import logging
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@ -37,7 +38,6 @@ from ubuntutools.config import UDTConfig, ubu_email
|
|||||||
from ubuntutools.lp import udtexceptions
|
from ubuntutools.lp import udtexceptions
|
||||||
from ubuntutools.lp.lpapicache import (Distribution, Launchpad, PersonTeam,
|
from ubuntutools.lp.lpapicache import (Distribution, Launchpad, PersonTeam,
|
||||||
SourcePackagePublishingHistory)
|
SourcePackagePublishingHistory)
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.misc import split_release_pocket
|
from ubuntutools.misc import split_release_pocket
|
||||||
from ubuntutools.question import YesNoQuestion
|
from ubuntutools.question import YesNoQuestion
|
||||||
from ubuntutools.requestsync.mail import (
|
from ubuntutools.requestsync.mail import (
|
||||||
@ -45,6 +45,9 @@ from ubuntutools.requestsync.mail import (
|
|||||||
from ubuntutools.requestsync.lp import get_debian_srcpkg, get_ubuntu_srcpkg
|
from ubuntutools.requestsync.lp import get_debian_srcpkg, get_ubuntu_srcpkg
|
||||||
from ubuntutools.version import Version
|
from ubuntutools.version import Version
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def remove_signature(dscname):
|
def remove_signature(dscname):
|
||||||
'''Removes the signature from a .dsc file if the .dsc file is signed.'''
|
'''Removes the signature from a .dsc file if the .dsc file is signed.'''
|
||||||
@ -116,7 +119,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
ubuntu_ver = Version('~')
|
ubuntu_ver = Version('~')
|
||||||
ubu_pkg = None
|
ubu_pkg = None
|
||||||
need_orig = True
|
need_orig = True
|
||||||
Logger.normal('%s does not exist in Ubuntu.', name)
|
Logger.info('%s does not exist in Ubuntu.', name)
|
||||||
|
|
||||||
Logger.debug('Source %s: current version %s, new version %s',
|
Logger.debug('Source %s: current version %s, new version %s',
|
||||||
src_pkg.source, ubuntu_ver, new_ver)
|
src_pkg.source, ubuntu_ver, new_ver)
|
||||||
@ -128,7 +131,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
Logger.error('--force is required to discard Ubuntu changes.')
|
Logger.error('--force is required to discard Ubuntu changes.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
Logger.warn('Overwriting modified Ubuntu version %s, '
|
Logger.warning('Overwriting modified Ubuntu version %s, '
|
||||||
'setting current version to %s',
|
'setting current version to %s',
|
||||||
ubuntu_ver.full_version, cur_ver.full_version)
|
ubuntu_ver.full_version, cur_ver.full_version)
|
||||||
if simulate:
|
if simulate:
|
||||||
@ -144,7 +147,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
needs_fakesync = not (need_orig or ubu_pkg.verify_orig())
|
needs_fakesync = not (need_orig or ubu_pkg.verify_orig())
|
||||||
|
|
||||||
if needs_fakesync and fakesync:
|
if needs_fakesync and fakesync:
|
||||||
Logger.warn('Performing a fakesync')
|
Logger.warning('Performing a fakesync')
|
||||||
elif not needs_fakesync and fakesync:
|
elif not needs_fakesync and fakesync:
|
||||||
Logger.error('Fakesync not required, aborting.')
|
Logger.error('Fakesync not required, aborting.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -163,7 +166,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
|
|
||||||
# change into package directory
|
# change into package directory
|
||||||
directory = src_pkg.source + '-' + new_ver.upstream_version
|
directory = src_pkg.source + '-' + new_ver.upstream_version
|
||||||
Logger.command(('cd', directory))
|
Logger.debug('cd' + directory)
|
||||||
os.chdir(directory)
|
os.chdir(directory)
|
||||||
|
|
||||||
# read Debian distribution from debian/changelog if not specified
|
# read Debian distribution from debian/changelog if not specified
|
||||||
@ -183,9 +186,9 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
cmd.append("-sa")
|
cmd.append("-sa")
|
||||||
else:
|
else:
|
||||||
cmd.append("-sd")
|
cmd.append("-sd")
|
||||||
if not Logger.verbose:
|
if not Logger.isEnabledFor(logging.DEBUG):
|
||||||
cmd += ["-q"]
|
cmd += ["-q"]
|
||||||
Logger.command(cmd + ['>', '../' + changes_filename])
|
Logger.debug(' '.join(cmd) + '> ../' + changes_filename)
|
||||||
changes = subprocess.check_output(cmd, encoding='utf-8')
|
changes = subprocess.check_output(cmd, encoding='utf-8')
|
||||||
|
|
||||||
# Add additional bug numbers
|
# Add additional bug numbers
|
||||||
@ -193,7 +196,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
changes = add_fixed_bugs(changes, bugs)
|
changes = add_fixed_bugs(changes, bugs)
|
||||||
|
|
||||||
# remove extracted (temporary) files
|
# remove extracted (temporary) files
|
||||||
Logger.command(('cd', '..'))
|
Logger.debug('cd ..')
|
||||||
os.chdir('..')
|
os.chdir('..')
|
||||||
shutil.rmtree(directory, True)
|
shutil.rmtree(directory, True)
|
||||||
|
|
||||||
@ -208,7 +211,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
cmd = ["debsign", changes_filename]
|
cmd = ["debsign", changes_filename]
|
||||||
if keyid is not None:
|
if keyid is not None:
|
||||||
cmd.insert(1, "-k" + keyid)
|
cmd.insert(1, "-k" + keyid)
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
subprocess.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
else:
|
else:
|
||||||
# Create fakesync changelog entry
|
# Create fakesync changelog entry
|
||||||
@ -223,14 +226,14 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
cmd = ['dch', '-v', new_ver.full_version, '--force-distribution',
|
cmd = ['dch', '-v', new_ver.full_version, '--force-distribution',
|
||||||
'-D', release, message]
|
'-D', release, message]
|
||||||
env = {'DEBFULLNAME': name, 'DEBEMAIL': email}
|
env = {'DEBFULLNAME': name, 'DEBEMAIL': email}
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
subprocess.check_call(cmd, env=env)
|
subprocess.check_call(cmd, env=env)
|
||||||
|
|
||||||
# update the Maintainer field
|
# update the Maintainer field
|
||||||
cmd = ["update-maintainer"]
|
cmd = ["update-maintainer"]
|
||||||
if not Logger.verbose:
|
if not Logger.isEnabledFor(logging.DEBUG):
|
||||||
cmd.append("-q")
|
cmd.append("-q")
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
subprocess.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
# Build source package
|
# Build source package
|
||||||
@ -240,7 +243,7 @@ def sync_dsc(src_pkg, debian_dist, release, name, email, bugs, ubuntu_mirror,
|
|||||||
cmd += ['-sa']
|
cmd += ['-sa']
|
||||||
if keyid:
|
if keyid:
|
||||||
cmd += ["-k" + keyid]
|
cmd += ["-k" + keyid]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
returncode = subprocess.call(cmd)
|
returncode = subprocess.call(cmd)
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
Logger.error('Source-only build with debuild failed. '
|
Logger.error('Source-only build with debuild failed. '
|
||||||
@ -339,7 +342,7 @@ def copy(src_pkg, release, bugs, sponsoree=None, simulate=False, force=False):
|
|||||||
ubuntu_spph.getComponent(),
|
ubuntu_spph.getComponent(),
|
||||||
mirrors=[])
|
mirrors=[])
|
||||||
|
|
||||||
Logger.normal('Source %s -> %s/%s: current version %s, new version %s',
|
Logger.info('Source %s -> %s/%s: current version %s, new version %s',
|
||||||
src_pkg.source, ubuntu_series, ubuntu_pocket,
|
src_pkg.source, ubuntu_series, ubuntu_pocket,
|
||||||
ubuntu_pkg.version, src_pkg.version)
|
ubuntu_pkg.version, src_pkg.version)
|
||||||
|
|
||||||
@ -358,20 +361,20 @@ def copy(src_pkg, release, bugs, sponsoree=None, simulate=False, force=False):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except udtexceptions.PackageNotFoundException:
|
except udtexceptions.PackageNotFoundException:
|
||||||
base_version = Version('~')
|
base_version = Version('~')
|
||||||
Logger.normal('Source %s -> %s/%s: not in Ubuntu, new version %s',
|
Logger.info('Source %s -> %s/%s: not in Ubuntu, new version %s',
|
||||||
src_pkg.source, ubuntu_series, ubuntu_pocket,
|
src_pkg.source, ubuntu_series, ubuntu_pocket,
|
||||||
src_pkg.version)
|
src_pkg.version)
|
||||||
|
|
||||||
changes = debian_spph.getChangelog(since_version=base_version)
|
changes = debian_spph.getChangelog(since_version=base_version)
|
||||||
if changes:
|
if changes:
|
||||||
changes = changes.strip()
|
changes = changes.strip()
|
||||||
Logger.normal("New changes:\n%s", changes)
|
Logger.info("New changes:\n%s", changes)
|
||||||
|
|
||||||
if simulate:
|
if simulate:
|
||||||
return
|
return
|
||||||
|
|
||||||
if sponsoree:
|
if sponsoree:
|
||||||
Logger.normal("Sponsoring this sync for %s (%s)",
|
Logger.info("Sponsoring this sync for %s (%s)",
|
||||||
sponsoree.display_name, sponsoree.name)
|
sponsoree.display_name, sponsoree.name)
|
||||||
answer = YesNoQuestion().ask("Sync this package", "no")
|
answer = YesNoQuestion().ask("Sync this package", "no")
|
||||||
if answer != "yes":
|
if answer != "yes":
|
||||||
@ -392,13 +395,13 @@ def copy(src_pkg, release, bugs, sponsoree=None, simulate=False, force=False):
|
|||||||
Logger.error(error.content)
|
Logger.error(error.content)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
Logger.normal('Request succeeded; you should get an e-mail once it is '
|
Logger.info('Request succeeded; you should get an e-mail once it is '
|
||||||
'processed.')
|
'processed.')
|
||||||
bugs = sorted(set(bugs))
|
bugs = sorted(set(bugs))
|
||||||
if bugs:
|
if bugs:
|
||||||
Logger.normal("Launchpad bugs to be closed: %s",
|
Logger.info("Launchpad bugs to be closed: %s",
|
||||||
', '.join(str(bug) for bug in bugs))
|
', '.join(str(bug) for bug in bugs))
|
||||||
Logger.normal('Please wait for the sync to be successful before '
|
Logger.info('Please wait for the sync to be successful before '
|
||||||
'closing bugs.')
|
'closing bugs.')
|
||||||
answer = YesNoQuestion().ask("Close bugs", "yes")
|
answer = YesNoQuestion().ask("Close bugs", "yes")
|
||||||
if answer == "yes":
|
if answer == "yes":
|
||||||
@ -468,7 +471,7 @@ def close_bugs(bugs, package, version, changes, sponsoree):
|
|||||||
if target == ubuntu or (target.name == package and
|
if target == ubuntu or (target.name == package and
|
||||||
getattr(target, 'distribution', None) == ubuntu):
|
getattr(target, 'distribution', None) == ubuntu):
|
||||||
if task.status != 'Fix Released':
|
if task.status != 'Fix Released':
|
||||||
Logger.normal("Closed bug %s", task.web_link)
|
Logger.info("Closed bug %s", task.web_link)
|
||||||
task.status = 'Fix Released'
|
task.status = 'Fix Released'
|
||||||
task.lp_save()
|
task.lp_save()
|
||||||
bug.newMessage(content=message)
|
bug.newMessage(content=message)
|
||||||
@ -597,7 +600,8 @@ def main():
|
|||||||
'''Handle parameters and get the ball rolling'''
|
'''Handle parameters and get the ball rolling'''
|
||||||
(options, package) = parse()
|
(options, package) = parse()
|
||||||
|
|
||||||
Logger.verbose = options.verbose
|
if options.verbose:
|
||||||
|
Logger.setLevel('DEBUG')
|
||||||
config = UDTConfig(options.no_conf)
|
config = UDTConfig(options.no_conf)
|
||||||
if options.debian_mirror is None:
|
if options.debian_mirror is None:
|
||||||
options.debian_mirror = config.get_value('DEBIAN_MIRROR')
|
options.debian_mirror = config.get_value('DEBIAN_MIRROR')
|
||||||
@ -626,7 +630,7 @@ def main():
|
|||||||
options.release = "%s-proposed" % ubuntu.current_series.name
|
options.release = "%s-proposed" % ubuntu.current_series.name
|
||||||
|
|
||||||
if not options.fakesync and not options.lp:
|
if not options.fakesync and not options.lp:
|
||||||
Logger.warn("The use of --no-lp is not recommended for uploads "
|
Logger.warning("The use of --no-lp is not recommended for uploads "
|
||||||
"targeted at Ubuntu. "
|
"targeted at Ubuntu. "
|
||||||
"The archive-admins discourage its use, except for "
|
"The archive-admins discourage its use, except for "
|
||||||
"fakesyncs.")
|
"fakesyncs.")
|
||||||
@ -687,17 +691,17 @@ def main():
|
|||||||
if blacklist_fail:
|
if blacklist_fail:
|
||||||
Logger.error("Source package %s is blacklisted.", src_pkg.source)
|
Logger.error("Source package %s is blacklisted.", src_pkg.source)
|
||||||
elif blacklisted == 'ALWAYS':
|
elif blacklisted == 'ALWAYS':
|
||||||
Logger.normal("Source package %s is blacklisted.", src_pkg.source)
|
Logger.info(u"Source package %s is blacklisted.", src_pkg.source)
|
||||||
if messages:
|
if messages:
|
||||||
for message in messages:
|
for message in messages:
|
||||||
for line in textwrap.wrap(message):
|
for line in textwrap.wrap(message):
|
||||||
Logger.normal(line)
|
Logger.info(line)
|
||||||
|
|
||||||
if comments:
|
if comments:
|
||||||
Logger.normal("Blacklist Comments:")
|
Logger.info("Blacklist Comments:")
|
||||||
for comment in comments:
|
for comment in comments:
|
||||||
for line in textwrap.wrap(comment):
|
for line in textwrap.wrap(comment):
|
||||||
Logger.normal(" " + line)
|
Logger.info(" " + line)
|
||||||
|
|
||||||
if blacklist_fail:
|
if blacklist_fail:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -717,4 +721,4 @@ if __name__ == "__main__":
|
|||||||
try:
|
try:
|
||||||
main()
|
main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
Logger.normal('User abort.')
|
Logger.info('User abort.')
|
||||||
|
68
ubuntu-build
68
ubuntu-build
@ -32,6 +32,9 @@ from ubuntutools.lp.udtexceptions import (SeriesNotFoundException,
|
|||||||
from ubuntutools.lp.lpapicache import Distribution, PersonTeam
|
from ubuntutools.lp.lpapicache import Distribution, PersonTeam
|
||||||
from ubuntutools.misc import split_release_pocket
|
from ubuntutools.misc import split_release_pocket
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Usage.
|
# Usage.
|
||||||
@ -108,15 +111,15 @@ def main():
|
|||||||
|
|
||||||
# Check our operation.
|
# Check our operation.
|
||||||
if op not in ("rescore", "retry", "status"):
|
if op not in ("rescore", "retry", "status"):
|
||||||
print("Invalid operation: %s." % op, file=sys.stderr)
|
Logger.error("Invalid operation: %s." % op)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# If the user has specified an architecture to build, we only wish to
|
# If the user has specified an architecture to build, we only wish to
|
||||||
# rebuild it and nothing else.
|
# rebuild it and nothing else.
|
||||||
if options.architecture:
|
if options.architecture:
|
||||||
if options.architecture[0] not in valid_archs:
|
if options.architecture[0] not in valid_archs:
|
||||||
print("Invalid architecture specified: %s."
|
Logger.error("Invalid architecture specified: %s."
|
||||||
% options.architecture[0], file=sys.stderr)
|
% options.architecture[0])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
else:
|
else:
|
||||||
one_arch = True
|
one_arch = True
|
||||||
@ -127,7 +130,7 @@ def main():
|
|||||||
try:
|
try:
|
||||||
(release, pocket) = split_release_pocket(release)
|
(release, pocket) = split_release_pocket(release)
|
||||||
except PocketDoesNotExistError as error:
|
except PocketDoesNotExistError as error:
|
||||||
print('E: %s' % error)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Get the ubuntu archive
|
# Get the ubuntu archive
|
||||||
@ -141,7 +144,7 @@ def main():
|
|||||||
sources = ubuntu_archive.getSourcePackage(package, release, pocket)
|
sources = ubuntu_archive.getSourcePackage(package, release, pocket)
|
||||||
distroseries = Distribution('ubuntu').getSeries(release)
|
distroseries = Distribution('ubuntu').getSeries(release)
|
||||||
except (SeriesNotFoundException, PackageNotFoundException) as error:
|
except (SeriesNotFoundException, PackageNotFoundException) as error:
|
||||||
print(error)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
# Get list of builds for that package.
|
# Get list of builds for that package.
|
||||||
builds = sources.getBuilds()
|
builds = sources.getBuilds()
|
||||||
@ -163,16 +166,16 @@ def main():
|
|||||||
pocket=pocket)
|
pocket=pocket)
|
||||||
|
|
||||||
if op in ('rescore', 'retry') and not necessary_privs:
|
if op in ('rescore', 'retry') and not necessary_privs:
|
||||||
print(("You cannot perform the %s operation on a %s package as "
|
Logger.error("You cannot perform the %s operation on a %s "
|
||||||
"you do not have the permissions to do this action.")
|
"package as you do not have the permissions "
|
||||||
% (op, component), file=sys.stderr)
|
"to do this action." % (op, component))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Output details.
|
# Output details.
|
||||||
print("The source version for '%s' in %s (%s) is at %s."
|
Logger.info("The source version for '%s' in %s (%s) is at %s." %
|
||||||
% (package, release.capitalize(), component, version))
|
(package, release.capitalize(), component, version))
|
||||||
|
|
||||||
print("Current build status for this package:")
|
Logger.info("Current build status for this package:")
|
||||||
|
|
||||||
# Output list of arches for package and their status.
|
# Output list of arches for package and their status.
|
||||||
done = False
|
done = False
|
||||||
@ -182,29 +185,28 @@ def main():
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
done = True
|
done = True
|
||||||
print("%s: %s." % (build.arch_tag, build.buildstate))
|
Logger.info("%s: %s." % (build.arch_tag, build.buildstate))
|
||||||
if op == 'rescore':
|
if op == 'rescore':
|
||||||
if build.can_be_rescored:
|
if build.can_be_rescored:
|
||||||
# FIXME: make priority an option
|
# FIXME: make priority an option
|
||||||
priority = 5000
|
priority = 5000
|
||||||
print('Rescoring build %s to %d...'
|
Logger.info('Rescoring build %s to %d...' % (build.arch_tag, priority))
|
||||||
% (build.arch_tag, priority))
|
|
||||||
build.rescore(score=priority)
|
build.rescore(score=priority)
|
||||||
else:
|
else:
|
||||||
print('Cannot rescore build on %s.' % build.arch_tag)
|
Logger.info('Cannot rescore build on %s.' % build.arch_tag)
|
||||||
if op == 'retry':
|
if op == 'retry':
|
||||||
if build.can_be_retried:
|
if build.can_be_retried:
|
||||||
print('Retrying build on %s...' % build.arch_tag)
|
Logger.info('Retrying build on %s...' % build.arch_tag)
|
||||||
build.retry()
|
build.retry()
|
||||||
else:
|
else:
|
||||||
print('Cannot retry build on %s.' % build.arch_tag)
|
Logger.info('Cannot retry build on %s.' % build.arch_tag)
|
||||||
|
|
||||||
# We are done
|
# We are done
|
||||||
if done:
|
if done:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
print(("No builds for '%s' found in the %s release - it may have been "
|
Logger.info("No builds for '%s' found in the %s release" % (package, release.capitalize()))
|
||||||
"built in a former release.") % (package, release.capitalize()))
|
Logger.info("It may have been built in a former release.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Batch mode
|
# Batch mode
|
||||||
@ -225,14 +227,14 @@ def main():
|
|||||||
try:
|
try:
|
||||||
(release, pocket) = split_release_pocket(release)
|
(release, pocket) = split_release_pocket(release)
|
||||||
except PocketDoesNotExistError as error:
|
except PocketDoesNotExistError as error:
|
||||||
print('E: %s' % error)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
ubuntu_archive = Distribution('ubuntu').getArchive()
|
ubuntu_archive = Distribution('ubuntu').getArchive()
|
||||||
try:
|
try:
|
||||||
distroseries = Distribution('ubuntu').getSeries(release)
|
distroseries = Distribution('ubuntu').getSeries(release)
|
||||||
except SeriesNotFoundException as error:
|
except SeriesNotFoundException as error:
|
||||||
print(error)
|
Logger.error(error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
me = PersonTeam.me
|
me = PersonTeam.me
|
||||||
|
|
||||||
@ -241,14 +243,14 @@ def main():
|
|||||||
and me.isLpTeamMember('launchpad-buildd-admins'))
|
and me.isLpTeamMember('launchpad-buildd-admins'))
|
||||||
or False)
|
or False)
|
||||||
if options.priority and not can_rescore:
|
if options.priority and not can_rescore:
|
||||||
print("You don't have the permissions to rescore builds. "
|
Logger.error("You don't have the permissions to rescore "
|
||||||
"Ignoring your rescore request.", file=sys.stderr)
|
"builds. Ignoring your rescore request.")
|
||||||
|
|
||||||
for pkg in args:
|
for pkg in args:
|
||||||
try:
|
try:
|
||||||
pkg = ubuntu_archive.getSourcePackage(pkg, release, pocket)
|
pkg = ubuntu_archive.getSourcePackage(pkg, release, pocket)
|
||||||
except PackageNotFoundException as error:
|
except PackageNotFoundException as error:
|
||||||
print(error)
|
Logger.error(error)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check permissions (part 2): check upload permissions for the source
|
# Check permissions (part 2): check upload permissions for the source
|
||||||
@ -258,20 +260,20 @@ def main():
|
|||||||
pkg.getPackageName(),
|
pkg.getPackageName(),
|
||||||
pkg.getComponent())
|
pkg.getComponent())
|
||||||
if options.retry and not can_retry:
|
if options.retry and not can_retry:
|
||||||
print(("You don't have the permissions to retry the build of "
|
Logger.error("You don't have the permissions to retry the "
|
||||||
"'%s'. Ignoring your request.")
|
"build of '%s'. Ignoring your request."
|
||||||
% pkg.getPackageName(), file=sys.stderr)
|
% pkg.getPackageName())
|
||||||
|
|
||||||
print("The source version for '%s' in '%s' (%s) is: %s"
|
Logger.info("The source version for '%s' in '%s' (%s) is: %s" %
|
||||||
% (pkg.getPackageName(), release, pocket, pkg.getVersion()))
|
(pkg.getPackageName(), release, pocket, pkg.getVersion()))
|
||||||
|
|
||||||
print(pkg.getBuildStates(archs))
|
Logger.info(pkg.getBuildStates(archs))
|
||||||
if can_retry:
|
if can_retry:
|
||||||
print(pkg.retryBuilds(archs))
|
Logger.info(pkg.retryBuilds(archs))
|
||||||
if options.priority and can_rescore:
|
if options.priority and can_rescore:
|
||||||
print(pkg.rescoreBuilds(archs, options.priority))
|
Logger.info(pkg.rescoreBuilds(archs, options.priority))
|
||||||
|
|
||||||
print()
|
Logger.info('')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
18
ubuntu-iso
18
ubuntu-iso
@ -24,18 +24,21 @@ import optparse
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def extract(iso, path):
|
def extract(iso, path):
|
||||||
command = ['isoinfo', '-R', '-i', iso, '-x', path]
|
command = ['isoinfo', '-R', '-i', iso, '-x', path]
|
||||||
pipe = subprocess.Popen(command, stdout=subprocess.PIPE,
|
pipe = subprocess.run(command, encoding='utf-8',
|
||||||
stderr=subprocess.PIPE, encoding='utf-8')
|
stdout=subprocess.PIPE,
|
||||||
stdout, stderr = pipe.communicate()
|
stderr=subprocess.PIPE)
|
||||||
|
|
||||||
if pipe.returncode != 0:
|
if pipe.returncode != 0:
|
||||||
sys.stderr.write(stderr)
|
sys.stderr.write(pipe.stderr)
|
||||||
sys.exit(pipe.returncode)
|
sys.exit(pipe.returncode)
|
||||||
|
|
||||||
return stdout
|
return pipe.stdout
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -54,12 +57,11 @@ def main():
|
|||||||
version = extract(iso, '/.disk/info')
|
version = extract(iso, '/.disk/info')
|
||||||
|
|
||||||
if len(version) == 0:
|
if len(version) == 0:
|
||||||
print('%s does not appear to be an Ubuntu ISO' % iso,
|
Logger.error('%s does not appear to be an Ubuntu ISO' % iso)
|
||||||
file=sys.stderr)
|
|
||||||
err = True
|
err = True
|
||||||
continue
|
continue
|
||||||
|
|
||||||
print(prefix + version)
|
Logger.info(prefix + version)
|
||||||
|
|
||||||
if err:
|
if err:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -20,9 +20,11 @@ import sys
|
|||||||
from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam,
|
from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam,
|
||||||
Packageset, PackageNotFoundException,
|
Packageset, PackageNotFoundException,
|
||||||
SeriesNotFoundException)
|
SeriesNotFoundException)
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.misc import split_release_pocket
|
from ubuntutools.misc import split_release_pocket
|
||||||
|
|
||||||
|
from ubuntutools import getLogger
|
||||||
|
Logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments():
|
def parse_arguments():
|
||||||
'''Parse arguments and return (options, package)'''
|
'''Parse arguments and return (options, package)'''
|
||||||
@ -77,51 +79,49 @@ def main():
|
|||||||
|
|
||||||
component_uploader = archive.getUploadersForComponent(
|
component_uploader = archive.getUploadersForComponent(
|
||||||
component_name=component)[0]
|
component_name=component)[0]
|
||||||
print("All upload permissions for %s:" % package)
|
Logger.info("All upload permissions for %s:" % package)
|
||||||
print()
|
Logger.info("")
|
||||||
print("Component (%s)" % component)
|
Logger.info("Component (%s)" % component)
|
||||||
print("============" + ("=" * len(component)))
|
Logger.info("============" + ("=" * len(component)))
|
||||||
print_uploaders([component_uploader], options.list_team_members)
|
print_uploaders([component_uploader], options.list_team_members)
|
||||||
|
|
||||||
packagesets = sorted(Packageset.setsIncludingSource(
|
packagesets = sorted(Packageset.setsIncludingSource(
|
||||||
distroseries=series,
|
distroseries=series,
|
||||||
sourcepackagename=package))
|
sourcepackagename=package))
|
||||||
if packagesets:
|
if packagesets:
|
||||||
print()
|
Logger.info("")
|
||||||
print("Packagesets")
|
Logger.info("Packagesets")
|
||||||
print("===========")
|
Logger.info("===========")
|
||||||
for packageset in packagesets:
|
for packageset in packagesets:
|
||||||
print()
|
Logger.info("")
|
||||||
print("%s:" % packageset.name)
|
Logger.info("%s:" % packageset.name)
|
||||||
print_uploaders(archive.getUploadersForPackageset(
|
print_uploaders(archive.getUploadersForPackageset(
|
||||||
packageset=packageset), options.list_team_members)
|
packageset=packageset), options.list_team_members)
|
||||||
|
|
||||||
ppu_uploaders = archive.getUploadersForPackage(
|
ppu_uploaders = archive.getUploadersForPackage(
|
||||||
source_package_name=package)
|
source_package_name=package)
|
||||||
if ppu_uploaders:
|
if ppu_uploaders:
|
||||||
print()
|
Logger.info("")
|
||||||
print("Per-Package-Uploaders")
|
Logger.info("Per-Package-Uploaders")
|
||||||
print("=====================")
|
Logger.info("=====================")
|
||||||
print()
|
Logger.info("")
|
||||||
print_uploaders(ppu_uploaders, options.list_team_members)
|
print_uploaders(ppu_uploaders, options.list_team_members)
|
||||||
print()
|
Logger.info("")
|
||||||
|
|
||||||
if PersonTeam.me.canUploadPackage(archive, series, package, component,
|
if PersonTeam.me.canUploadPackage(archive, series, package, component,
|
||||||
pocket):
|
pocket):
|
||||||
print("You can upload %s to %s." % (package, options.release))
|
Logger.info("You can upload %s to %s." % (package, options.release))
|
||||||
else:
|
else:
|
||||||
print("You can not upload %s to %s, yourself."
|
Logger.info("You can not upload %s to %s, yourself." % (package, options.release))
|
||||||
% (package, options.release))
|
|
||||||
if (series.status in ('Current Stable Release', 'Supported', 'Obsolete')
|
if (series.status in ('Current Stable Release', 'Supported', 'Obsolete')
|
||||||
and pocket == 'Release'):
|
and pocket == 'Release'):
|
||||||
print(("%s is in the '%s' state. You may want to query the "
|
Logger.info("%s is in the '%s' state. You may want to query the %s-proposed pocket." %
|
||||||
"%s-proposed pocket.")
|
(release, series.status, release))
|
||||||
% (release, series.status, release))
|
|
||||||
else:
|
else:
|
||||||
print("But you can still contribute to it via the sponsorship "
|
Logger.info("But you can still contribute to it via the sponsorship "
|
||||||
"process: https://wiki.ubuntu.com/SponsorshipProcess")
|
"process: https://wiki.ubuntu.com/SponsorshipProcess")
|
||||||
if not options.list_uploaders:
|
if not options.list_uploaders:
|
||||||
print("To see who has the necessary upload rights, "
|
Logger.info("To see who has the necessary upload rights, "
|
||||||
"use the --list-uploaders option.")
|
"use the --list-uploaders option.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@ -133,9 +133,9 @@ def print_uploaders(uploaders, expand_teams=False, prefix=''):
|
|||||||
recursion.
|
recursion.
|
||||||
"""
|
"""
|
||||||
for uploader in sorted(uploaders, key=lambda p: p.display_name):
|
for uploader in sorted(uploaders, key=lambda p: p.display_name):
|
||||||
print(("%s* %s (%s)%s" %
|
Logger.info("%s* %s (%s)%s" %
|
||||||
(prefix, uploader.display_name, uploader.name,
|
(prefix, uploader.display_name, uploader.name,
|
||||||
' [team]' if uploader.is_team else '')))
|
' [team]' if uploader.is_team else ''))
|
||||||
if expand_teams and uploader.is_team:
|
if expand_teams and uploader.is_team:
|
||||||
print_uploaders(uploader.participants, True, prefix=prefix + ' ')
|
print_uploaders(uploader.participants, True, prefix=prefix + ' ')
|
||||||
|
|
||||||
|
@ -2,3 +2,20 @@
|
|||||||
#
|
#
|
||||||
# Ubuntu Development Tools
|
# Ubuntu Development Tools
|
||||||
# https://launchpad.net/ubuntu-dev-tools
|
# https://launchpad.net/ubuntu-dev-tools
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
def _loggingBasicConfig(**kwargs):
|
||||||
|
'''Set log level to INFO and define log format to use.'''
|
||||||
|
if 'level' not in kwargs:
|
||||||
|
kwargs['level'] = logging.INFO
|
||||||
|
if 'format' not in kwargs:
|
||||||
|
kwargs['format'] = '%(message)s'
|
||||||
|
logging.basicConfig(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def getLogger(name=None):
|
||||||
|
'''Get standard Python logging.Logger with some ubuntutools defaults.'''
|
||||||
|
_loggingBasicConfig()
|
||||||
|
return logging.getLogger(name)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,8 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _build_preparation(result_directory):
|
def _build_preparation(result_directory):
|
||||||
@ -34,8 +35,7 @@ class Builder(object):
|
|||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
cmd = ["dpkg-architecture", "-qDEB_BUILD_ARCH_CPU"]
|
cmd = ["dpkg-architecture", "-qDEB_BUILD_ARCH_CPU"]
|
||||||
self.architecture = subprocess.check_output(
|
self.architecture = subprocess.check_output(cmd, encoding='utf-8').strip()
|
||||||
cmd, encoding='utf-8').strip()
|
|
||||||
|
|
||||||
def _build_failure(self, returncode, dsc_file):
|
def _build_failure(self, returncode, dsc_file):
|
||||||
if returncode != 0:
|
if returncode != 0:
|
||||||
@ -72,7 +72,7 @@ class Pbuilder(Builder):
|
|||||||
self.name, "--build",
|
self.name, "--build",
|
||||||
"--architecture", self.architecture, "--distribution", dist,
|
"--architecture", self.architecture, "--distribution", dist,
|
||||||
"--buildresult", result_directory, dsc_file]
|
"--buildresult", result_directory, dsc_file]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
returncode = subprocess.call(cmd)
|
returncode = subprocess.call(cmd)
|
||||||
return self._build_failure(returncode, dsc_file)
|
return self._build_failure(returncode, dsc_file)
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ class Pbuilder(Builder):
|
|||||||
cmd = ["sudo", "-E", "ARCH=" + self.architecture, "DIST=" + dist,
|
cmd = ["sudo", "-E", "ARCH=" + self.architecture, "DIST=" + dist,
|
||||||
self.name, "--update",
|
self.name, "--update",
|
||||||
"--architecture", self.architecture, "--distribution", dist]
|
"--architecture", self.architecture, "--distribution", dist]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
returncode = subprocess.call(cmd)
|
returncode = subprocess.call(cmd)
|
||||||
return self._update_failure(returncode, dist)
|
return self._update_failure(returncode, dist)
|
||||||
|
|
||||||
@ -93,13 +93,13 @@ class Pbuilderdist(Builder):
|
|||||||
_build_preparation(result_directory)
|
_build_preparation(result_directory)
|
||||||
cmd = [self.name, dist, self.architecture,
|
cmd = [self.name, dist, self.architecture,
|
||||||
"build", dsc_file, "--buildresult", result_directory]
|
"build", dsc_file, "--buildresult", result_directory]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
returncode = subprocess.call(cmd)
|
returncode = subprocess.call(cmd)
|
||||||
return self._build_failure(returncode, dsc_file)
|
return self._build_failure(returncode, dsc_file)
|
||||||
|
|
||||||
def update(self, dist):
|
def update(self, dist):
|
||||||
cmd = [self.name, dist, self.architecture, "update"]
|
cmd = [self.name, dist, self.architecture, "update"]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
returncode = subprocess.call(cmd)
|
returncode = subprocess.call(cmd)
|
||||||
return self._update_failure(returncode, dist)
|
return self._update_failure(returncode, dist)
|
||||||
|
|
||||||
@ -111,22 +111,21 @@ class Sbuild(Builder):
|
|||||||
def build(self, dsc_file, dist, result_directory):
|
def build(self, dsc_file, dist, result_directory):
|
||||||
_build_preparation(result_directory)
|
_build_preparation(result_directory)
|
||||||
workdir = os.getcwd()
|
workdir = os.getcwd()
|
||||||
Logger.command(["cd", result_directory])
|
Logger.debug("cd " + result_directory)
|
||||||
os.chdir(result_directory)
|
os.chdir(result_directory)
|
||||||
cmd = ["sbuild", "--arch-all", "--dist=" + dist,
|
cmd = ["sbuild", "--arch-all", "--dist=" + dist,
|
||||||
"--arch=" + self.architecture, dsc_file]
|
"--arch=" + self.architecture, dsc_file]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
returncode = subprocess.call(cmd)
|
returncode = subprocess.call(cmd)
|
||||||
Logger.command(["cd", workdir])
|
Logger.debug("cd " + workdir)
|
||||||
os.chdir(workdir)
|
os.chdir(workdir)
|
||||||
return self._build_failure(returncode, dsc_file)
|
return self._build_failure(returncode, dsc_file)
|
||||||
|
|
||||||
def update(self, dist):
|
def update(self, dist):
|
||||||
cmd = ["schroot", "--list"]
|
cmd = ["schroot", "--list"]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
process = subprocess.Popen(
|
process = subprocess.run(cmd, stdout=subprocess.PIPE, encoding='utf-8')
|
||||||
cmd, stdout=subprocess.PIPE, encoding='utf-8')
|
chroots, _ = process.stdout.strip().split()
|
||||||
chroots, _ = process.communicate()[0].strip().split()
|
|
||||||
if process.returncode != 0:
|
if process.returncode != 0:
|
||||||
return process.returncode
|
return process.returncode
|
||||||
|
|
||||||
@ -146,7 +145,7 @@ class Sbuild(Builder):
|
|||||||
["sbuild-clean", "-a", "-c"]]
|
["sbuild-clean", "-a", "-c"]]
|
||||||
for cmd in commands:
|
for cmd in commands:
|
||||||
# pylint: disable=W0631
|
# pylint: disable=W0631
|
||||||
Logger.command(cmd + [chroot])
|
Logger.debug(' '.join(cmd) + " " + chroot)
|
||||||
ret = subprocess.call(cmd + [chroot])
|
ret = subprocess.call(cmd + [chroot])
|
||||||
# pylint: enable=W0631
|
# pylint: enable=W0631
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
|
@ -23,7 +23,8 @@ import socket
|
|||||||
import sys
|
import sys
|
||||||
import locale
|
import locale
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class UDTConfig(object):
|
class UDTConfig(object):
|
||||||
@ -37,10 +38,12 @@ class UDTConfig(object):
|
|||||||
'BUILDER': 'pbuilder',
|
'BUILDER': 'pbuilder',
|
||||||
'DEBIAN_MIRROR': 'http://deb.debian.org/debian',
|
'DEBIAN_MIRROR': 'http://deb.debian.org/debian',
|
||||||
'DEBSEC_MIRROR': 'http://security.debian.org',
|
'DEBSEC_MIRROR': 'http://security.debian.org',
|
||||||
|
'DEBIAN_DDEBS_MIRROR': 'http://debug.mirrors.debian.org/debian-debug',
|
||||||
'LPINSTANCE': 'production',
|
'LPINSTANCE': 'production',
|
||||||
'MIRROR_FALLBACK': True,
|
'MIRROR_FALLBACK': True,
|
||||||
'UBUNTU_MIRROR': 'http://archive.ubuntu.com/ubuntu',
|
'UBUNTU_MIRROR': 'http://archive.ubuntu.com/ubuntu',
|
||||||
'UBUNTU_PORTS_MIRROR': 'http://ports.ubuntu.com',
|
'UBUNTU_PORTS_MIRROR': 'http://ports.ubuntu.com',
|
||||||
|
'UBUNTU_DDEBS_MIRROR': 'http://ddebs.ubuntu.com',
|
||||||
'UPDATE_BUILDER': False,
|
'UPDATE_BUILDER': False,
|
||||||
'WORKDIR': None,
|
'WORKDIR': None,
|
||||||
'KEYID': None,
|
'KEYID': None,
|
||||||
@ -69,7 +72,7 @@ class UDTConfig(object):
|
|||||||
for line in f:
|
for line in f:
|
||||||
parsed = shlex.split(line, comments=True)
|
parsed = shlex.split(line, comments=True)
|
||||||
if len(parsed) > 1:
|
if len(parsed) > 1:
|
||||||
Logger.warn('Cannot parse variable assignment in %s: %s',
|
Logger.warning('Cannot parse variable assignment in %s: %s',
|
||||||
getattr(f, 'name', '<config>'), line)
|
getattr(f, 'name', '<config>'), line)
|
||||||
if len(parsed) >= 1 and '=' in parsed[0]:
|
if len(parsed) >= 1 and '=' in parsed[0]:
|
||||||
key, value = parsed[0].split('=', 1)
|
key, value = parsed[0].split('=', 1)
|
||||||
@ -109,10 +112,8 @@ class UDTConfig(object):
|
|||||||
replacements = self.prefix + '_' + key
|
replacements = self.prefix + '_' + key
|
||||||
if key in self.defaults:
|
if key in self.defaults:
|
||||||
replacements += 'or UBUNTUTOOLS_' + key
|
replacements += 'or UBUNTUTOOLS_' + key
|
||||||
Logger.warn(
|
Logger.warning('Using deprecated configuration variable %s. '
|
||||||
'Using deprecated configuration variable %s. '
|
'You should use %s.', k, replacements)
|
||||||
'You should use %s.',
|
|
||||||
k, replacements)
|
|
||||||
return value
|
return value
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
#
|
|
||||||
# logger.py - A simple logging helper class
|
|
||||||
#
|
|
||||||
# Copyright (C) 2010, Benjamin Drung <bdrung@debian.org>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and/or distribute this software
|
|
||||||
# for any purpose with or without fee is hereby granted, provided
|
|
||||||
# that the above copyright notice and this permission notice appear
|
|
||||||
# in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
||||||
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
||||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
||||||
# AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
||||||
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
||||||
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def escape_arg(arg):
|
|
||||||
"""Shell-escpae arg, if necessary.
|
|
||||||
Fairly simplistic, doesn't escape anything except whitespace.
|
|
||||||
"""
|
|
||||||
if ' ' not in arg:
|
|
||||||
return arg
|
|
||||||
return '"%s"' % arg.replace('\\', r'\\').replace('"', r'\"')
|
|
||||||
|
|
||||||
|
|
||||||
class Logger(object):
|
|
||||||
script_name = os.path.basename(sys.argv[0])
|
|
||||||
verbose = False
|
|
||||||
|
|
||||||
stdout = sys.stdout
|
|
||||||
stderr = sys.stderr
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _print(cls, format_, message, args=None, stderr=False):
|
|
||||||
if args:
|
|
||||||
message = message % args
|
|
||||||
stream = cls.stderr if stderr else cls.stdout
|
|
||||||
stream.write((format_ + "\n") % (cls.script_name, message))
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def command(cls, cmd):
|
|
||||||
if cls.verbose:
|
|
||||||
cls._print("%s: I: %s", " ".join(escape_arg(arg) for arg in cmd))
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def debug(cls, message, *args):
|
|
||||||
if cls.verbose:
|
|
||||||
cls._print("%s: D: %s", message, args, stderr=True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def error(cls, message, *args):
|
|
||||||
cls._print("%s: Error: %s", message, args, stderr=True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def warn(cls, message, *args):
|
|
||||||
cls._print("%s: Warning: %s", message, args, stderr=True)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def info(cls, message, *args):
|
|
||||||
if cls.verbose:
|
|
||||||
cls._print("%s: I: %s", message, args)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def normal(cls, message, *args):
|
|
||||||
cls._print("%s: %s", message, args)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def set_verbosity(cls, verbose):
|
|
||||||
cls.verbose = verbose
|
|
@ -3,4 +3,4 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
service = 'production'
|
service = 'production'
|
||||||
api_version = '1.0'
|
api_version = 'devel'
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
# httplib2.debuglevel = 1
|
# httplib2.debuglevel = 1
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
import sys
|
import re
|
||||||
|
|
||||||
from debian.changelog import Changelog
|
from debian.changelog import Changelog
|
||||||
from httplib2 import Http, HttpLib2Error
|
from httplib2 import Http, HttpLib2Error
|
||||||
@ -36,6 +36,9 @@ from lazr.restfulclient.resource import Entry
|
|||||||
|
|
||||||
from ubuntutools.version import Version
|
from ubuntutools.version import Version
|
||||||
from ubuntutools.lp import (service, api_version)
|
from ubuntutools.lp import (service, api_version)
|
||||||
|
from ubuntutools.misc import (host_architecture,
|
||||||
|
DEFAULT_POCKETS, POCKETS,
|
||||||
|
DEFAULT_STATUSES, STATUSES)
|
||||||
from ubuntutools.lp.udtexceptions import (AlreadyLoggedInError,
|
from ubuntutools.lp.udtexceptions import (AlreadyLoggedInError,
|
||||||
ArchiveNotFoundException,
|
ArchiveNotFoundException,
|
||||||
ArchSeriesNotFoundException,
|
ArchSeriesNotFoundException,
|
||||||
@ -43,6 +46,9 @@ from ubuntutools.lp.udtexceptions import (AlreadyLoggedInError,
|
|||||||
PocketDoesNotExistError,
|
PocketDoesNotExistError,
|
||||||
SeriesNotFoundException)
|
SeriesNotFoundException)
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Archive',
|
'Archive',
|
||||||
@ -51,13 +57,12 @@ __all__ = [
|
|||||||
'Distribution',
|
'Distribution',
|
||||||
'DistributionSourcePackage',
|
'DistributionSourcePackage',
|
||||||
'DistroSeries',
|
'DistroSeries',
|
||||||
|
'DistroArchSeries',
|
||||||
'Launchpad',
|
'Launchpad',
|
||||||
'PersonTeam',
|
'PersonTeam',
|
||||||
'SourcePackagePublishingHistory',
|
'SourcePackagePublishingHistory',
|
||||||
]
|
]
|
||||||
|
|
||||||
_POCKETS = ('Release', 'Security', 'Updates', 'Proposed', 'Backports')
|
|
||||||
|
|
||||||
|
|
||||||
class _Launchpad(object):
|
class _Launchpad(object):
|
||||||
'''Singleton for LP API access.'''
|
'''Singleton for LP API access.'''
|
||||||
@ -69,7 +74,7 @@ class _Launchpad(object):
|
|||||||
self.__lp = LP.login_with('ubuntu-dev-tools', service,
|
self.__lp = LP.login_with('ubuntu-dev-tools', service,
|
||||||
version=api_version)
|
version=api_version)
|
||||||
except IOError as error:
|
except IOError as error:
|
||||||
print('E: %s' % error, file=sys.stderr)
|
Logger.error(str(error))
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
raise AlreadyLoggedInError('Already logged in to Launchpad.')
|
raise AlreadyLoggedInError('Already logged in to Launchpad.')
|
||||||
@ -150,6 +155,7 @@ class BaseWrapper(object, metaclass=MetaWrapper):
|
|||||||
cached._lpobject = data
|
cached._lpobject = data
|
||||||
# and add it to our cache
|
# and add it to our cache
|
||||||
cls._cache[data.self_link] = cached
|
cls._cache[data.self_link] = cached
|
||||||
|
Logger.debug("%s: %s" % (cls.__name__, data.self_link))
|
||||||
# add additional class specific caching (if available)
|
# add additional class specific caching (if available)
|
||||||
cache = getattr(cls, 'cache', None)
|
cache = getattr(cls, 'cache', None)
|
||||||
if isinstance(cache, collections.Callable):
|
if isinstance(cache, collections.Callable):
|
||||||
@ -188,15 +194,23 @@ class Distribution(BaseWrapper):
|
|||||||
resource_type = 'distribution'
|
resource_type = 'distribution'
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
# Don't share _series and _archives between different Distributions
|
|
||||||
if '_series' not in self.__dict__:
|
|
||||||
self._series = dict()
|
|
||||||
if '_archives' not in self.__dict__:
|
|
||||||
self._archives = dict()
|
self._archives = dict()
|
||||||
|
self._series_by_name = dict()
|
||||||
|
self._series = dict()
|
||||||
|
self._dev_series = None
|
||||||
|
self._have_all_series = False
|
||||||
|
|
||||||
def cache(self):
|
def cache(self):
|
||||||
self._cache[self.name] = self
|
self._cache[self.name] = self
|
||||||
|
|
||||||
|
def _cache_series(self, series):
|
||||||
|
'''
|
||||||
|
Add the DistroSeries to the cache if needed.
|
||||||
|
'''
|
||||||
|
if series.version not in self._series:
|
||||||
|
self._series_by_name[series.name] = series
|
||||||
|
self._series[series.version] = series
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fetch(cls, dist):
|
def fetch(cls, dist):
|
||||||
'''
|
'''
|
||||||
@ -243,28 +257,49 @@ class Distribution(BaseWrapper):
|
|||||||
(e.g. 'karmic') or version (e.g. '9.10').
|
(e.g. 'karmic') or version (e.g. '9.10').
|
||||||
If the series is not found: raise SeriesNotFoundException
|
If the series is not found: raise SeriesNotFoundException
|
||||||
'''
|
'''
|
||||||
if name_or_version not in self._series:
|
if name_or_version in self._series:
|
||||||
|
return self._series[name_or_version]
|
||||||
|
if name_or_version in self._series_by_name:
|
||||||
|
return self._series_by_name[name_or_version]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
series = DistroSeries(self().getSeries(name_or_version=name_or_version))
|
series = DistroSeries(self().getSeries(name_or_version=name_or_version))
|
||||||
# Cache with name and version
|
|
||||||
self._series[series.name] = series
|
|
||||||
self._series[series.version] = series
|
|
||||||
except HTTPError:
|
except HTTPError:
|
||||||
message = "Release '%s' is unknown in '%s'." % \
|
message = "Release '%s' is unknown in '%s'." % \
|
||||||
(name_or_version, self.display_name)
|
(name_or_version, self.display_name)
|
||||||
raise SeriesNotFoundException(message)
|
raise SeriesNotFoundException(message)
|
||||||
return self._series[name_or_version]
|
|
||||||
|
self._cache_series(series)
|
||||||
|
return series
|
||||||
|
|
||||||
def getDevelopmentSeries(self):
|
def getDevelopmentSeries(self):
|
||||||
'''
|
'''
|
||||||
Returns a DistroSeries object of the current development series.
|
Returns a DistroSeries object of the current development series.
|
||||||
'''
|
'''
|
||||||
dev = DistroSeries(self.current_series_link)
|
if not self._dev_series:
|
||||||
# Cache it in _series if not already done
|
series = DistroSeries(self.current_series_link)
|
||||||
if dev.name not in self._series:
|
self._cache_series(series)
|
||||||
self._series[dev.name] = dev
|
self._dev_series = series
|
||||||
self._series[dev.version] = dev
|
return self._dev_series
|
||||||
return dev
|
|
||||||
|
def getAllSeries(self, active=True):
|
||||||
|
'''
|
||||||
|
Returns a list of all DistroSeries objects.
|
||||||
|
'''
|
||||||
|
if not self._have_all_series:
|
||||||
|
for s in Launchpad.load(self.series_collection_link).entries:
|
||||||
|
series = DistroSeries(s['self_link'])
|
||||||
|
self._cache_series(series)
|
||||||
|
self._have_all_series = True
|
||||||
|
|
||||||
|
allseries = filter(lambda s: s.active, self._series.values())
|
||||||
|
allseries = sorted(allseries,
|
||||||
|
key=lambda s: float(s.version),
|
||||||
|
reverse=True)
|
||||||
|
Logger.debug("Found series: %s" % ", ".join(map(lambda s: "%s (%s)" %
|
||||||
|
(s.name, s.version),
|
||||||
|
allseries)))
|
||||||
|
return collections.OrderedDict((s.name, s) for s in allseries)
|
||||||
|
|
||||||
|
|
||||||
class DistroArchSeries(BaseWrapper):
|
class DistroArchSeries(BaseWrapper):
|
||||||
@ -273,6 +308,12 @@ class DistroArchSeries(BaseWrapper):
|
|||||||
'''
|
'''
|
||||||
resource_type = 'distro_arch_series'
|
resource_type = 'distro_arch_series'
|
||||||
|
|
||||||
|
def getSeries(self):
|
||||||
|
'''
|
||||||
|
Get DistroSeries for this.
|
||||||
|
'''
|
||||||
|
return DistroSeries(self._lpobject.distroseries_link)
|
||||||
|
|
||||||
|
|
||||||
class DistroSeries(BaseWrapper):
|
class DistroSeries(BaseWrapper):
|
||||||
'''
|
'''
|
||||||
@ -284,12 +325,16 @@ class DistroSeries(BaseWrapper):
|
|||||||
if "_architectures" not in self.__dict__:
|
if "_architectures" not in self.__dict__:
|
||||||
self._architectures = dict()
|
self._architectures = dict()
|
||||||
|
|
||||||
def getArchSeries(self, archtag):
|
def getArchSeries(self, archtag=None):
|
||||||
'''
|
'''
|
||||||
Returns a DistroArchSeries object for an architecture passed by name
|
Returns a DistroArchSeries object for an architecture passed by name
|
||||||
(e.g. 'amd64').
|
(e.g. 'amd64').
|
||||||
|
If arch is not specified, get the DistroArchSeries for the system arch.
|
||||||
|
The special archtag 'all' will get the system arch.
|
||||||
If the architecture is not found: raise ArchSeriesNotFoundException.
|
If the architecture is not found: raise ArchSeriesNotFoundException.
|
||||||
'''
|
'''
|
||||||
|
if not archtag or archtag == 'all':
|
||||||
|
archtag = host_architecture()
|
||||||
if archtag not in self._architectures:
|
if archtag not in self._architectures:
|
||||||
try:
|
try:
|
||||||
architecture = DistroArchSeries(
|
architecture = DistroArchSeries(
|
||||||
@ -315,16 +360,35 @@ class Archive(BaseWrapper):
|
|||||||
self._pkgset_uploaders = {}
|
self._pkgset_uploaders = {}
|
||||||
self._component_uploaders = {}
|
self._component_uploaders = {}
|
||||||
|
|
||||||
def getSourcePackage(self, name, series=None, pocket=None):
|
def getSourcePackage(self, name, series=None, pocket=None, version=None,
|
||||||
|
status=None, wrapper=None, search_all_series=False):
|
||||||
'''
|
'''
|
||||||
Returns a SourcePackagePublishingHistory object for the most
|
Returns a SourcePackagePublishingHistory object for the most
|
||||||
recent source package in the distribution 'dist', series and
|
recent source package in the distribution 'dist', series and
|
||||||
pocket.
|
pocket.
|
||||||
|
|
||||||
series defaults to the current development series if not specified.
|
series defaults to the current development series if not specified.
|
||||||
|
series must be either a series name string, or DistroSeries object.
|
||||||
|
|
||||||
pocket may be a list, if so, the highest version will be returned.
|
version may be specified to get only the exact version requested.
|
||||||
It defaults to all pockets except backports.
|
|
||||||
|
pocket may be a string or a list. If no version is provided, it
|
||||||
|
defaults to all pockets except 'Backports'; if searching for a
|
||||||
|
specific version, it defaults to all pockets. Pocket strings must
|
||||||
|
be capitalized.
|
||||||
|
|
||||||
|
status may be a string or a list. If no version is provided, it
|
||||||
|
defaults to only 'Pending' and 'Published'; if searching for a
|
||||||
|
specific version, it defaults to all statuses. Status strings must
|
||||||
|
be capitalized.
|
||||||
|
|
||||||
|
wrapper is the class to return an instance of; defaults to
|
||||||
|
SourcePackagePublishingHistory.
|
||||||
|
|
||||||
|
search_all_series is used if series is None. If False, this will
|
||||||
|
search only the latest devel series, and if True all series
|
||||||
|
will be searched, in reverse order, starting with the latest
|
||||||
|
devel series. Defaults to False.
|
||||||
|
|
||||||
If the requested source package doesn't exist a
|
If the requested source package doesn't exist a
|
||||||
PackageNotFoundException is raised.
|
PackageNotFoundException is raised.
|
||||||
@ -332,114 +396,237 @@ class Archive(BaseWrapper):
|
|||||||
return self._getPublishedItem(name, series, pocket, cache=self._srcpkgs,
|
return self._getPublishedItem(name, series, pocket, cache=self._srcpkgs,
|
||||||
function='getPublishedSources',
|
function='getPublishedSources',
|
||||||
name_key='source_name',
|
name_key='source_name',
|
||||||
wrapper=SourcePackagePublishingHistory)
|
wrapper=wrapper or SourcePackagePublishingHistory,
|
||||||
|
version=version,
|
||||||
|
status=status,
|
||||||
|
search_all_series=search_all_series,
|
||||||
|
binary=False)
|
||||||
|
|
||||||
def getBinaryPackage(self, name, archtag=None, series=None, pocket=None):
|
def getBinaryPackage(self, name, archtag=None, series=None, pocket=None,
|
||||||
|
version=None, status=None, wrapper=None,
|
||||||
|
search_all_series=False):
|
||||||
'''
|
'''
|
||||||
Returns a BinaryPackagePublishingHistory object for the most
|
Returns a BinaryPackagePublishingHistory object for the most
|
||||||
recent source package in the distribution 'dist', architecture
|
recent source package in the distribution 'dist', architecture
|
||||||
'archtag', series and pocket.
|
'archtag', series and pocket.
|
||||||
|
|
||||||
series defaults to the current development series if not specified.
|
series defaults to the current development series if not specified.
|
||||||
|
series must be either a series name string, or DistroArchSeries object.
|
||||||
|
series may be omitted if version is specified.
|
||||||
|
|
||||||
pocket may be a list, if so, the highest version will be returned.
|
version may be specified to get only the exact version requested.
|
||||||
It defaults to all pockets except backports.
|
|
||||||
|
pocket may be a string or a list. If no version is provided, it
|
||||||
|
defaults to all pockets except 'Backports'; if searching for a
|
||||||
|
specific version, it defaults to all pockets. Pocket strings must
|
||||||
|
be capitalized.
|
||||||
|
|
||||||
|
status may be a string or a list. If no version is provided, it
|
||||||
|
defaults to only 'Pending' and 'Published'; if searching for a
|
||||||
|
specific version, it defaults to all statuses. Status strings must
|
||||||
|
be capitalized.
|
||||||
|
|
||||||
|
wrapper is the class to return an instance of; defaults to
|
||||||
|
BinaryPackagePublishingHistory.
|
||||||
|
|
||||||
|
search_all_series is used if series is None. If False, this will
|
||||||
|
search only the latest devel series, and if True all series
|
||||||
|
will be searched, in reverse order, starting with the latest
|
||||||
|
devel series. Defaults to False.
|
||||||
|
|
||||||
If the requested binary package doesn't exist a
|
If the requested binary package doesn't exist a
|
||||||
PackageNotFoundException is raised.
|
PackageNotFoundException is raised.
|
||||||
'''
|
'''
|
||||||
if archtag is None:
|
|
||||||
archtag = []
|
|
||||||
return self._getPublishedItem(name, series, pocket, archtag=archtag,
|
return self._getPublishedItem(name, series, pocket, archtag=archtag,
|
||||||
cache=self._binpkgs,
|
cache=self._binpkgs,
|
||||||
function='getPublishedBinaries',
|
function='getPublishedBinaries',
|
||||||
name_key='binary_name',
|
name_key='binary_name',
|
||||||
wrapper=BinaryPackagePublishingHistory)
|
wrapper=wrapper or BinaryPackagePublishingHistory,
|
||||||
|
version=version,
|
||||||
|
status=status,
|
||||||
|
search_all_series=search_all_series,
|
||||||
|
binary=True)
|
||||||
|
|
||||||
def _getPublishedItem(self, name, series, pocket, cache,
|
def _getPublishedItem(self, name, series, pocket, cache,
|
||||||
function, name_key, wrapper, archtag=None):
|
function, name_key, wrapper, archtag=None,
|
||||||
'''Common code between getSourcePackage and getBinaryPackage
|
version=None, status=None, search_all_series=False,
|
||||||
|
binary=False):
|
||||||
'''
|
'''
|
||||||
if pocket is None:
|
Common code between getSourcePackage and getBinaryPackage.
|
||||||
pockets = frozenset(('Proposed', 'Updates', 'Security', 'Release'))
|
|
||||||
elif isinstance(pocket, str):
|
|
||||||
pockets = frozenset((pocket,))
|
|
||||||
else:
|
|
||||||
pockets = frozenset(pocket)
|
|
||||||
|
|
||||||
for pocket in pockets:
|
Don't use this directly.
|
||||||
if pocket not in _POCKETS:
|
'''
|
||||||
raise PocketDoesNotExistError("Pocket '%s' does not exist." %
|
if not pocket:
|
||||||
pocket)
|
if version and not series:
|
||||||
|
# check ALL pockets if specific version in any series
|
||||||
|
pockets = POCKETS
|
||||||
|
else:
|
||||||
|
# otherwise, check all pockets EXCEPT 'Backports'
|
||||||
|
pockets = DEFAULT_POCKETS
|
||||||
|
elif isinstance(pocket, str):
|
||||||
|
pockets = (pocket,)
|
||||||
|
else:
|
||||||
|
pockets = tuple(pocket)
|
||||||
|
|
||||||
|
for p in pockets:
|
||||||
|
if p not in POCKETS:
|
||||||
|
raise PocketDoesNotExistError("Pocket '%s' does not exist." % p)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
if version:
|
||||||
|
# check ALL statuses if specific version
|
||||||
|
statuses = STATUSES
|
||||||
|
else:
|
||||||
|
# otherwise, only check 'Pending' and 'Published'
|
||||||
|
statuses = DEFAULT_STATUSES
|
||||||
|
elif isinstance(status, str):
|
||||||
|
statuses = (status,)
|
||||||
|
else:
|
||||||
|
statuses = tuple(status)
|
||||||
|
|
||||||
|
for s in statuses:
|
||||||
|
if s not in STATUSES:
|
||||||
|
raise ValueError("Status '%s' is not valid." % s)
|
||||||
|
|
||||||
dist = Distribution(self.distribution_link)
|
dist = Distribution(self.distribution_link)
|
||||||
# Check if series is already a DistroSeries object or not
|
|
||||||
if not isinstance(series, DistroSeries):
|
# please don't pass DistroArchSeries as archtag!
|
||||||
if series:
|
# but, the code was like that before so keep
|
||||||
|
# backwards compatibility.
|
||||||
|
if isinstance(archtag, DistroArchSeries):
|
||||||
|
series = archtag
|
||||||
|
archtag = None
|
||||||
|
|
||||||
|
series_to_check = [series]
|
||||||
|
if not version and not series:
|
||||||
|
# if neither version or series are specified, use either the
|
||||||
|
# devel series or search all series
|
||||||
|
if search_all_series:
|
||||||
|
series_to_check = dist.getAllSeries().values()
|
||||||
|
else:
|
||||||
|
series_to_check = [dist.getDevelopmentSeries()]
|
||||||
|
|
||||||
|
# check each series - if only version was provided, series will be None
|
||||||
|
for series in series_to_check:
|
||||||
|
arch_series = None
|
||||||
|
|
||||||
|
if isinstance(series, DistroArchSeries):
|
||||||
|
arch_series = series
|
||||||
|
series = series.getSeries()
|
||||||
|
elif isinstance(series, DistroSeries):
|
||||||
|
pass
|
||||||
|
elif series:
|
||||||
series = dist.getSeries(series)
|
series = dist.getSeries(series)
|
||||||
else:
|
|
||||||
series = dist.getDevelopmentSeries()
|
|
||||||
|
|
||||||
# getPublishedSources requires a distro_series, while
|
if binary:
|
||||||
# getPublishedBinaries requires a distro_arch_series.
|
if arch_series is None and series:
|
||||||
# If archtag is not None, I'll assume it's getPublishedBinaries.
|
|
||||||
if archtag is not None and archtag != []:
|
|
||||||
if not isinstance(archtag, DistroArchSeries):
|
|
||||||
arch_series = series.getArchSeries(archtag=archtag)
|
arch_series = series.getArchSeries(archtag=archtag)
|
||||||
else:
|
if archtag is None and arch_series:
|
||||||
arch_series = archtag
|
archtag = arch_series.architecture_tag
|
||||||
|
if archtag is None:
|
||||||
|
archtag = host_architecture()
|
||||||
|
|
||||||
if archtag is not None and archtag != []:
|
index = (name, getattr(series, 'name', None), archtag, pockets, statuses, version)
|
||||||
index = (name, series.name, archtag, pockets)
|
|
||||||
else:
|
if index in cache:
|
||||||
index = (name, series.name, pockets)
|
return cache[index]
|
||||||
|
|
||||||
if index not in cache:
|
|
||||||
params = {
|
params = {
|
||||||
name_key: name,
|
name_key: name,
|
||||||
'status': 'Published',
|
|
||||||
'exact_match': True,
|
'exact_match': True,
|
||||||
}
|
}
|
||||||
if archtag is not None and archtag != []:
|
|
||||||
|
if arch_series:
|
||||||
params['distro_arch_series'] = arch_series()
|
params['distro_arch_series'] = arch_series()
|
||||||
else:
|
elif series:
|
||||||
params['distro_series'] = series()
|
params['distro_series'] = series()
|
||||||
|
|
||||||
if len(pockets) == 1:
|
if len(pockets) == 1:
|
||||||
params['pocket'] = list(pockets)[0]
|
params['pocket'] = pockets[0]
|
||||||
|
|
||||||
|
if len(statuses) == 1:
|
||||||
|
params['status'] = statuses[0]
|
||||||
|
|
||||||
|
if version:
|
||||||
|
params['version'] = version
|
||||||
|
|
||||||
|
Logger.debug('Calling %s(%s)' % (function,
|
||||||
|
', '.join(['%s=%s' % (k, v)
|
||||||
|
for (k, v) in params.items()])))
|
||||||
records = getattr(self, function)(**params)
|
records = getattr(self, function)(**params)
|
||||||
|
|
||||||
latest = None
|
err_msg = ("does not exist in the %s %s archive" %
|
||||||
for record in records:
|
(dist.display_name, self.name))
|
||||||
if record.pocket not in pockets:
|
|
||||||
continue
|
for record in records:
|
||||||
if latest is None or (Version(latest.source_package_version)
|
if binary:
|
||||||
< Version(record.source_package_version)):
|
rversion = getattr(record, 'binary_package_version', None)
|
||||||
latest = record
|
else:
|
||||||
|
rversion = getattr(record, 'source_package_version', None)
|
||||||
|
skipmsg = ('Skipping version %s: ' % rversion)
|
||||||
|
|
||||||
|
if record.pocket not in pockets:
|
||||||
|
err_msg = 'pocket %s not in (%s)' % (record.pocket, ','.join(pockets))
|
||||||
|
Logger.debug(skipmsg + err_msg)
|
||||||
|
continue
|
||||||
|
if record.status not in statuses:
|
||||||
|
err_msg = 'status %s not in (%s)' % (record.status, ','.join(statuses))
|
||||||
|
Logger.debug(skipmsg + err_msg)
|
||||||
|
continue
|
||||||
|
r = wrapper(record)
|
||||||
|
if binary and archtag and archtag != r.arch:
|
||||||
|
err_msg = 'arch %s does not match requested arch %s' % (r.arch, archtag)
|
||||||
|
Logger.debug(skipmsg + err_msg)
|
||||||
|
continue
|
||||||
|
# results are ordered so first is latest
|
||||||
|
cache[index] = r
|
||||||
|
return r
|
||||||
|
|
||||||
|
version_with_epoch = None
|
||||||
|
if version and version == Version(version).strip_epoch() and len(records) == 0:
|
||||||
|
# a specific version was asked for, but we found none;
|
||||||
|
# check if one exists with an epoch to give a hint in error msg
|
||||||
|
for epoch in range(1, 9):
|
||||||
|
v = Version(version)
|
||||||
|
v.epoch = epoch
|
||||||
|
params['version'] = v.full_version
|
||||||
|
if len(getattr(self, function)(**params)) > 0:
|
||||||
|
version_with_epoch = v.full_version
|
||||||
|
Logger.debug('Found version with epoch %s' % version_with_epoch)
|
||||||
|
break
|
||||||
|
|
||||||
if latest is None:
|
|
||||||
if name_key == 'binary_name':
|
if name_key == 'binary_name':
|
||||||
package_type = "binary package"
|
package_type = "binary package"
|
||||||
elif name_key == 'source_name':
|
elif name_key == 'source_name':
|
||||||
package_type = "source package"
|
package_type = "source package"
|
||||||
else:
|
else:
|
||||||
package_type = "package"
|
package_type = "package"
|
||||||
msg = ("The %s '%s' does not exist in the %s %s archive" %
|
msg = "The %s '%s' " % (package_type, name)
|
||||||
(package_type, name, dist.display_name, self.name))
|
if version:
|
||||||
if archtag is not None and archtag != []:
|
msg += "version %s " % version
|
||||||
|
msg += err_msg
|
||||||
|
if binary and archtag:
|
||||||
msg += " for architecture %s" % archtag
|
msg += " for architecture %s" % archtag
|
||||||
pockets = [series.name if pocket == 'Release'
|
if len(series_to_check) > 1:
|
||||||
else '%s-%s' % (series.name, pocket.lower())
|
msg += " in any release"
|
||||||
for pocket in pockets]
|
if len(pockets) == 1:
|
||||||
if len(pockets) > 1:
|
msg += " for pocket %s" % pockets[0]
|
||||||
pockets[-2:] = [' or '.join(pockets[-2:])]
|
elif len(pockets) != len(POCKETS):
|
||||||
msg += " in " + ', '.join(pockets)
|
msg += " for pockets " + ', '.join(pockets)
|
||||||
|
elif series:
|
||||||
|
msg += " in %s" % series.name
|
||||||
|
if len(pockets) == 1:
|
||||||
|
msg += "-%s" % pockets[0]
|
||||||
|
elif len(pockets) != len(POCKETS):
|
||||||
|
msg += " for pockets " + ', '.join(pockets)
|
||||||
|
if len(statuses) == 1:
|
||||||
|
msg += " with status %s" % statuses[0]
|
||||||
|
elif len(statuses) != len(STATUSES):
|
||||||
|
msg += " with status in " + ', '.join(statuses)
|
||||||
|
if version_with_epoch:
|
||||||
|
msg += " (did you forget the epoch? try %s)" % version_with_epoch
|
||||||
raise PackageNotFoundException(msg)
|
raise PackageNotFoundException(msg)
|
||||||
|
|
||||||
cache[index] = wrapper(latest)
|
|
||||||
return cache[index]
|
|
||||||
|
|
||||||
def copyPackage(self, source_name, version, from_archive, to_pocket,
|
def copyPackage(self, source_name, version, from_archive, to_pocket,
|
||||||
to_series=None, sponsored=None, include_binaries=False):
|
to_series=None, sponsored=None, include_binaries=False):
|
||||||
'''Copy a single named source into this archive.
|
'''Copy a single named source into this archive.
|
||||||
@ -509,13 +696,24 @@ class SourcePackagePublishingHistory(BaseWrapper):
|
|||||||
resource_type = 'source_package_publishing_history'
|
resource_type = 'source_package_publishing_history'
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
|
self._archive = None
|
||||||
self._changelog = None
|
self._changelog = None
|
||||||
self._binaries = None
|
self._binaries = {}
|
||||||
|
self._have_all_binaries = False
|
||||||
|
self._distro_series = None
|
||||||
# Don't share _builds between different
|
# Don't share _builds between different
|
||||||
# SourcePackagePublishingHistory objects
|
# SourcePackagePublishingHistory objects
|
||||||
if '_builds' not in self.__dict__:
|
if '_builds' not in self.__dict__:
|
||||||
self._builds = dict()
|
self._builds = dict()
|
||||||
|
|
||||||
|
def getDistroSeries(self):
|
||||||
|
'''
|
||||||
|
Return the DistroSeries.
|
||||||
|
'''
|
||||||
|
if not self._distro_series:
|
||||||
|
self._distro_series = DistroSeries(self._lpobject.distro_series_link)
|
||||||
|
return self._distro_series
|
||||||
|
|
||||||
def getPackageName(self):
|
def getPackageName(self):
|
||||||
'''
|
'''
|
||||||
Returns the source package name.
|
Returns the source package name.
|
||||||
@ -534,16 +732,33 @@ class SourcePackagePublishingHistory(BaseWrapper):
|
|||||||
'''
|
'''
|
||||||
return self._lpobject.component_name
|
return self._lpobject.component_name
|
||||||
|
|
||||||
|
def getSeriesName(self):
|
||||||
|
'''
|
||||||
|
Returns the series
|
||||||
|
|
||||||
|
Named getSeriesName() to avoid confusion with
|
||||||
|
getDistroSeries()
|
||||||
|
'''
|
||||||
|
return self.getDistroSeries().name
|
||||||
|
|
||||||
def getSeriesAndPocket(self):
|
def getSeriesAndPocket(self):
|
||||||
'''
|
'''
|
||||||
Returns a human-readable release-pocket
|
Returns a human-readable release-pocket
|
||||||
'''
|
'''
|
||||||
series = DistroSeries(self._lpobject.distro_series_link)
|
release = self.getSeriesName()
|
||||||
release = series.name
|
if self.pocket != 'Release':
|
||||||
if self._lpobject.pocket != 'Release':
|
release += '-' + self.pocket.lower()
|
||||||
release += '-' + self._lpobject.pocket.lower()
|
|
||||||
return release
|
return release
|
||||||
|
|
||||||
|
def getArchive(self):
|
||||||
|
'''
|
||||||
|
Get this SPPH's archive.
|
||||||
|
'''
|
||||||
|
if not self._archive:
|
||||||
|
self._archive = Archive(self._lpobject.archive_link)
|
||||||
|
|
||||||
|
return self._archive
|
||||||
|
|
||||||
def getChangelog(self, since_version=None):
|
def getChangelog(self, since_version=None):
|
||||||
'''
|
'''
|
||||||
Return the changelog, optionally since a particular version
|
Return the changelog, optionally since a particular version
|
||||||
@ -553,17 +768,17 @@ class SourcePackagePublishingHistory(BaseWrapper):
|
|||||||
if self._changelog is None:
|
if self._changelog is None:
|
||||||
url = self._lpobject.changelogUrl()
|
url = self._lpobject.changelogUrl()
|
||||||
if url is None:
|
if url is None:
|
||||||
print('E: No changelog available for %s %s' %
|
Logger.error('No changelog available for %s %s' %
|
||||||
(self.getPackageName(), self.getVersion()), file=sys.stderr)
|
(self.getPackageName(), self.getVersion()))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response, changelog = Http().request(url)
|
response, changelog = Http().request(url)
|
||||||
except HttpLib2Error as e:
|
except HttpLib2Error as e:
|
||||||
print(str(e), file=sys.stderr)
|
Logger.error(str(e))
|
||||||
return None
|
return None
|
||||||
if response.status != 200:
|
if response.status != 200:
|
||||||
print('%s: %s %s' % (url, response.status, response.reason), file=sys.stderr)
|
Logger.error('%s: %s %s' % (url, response.status, response.reason))
|
||||||
return None
|
return None
|
||||||
self._changelog = changelog
|
self._changelog = changelog
|
||||||
|
|
||||||
@ -580,15 +795,97 @@ class SourcePackagePublishingHistory(BaseWrapper):
|
|||||||
new_entries.append(str(block))
|
new_entries.append(str(block))
|
||||||
return ''.join(new_entries)
|
return ''.join(new_entries)
|
||||||
|
|
||||||
def getBinaries(self):
|
def getBinaries(self, arch, name=None, ext=None):
|
||||||
'''
|
'''
|
||||||
Returns the resulting BinaryPackagePublishingHistorys
|
Returns the resulting BinaryPackagePublishingHistorys.
|
||||||
|
Must specify arch, or use 'all' to get all archs.
|
||||||
|
|
||||||
|
If name is specified, only returns BPPH matching that (regex) name.
|
||||||
|
|
||||||
|
If ext is specified, only returns BPPH matching that (regex) ext.
|
||||||
'''
|
'''
|
||||||
if self._binaries is None:
|
if not arch:
|
||||||
self._binaries = [BinaryPackagePublishingHistory(bpph)
|
raise RuntimeError("Must specify arch")
|
||||||
for bpph in
|
|
||||||
self._lpobject.getPublishedBinaries()]
|
# debs with arch 'all' have to be categorized as a specific arch
|
||||||
return self._binaries
|
# so use requested arch if not 'all', or system arch
|
||||||
|
fallback_arch = arch
|
||||||
|
if fallback_arch == 'all':
|
||||||
|
fallback_arch = host_architecture()
|
||||||
|
|
||||||
|
if self._have_all_binaries:
|
||||||
|
# Great!
|
||||||
|
pass
|
||||||
|
elif self.status in ["Pending", "Published"]:
|
||||||
|
# Published, great! Directly query the list of binaries
|
||||||
|
binaries = map(BinaryPackagePublishingHistory,
|
||||||
|
self._lpobject.getPublishedBinaries())
|
||||||
|
for b in binaries:
|
||||||
|
a = b.arch
|
||||||
|
if a == 'all':
|
||||||
|
a = fallback_arch
|
||||||
|
if a not in self._binaries:
|
||||||
|
self._binaries[a] = {}
|
||||||
|
self._binaries[a][b.binary_package_name] = b
|
||||||
|
self._have_all_binaries = True
|
||||||
|
else:
|
||||||
|
# we have to go the long way :(
|
||||||
|
Logger.info("Please wait, this may take some time...")
|
||||||
|
archive = self.getArchive()
|
||||||
|
urls = self.binaryFileUrls()
|
||||||
|
for url in urls:
|
||||||
|
# strip out the URL leading text.
|
||||||
|
filename = url.rsplit('/', 1)[1]
|
||||||
|
# strip the file suffix
|
||||||
|
(pkgname, _, e) = filename.rpartition('.')
|
||||||
|
# split into name, version, arch
|
||||||
|
(n, v, a) = pkgname.rsplit('_', 2)
|
||||||
|
if a == 'all':
|
||||||
|
a = fallback_arch
|
||||||
|
# Only check the arch requested - saves time
|
||||||
|
if arch != 'all' and arch != a:
|
||||||
|
continue
|
||||||
|
# Only check the name requested - saves time
|
||||||
|
if name and not re.match(name, n):
|
||||||
|
continue
|
||||||
|
# Only check the ext requested - saves time
|
||||||
|
if ext and not re.match(ext, e):
|
||||||
|
continue
|
||||||
|
# If we already have this BPPH, keep going
|
||||||
|
if a in self._binaries and n in self._binaries[a]:
|
||||||
|
continue
|
||||||
|
# we ignore the version, as it may be missing epoch
|
||||||
|
# also we can't use series, as some package versions
|
||||||
|
# span multiple series! (e.g. for different archs)
|
||||||
|
params = {'name': n,
|
||||||
|
'archtag': a,
|
||||||
|
'version': self.getVersion()}
|
||||||
|
try:
|
||||||
|
bpph = archive.getBinaryPackage(**params)
|
||||||
|
except PackageNotFoundException:
|
||||||
|
Logger.debug("Could not find pkg in archive: %s" % filename)
|
||||||
|
continue
|
||||||
|
if a not in self._binaries:
|
||||||
|
self._binaries[a] = {}
|
||||||
|
self._binaries[a][n] = bpph
|
||||||
|
if not name and not ext and arch == 'all':
|
||||||
|
# We must have got them all
|
||||||
|
self._have_all_binaries = True
|
||||||
|
|
||||||
|
bpphs = []
|
||||||
|
if arch == 'all':
|
||||||
|
for a in self._binaries.values():
|
||||||
|
bpphs += a.values()
|
||||||
|
elif arch in self._binaries:
|
||||||
|
bpphs = self._binaries[arch].copy().values()
|
||||||
|
|
||||||
|
if name:
|
||||||
|
bpphs = [b for b in bpphs if re.match(name, b.binary_package_name)]
|
||||||
|
|
||||||
|
if ext:
|
||||||
|
bpphs = [b for b in bpphs if re.match(ext, b.getFileExt())]
|
||||||
|
|
||||||
|
return bpphs
|
||||||
|
|
||||||
def _fetch_builds(self):
|
def _fetch_builds(self):
|
||||||
'''Populate self._builds with the build records.'''
|
'''Populate self._builds with the build records.'''
|
||||||
@ -648,6 +945,23 @@ class BinaryPackagePublishingHistory(BaseWrapper):
|
|||||||
'''
|
'''
|
||||||
resource_type = 'binary_package_publishing_history'
|
resource_type = 'binary_package_publishing_history'
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
self._arch = None
|
||||||
|
self._ext = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def arch(self):
|
||||||
|
if not self._arch:
|
||||||
|
das = DistroArchSeries(self._lpobject.distro_arch_series_link)
|
||||||
|
self._arch = das.architecture_tag
|
||||||
|
return self._arch
|
||||||
|
|
||||||
|
def getSourcePackageName(self):
|
||||||
|
'''
|
||||||
|
Returns the source package name.
|
||||||
|
'''
|
||||||
|
return self.getBuild().source_package_name
|
||||||
|
|
||||||
def getPackageName(self):
|
def getPackageName(self):
|
||||||
'''
|
'''
|
||||||
Returns the binary package name.
|
Returns the binary package name.
|
||||||
@ -672,11 +986,84 @@ class BinaryPackagePublishingHistory(BaseWrapper):
|
|||||||
Only available in the devel API, not 1.0
|
Only available in the devel API, not 1.0
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
return self._lpobject.binaryFileUrls()
|
urls = self._lpobject.binaryFileUrls()
|
||||||
|
if not urls:
|
||||||
|
Logger.warning('BPPH %s_%s has no binaryFileUrls' %
|
||||||
|
(self.getPackageName(), self.getVersion()))
|
||||||
|
return urls
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise AttributeError("binaryFileUrls can only be found in lpapi "
|
raise AttributeError("binaryFileUrls can only be found in lpapi "
|
||||||
"devel, not 1.0. Login using devel to have it.")
|
"devel, not 1.0. Login using devel to have it.")
|
||||||
|
|
||||||
|
def getBuild(self):
|
||||||
|
'''
|
||||||
|
Returns the original build of the binary package.
|
||||||
|
'''
|
||||||
|
return Build(self._lpobject.build_link)
|
||||||
|
|
||||||
|
def getUrl(self):
|
||||||
|
'''
|
||||||
|
Returns the original build URL of the binary package.
|
||||||
|
'''
|
||||||
|
return "{build}/+files/{filename}".format(build=self.getBuild().getUrl(),
|
||||||
|
filename=self.getFileName())
|
||||||
|
|
||||||
|
def getFileVersion(self):
|
||||||
|
'''
|
||||||
|
Returns the file version, which is the package version without the epoch
|
||||||
|
'''
|
||||||
|
return Version(self.getVersion()).strip_epoch()
|
||||||
|
|
||||||
|
def getFileArch(self):
|
||||||
|
'''
|
||||||
|
Returns the file arch, which is 'all' if not arch-specific
|
||||||
|
'''
|
||||||
|
if bool(self._lpobject.architecture_specific):
|
||||||
|
return self.arch
|
||||||
|
else:
|
||||||
|
return 'all'
|
||||||
|
|
||||||
|
def getFileExt(self):
|
||||||
|
'''
|
||||||
|
Returns the file extension; "deb", "ddeb", or "udeb".
|
||||||
|
'''
|
||||||
|
if not self._ext:
|
||||||
|
self._ext = self._getFileExt()
|
||||||
|
|
||||||
|
return self._ext
|
||||||
|
|
||||||
|
def _getFileExt(self):
|
||||||
|
try:
|
||||||
|
# this is the best way, from the actual URL filename
|
||||||
|
return self.binaryFileUrls()[0].rpartition('.')[2]
|
||||||
|
except (AttributeError, IndexError):
|
||||||
|
Logger.debug('Could not get file ext from url, trying to guess...')
|
||||||
|
|
||||||
|
# is_debug should be reliable way of detecting ddeb...?
|
||||||
|
try:
|
||||||
|
if self.is_debug:
|
||||||
|
return "ddeb"
|
||||||
|
except AttributeError:
|
||||||
|
# is_debug only available with api version 'devel'
|
||||||
|
if self.getPackageName().endswith("-dbgsym"):
|
||||||
|
return "ddeb"
|
||||||
|
|
||||||
|
# is this reliable?
|
||||||
|
if self.getPackageName().endswith("-di") or self.getPackageName().endswith("-udeb"):
|
||||||
|
return "udeb"
|
||||||
|
|
||||||
|
# everything else - assume regular deb
|
||||||
|
return "deb"
|
||||||
|
|
||||||
|
def getFileName(self):
|
||||||
|
'''
|
||||||
|
Returns the filename for this binary package.
|
||||||
|
'''
|
||||||
|
return "{name}_{version}_{arch}.{ext}".format(name=self.getPackageName(),
|
||||||
|
version=self.getFileVersion(),
|
||||||
|
arch=self.getFileArch(),
|
||||||
|
ext=self.getFileExt())
|
||||||
|
|
||||||
|
|
||||||
class MetaPersonTeam(MetaWrapper):
|
class MetaPersonTeam(MetaWrapper):
|
||||||
@property
|
@property
|
||||||
@ -705,6 +1092,7 @@ class PersonTeam(BaseWrapper, metaclass=MetaPersonTeam):
|
|||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
# Don't share _upload between different PersonTeams
|
# Don't share _upload between different PersonTeams
|
||||||
|
self._ppas = None
|
||||||
if '_upload' not in self.__dict__:
|
if '_upload' not in self.__dict__:
|
||||||
self._upload = dict()
|
self._upload = dict()
|
||||||
|
|
||||||
@ -754,7 +1142,7 @@ class PersonTeam(BaseWrapper, metaclass=MetaPersonTeam):
|
|||||||
if package is None and component is None:
|
if package is None and component is None:
|
||||||
raise ValueError('Either a source package name or a component has '
|
raise ValueError('Either a source package name or a component has '
|
||||||
'to be specified.')
|
'to be specified.')
|
||||||
if pocket not in _POCKETS:
|
if pocket not in POCKETS:
|
||||||
raise PocketDoesNotExistError("Pocket '%s' does not exist." %
|
raise PocketDoesNotExistError("Pocket '%s' does not exist." %
|
||||||
pocket)
|
pocket)
|
||||||
|
|
||||||
@ -782,6 +1170,16 @@ class PersonTeam(BaseWrapper, metaclass=MetaPersonTeam):
|
|||||||
|
|
||||||
return canUpload
|
return canUpload
|
||||||
|
|
||||||
|
def getPPAs(self):
|
||||||
|
if self._ppas is None:
|
||||||
|
ppas = [Archive(ppa['self_link']) for ppa in
|
||||||
|
Launchpad.load(self._lpobject.ppas_collection_link).entries]
|
||||||
|
self._ppas = {ppa.name: ppa for ppa in ppas}
|
||||||
|
return self._ppas
|
||||||
|
|
||||||
|
def getPPAByName(self, name):
|
||||||
|
return Archive(self._lpobject.getPPAByName(name=name))
|
||||||
|
|
||||||
|
|
||||||
class Build(BaseWrapper):
|
class Build(BaseWrapper):
|
||||||
'''
|
'''
|
||||||
@ -792,6 +1190,18 @@ class Build(BaseWrapper):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return u'%s: %s' % (self.arch_tag, self.buildstate)
|
return u'%s: %s' % (self.arch_tag, self.buildstate)
|
||||||
|
|
||||||
|
def getSourcePackagePublishingHistory(self):
|
||||||
|
link = self._lpobject.current_source_publication_link
|
||||||
|
if link:
|
||||||
|
if re.search('redacted', link):
|
||||||
|
# Too old - the link has been 'redacted'
|
||||||
|
return None
|
||||||
|
return SourcePackagePublishingHistory(link)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getUrl(self):
|
||||||
|
return self()
|
||||||
|
|
||||||
def rescore(self, score):
|
def rescore(self, score):
|
||||||
if self.can_be_rescored:
|
if self.can_be_rescored:
|
||||||
self().rescore(score=score)
|
self().rescore(score=score)
|
||||||
|
@ -26,3 +26,8 @@ class AlreadyLoggedInError(Exception):
|
|||||||
class ArchSeriesNotFoundException(BaseException):
|
class ArchSeriesNotFoundException(BaseException):
|
||||||
"""Thrown when a distroarchseries is not found."""
|
"""Thrown when a distroarchseries is not found."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidDistroValueError(ValueError):
|
||||||
|
""" Thrown when distro value is invalid """
|
||||||
|
pass
|
||||||
|
@ -32,6 +32,12 @@ import distro_info
|
|||||||
|
|
||||||
from ubuntutools.lp.udtexceptions import PocketDoesNotExistError
|
from ubuntutools.lp.udtexceptions import PocketDoesNotExistError
|
||||||
|
|
||||||
|
DEFAULT_POCKETS = ('Release', 'Security', 'Updates', 'Proposed')
|
||||||
|
POCKETS = DEFAULT_POCKETS + ('Backports',)
|
||||||
|
|
||||||
|
DEFAULT_STATUSES = ('Pending', 'Published')
|
||||||
|
STATUSES = DEFAULT_STATUSES + ('Superseded', 'Deleted', 'Obsolete')
|
||||||
|
|
||||||
_system_distribution_chain = []
|
_system_distribution_chain = []
|
||||||
|
|
||||||
|
|
||||||
@ -141,7 +147,7 @@ def split_release_pocket(release, default='Release'):
|
|||||||
(release, pocket) = release.rsplit('-', 1)
|
(release, pocket) = release.rsplit('-', 1)
|
||||||
pocket = pocket.capitalize()
|
pocket = pocket.capitalize()
|
||||||
|
|
||||||
if pocket not in ('Release', 'Security', 'Updates', 'Proposed', 'Backports'):
|
if pocket not in POCKETS:
|
||||||
raise PocketDoesNotExistError("Pocket '%s' does not exist." % pocket)
|
raise PocketDoesNotExistError("Pocket '%s' does not exist." % pocket)
|
||||||
|
|
||||||
return (release, pocket)
|
return (release, pocket)
|
||||||
|
420
ubuntutools/pullpkg.py
Normal file
420
ubuntutools/pullpkg.py
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
# pullpkg.py -- pull package files for debian/ubuntu/uca
|
||||||
|
# modified from ../pull-lp-source and converted to module
|
||||||
|
#
|
||||||
|
# Copyright (C) 2008, Iain Lane <iain@orangesquash.org.uk>,
|
||||||
|
# 2010-2011, Stefano Rivera <stefanor@ubuntu.com>
|
||||||
|
# 2017, Dan Streetman <dan.streetman@canonical.com>
|
||||||
|
#
|
||||||
|
# ##################################################################
|
||||||
|
#
|
||||||
|
# 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 3
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# See file /usr/share/common-licenses/GPL for more details.
|
||||||
|
#
|
||||||
|
# ##################################################################
|
||||||
|
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import errno
|
||||||
|
|
||||||
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
|
from distro_info import DebianDistroInfo
|
||||||
|
|
||||||
|
from ubuntutools.archive import (UbuntuSourcePackage, DebianSourcePackage,
|
||||||
|
UbuntuCloudArchiveSourcePackage,
|
||||||
|
PersonalPackageArchiveSourcePackage)
|
||||||
|
from ubuntutools.config import UDTConfig
|
||||||
|
from ubuntutools.lp.lpapicache import (Distribution, Launchpad)
|
||||||
|
from ubuntutools.lp.udtexceptions import (SeriesNotFoundException,
|
||||||
|
PackageNotFoundException,
|
||||||
|
PocketDoesNotExistError,
|
||||||
|
InvalidDistroValueError)
|
||||||
|
from ubuntutools.misc import (split_release_pocket, host_architecture, STATUSES)
|
||||||
|
|
||||||
|
from ubuntutools import _loggingBasicConfig
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PULL_SOURCE = 'source'
|
||||||
|
PULL_DEBS = 'debs'
|
||||||
|
PULL_DDEBS = 'ddebs'
|
||||||
|
PULL_UDEBS = 'udebs'
|
||||||
|
PULL_LIST = 'list'
|
||||||
|
|
||||||
|
VALID_PULLS = [PULL_SOURCE, PULL_DEBS, PULL_DDEBS, PULL_UDEBS, PULL_LIST]
|
||||||
|
VALID_BINARY_PULLS = [PULL_DEBS, PULL_DDEBS, PULL_UDEBS]
|
||||||
|
|
||||||
|
DISTRO_DEBIAN = 'debian'
|
||||||
|
DISTRO_UBUNTU = 'ubuntu'
|
||||||
|
DISTRO_UCA = 'uca'
|
||||||
|
DISTRO_PPA = 'ppa'
|
||||||
|
|
||||||
|
DISTRO_PKG_CLASS = {
|
||||||
|
DISTRO_DEBIAN: DebianSourcePackage,
|
||||||
|
DISTRO_UBUNTU: UbuntuSourcePackage,
|
||||||
|
DISTRO_UCA: UbuntuCloudArchiveSourcePackage,
|
||||||
|
DISTRO_PPA: PersonalPackageArchiveSourcePackage,
|
||||||
|
}
|
||||||
|
VALID_DISTROS = DISTRO_PKG_CLASS.keys()
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidPullValueError(ValueError):
|
||||||
|
""" Thrown when --pull value is invalid """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PullPkg(object):
|
||||||
|
"""Class used to pull file(s) associated with a specific package"""
|
||||||
|
@classmethod
|
||||||
|
def main(cls, *args, **kwargs):
|
||||||
|
"""For use by stand-alone cmdline scripts.
|
||||||
|
|
||||||
|
This will handle catching certain exceptions or kbd interrupts,
|
||||||
|
setting up the root logger level to INFO, and printing out
|
||||||
|
(via Logger) a caught error message, instead of allowing the
|
||||||
|
exception to flow up to the script. This does not catch
|
||||||
|
unexpected exceptions, such as internal errors.
|
||||||
|
|
||||||
|
On (expected) error, this will call sys.exit(error);
|
||||||
|
unexpected errors will flow up to the caller.
|
||||||
|
On success, this simply returns.
|
||||||
|
"""
|
||||||
|
_loggingBasicConfig()
|
||||||
|
|
||||||
|
try:
|
||||||
|
cls(*args, **kwargs).pull()
|
||||||
|
return
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
Logger.info('User abort.')
|
||||||
|
except (PackageNotFoundException, SeriesNotFoundException,
|
||||||
|
PocketDoesNotExistError, InvalidDistroValueError) as e:
|
||||||
|
Logger.error(str(e))
|
||||||
|
sys.exit(errno.ENOENT)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self._default_pull = kwargs.get('pull')
|
||||||
|
self._default_distro = kwargs.get('distro')
|
||||||
|
self._default_arch = kwargs.get('arch', host_architecture())
|
||||||
|
|
||||||
|
def parse_args(self, args):
|
||||||
|
args = args[:]
|
||||||
|
|
||||||
|
help_default_pull = "What to pull: " + ", ".join(VALID_PULLS)
|
||||||
|
if self._default_pull:
|
||||||
|
help_default_pull += (" (default: %s)" % self._default_pull)
|
||||||
|
help_default_distro = "Pull from: " + ", ".join(VALID_DISTROS)
|
||||||
|
if self._default_distro:
|
||||||
|
help_default_distro += (" (default: %s)" % self._default_distro)
|
||||||
|
help_default_arch = ("Get binary packages for arch")
|
||||||
|
help_default_arch += ("(default: %s)" % self._default_arch)
|
||||||
|
|
||||||
|
# use add_help=False because we do parse_known_args() below, and if
|
||||||
|
# that sees --help then it exits immediately
|
||||||
|
parser = ArgumentParser(add_help=False)
|
||||||
|
parser.add_argument('-v', '--verbose', action='count', default=0,
|
||||||
|
help="Increase verbosity/debug")
|
||||||
|
parser.add_argument('-d', '--download-only', action='store_true',
|
||||||
|
help="Do not extract the source package")
|
||||||
|
parser.add_argument('-m', '--mirror', action='append',
|
||||||
|
help='Preferred mirror(s)')
|
||||||
|
parser.add_argument('--no-conf', action='store_true',
|
||||||
|
help="Don't read config files or environment variables")
|
||||||
|
parser.add_argument('--no-verify-signature', action='store_true',
|
||||||
|
help="Don't fail if dsc signature can't be verified")
|
||||||
|
parser.add_argument('-s', '--status', action='append', default=[],
|
||||||
|
help="Search for packages with specific status(es)")
|
||||||
|
parser.add_argument('-a', '--arch', default=self._default_arch,
|
||||||
|
help=help_default_arch)
|
||||||
|
parser.add_argument('-p', '--pull', default=self._default_pull,
|
||||||
|
help=help_default_pull)
|
||||||
|
parser.add_argument('-D', '--distro', default=self._default_distro,
|
||||||
|
help=help_default_distro)
|
||||||
|
|
||||||
|
# add distro-specific params
|
||||||
|
try:
|
||||||
|
distro = self.parse_distro(parser.parse_known_args(args)[0].distro)
|
||||||
|
except InvalidDistroValueError:
|
||||||
|
# don't fail at this point, finish setting up parser help/usage
|
||||||
|
distro = None
|
||||||
|
|
||||||
|
if distro == DISTRO_UBUNTU:
|
||||||
|
parser.add_argument('--security', action='store_true',
|
||||||
|
help='Check the Ubuntu Security Team PPA')
|
||||||
|
if distro == DISTRO_PPA:
|
||||||
|
parser.add_argument('--ppa', help='PPA to pull from')
|
||||||
|
if parser.parse_known_args(args)[0].ppa is None:
|
||||||
|
# check for any param starting with "ppa:"
|
||||||
|
# if found, move it to a --ppa param
|
||||||
|
for param in args:
|
||||||
|
if param.startswith('ppa:'):
|
||||||
|
args.remove(param)
|
||||||
|
args.insert(0, param)
|
||||||
|
args.insert(0, '--ppa')
|
||||||
|
break
|
||||||
|
|
||||||
|
# add the positional params
|
||||||
|
parser.add_argument('package', help="Package name to pull")
|
||||||
|
parser.add_argument('release', nargs='?', help="Release to pull from")
|
||||||
|
parser.add_argument('version', nargs='?', help="Package version to pull")
|
||||||
|
|
||||||
|
epilog = ("Note on --status: if a version is provided, all status types "
|
||||||
|
"will be searched; if no version is provided, by default only "
|
||||||
|
"'Pending' and 'Published' status will be searched.")
|
||||||
|
|
||||||
|
# since parser has no --help handler, create a new parser that does
|
||||||
|
newparser = ArgumentParser(parents=[parser], epilog=epilog)
|
||||||
|
|
||||||
|
return self.parse_options(vars(newparser.parse_args(args)))
|
||||||
|
|
||||||
|
def parse_pull(self, pull):
|
||||||
|
if not pull:
|
||||||
|
raise InvalidPullValueError("Must specify --pull")
|
||||||
|
|
||||||
|
# allow 'dbgsym' as alias for 'ddebs'
|
||||||
|
if pull == 'dbgsym':
|
||||||
|
Logger.debug("Pulling '%s' for '%s'", PULL_DDEBS, pull)
|
||||||
|
pull = PULL_DDEBS
|
||||||
|
# assume anything starting with 'bin' means 'debs'
|
||||||
|
if str(pull).startswith('bin'):
|
||||||
|
Logger.debug("Pulling '%s' for '%s'", PULL_DEBS, pull)
|
||||||
|
pull = PULL_DEBS
|
||||||
|
# verify pull action is valid
|
||||||
|
if pull not in VALID_PULLS:
|
||||||
|
raise InvalidPullValueError("Invalid pull action '%s'" % pull)
|
||||||
|
|
||||||
|
return pull
|
||||||
|
|
||||||
|
def parse_distro(self, distro):
|
||||||
|
if not distro:
|
||||||
|
raise InvalidDistroValueError("Must specify --distro")
|
||||||
|
|
||||||
|
distro = distro.lower()
|
||||||
|
|
||||||
|
# allow 'lp' for 'ubuntu'
|
||||||
|
if distro == 'lp':
|
||||||
|
Logger.debug("Using distro '%s' for '%s'", DISTRO_UBUNTU, distro)
|
||||||
|
distro = DISTRO_UBUNTU
|
||||||
|
# assume anything with 'cloud' is UCA
|
||||||
|
if re.match(r'.*cloud.*', distro):
|
||||||
|
Logger.debug("Using distro '%s' for '%s'", DISTRO_UCA, distro)
|
||||||
|
distro = DISTRO_UCA
|
||||||
|
# verify distro is valid
|
||||||
|
if distro not in VALID_DISTROS:
|
||||||
|
raise InvalidDistroValueError("Invalid distro '%s'" % distro)
|
||||||
|
|
||||||
|
return distro
|
||||||
|
|
||||||
|
def parse_release(self, distro, release):
|
||||||
|
if distro == DISTRO_UCA:
|
||||||
|
# UCA is special; it is specified UBUNTURELEASE-UCARELEASE or just
|
||||||
|
# UCARELEASE. The user could also specify UCARELEASE-POCKET. But UCA
|
||||||
|
# archives always correspond to only one UBUNTURELEASE, and UCA archives
|
||||||
|
# have only the Release pocket, so only UCARELEASE matters to us.
|
||||||
|
for r in release.split('-'):
|
||||||
|
if UbuntuCloudArchiveSourcePackage.isValidRelease(r):
|
||||||
|
Logger.debug("Using UCA release '%s'", r)
|
||||||
|
return (r, None)
|
||||||
|
raise SeriesNotFoundException('UCA release {} not found.'.format(release))
|
||||||
|
|
||||||
|
# Check if release[-pocket] is specified
|
||||||
|
(release, pocket) = split_release_pocket(release, default=None)
|
||||||
|
Logger.debug("Parsed release '%s' pocket '%s'", release, pocket)
|
||||||
|
|
||||||
|
if distro == DISTRO_DEBIAN:
|
||||||
|
# This converts from the aliases like 'unstable'
|
||||||
|
debian_info = DebianDistroInfo()
|
||||||
|
codename = debian_info.codename(release)
|
||||||
|
if codename:
|
||||||
|
Logger.info("Using release '%s' for '%s'", codename, release)
|
||||||
|
release = codename
|
||||||
|
|
||||||
|
if distro == DISTRO_PPA:
|
||||||
|
# PPAs are part of Ubuntu distribution
|
||||||
|
d = Distribution(DISTRO_UBUNTU)
|
||||||
|
else:
|
||||||
|
d = Distribution(distro)
|
||||||
|
|
||||||
|
# let SeriesNotFoundException flow up
|
||||||
|
d.getSeries(release)
|
||||||
|
|
||||||
|
Logger.debug("Using distro '%s' release '%s' pocket '%s'",
|
||||||
|
distro, release, pocket)
|
||||||
|
return (release, pocket)
|
||||||
|
|
||||||
|
def parse_release_and_version(self, distro, release, version, try_swap=True):
|
||||||
|
# Verify specified release is valid, and params in correct order
|
||||||
|
pocket = None
|
||||||
|
try:
|
||||||
|
(release, pocket) = self.parse_release(distro, release)
|
||||||
|
except (SeriesNotFoundException, PocketDoesNotExistError):
|
||||||
|
if try_swap:
|
||||||
|
Logger.debug("Param '%s' not valid series, must be version", release)
|
||||||
|
release, version = version, release
|
||||||
|
if release:
|
||||||
|
return self.parse_release_and_version(distro, release, version, False)
|
||||||
|
else:
|
||||||
|
Logger.error("Can't find series for '%s' or '%s'", release, version)
|
||||||
|
raise
|
||||||
|
return (release, version, pocket)
|
||||||
|
|
||||||
|
def parse_options(self, options):
|
||||||
|
# if any of these fail, there is a problem with the parser
|
||||||
|
# they should all be provided, though the optional ones may be None
|
||||||
|
|
||||||
|
# type bool
|
||||||
|
assert 'verbose' in options
|
||||||
|
assert 'download_only' in options
|
||||||
|
assert 'no_conf' in options
|
||||||
|
assert 'no_verify_signature' in options
|
||||||
|
assert 'status' in options
|
||||||
|
# type string
|
||||||
|
assert 'pull' in options
|
||||||
|
assert 'distro' in options
|
||||||
|
assert 'arch' in options
|
||||||
|
assert 'package' in options
|
||||||
|
# type string, optional
|
||||||
|
assert 'release' in options
|
||||||
|
assert 'version' in options
|
||||||
|
# type list of strings, optional
|
||||||
|
assert 'mirror' in options
|
||||||
|
|
||||||
|
options['pull'] = self.parse_pull(options['pull'])
|
||||||
|
options['distro'] = self.parse_distro(options['distro'])
|
||||||
|
|
||||||
|
# ensure these are always included so we can just check for None/False later
|
||||||
|
options['ppa'] = options.get('ppa', None)
|
||||||
|
options['security'] = options.get('security', False)
|
||||||
|
|
||||||
|
return options
|
||||||
|
|
||||||
|
def _get_params(self, options):
|
||||||
|
distro = options['distro']
|
||||||
|
pull = options['pull']
|
||||||
|
|
||||||
|
params = {}
|
||||||
|
params['package'] = options['package']
|
||||||
|
|
||||||
|
if options['release']:
|
||||||
|
(r, v, p) = self.parse_release_and_version(distro, options['release'],
|
||||||
|
options['version'])
|
||||||
|
params['series'] = r
|
||||||
|
params['version'] = v
|
||||||
|
params['pocket'] = p
|
||||||
|
|
||||||
|
if (params['package'].endswith('.dsc') and not params['series'] and not params['version']):
|
||||||
|
params['dscfile'] = params['package']
|
||||||
|
params.pop('package')
|
||||||
|
|
||||||
|
if options['security']:
|
||||||
|
if options['ppa']:
|
||||||
|
Logger.warning('Both --security and --ppa specified, ignoring --ppa')
|
||||||
|
Logger.debug('Checking Ubuntu Security PPA')
|
||||||
|
# --security is just a shortcut for --ppa ppa:ubuntu-security-proposed/ppa
|
||||||
|
options['ppa'] = 'ubuntu-security-proposed/ppa'
|
||||||
|
|
||||||
|
if options['ppa']:
|
||||||
|
if options['ppa'].startswith('ppa:'):
|
||||||
|
params['ppa'] = options['ppa'][4:]
|
||||||
|
else:
|
||||||
|
params['ppa'] = options['ppa']
|
||||||
|
elif distro == DISTRO_PPA:
|
||||||
|
raise ValueError('Must specify PPA to pull from')
|
||||||
|
|
||||||
|
mirrors = []
|
||||||
|
if options['mirror']:
|
||||||
|
mirrors.append(options['mirror'])
|
||||||
|
if pull == PULL_DDEBS:
|
||||||
|
config = UDTConfig(options['no_conf'])
|
||||||
|
ddebs_mirror = config.get_value(distro.upper() + '_DDEBS_MIRROR')
|
||||||
|
if ddebs_mirror:
|
||||||
|
mirrors.append(ddebs_mirror)
|
||||||
|
if mirrors:
|
||||||
|
Logger.debug("using mirrors %s", ", ".join(mirrors))
|
||||||
|
params['mirrors'] = mirrors
|
||||||
|
|
||||||
|
params['verify_signature'] = not options['no_verify_signature']
|
||||||
|
|
||||||
|
params['status'] = STATUSES if 'all' in options['status'] else options['status']
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
def pull(self, args=sys.argv[1:]):
|
||||||
|
"""Pull (download) specified package file(s)"""
|
||||||
|
options = self.parse_args(args)
|
||||||
|
|
||||||
|
if options['verbose']:
|
||||||
|
Logger.setLevel(logging.DEBUG)
|
||||||
|
if options['verbose'] > 1:
|
||||||
|
logging.getLogger(__package__).setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
Logger.debug("pullpkg options: %s", options)
|
||||||
|
|
||||||
|
# Login anonymously to LP
|
||||||
|
Launchpad.login_anonymously()
|
||||||
|
|
||||||
|
pull = options['pull']
|
||||||
|
distro = options['distro']
|
||||||
|
|
||||||
|
params = self._get_params(options)
|
||||||
|
package = params['package']
|
||||||
|
|
||||||
|
# call implementation, and allow exceptions to flow up to caller
|
||||||
|
srcpkg = DISTRO_PKG_CLASS[distro](**params)
|
||||||
|
spph = srcpkg.lp_spph
|
||||||
|
|
||||||
|
Logger.info('Found %s', spph.display_name)
|
||||||
|
|
||||||
|
if pull == PULL_LIST:
|
||||||
|
Logger.info("Source files:")
|
||||||
|
for f in srcpkg.dsc['Files']:
|
||||||
|
Logger.info(" %s", f['name'])
|
||||||
|
Logger.info("Binary files:")
|
||||||
|
for f in spph.getBinaries(options['arch']):
|
||||||
|
Logger.info(" %s", f.getFileName())
|
||||||
|
elif pull == PULL_SOURCE:
|
||||||
|
# allow DownloadError to flow up to caller
|
||||||
|
srcpkg.pull()
|
||||||
|
if options['download_only']:
|
||||||
|
Logger.debug("--download-only specified, not extracting")
|
||||||
|
else:
|
||||||
|
srcpkg.unpack()
|
||||||
|
elif pull in VALID_BINARY_PULLS:
|
||||||
|
name = None
|
||||||
|
if package != spph.getPackageName():
|
||||||
|
Logger.info("Pulling only binary package '%s'", package)
|
||||||
|
Logger.info("Use package name '%s' to pull all binary packages",
|
||||||
|
spph.getPackageName())
|
||||||
|
name = package
|
||||||
|
|
||||||
|
# e.g. 'debs' -> 'deb'
|
||||||
|
ext = pull.rstrip('s')
|
||||||
|
|
||||||
|
if distro == DISTRO_DEBIAN:
|
||||||
|
# Debian ddebs don't use .ddeb extension, unfortunately :(
|
||||||
|
if pull in [PULL_DEBS, PULL_DDEBS]:
|
||||||
|
name = name or '.*'
|
||||||
|
ext = 'deb'
|
||||||
|
if pull == PULL_DEBS:
|
||||||
|
name += r'(?<!-dbgsym)$'
|
||||||
|
if pull == PULL_DDEBS:
|
||||||
|
name += r'-dbgsym$'
|
||||||
|
|
||||||
|
# allow DownloadError to flow up to caller
|
||||||
|
total = srcpkg.pull_binaries(name=name, ext=ext, arch=options['arch'])
|
||||||
|
if total < 1:
|
||||||
|
Logger.error("No %s found for %s %s", pull,
|
||||||
|
package, spph.getVersion())
|
||||||
|
else:
|
||||||
|
Logger.error("Internal error: invalid pull value after parse_pull()")
|
||||||
|
raise InvalidPullValueError("Invalid pull value '%s'" % pull)
|
@ -29,9 +29,11 @@ from httplib2 import Http, HttpLib2Error
|
|||||||
from ubuntutools.lp import udtexceptions
|
from ubuntutools.lp import udtexceptions
|
||||||
from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam,
|
from ubuntutools.lp.lpapicache import (Launchpad, Distribution, PersonTeam,
|
||||||
DistributionSourcePackage)
|
DistributionSourcePackage)
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.question import confirmation_prompt
|
from ubuntutools.question import confirmation_prompt
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_debian_srcpkg(name, release):
|
def get_debian_srcpkg(name, release):
|
||||||
debian = Distribution('debian')
|
debian = Distribution('debian')
|
||||||
@ -40,7 +42,7 @@ def get_debian_srcpkg(name, release):
|
|||||||
try:
|
try:
|
||||||
release = DebianDistroInfo().codename(release, None, release)
|
release = DebianDistroInfo().codename(release, None, release)
|
||||||
except DistroDataOutdated as e:
|
except DistroDataOutdated as e:
|
||||||
Logger.warn(e)
|
Logger.warning(e)
|
||||||
|
|
||||||
return debian_archive.getSourcePackage(name, release)
|
return debian_archive.getSourcePackage(name, release)
|
||||||
|
|
||||||
|
@ -31,11 +31,12 @@ import tempfile
|
|||||||
from debian.changelog import Changelog
|
from debian.changelog import Changelog
|
||||||
from distro_info import DebianDistroInfo, DistroDataOutdated
|
from distro_info import DebianDistroInfo, DistroDataOutdated
|
||||||
|
|
||||||
from ubuntutools.archive import rmadison, FakeSPPH
|
from ubuntutools.archive import DebianSourcePackage, UbuntuSourcePackage
|
||||||
from ubuntutools.lp.udtexceptions import PackageNotFoundException
|
from ubuntutools.lp.udtexceptions import PackageNotFoundException
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.question import confirmation_prompt, YesNoQuestion
|
from ubuntutools.question import confirmation_prompt, YesNoQuestion
|
||||||
from ubuntutools.version import Version
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@ -48,32 +49,21 @@ __all__ = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _get_srcpkg(distro, name, release):
|
def get_debian_srcpkg(name, release):
|
||||||
if distro == 'debian':
|
|
||||||
# Canonicalise release:
|
# Canonicalise release:
|
||||||
debian_info = DebianDistroInfo()
|
debian_info = DebianDistroInfo()
|
||||||
try:
|
try:
|
||||||
codename = debian_info.codename(release, default=release)
|
codename = debian_info.codename(release, default=release)
|
||||||
|
return DebianSourcePackage(package=name, series=codename).lp_spph
|
||||||
except DistroDataOutdated as e:
|
except DistroDataOutdated as e:
|
||||||
Logger.warn(e)
|
Logger.warning(e)
|
||||||
|
except PackageNotFoundException:
|
||||||
lines = list(rmadison(distro, name, suite=codename, arch='source'))
|
pass
|
||||||
if not lines:
|
return DebianSourcePackage(package=name, series=release).lp_spph
|
||||||
lines = list(rmadison(distro, name, suite=release, arch='source'))
|
|
||||||
if not lines:
|
|
||||||
raise PackageNotFoundException("'%s' doesn't appear to exist in %s '%s'" %
|
|
||||||
(name, distro.capitalize(), release))
|
|
||||||
pkg = max(lines, key=lambda x: Version(x['version']))
|
|
||||||
|
|
||||||
return FakeSPPH(pkg['source'], pkg['version'], pkg['component'], distro)
|
|
||||||
|
|
||||||
|
|
||||||
def get_debian_srcpkg(name, release):
|
|
||||||
return _get_srcpkg('debian', name, release)
|
|
||||||
|
|
||||||
|
|
||||||
def get_ubuntu_srcpkg(name, release):
|
def get_ubuntu_srcpkg(name, release):
|
||||||
return _get_srcpkg('ubuntu', name, release)
|
return UbuntuSourcePackage(package=name, series=release).lp_spph
|
||||||
|
|
||||||
|
|
||||||
def need_sponsorship(name, component, release):
|
def need_sponsorship(name, component, release):
|
||||||
@ -185,13 +175,13 @@ Content-Type: text/plain; charset=UTF-8
|
|||||||
with backup:
|
with backup:
|
||||||
backup.write(mail)
|
backup.write(mail)
|
||||||
|
|
||||||
Logger.normal('The e-mail has been saved in %s and will be deleted '
|
Logger.info('The e-mail has been saved in %s and will be deleted '
|
||||||
'after succesful transmission', backup.name)
|
'after succesful transmission', backup.name)
|
||||||
|
|
||||||
# connect to the server
|
# connect to the server
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
Logger.normal('Connecting to %s:%s ...', mailserver_host,
|
Logger.info('Connecting to %s:%s ...', mailserver_host,
|
||||||
mailserver_port)
|
mailserver_port)
|
||||||
s = smtplib.SMTP(mailserver_host, mailserver_port)
|
s = smtplib.SMTP(mailserver_host, mailserver_port)
|
||||||
break
|
break
|
||||||
@ -238,7 +228,7 @@ Content-Type: text/plain; charset=UTF-8
|
|||||||
s.sendmail(myemailaddr, to, mail.encode('utf-8'))
|
s.sendmail(myemailaddr, to, mail.encode('utf-8'))
|
||||||
s.quit()
|
s.quit()
|
||||||
os.remove(backup.name)
|
os.remove(backup.name)
|
||||||
Logger.normal('Sync request mailed.')
|
Logger.info('Sync request mailed.')
|
||||||
break
|
break
|
||||||
except smtplib.SMTPRecipientsRefused as smtperror:
|
except smtplib.SMTPRecipientsRefused as smtperror:
|
||||||
smtp_code, smtp_message = smtperror.recipients[to]
|
smtp_code, smtp_message = smtperror.recipients[to]
|
||||||
|
@ -23,9 +23,11 @@ from urllib.request import urlretrieve
|
|||||||
import distro_info
|
import distro_info
|
||||||
import httplib2
|
import httplib2
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.version import Version
|
from ubuntutools.version import Version
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def is_sync(bug):
|
def is_sync(bug):
|
||||||
"""Checks if a Launchpad bug is a sync request.
|
"""Checks if a Launchpad bug is a sync request.
|
||||||
@ -66,7 +68,7 @@ class BugTask(object):
|
|||||||
dsc_file = ""
|
dsc_file = ""
|
||||||
for url in source_files:
|
for url in source_files:
|
||||||
filename = unquote(os.path.basename(url))
|
filename = unquote(os.path.basename(url))
|
||||||
Logger.info("Downloading %s..." % (filename))
|
Logger.debug("Downloading %s..." % (filename))
|
||||||
# HttpLib2 isn't suitable for large files (it reads into memory),
|
# HttpLib2 isn't suitable for large files (it reads into memory),
|
||||||
# but we want its https certificate validation on the .dsc
|
# but we want its https certificate validation on the .dsc
|
||||||
if url.endswith(".dsc"):
|
if url.endswith(".dsc"):
|
||||||
|
@ -19,10 +19,12 @@ import os
|
|||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.sponsor_patch.question import ask_for_manual_fixing
|
from ubuntutools.sponsor_patch.question import ask_for_manual_fixing
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Patch(object):
|
class Patch(object):
|
||||||
"""This object represents a patch that can be downloaded from Launchpad."""
|
"""This object represents a patch that can be downloaded from Launchpad."""
|
||||||
@ -32,7 +34,7 @@ class Patch(object):
|
|||||||
self._patch_file = re.sub(" |/", "_", patch.title)
|
self._patch_file = re.sub(" |/", "_", patch.title)
|
||||||
if not reduce(lambda r, x: r or self._patch.title.endswith(x),
|
if not reduce(lambda r, x: r or self._patch.title.endswith(x),
|
||||||
(".debdiff", ".diff", ".patch"), False):
|
(".debdiff", ".diff", ".patch"), False):
|
||||||
Logger.info("Patch %s does not have a proper file extension." %
|
Logger.debug("Patch %s does not have a proper file extension." %
|
||||||
(self._patch.title))
|
(self._patch.title))
|
||||||
self._patch_file += ".patch"
|
self._patch_file += ".patch"
|
||||||
self._full_path = os.path.realpath(self._patch_file)
|
self._full_path = os.path.realpath(self._patch_file)
|
||||||
@ -45,7 +47,7 @@ class Patch(object):
|
|||||||
if self.is_debdiff():
|
if self.is_debdiff():
|
||||||
cmd = ["patch", "--merge", "--force", "-p",
|
cmd = ["patch", "--merge", "--force", "-p",
|
||||||
str(self.get_strip_level()), "-i", self._full_path]
|
str(self.get_strip_level()), "-i", self._full_path]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Failed to apply debdiff %s to %s %s.",
|
Logger.error("Failed to apply debdiff %s to %s %s.",
|
||||||
self._patch_file, task.package, task.get_version())
|
self._patch_file, task.package, task.get_version())
|
||||||
@ -54,7 +56,7 @@ class Patch(object):
|
|||||||
edit = True
|
edit = True
|
||||||
else:
|
else:
|
||||||
cmd = ["add-patch", self._full_path]
|
cmd = ["add-patch", self._full_path]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Failed to apply diff %s to %s %s.",
|
Logger.error("Failed to apply diff %s to %s %s.",
|
||||||
self._patch_file, task.package, task.get_version())
|
self._patch_file, task.package, task.get_version())
|
||||||
@ -65,7 +67,7 @@ class Patch(object):
|
|||||||
|
|
||||||
def download(self):
|
def download(self):
|
||||||
"""Downloads the patch from Launchpad."""
|
"""Downloads the patch from Launchpad."""
|
||||||
Logger.info("Downloading %s." % (self._patch_file))
|
Logger.debug("Downloading %s." % (self._patch_file))
|
||||||
patch_f = open(self._patch_file, "w")
|
patch_f = open(self._patch_file, "w")
|
||||||
patch_f.write(self._patch.data.open().read())
|
patch_f.write(self._patch.data.open().read())
|
||||||
patch_f.close()
|
patch_f.close()
|
||||||
|
@ -23,13 +23,15 @@ import sys
|
|||||||
import debian.changelog
|
import debian.changelog
|
||||||
import debian.deb822
|
import debian.deb822
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.question import Question, YesNoQuestion
|
from ubuntutools.question import Question, YesNoQuestion
|
||||||
|
|
||||||
from ubuntutools.sponsor_patch.question import (ask_for_ignoring_or_fixing,
|
from ubuntutools.sponsor_patch.question import (ask_for_ignoring_or_fixing,
|
||||||
ask_for_manual_fixing,
|
ask_for_manual_fixing,
|
||||||
user_abort)
|
user_abort)
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def _get_series(launchpad):
|
def _get_series(launchpad):
|
||||||
"""Returns a tuple with the development and list of supported series."""
|
"""Returns a tuple with the development and list of supported series."""
|
||||||
@ -84,7 +86,7 @@ class SourcePackage(object):
|
|||||||
if task.importance == "Undecided":
|
if task.importance == "Undecided":
|
||||||
task.importance = "Wishlist"
|
task.importance = "Wishlist"
|
||||||
task.lp_save()
|
task.lp_save()
|
||||||
Logger.info("Set bug #%i status to Confirmed.", bug.id)
|
Logger.debug("Set bug #%i status to Confirmed.", bug.id)
|
||||||
|
|
||||||
msg = "Sync request ACK'd."
|
msg = "Sync request ACK'd."
|
||||||
if self._build_log:
|
if self._build_log:
|
||||||
@ -92,25 +94,25 @@ class SourcePackage(object):
|
|||||||
(self._package, self._version,
|
(self._package, self._version,
|
||||||
self._builder.get_architecture())
|
self._builder.get_architecture())
|
||||||
bug.newMessage(content=msg, subject="sponsor-patch")
|
bug.newMessage(content=msg, subject="sponsor-patch")
|
||||||
Logger.info("Acknowledged sync request bug #%i.", bug.id)
|
Logger.debug("Acknowledged sync request bug #%i.", bug.id)
|
||||||
|
|
||||||
bug.subscribe(person=launchpad.people['ubuntu-archive'])
|
bug.subscribe(person=launchpad.people['ubuntu-archive'])
|
||||||
Logger.info("Subscribed ubuntu-archive to bug #%i.", bug.id)
|
Logger.debug("Subscribed ubuntu-archive to bug #%i.", bug.id)
|
||||||
|
|
||||||
bug.subscribe(person=launchpad.me)
|
bug.subscribe(person=launchpad.me)
|
||||||
Logger.info("Subscribed me to bug #%i.", bug.id)
|
Logger.debug("Subscribed me to bug #%i.", bug.id)
|
||||||
|
|
||||||
sponsorsteam = launchpad.people['ubuntu-sponsors']
|
sponsorsteam = launchpad.people['ubuntu-sponsors']
|
||||||
for sub in bug.subscriptions:
|
for sub in bug.subscriptions:
|
||||||
if sub.person == sponsorsteam and sub.canBeUnsubscribedByUser():
|
if sub.person == sponsorsteam and sub.canBeUnsubscribedByUser():
|
||||||
bug.unsubscribe(person=launchpad.people['ubuntu-sponsors'])
|
bug.unsubscribe(person=launchpad.people['ubuntu-sponsors'])
|
||||||
Logger.info("Unsubscribed ubuntu-sponsors from bug #%i.",
|
Logger.debug("Unsubscribed ubuntu-sponsors from bug #%i.",
|
||||||
bug.id)
|
bug.id)
|
||||||
elif sub.person == sponsorsteam:
|
elif sub.person == sponsorsteam:
|
||||||
Logger.info("Couldn't unsubscribe ubuntu-sponsors from "
|
Logger.debug("Couldn't unsubscribe ubuntu-sponsors from "
|
||||||
"bug #%i.", bug.id)
|
"bug #%i.", bug.id)
|
||||||
|
|
||||||
Logger.normal("Successfully acknowledged sync request bug #%i.",
|
Logger.info("Successfully acknowledged sync request bug #%i.",
|
||||||
bug.id)
|
bug.id)
|
||||||
else:
|
else:
|
||||||
Logger.error("Sync requests can only be acknowledged when the "
|
Logger.error("Sync requests can only be acknowledged when the "
|
||||||
@ -139,7 +141,7 @@ class SourcePackage(object):
|
|||||||
elif answer == "no":
|
elif answer == "no":
|
||||||
user_abort()
|
user_abort()
|
||||||
cmd = ["dput", "--force", upload, self._changes_file]
|
cmd = ["dput", "--force", upload, self._changes_file]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Upload of %s to %s failed." %
|
Logger.error("Upload of %s to %s failed." %
|
||||||
(os.path.basename(self._changes_file), upload))
|
(os.path.basename(self._changes_file), upload))
|
||||||
@ -148,17 +150,17 @@ class SourcePackage(object):
|
|||||||
# Push the branch if the package is uploaded to the Ubuntu archive.
|
# Push the branch if the package is uploaded to the Ubuntu archive.
|
||||||
if upload == "ubuntu" and self._branch:
|
if upload == "ubuntu" and self._branch:
|
||||||
cmd = ['debcommit']
|
cmd = ['debcommit']
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error('Bzr commit failed.')
|
Logger.error('Bzr commit failed.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
cmd = ['bzr', 'mark-uploaded']
|
cmd = ['bzr', 'mark-uploaded']
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error('Bzr tagging failed.')
|
Logger.error('Bzr tagging failed.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
cmd = ['bzr', 'push', ':parent']
|
cmd = ['bzr', 'push', ':parent']
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error('Bzr push failed.')
|
Logger.error('Bzr push failed.')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -239,7 +241,7 @@ class SourcePackage(object):
|
|||||||
env = os.environ
|
env = os.environ
|
||||||
if upload == 'ubuntu':
|
if upload == 'ubuntu':
|
||||||
env['DEB_VENDOR'] = 'Ubuntu'
|
env['DEB_VENDOR'] = 'Ubuntu'
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd, env=env) != 0:
|
if subprocess.call(cmd, env=env) != 0:
|
||||||
Logger.error("Failed to build source tarball.")
|
Logger.error("Failed to build source tarball.")
|
||||||
# TODO: Add a "retry" option
|
# TODO: Add a "retry" option
|
||||||
@ -322,9 +324,9 @@ class SourcePackage(object):
|
|||||||
assert os.path.isfile(self._dsc_file), "%s does not exist." % \
|
assert os.path.isfile(self._dsc_file), "%s does not exist." % \
|
||||||
(self._dsc_file)
|
(self._dsc_file)
|
||||||
cmd = ["debdiff", dsc_file, self._dsc_file]
|
cmd = ["debdiff", dsc_file, self._dsc_file]
|
||||||
if not Logger.verbose:
|
if not Logger.isEnabledFor(logging.DEBUG):
|
||||||
cmd.insert(1, "-q")
|
cmd.insert(1, "-q")
|
||||||
Logger.command(cmd + [">", self._debdiff_filename])
|
Logger.debug(' '.join(cmd) + " > " + self._debdiff_filename)
|
||||||
debdiff = subprocess.check_output(cmd, encoding='utf-8')
|
debdiff = subprocess.check_output(cmd, encoding='utf-8')
|
||||||
|
|
||||||
# write debdiff file
|
# write debdiff file
|
||||||
@ -417,7 +419,7 @@ class SourcePackage(object):
|
|||||||
lintian_filename = os.path.join(self._workdir,
|
lintian_filename = os.path.join(self._workdir,
|
||||||
self._package + "_" +
|
self._package + "_" +
|
||||||
strip_epoch(self._version) + ".lintian")
|
strip_epoch(self._version) + ".lintian")
|
||||||
Logger.command(cmd + [">", lintian_filename])
|
Logger.debug(' '.join(cmd) + " > " + lintian_filename)
|
||||||
report = subprocess.check_output(cmd, encoding='utf-8')
|
report = subprocess.check_output(cmd, encoding='utf-8')
|
||||||
|
|
||||||
# write lintian report file
|
# write lintian report file
|
||||||
@ -434,7 +436,7 @@ class SourcePackage(object):
|
|||||||
cmd = ["syncpackage", self._package, "-b", str(bug_number), "-f",
|
cmd = ["syncpackage", self._package, "-b", str(bug_number), "-f",
|
||||||
"-s", requester, "-V", str(self._version),
|
"-s", requester, "-V", str(self._version),
|
||||||
"-d", series]
|
"-d", series]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Syncing of %s %s failed.", self._package,
|
Logger.error("Syncing of %s %s failed.", self._package,
|
||||||
str(self._version))
|
str(self._version))
|
||||||
|
@ -25,7 +25,6 @@ from distro_info import UbuntuDistroInfo
|
|||||||
|
|
||||||
from launchpadlib.launchpad import Launchpad
|
from launchpadlib.launchpad import Launchpad
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.update_maintainer import (update_maintainer,
|
from ubuntutools.update_maintainer import (update_maintainer,
|
||||||
MaintainerUpdateException)
|
MaintainerUpdateException)
|
||||||
from ubuntutools.question import input_number
|
from ubuntutools.question import input_number
|
||||||
@ -35,6 +34,9 @@ from ubuntutools.sponsor_patch.patch import Patch
|
|||||||
from ubuntutools.sponsor_patch.question import ask_for_manual_fixing
|
from ubuntutools.sponsor_patch.question import ask_for_manual_fixing
|
||||||
from ubuntutools.sponsor_patch.source_package import SourcePackage
|
from ubuntutools.sponsor_patch.source_package import SourcePackage
|
||||||
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def is_command_available(command, check_sbin=False):
|
def is_command_available(command, check_sbin=False):
|
||||||
"Is command in $PATH?"
|
"Is command in $PATH?"
|
||||||
@ -59,7 +61,7 @@ def check_dependencies():
|
|||||||
missing.append('pbuilder/cowbuilder/sbuild')
|
missing.append('pbuilder/cowbuilder/sbuild')
|
||||||
|
|
||||||
if missing:
|
if missing:
|
||||||
Logger.warn("sponsor-patch requires %s to be installed for full "
|
Logger.warning("sponsor-patch requires %s to be installed for full "
|
||||||
"functionality", ', '.join(missing))
|
"functionality", ', '.join(missing))
|
||||||
|
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ def get_user_shell():
|
|||||||
def edit_source():
|
def edit_source():
|
||||||
# Spawn shell to allow modifications
|
# Spawn shell to allow modifications
|
||||||
cmd = [get_user_shell()]
|
cmd = [get_user_shell()]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
print("""An interactive shell was launched in
|
print("""An interactive shell was launched in
|
||||||
file://%s
|
file://%s
|
||||||
Edit your files. When you are done, exit the shell. If you wish to abort the
|
Edit your files. When you are done, exit the shell. If you wish to abort the
|
||||||
@ -112,7 +114,7 @@ def ask_for_patch_or_branch(bug, attached_patches, linked_branches):
|
|||||||
patches += "es"
|
patches += "es"
|
||||||
msg = "https://launchpad.net/bugs/%i has %s linked and %s attached:" % \
|
msg = "https://launchpad.net/bugs/%i has %s linked and %s attached:" % \
|
||||||
(bug.id, branches, patches)
|
(bug.id, branches, patches)
|
||||||
Logger.normal(msg)
|
Logger.info(msg)
|
||||||
i = 0
|
i = 0
|
||||||
for linked_branch in linked_branches:
|
for linked_branch in linked_branches:
|
||||||
i += 1
|
i += 1
|
||||||
@ -160,7 +162,7 @@ def download_branch(branch):
|
|||||||
if os.path.isdir(dir_name):
|
if os.path.isdir(dir_name):
|
||||||
shutil.rmtree(dir_name)
|
shutil.rmtree(dir_name)
|
||||||
cmd = ["bzr", "branch", branch]
|
cmd = ["bzr", "branch", branch]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Failed to download branch %s." % (branch))
|
Logger.error("Failed to download branch %s." % (branch))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -170,7 +172,7 @@ def download_branch(branch):
|
|||||||
def merge_branch(branch):
|
def merge_branch(branch):
|
||||||
edit = False
|
edit = False
|
||||||
cmd = ["bzr", "merge", branch]
|
cmd = ["bzr", "merge", branch]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Failed to merge branch %s." % (branch))
|
Logger.error("Failed to merge branch %s." % (branch))
|
||||||
ask_for_manual_fixing()
|
ask_for_manual_fixing()
|
||||||
@ -182,7 +184,7 @@ def extract_source(dsc_file, verbose=False):
|
|||||||
cmd = ["dpkg-source", "--no-preparation", "-x", dsc_file]
|
cmd = ["dpkg-source", "--no-preparation", "-x", dsc_file]
|
||||||
if not verbose:
|
if not verbose:
|
||||||
cmd.insert(1, "-q")
|
cmd.insert(1, "-q")
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.error("Extraction of %s failed." % (os.path.basename(dsc_file)))
|
Logger.error("Extraction of %s failed." % (os.path.basename(dsc_file)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -219,13 +221,13 @@ def get_open_ubuntu_bug_task(launchpad, bug, branch=None):
|
|||||||
task = tasks[0]
|
task = tasks[0]
|
||||||
elif len(ubuntu_tasks) > 1:
|
elif len(ubuntu_tasks) > 1:
|
||||||
task_list = [t.get_short_info() for t in ubuntu_tasks]
|
task_list = [t.get_short_info() for t in ubuntu_tasks]
|
||||||
Logger.info("%i Ubuntu tasks exist for bug #%i.\n%s", len(ubuntu_tasks),
|
Logger.debug("%i Ubuntu tasks exist for bug #%i.\n%s", len(ubuntu_tasks),
|
||||||
bug_id, "\n".join(task_list))
|
bug_id, "\n".join(task_list))
|
||||||
open_ubuntu_tasks = [x for x in ubuntu_tasks if not x.is_complete()]
|
open_ubuntu_tasks = [x for x in ubuntu_tasks if not x.is_complete()]
|
||||||
if len(open_ubuntu_tasks) == 1:
|
if len(open_ubuntu_tasks) == 1:
|
||||||
task = open_ubuntu_tasks[0]
|
task = open_ubuntu_tasks[0]
|
||||||
else:
|
else:
|
||||||
Logger.normal("https://launchpad.net/bugs/%i has %i Ubuntu tasks:" %
|
Logger.info("https://launchpad.net/bugs/%i has %i Ubuntu tasks:" %
|
||||||
(bug_id, len(ubuntu_tasks)))
|
(bug_id, len(ubuntu_tasks)))
|
||||||
for i in range(len(ubuntu_tasks)):
|
for i in range(len(ubuntu_tasks)):
|
||||||
print("%i) %s" % (i + 1,
|
print("%i) %s" % (i + 1,
|
||||||
@ -233,7 +235,7 @@ def get_open_ubuntu_bug_task(launchpad, bug, branch=None):
|
|||||||
selected = input_number("To which Ubuntu task does the patch belong",
|
selected = input_number("To which Ubuntu task does the patch belong",
|
||||||
1, len(ubuntu_tasks))
|
1, len(ubuntu_tasks))
|
||||||
task = ubuntu_tasks[selected - 1]
|
task = ubuntu_tasks[selected - 1]
|
||||||
Logger.info("Selected Ubuntu task: %s" % (task.get_short_info()))
|
Logger.debug("Selected Ubuntu task: %s" % (task.get_short_info()))
|
||||||
return task
|
return task
|
||||||
|
|
||||||
|
|
||||||
@ -248,15 +250,15 @@ def _create_and_change_into(workdir):
|
|||||||
(workdir, error.errno, error.strerror))
|
(workdir, error.errno, error.strerror))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if workdir != os.getcwd():
|
if workdir != os.getcwd():
|
||||||
Logger.command(["cd", workdir])
|
Logger.debug("cd " + workdir)
|
||||||
os.chdir(workdir)
|
os.chdir(workdir)
|
||||||
|
|
||||||
|
|
||||||
def _update_maintainer_field():
|
def _update_maintainer_field():
|
||||||
"""Update the Maintainer field in debian/control."""
|
"""Update the Maintainer field in debian/control."""
|
||||||
Logger.command(["update-maintainer"])
|
Logger.debug("update-maintainer")
|
||||||
try:
|
try:
|
||||||
update_maintainer("debian", Logger.verbose)
|
update_maintainer("debian", Logger.isEnabledFor(logging.DEBUG))
|
||||||
except MaintainerUpdateException as e:
|
except MaintainerUpdateException as e:
|
||||||
Logger.error("update-maintainer failed: %s", str(e))
|
Logger.error("update-maintainer failed: %s", str(e))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@ -265,9 +267,9 @@ def _update_maintainer_field():
|
|||||||
def _update_timestamp():
|
def _update_timestamp():
|
||||||
"""Run dch to update the timestamp of debian/changelog."""
|
"""Run dch to update the timestamp of debian/changelog."""
|
||||||
cmd = ["dch", "--maintmaint", "--release", ""]
|
cmd = ["dch", "--maintmaint", "--release", ""]
|
||||||
Logger.command(cmd)
|
Logger.debug(' '.join(cmd))
|
||||||
if subprocess.call(cmd) != 0:
|
if subprocess.call(cmd) != 0:
|
||||||
Logger.info("Failed to update timestamp in debian/changelog.")
|
Logger.debug("Failed to update timestamp in debian/changelog.")
|
||||||
|
|
||||||
|
|
||||||
def _download_and_change_into(task, dsc_file, patch, branch):
|
def _download_and_change_into(task, dsc_file, patch, branch):
|
||||||
@ -277,23 +279,23 @@ def _download_and_change_into(task, dsc_file, patch, branch):
|
|||||||
branch_dir = download_branch(task.get_branch_link())
|
branch_dir = download_branch(task.get_branch_link())
|
||||||
|
|
||||||
# change directory
|
# change directory
|
||||||
Logger.command(["cd", branch_dir])
|
Logger.debug("cd " + branch_dir)
|
||||||
os.chdir(branch_dir)
|
os.chdir(branch_dir)
|
||||||
else:
|
else:
|
||||||
if patch:
|
if patch:
|
||||||
patch.download()
|
patch.download()
|
||||||
|
|
||||||
Logger.info("Ubuntu package: %s" % (task.package))
|
Logger.debug("Ubuntu package: %s" % (task.package))
|
||||||
if task.is_merge():
|
if task.is_merge():
|
||||||
Logger.info("The task is a merge request.")
|
Logger.debug("The task is a merge request.")
|
||||||
if task.is_sync():
|
if task.is_sync():
|
||||||
Logger.info("The task is a sync request.")
|
Logger.debug("The task is a sync request.")
|
||||||
|
|
||||||
extract_source(dsc_file, Logger.verbose)
|
extract_source(dsc_file, Logger.isEnabledFor(logging.DEBUG))
|
||||||
|
|
||||||
# change directory
|
# change directory
|
||||||
directory = task.package + '-' + task.get_version().upstream_version
|
directory = task.package + '-' + task.get_version().upstream_version
|
||||||
Logger.command(["cd", directory])
|
Logger.debug("cd " + directory)
|
||||||
os.chdir(directory)
|
os.chdir(directory)
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,10 +20,9 @@ import os.path
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from urllib.error import HTTPError, URLError
|
from urllib.error import HTTPError
|
||||||
from urllib.request import OpenerDirector, urlopen
|
from urllib.request import OpenerDirector, urlopen
|
||||||
|
|
||||||
import debian.deb822
|
|
||||||
import httplib2
|
import httplib2
|
||||||
|
|
||||||
import ubuntutools.archive
|
import ubuntutools.archive
|
||||||
@ -85,7 +84,6 @@ class LocalSourcePackageTestCase(unittest.TestCase):
|
|||||||
self.workdir = tempfile.mkdtemp(prefix='udt-test')
|
self.workdir = tempfile.mkdtemp(prefix='udt-test')
|
||||||
|
|
||||||
self._stubout('ubuntutools.archive.Distribution')
|
self._stubout('ubuntutools.archive.Distribution')
|
||||||
self._stubout('ubuntutools.archive.rmadison')
|
|
||||||
|
|
||||||
self.mock_http = self._stubout('httplib2.Http.request')
|
self.mock_http = self._stubout('httplib2.Http.request')
|
||||||
self.mock_http.side_effect = self.request_proxy
|
self.mock_http.side_effect = self.request_proxy
|
||||||
@ -93,10 +91,6 @@ class LocalSourcePackageTestCase(unittest.TestCase):
|
|||||||
self.url_opener = mock.MagicMock(spec=OpenerDirector)
|
self.url_opener = mock.MagicMock(spec=OpenerDirector)
|
||||||
self.url_opener.open.side_effect = self.urlopen_proxy
|
self.url_opener.open.side_effect = self.urlopen_proxy
|
||||||
|
|
||||||
# Silence the tests a little:
|
|
||||||
self._stubout('ubuntutools.logger.Logger.stdout')
|
|
||||||
self._stubout('ubuntutools.logger.Logger.stderr')
|
|
||||||
|
|
||||||
def _stubout(self, stub):
|
def _stubout(self, stub):
|
||||||
patcher = mock.patch(stub)
|
patcher = mock.patch(stub)
|
||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
@ -146,11 +140,13 @@ class LocalSourcePackageTestCase(unittest.TestCase):
|
|||||||
return self.request_404(url)
|
return self.request_404(url)
|
||||||
|
|
||||||
def test_local_copy(self):
|
def test_local_copy(self):
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
pkg = self.SourcePackage(package='example',
|
||||||
|
version='1.0-1',
|
||||||
|
component='main',
|
||||||
dscfile='test-data/example_1.0-1.dsc',
|
dscfile='test-data/example_1.0-1.dsc',
|
||||||
workdir=self.workdir)
|
workdir=self.workdir,
|
||||||
pkg.quiet = True
|
verify_signature=False)
|
||||||
pkg.pull(verify_signature=False)
|
pkg.pull()
|
||||||
pkg.unpack()
|
pkg.unpack()
|
||||||
|
|
||||||
def test_workdir_srcpkg_noinfo(self):
|
def test_workdir_srcpkg_noinfo(self):
|
||||||
@ -160,9 +156,9 @@ class LocalSourcePackageTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
pkg = self.SourcePackage(dscfile=os.path.join(self.workdir,
|
pkg = self.SourcePackage(dscfile=os.path.join(self.workdir,
|
||||||
'example_1.0-1.dsc'),
|
'example_1.0-1.dsc'),
|
||||||
workdir=self.workdir)
|
workdir=self.workdir,
|
||||||
pkg.quiet = True
|
verify_signature=False)
|
||||||
pkg.pull(verify_signature=False)
|
pkg.pull()
|
||||||
pkg.unpack()
|
pkg.unpack()
|
||||||
|
|
||||||
def test_workdir_srcpkg_info(self):
|
def test_workdir_srcpkg_info(self):
|
||||||
@ -170,12 +166,13 @@ class LocalSourcePackageTestCase(unittest.TestCase):
|
|||||||
shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir)
|
shutil.copy2('test-data/example_1.0.orig.tar.gz', self.workdir)
|
||||||
shutil.copy2('test-data/example_1.0-1.debian.tar.xz', self.workdir)
|
shutil.copy2('test-data/example_1.0-1.debian.tar.xz', self.workdir)
|
||||||
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
pkg = self.SourcePackage(package='example', version='1.0-1',
|
||||||
|
component='main',
|
||||||
dscfile=os.path.join(self.workdir,
|
dscfile=os.path.join(self.workdir,
|
||||||
'example_1.0-1.dsc'),
|
'example_1.0-1.dsc'),
|
||||||
workdir=self.workdir)
|
workdir=self.workdir,
|
||||||
pkg.quiet = True
|
verify_signature=False)
|
||||||
pkg.pull(verify_signature=False)
|
pkg.pull()
|
||||||
pkg.unpack()
|
pkg.unpack()
|
||||||
|
|
||||||
def test_verification(self):
|
def test_verification(self):
|
||||||
@ -186,103 +183,18 @@ class LocalSourcePackageTestCase(unittest.TestCase):
|
|||||||
'r+b') as f:
|
'r+b') as f:
|
||||||
f.write(b'CORRUPTION')
|
f.write(b'CORRUPTION')
|
||||||
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
pkg = self.SourcePackage(package='example',
|
||||||
|
version='1.0-1',
|
||||||
|
component='main',
|
||||||
dscfile='test-data/example_1.0-1.dsc',
|
dscfile='test-data/example_1.0-1.dsc',
|
||||||
workdir=self.workdir)
|
workdir=self.workdir,
|
||||||
pkg.quiet = True
|
verify_signature=False)
|
||||||
pkg.pull(verify_signature=False)
|
pkg.pull()
|
||||||
|
|
||||||
def test_pull(self):
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
|
||||||
workdir=self.workdir)
|
|
||||||
|
|
||||||
pkg.url_opener = self.url_opener
|
|
||||||
pkg.quiet = True
|
|
||||||
pkg.pull(verify_signature=False)
|
|
||||||
|
|
||||||
def test_mirrors(self):
|
|
||||||
mirror = 'http://mirror'
|
|
||||||
sequence = [self.urlopen_null, self.urlopen_404, self.urlopen_proxy,
|
|
||||||
self.urlopen_proxy]
|
|
||||||
|
|
||||||
def _callable_iter(*args, **kwargs):
|
|
||||||
return sequence.pop(0)(*args, **kwargs)
|
|
||||||
url_opener = mock.MagicMock(spec=OpenerDirector)
|
|
||||||
url_opener.open.side_effect = _callable_iter
|
|
||||||
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
|
||||||
workdir=self.workdir, mirrors=[mirror])
|
|
||||||
pkg.url_opener = url_opener
|
|
||||||
pkg.quiet = True
|
|
||||||
pkg.pull(verify_signature=False)
|
|
||||||
|
|
||||||
def test_dsc_missing(self):
|
def test_dsc_missing(self):
|
||||||
self.mock_http.side_effect = self.request_404
|
self.mock_http.side_effect = self.request_404
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
pkg = self.SourcePackage(package='example',
|
||||||
|
version='1.0-1',
|
||||||
|
component='main',
|
||||||
workdir=self.workdir)
|
workdir=self.workdir)
|
||||||
pkg.quiet = True
|
|
||||||
self.assertRaises(ubuntutools.archive.DownloadError, pkg.pull)
|
self.assertRaises(ubuntutools.archive.DownloadError, pkg.pull)
|
||||||
|
|
||||||
|
|
||||||
class DebianLocalSourcePackageTestCase(LocalSourcePackageTestCase):
|
|
||||||
SourcePackage = ubuntutools.archive.DebianSourcePackage
|
|
||||||
|
|
||||||
def test_mirrors(self):
|
|
||||||
debian_mirror = 'http://mirror/debian'
|
|
||||||
debsec_mirror = 'http://mirror/debsec'
|
|
||||||
|
|
||||||
sequence = [self.urlopen_null,
|
|
||||||
self.urlopen_404,
|
|
||||||
self.urlopen_404,
|
|
||||||
self.urlopen_404,
|
|
||||||
self.urlopen_404,
|
|
||||||
lambda x: BytesIO(
|
|
||||||
b'{"fileinfo": {"hashabc": [{"name": "example_1.0.orig.tar.gz"}]}}'),
|
|
||||||
self.urlopen_file('example_1.0.orig.tar.gz'),
|
|
||||||
self.urlopen_proxy]
|
|
||||||
|
|
||||||
def _callable_iter(*args, **kwargs):
|
|
||||||
return sequence.pop(0)(*args, **kwargs)
|
|
||||||
url_opener = mock.MagicMock(spec=OpenerDirector)
|
|
||||||
url_opener.open.side_effect = _callable_iter
|
|
||||||
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
|
||||||
workdir=self.workdir, mirrors=[debian_mirror,
|
|
||||||
debsec_mirror])
|
|
||||||
pkg.quiet = True
|
|
||||||
pkg.url_opener = url_opener
|
|
||||||
pkg.pull(verify_signature=False)
|
|
||||||
pkg.unpack()
|
|
||||||
|
|
||||||
def test_dsc_missing(self):
|
|
||||||
mirror = 'http://mirror'
|
|
||||||
self.mock_http.side_effect = self.request_404_then_proxy
|
|
||||||
|
|
||||||
patcher = mock.patch.object(debian.deb822.GpgInfo, 'from_sequence')
|
|
||||||
self.addCleanup(patcher.stop)
|
|
||||||
mock_gpg_info = patcher.start()
|
|
||||||
mock_gpg_info.return_value = debian.deb822.GpgInfo.from_output(
|
|
||||||
'[GNUPG:] GOODSIG DEADBEEF Joe Developer '
|
|
||||||
'<joe@example.net>')
|
|
||||||
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
|
||||||
workdir=self.workdir, mirrors=[mirror])
|
|
||||||
pkg.url_opener = self.url_opener
|
|
||||||
pkg.pull(verify_signature=False)
|
|
||||||
|
|
||||||
def test_dsc_badsig(self):
|
|
||||||
mirror = 'http://mirror'
|
|
||||||
self.mock_http.side_effect = self.request_404_then_proxy
|
|
||||||
|
|
||||||
patcher = mock.patch.object(debian.deb822.GpgInfo, 'from_sequence')
|
|
||||||
self.addCleanup(patcher.stop)
|
|
||||||
mock_gpg_info = patcher.start()
|
|
||||||
mock_gpg_info.return_value = debian.deb822.GpgInfo.from_output(
|
|
||||||
'[GNUPG:] ERRSIG DEADBEEF')
|
|
||||||
|
|
||||||
pkg = self.SourcePackage('example', '1.0-1', 'main',
|
|
||||||
workdir=self.workdir, mirrors=[mirror])
|
|
||||||
try:
|
|
||||||
self.assertRaises(ubuntutools.archive.DownloadError, pkg.pull)
|
|
||||||
except URLError:
|
|
||||||
raise unittest.SkipTest('Test needs addr resolution to work')
|
|
||||||
|
@ -18,11 +18,10 @@
|
|||||||
import locale
|
import locale
|
||||||
import mock
|
import mock
|
||||||
import os
|
import os
|
||||||
import sys
|
# import sys
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from ubuntutools.config import UDTConfig, ubu_email
|
from ubuntutools.config import UDTConfig, ubu_email
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.test import unittest
|
from ubuntutools.test import unittest
|
||||||
|
|
||||||
|
|
||||||
@ -51,16 +50,16 @@ class ConfigTestCase(unittest.TestCase):
|
|||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
patcher.start()
|
patcher.start()
|
||||||
|
|
||||||
Logger.stdout = StringIO()
|
# Logger.stdout = StringIO()
|
||||||
Logger.stderr = StringIO()
|
# Logger.stderr = StringIO()
|
||||||
|
|
||||||
self.clean_environment()
|
self.clean_environment()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.assertEqual(Logger.stdout.getvalue(), '')
|
# self.assertEqual(Logger.stdout.getvalue(), '')
|
||||||
self.assertEqual(Logger.stderr.getvalue(), '')
|
# self.assertEqual(Logger.stderr.getvalue(), '')
|
||||||
Logger.stdout = sys.stdout
|
# Logger.stdout = sys.stdout
|
||||||
Logger.stderr = sys.stderr
|
# Logger.stderr = sys.stderr
|
||||||
|
|
||||||
self.clean_environment()
|
self.clean_environment()
|
||||||
|
|
||||||
@ -98,11 +97,11 @@ REPEAT=yes
|
|||||||
'INHERIT': 'user',
|
'INHERIT': 'user',
|
||||||
'REPEAT': 'yes',
|
'REPEAT': 'yes',
|
||||||
})
|
})
|
||||||
errs = Logger.stderr.getvalue().strip()
|
# errs = Logger.stderr.getvalue().strip()
|
||||||
Logger.stderr = StringIO()
|
# Logger.stderr = StringIO()
|
||||||
self.assertEqual(len(errs.splitlines()), 1)
|
# self.assertEqual(len(errs.splitlines()), 1)
|
||||||
self.assertRegex(errs,
|
# self.assertRegex(errs,
|
||||||
r'Warning: Cannot parse.*\bCOMMAND_EXECUTION=a')
|
# r'Warning: Cannot parse.*\bCOMMAND_EXECUTION=a')
|
||||||
|
|
||||||
def get_value(self, *args, **kwargs):
|
def get_value(self, *args, **kwargs):
|
||||||
config = UDTConfig(prefix='TEST')
|
config = UDTConfig(prefix='TEST')
|
||||||
@ -138,11 +137,11 @@ REPEAT=yes
|
|||||||
self._config_files['user'] = 'COMPATFOOBAR=bar'
|
self._config_files['user'] = 'COMPATFOOBAR=bar'
|
||||||
self.assertEqual(self.get_value('QUX', compat_keys=['COMPATFOOBAR']),
|
self.assertEqual(self.get_value('QUX', compat_keys=['COMPATFOOBAR']),
|
||||||
'bar')
|
'bar')
|
||||||
errs = Logger.stderr.getvalue().strip()
|
# errs = Logger.stderr.getvalue().strip()
|
||||||
Logger.stderr = StringIO()
|
# Logger.stderr = StringIO()
|
||||||
self.assertEqual(len(errs.splitlines()), 1)
|
# self.assertEqual(len(errs.splitlines()), 1)
|
||||||
self.assertRegex(errs,
|
# self.assertRegex(errs,
|
||||||
r'deprecated.*\bCOMPATFOOBAR\b.*\bTEST_QUX\b')
|
# r'deprecated.*\bCOMPATFOOBAR\b.*\bTEST_QUX\b')
|
||||||
|
|
||||||
def test_boolean(self):
|
def test_boolean(self):
|
||||||
self._config_files['user'] = "TEST_BOOLEAN=yes"
|
self._config_files['user'] = "TEST_BOOLEAN=yes"
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
# test_logger.py - Test ubuntutools.logger.Logger.
|
|
||||||
#
|
|
||||||
# Copyright (C) 2012, Stefano Rivera <stefanor@debian.org>
|
|
||||||
#
|
|
||||||
# Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
|
||||||
# copyright notice and this permission notice appear in all copies.
|
|
||||||
#
|
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
||||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
||||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
||||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
||||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
||||||
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
||||||
# PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
from io import StringIO
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.test import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class LoggerTestCase(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
Logger.stdout = StringIO()
|
|
||||||
Logger.stderr = StringIO()
|
|
||||||
self._script_name = Logger.script_name
|
|
||||||
Logger.script_name = 'test'
|
|
||||||
self._verbose = Logger.verbose
|
|
||||||
|
|
||||||
def tearDown(self):
|
|
||||||
Logger.stdout = sys.stdout
|
|
||||||
Logger.stderr = sys.stderr
|
|
||||||
Logger.script_name = self._script_name
|
|
||||||
Logger.verbose = self._verbose
|
|
||||||
|
|
||||||
def testCommand(self):
|
|
||||||
Logger.command(('ls', 'a b'))
|
|
||||||
self.assertEqual(Logger.stdout.getvalue(), '')
|
|
||||||
Logger.set_verbosity(True)
|
|
||||||
Logger.command(('ls', 'a b'))
|
|
||||||
self.assertEqual(Logger.stdout.getvalue(), 'test: I: ls "a b"\n')
|
|
||||||
self.assertEqual(Logger.stderr.getvalue(), '')
|
|
||||||
|
|
||||||
def testNoArgs(self):
|
|
||||||
Logger.normal('hello %s')
|
|
||||||
self.assertEqual(Logger.stdout.getvalue(), 'test: hello %s\n')
|
|
||||||
self.assertEqual(Logger.stderr.getvalue(), '')
|
|
||||||
|
|
||||||
def testArgs(self):
|
|
||||||
Logger.normal('hello %s', 'world')
|
|
||||||
self.assertEqual(Logger.stdout.getvalue(), 'test: hello world\n')
|
|
||||||
self.assertEqual(Logger.stderr.getvalue(), '')
|
|
@ -18,10 +18,9 @@
|
|||||||
|
|
||||||
import mock
|
import mock
|
||||||
import os
|
import os
|
||||||
import sys
|
# import sys
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
from ubuntutools.test import unittest
|
from ubuntutools.test import unittest
|
||||||
from ubuntutools.update_maintainer import update_maintainer
|
from ubuntutools.update_maintainer import update_maintainer
|
||||||
|
|
||||||
@ -236,18 +235,18 @@ class UpdateMaintainerTestCase(unittest.TestCase):
|
|||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
patcher.start()
|
patcher.start()
|
||||||
self._files["rules"] = StringIO(_SIMPLE_RULES)
|
self._files["rules"] = StringIO(_SIMPLE_RULES)
|
||||||
Logger.stdout = StringIO()
|
# Logger.stdout = StringIO()
|
||||||
Logger.stderr = StringIO()
|
# Logger.stderr = StringIO()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.assertEqual(Logger.stdout.getvalue(), '')
|
# self.assertEqual(Logger.stdout.getvalue(), '')
|
||||||
self.assertEqual(Logger.stderr.getvalue(), '')
|
# self.assertEqual(Logger.stderr.getvalue(), '')
|
||||||
self._files["changelog"] = None
|
self._files["changelog"] = None
|
||||||
self._files["control"] = None
|
self._files["control"] = None
|
||||||
self._files["control.in"] = None
|
self._files["control.in"] = None
|
||||||
self._files["rules"] = None
|
self._files["rules"] = None
|
||||||
Logger.stdout = sys.stdout
|
# Logger.stdout = sys.stdout
|
||||||
Logger.stderr = sys.stderr
|
# Logger.stderr = sys.stderr
|
||||||
|
|
||||||
# pylint: enable=C0103
|
# pylint: enable=C0103
|
||||||
def test_debian_package(self):
|
def test_debian_package(self):
|
||||||
@ -266,11 +265,11 @@ class UpdateMaintainerTestCase(unittest.TestCase):
|
|||||||
self._files["control"] = StringIO(_AXIS2C_CONTROL)
|
self._files["control"] = StringIO(_AXIS2C_CONTROL)
|
||||||
update_maintainer(self._directory)
|
update_maintainer(self._directory)
|
||||||
self.assertEqual(self._files["control"].getvalue(), _AXIS2C_UPDATED)
|
self.assertEqual(self._files["control"].getvalue(), _AXIS2C_UPDATED)
|
||||||
warnings = Logger.stderr.getvalue().strip()
|
# warnings = Logger.stderr.getvalue().strip()
|
||||||
Logger.stderr = StringIO()
|
# Logger.stderr = StringIO()
|
||||||
self.assertEqual(len(warnings.splitlines()), 1)
|
# self.assertEqual(len(warnings.splitlines()), 1)
|
||||||
self.assertRegex(warnings, "Warning: Overwriting original maintainer: "
|
# self.assertRegex(warnings, "Warning: Overwriting original maintainer: "
|
||||||
"Soren Hansen <soren@ubuntu.com>")
|
# "Soren Hansen <soren@ubuntu.com>")
|
||||||
|
|
||||||
def test_update_maintainer(self):
|
def test_update_maintainer(self):
|
||||||
"""Test: Update Maintainer field."""
|
"""Test: Update Maintainer field."""
|
||||||
|
@ -20,7 +20,9 @@ import os
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import debian.changelog
|
import debian.changelog
|
||||||
from ubuntutools.logger import Logger
|
|
||||||
|
import logging
|
||||||
|
Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Prior May 2009 these Maintainers were used:
|
# Prior May 2009 these Maintainers were used:
|
||||||
_PREVIOUS_UBUNTU_MAINTAINER = (
|
_PREVIOUS_UBUNTU_MAINTAINER = (
|
||||||
@ -176,7 +178,7 @@ def update_maintainer(debian_directory, verbose=False):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if control.get_original_maintainer() is not None:
|
if control.get_original_maintainer() is not None:
|
||||||
Logger.warn("Overwriting original maintainer: %s",
|
Logger.warning("Overwriting original maintainer: %s",
|
||||||
control.get_original_maintainer())
|
control.get_original_maintainer())
|
||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user