mirror of
https://git.launchpad.net/ubuntu-dev-tools
synced 2025-03-13 08:01:09 +00:00
``` flynt -ll 99 -tc -tj -a pbuilder-dist pm-helper running-autopkgtests ubuntu-build ubuntutools ```
212 lines
8.1 KiB
Python
212 lines
8.1 KiB
Python
# update_maintainer.py - updates the Maintainer field of an Ubuntu package
|
|
#
|
|
# Copyright (C) 2010, Benjamin Drung <bdrung@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.
|
|
|
|
"""This module is for updating the Maintainer field of an Ubuntu package."""
|
|
|
|
import logging
|
|
import os
|
|
import re
|
|
|
|
import debian.changelog
|
|
|
|
Logger = logging.getLogger(__name__)
|
|
|
|
# Prior May 2009 these Maintainers were used:
|
|
_PREVIOUS_UBUNTU_MAINTAINER = (
|
|
"ubuntu core developers <ubuntu-devel@lists.ubuntu.com>",
|
|
"ubuntu core developers <ubuntu-devel-discuss@lists.ubuntu.com>",
|
|
"ubuntu motu developers <ubuntu-motu@lists.ubuntu.com>",
|
|
)
|
|
_UBUNTU_MAINTAINER = "Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>"
|
|
|
|
|
|
class MaintainerUpdateException(Exception):
|
|
pass
|
|
|
|
|
|
class Control:
|
|
"""Represents a debian/control file"""
|
|
|
|
def __init__(self, filename):
|
|
assert os.path.isfile(filename), f"{filename} does not exist."
|
|
self._filename = filename
|
|
self._content = open(filename, encoding="utf-8").read()
|
|
|
|
def get_maintainer(self):
|
|
"""Returns the value of the Maintainer field."""
|
|
maintainer = re.search("^Maintainer: ?(.*)$", self._content, re.MULTILINE)
|
|
if maintainer:
|
|
maintainer = maintainer.group(1)
|
|
return maintainer
|
|
|
|
def get_original_maintainer(self):
|
|
"""Returns the value of the XSBC-Original-Maintainer field."""
|
|
orig_maintainer = re.search(
|
|
"^(?:[XSBC]*-)?Original-Maintainer: ?(.*)$", self._content, re.MULTILINE
|
|
)
|
|
if orig_maintainer:
|
|
orig_maintainer = orig_maintainer.group(1)
|
|
return orig_maintainer
|
|
|
|
def save(self, filename=None):
|
|
"""Saves the control file."""
|
|
if filename:
|
|
self._filename = filename
|
|
control_file = open(self._filename, "w", encoding="utf-8")
|
|
control_file.write(self._content)
|
|
control_file.close()
|
|
|
|
def set_maintainer(self, maintainer):
|
|
"""Sets the value of the Maintainer field."""
|
|
pattern = re.compile("^Maintainer: ?.*$", re.MULTILINE)
|
|
self._content = pattern.sub(f"Maintainer: {maintainer}", self._content)
|
|
|
|
def set_original_maintainer(self, original_maintainer):
|
|
"""Sets the value of the XSBC-Original-Maintainer field."""
|
|
original_maintainer = f"XSBC-Original-Maintainer: {original_maintainer}"
|
|
if self.get_original_maintainer():
|
|
pattern = re.compile("^(?:[XSBC]*-)?Original-Maintainer:.*$", re.MULTILINE)
|
|
self._content = pattern.sub(original_maintainer, self._content)
|
|
else:
|
|
pattern = re.compile("^(Maintainer:.*)$", re.MULTILINE)
|
|
self._content = pattern.sub(f"\\1\\n{original_maintainer}", self._content)
|
|
|
|
def remove_original_maintainer(self):
|
|
"""Strip out out the XSBC-Original-Maintainer line"""
|
|
pattern = re.compile(
|
|
"^(?:[XSBC]*-)?Original-Maintainer:.*?$.*?^", re.MULTILINE | re.DOTALL
|
|
)
|
|
self._content = pattern.sub("", self._content)
|
|
|
|
|
|
def _get_distribution(changelog_file):
|
|
"""get distribution of latest changelog entry"""
|
|
changelog = debian.changelog.Changelog(
|
|
open(changelog_file, encoding="utf-8"), strict=False, max_blocks=1
|
|
)
|
|
distribution = changelog.distributions.split()[0]
|
|
# Strip things like "-proposed-updates" or "-security" from distribution
|
|
return distribution.split("-", 1)[0]
|
|
|
|
|
|
def _find_files(debian_directory, verbose):
|
|
"""Find possible control files.
|
|
Returns (changelog, control files list)
|
|
Raises an exception if none can be found.
|
|
"""
|
|
possible_contol_files = [os.path.join(debian_directory, f) for f in ["control.in", "control"]]
|
|
|
|
changelog_file = os.path.join(debian_directory, "changelog")
|
|
control_files = [f for f in possible_contol_files if os.path.isfile(f)]
|
|
|
|
# Make sure that a changelog and control file is available
|
|
if len(control_files) == 0:
|
|
raise MaintainerUpdateException(f"No control file found in {debian_directory}.")
|
|
if not os.path.isfile(changelog_file):
|
|
raise MaintainerUpdateException(f"No changelog file found in {debian_directory}.")
|
|
|
|
# If the rules file accounts for XSBC-Original-Maintainer, we should not
|
|
# touch it in this package (e.g. the python package).
|
|
rules_file = os.path.join(debian_directory, "rules")
|
|
if (
|
|
os.path.isfile(rules_file)
|
|
and "XSBC-Original-" in open(rules_file, encoding="utf-8").read()
|
|
):
|
|
if verbose:
|
|
print("XSBC-Original is managed by 'rules' file. Doing nothing.")
|
|
control_files = []
|
|
|
|
return (changelog_file, control_files)
|
|
|
|
|
|
def update_maintainer(debian_directory, verbose=False):
|
|
"""updates the Maintainer field of an Ubuntu package
|
|
|
|
* No modifications are made if the Maintainer field contains an ubuntu.com
|
|
email address. Otherwise, the Maintainer field will be set to
|
|
Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
|
|
* The old value will be saved in a field named XSBC-Original-Maintainer
|
|
if the Maintainer field is modified.
|
|
|
|
Policy: https://wiki.ubuntu.com/DebianMaintainerField
|
|
"""
|
|
try:
|
|
changelog_file, control_files = _find_files(debian_directory, verbose)
|
|
except MaintainerUpdateException as e:
|
|
Logger.error(str(e))
|
|
raise
|
|
|
|
distribution = _get_distribution(changelog_file)
|
|
for control_file in control_files:
|
|
control = Control(control_file)
|
|
original_maintainer = control.get_maintainer()
|
|
|
|
if original_maintainer is None:
|
|
Logger.error("No Maintainer field found in %s.", control_file)
|
|
raise MaintainerUpdateException("No Maintainer field found")
|
|
|
|
if original_maintainer.strip().lower() in _PREVIOUS_UBUNTU_MAINTAINER:
|
|
if verbose:
|
|
print(f"The old maintainer was: {original_maintainer}")
|
|
print(f"Resetting as: {_UBUNTU_MAINTAINER}")
|
|
control.set_maintainer(_UBUNTU_MAINTAINER)
|
|
control.save()
|
|
continue
|
|
|
|
if original_maintainer.strip().endswith("ubuntu.com>"):
|
|
if verbose:
|
|
print("The Maintainer email is set to an ubuntu.com address. Doing nothing.")
|
|
continue
|
|
|
|
if distribution in ("stable", "testing", "unstable", "experimental"):
|
|
if verbose:
|
|
print("The package targets Debian. Doing nothing.")
|
|
return
|
|
|
|
if control.get_original_maintainer() is not None:
|
|
Logger.warning(
|
|
"Overwriting original maintainer: %s", control.get_original_maintainer()
|
|
)
|
|
|
|
if verbose:
|
|
print(f"The original maintainer is: {original_maintainer}")
|
|
print(f"Resetting as: {_UBUNTU_MAINTAINER}")
|
|
control.set_original_maintainer(original_maintainer)
|
|
control.set_maintainer(_UBUNTU_MAINTAINER)
|
|
control.save()
|
|
|
|
return
|
|
|
|
|
|
def restore_maintainer(debian_directory, verbose=False):
|
|
"""Restore the original maintainer"""
|
|
try:
|
|
control_files = _find_files(debian_directory, verbose)[1]
|
|
except MaintainerUpdateException as e:
|
|
Logger.error(str(e))
|
|
raise
|
|
|
|
for control_file in control_files:
|
|
control = Control(control_file)
|
|
orig_maintainer = control.get_original_maintainer()
|
|
if not orig_maintainer:
|
|
continue
|
|
if verbose:
|
|
print(f"Restoring original maintainer: {orig_maintainer}")
|
|
control.set_maintainer(orig_maintainer)
|
|
control.remove_original_maintainer()
|
|
control.save()
|