mirror of
https://github.com/rpm-software-management/tito.git
synced 2025-02-23 12:12:47 +00:00
Merge pull request #325 from Conan-Kudo/susetagger
Add support for SUSE-style detached changelogs
This commit is contained in:
commit
1d311e7916
5 changed files with 212 additions and 1 deletions
|
@ -68,7 +68,7 @@ class FedoraGitReleaser(Releaser):
|
|||
self.build_targets = build_target_parser.get_build_targets()
|
||||
|
||||
# Files we should copy to git during a release:
|
||||
self.copy_extensions = (".spec", ".patch")
|
||||
self.copy_extensions = (".spec", ".changes", ".rpmlintrc", ".patch")
|
||||
|
||||
def release(self, dry_run=False, no_build=False, scratch=False):
|
||||
self.scratch = scratch
|
||||
|
|
|
@ -8,3 +8,4 @@ from tito.tagger.main import \
|
|||
from tito.tagger.rheltagger import RHELTagger
|
||||
from tito.tagger.zstreamtagger import zStreamTagger
|
||||
from tito.tagger.cargobump import CargoBump
|
||||
from tito.tagger.susetagger import SUSETagger
|
||||
|
|
202
src/tito/tagger/susetagger.py
Normal file
202
src/tito/tagger/susetagger.py
Normal file
|
@ -0,0 +1,202 @@
|
|||
# Copyright (c) 2012-2016 SUSE Linux Products GmbH
|
||||
# Copyright (c) 2018 Neal Gompa.
|
||||
#
|
||||
# This software is licensed to you under the GNU General Public License,
|
||||
# version 2 (GPLv2). There is NO WARRANTY for this software, express or
|
||||
# implied, including the implied warranties of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
|
||||
# along with this software; if not, see
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
||||
"""
|
||||
Code for tagging packages in SUSE Style.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import textwrap
|
||||
from tito.common import (debug, run_command, get_latest_tagged_version)
|
||||
from tito.compat import write, StringIO
|
||||
from tito.tagger import VersionTagger
|
||||
|
||||
from time import strftime
|
||||
|
||||
|
||||
class SUSETagger(VersionTagger):
|
||||
"""
|
||||
Tagger which is based on VersionTagger and use SUSE format of Changelog
|
||||
and SUSE specific changes file:
|
||||
|
||||
If you want it put in tito.pros (global) or localy in build.py.props:
|
||||
[buildconfig]
|
||||
tagger = tito.susetagger.SUSETagger
|
||||
"""
|
||||
|
||||
def __init__(self, config=None, keep_version=False, offline=False, user_config=None):
|
||||
VersionTagger.__init__(self, config=config, keep_version=keep_version,
|
||||
offline=offline, user_config=user_config)
|
||||
self.today = strftime("%a %b %d %T %Z %Y")
|
||||
self.changes_file_name = self.spec_file_name.replace('.spec', '.changes')
|
||||
self.changes_file = os.path.join(self.full_project_dir,
|
||||
self.changes_file_name)
|
||||
self._new_changelog_msg = "Initial package release"
|
||||
self.changelog_regex = re.compile('^\s%s\s%s(\s<%s>)?' % (self.today,
|
||||
self.git_user, self.git_email.replace("+", "\+").replace(".", "\.")))
|
||||
|
||||
def _make_changelog(self):
|
||||
"""
|
||||
Create a new changelog entry in the changes, with line items from git
|
||||
"""
|
||||
if self._no_auto_changelog:
|
||||
debug("Skipping changelog generation.")
|
||||
return
|
||||
|
||||
# Attempt to open the file if it exists, but create it if it doesn't
|
||||
try:
|
||||
in_f = open(self.changes_file, 'r')
|
||||
except FileNotFoundError:
|
||||
new_in_f = open(self.changes_file, 'w')
|
||||
new_in_f.close()
|
||||
in_f = open(self.changes_file, 'r')
|
||||
|
||||
out_f = open(self.changes_file + ".new", 'w')
|
||||
|
||||
old_version = get_latest_tagged_version(self.project_name)
|
||||
|
||||
# don't die if this is a new package with no history
|
||||
if old_version is not None:
|
||||
last_tag = "%s-%s" % (self.project_name, old_version)
|
||||
output = self._generate_default_changelog(last_tag)
|
||||
else:
|
||||
output = self._new_changelog_msg
|
||||
|
||||
fd, name = tempfile.mkstemp()
|
||||
write(fd, "# Create your changelog entry below:\n")
|
||||
header = "-------------------------------------------------------------------\n"
|
||||
if self.git_email is None or (('HIDE_EMAIL' in self.user_config) and
|
||||
(self.user_config['HIDE_EMAIL'] not in ['0', ''])):
|
||||
header = header + "%s - %s\n\n" % (self.today, self.git_user)
|
||||
else:
|
||||
header = header + "%s - %s <%s>\n\n" % (self.today, self.git_user,
|
||||
self.git_email)
|
||||
|
||||
write(fd, header)
|
||||
|
||||
for cmd_out in output.split("\n"):
|
||||
write(fd, "- ")
|
||||
write(fd, "\n ".join(textwrap.wrap(cmd_out, 77)))
|
||||
write(fd, "\n")
|
||||
|
||||
write(fd, "\n")
|
||||
|
||||
if not self._accept_auto_changelog:
|
||||
write(fd, "###################################################\n")
|
||||
write(fd, "# These are the already existing changelog entries:\n")
|
||||
write(fd, "###################################################\n")
|
||||
for line in in_f.readlines():
|
||||
write(fd, "#" + line)
|
||||
in_f.seek(0, 0)
|
||||
|
||||
# Give the user a chance to edit the generated changelog:
|
||||
editor = 'vi'
|
||||
if "EDITOR" in os.environ:
|
||||
editor = os.environ["EDITOR"]
|
||||
subprocess.call([editor, name])
|
||||
|
||||
os.lseek(fd, 0, 0)
|
||||
file = os.fdopen(fd)
|
||||
|
||||
for line in file.readlines():
|
||||
if not line.startswith("#"):
|
||||
out_f.write(line)
|
||||
|
||||
output = file.read()
|
||||
|
||||
file.close()
|
||||
os.unlink(name)
|
||||
|
||||
for line in in_f.readlines():
|
||||
out_f.write(line)
|
||||
|
||||
in_f.close()
|
||||
out_f.close()
|
||||
|
||||
shutil.move(self.changes_file + ".new", self.changes_file)
|
||||
|
||||
def _update_changelog(self, new_version):
|
||||
"""
|
||||
Update the changelog with the new version.
|
||||
"""
|
||||
# Not thrilled about having to re-read the file here but we need to
|
||||
# check for the changelog entry before making any modifications, then
|
||||
# bump the version, then update the changelog.
|
||||
f = open(self.changes_file, 'r')
|
||||
buf = StringIO()
|
||||
found_match = False
|
||||
done = False
|
||||
empty_line_regex = re.compile('^\s*$')
|
||||
|
||||
for line in f.readlines():
|
||||
if not done and not found_match and self.changelog_regex.match(line):
|
||||
buf.write(line)
|
||||
found_match = True
|
||||
elif not done and found_match and empty_line_regex.match(line):
|
||||
buf.write("\n- version %s\n" % new_version)
|
||||
done = True
|
||||
else:
|
||||
buf.write(line)
|
||||
f.close()
|
||||
|
||||
# Write out the new file contents with our modified changelog entry:
|
||||
f = open(self.changes_file, 'w')
|
||||
f.write(buf.getvalue())
|
||||
f.close()
|
||||
buf.close()
|
||||
|
||||
def _update_package_metadata(self, new_version):
|
||||
"""
|
||||
We track package metadata in the rel-eng/packages/ directory. Each
|
||||
file here stores the latest package version (for the git branch you
|
||||
are on) as well as the relative path to the project's code. (from the
|
||||
git root)
|
||||
"""
|
||||
self._clear_package_metadata()
|
||||
|
||||
suffix = ""
|
||||
# If global config specifies a tag suffix, use it:
|
||||
if self.config.has_option("globalconfig", "tag_suffix"):
|
||||
suffix = self.config.get("globalconfig", "tag_suffix")
|
||||
|
||||
new_version_w_suffix = "%s%s" % (new_version, suffix)
|
||||
# Write out our package metadata:
|
||||
metadata_file = os.path.join(self.rel_eng_dir, "packages",
|
||||
self.project_name)
|
||||
f = open(metadata_file, 'w')
|
||||
f.write("%s %s\n" % (new_version_w_suffix, self.relative_project_dir))
|
||||
f.close()
|
||||
|
||||
# Git add it (in case it's a new file):
|
||||
run_command("git add %s" % metadata_file)
|
||||
run_command("git add %s" % os.path.join(self.full_project_dir,
|
||||
self.spec_file_name))
|
||||
if not self._no_auto_changelog:
|
||||
run_command("git add %s" % os.path.join(self.full_project_dir,
|
||||
self.changes_file_name))
|
||||
|
||||
run_command('git commit -m "Automatic commit of package ' +
|
||||
'[%s] %s [%s]."' % (self.project_name, self.release_type(),
|
||||
new_version_w_suffix))
|
||||
|
||||
tag_msg = "Tagging package [%s] version [%s] in directory [%s]." % \
|
||||
(self.project_name, new_version_w_suffix,
|
||||
self.relative_project_dir)
|
||||
|
||||
new_tag = self._get_new_tag(new_version)
|
||||
run_command('git tag -m "%s" %s' % (tag_msg, new_tag))
|
||||
print
|
||||
print("Created tag: %s" % new_tag)
|
||||
print(" View: git show HEAD")
|
||||
print(" Undo: tito tag -u")
|
||||
print(" Push: git push origin HEAD && git push origin %s" % new_tag)
|
||||
print("or Push: git push origin HEAD && git push origin --tags")
|
|
@ -65,6 +65,10 @@ patches applied within it), you can change the tagger class in
|
|||
branch; if you'd prefer to do this on a per-package basis you can do so in a
|
||||
package specific `tito.props`.
|
||||
|
||||
If you work in a OBS style git with a separate .changes file for the changelog,
|
||||
change the tagger class to `tito.susetagger.SUSETagger`. The SUSETagger is based
|
||||
on the VersionTagger.
|
||||
|
||||
-h, --help::
|
||||
show this help message and exit
|
||||
|
||||
|
|
|
@ -231,6 +231,10 @@ And it will push package into ruby193-rubygem-simple-navigation dist-git despite
|
|||
fact that it is in /rubygem-simple-navigation directory. And project name (as taken
|
||||
from spec file) is rubygem-simple-navigation.
|
||||
|
||||
tito.susetagger.SUSETagger::
|
||||
Tagger which is based on VersionTagger and deal with SUSE / OBS specific
|
||||
separate changes file and format.
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
[buildconfig]
|
||||
|
|
Loading…
Add table
Reference in a new issue