Add latest upstream builder to add support for GitLfsBuilder

This commit is contained in:
Daniel Berteaud 2018-11-26 22:40:07 +01:00
parent 0e72e6adf9
commit df761bd552
3 changed files with 1604 additions and 0 deletions

View File

@ -0,0 +1,18 @@
# Import our builders so they can be referenced in config as tito.builder.Class
# regardless of which submodule they're in.
# flake8: noqa
from fws_tito.builder.main import \
Builder, \
NoTgzBuilder, \
GemBuilder, \
UpstreamBuilder, \
SatelliteBuilder, \
MockBuilder, \
BrewDownloadBuilder, \
GitAnnexBuilder, \
GitLfsBuilder, \
MeadBuilder
from fws_tito.builder.fetch import FetchBuilder

212
fws_tito/builder/fetch.py Normal file
View File

@ -0,0 +1,212 @@
# Copyright (c) 2008-2014 Red Hat, Inc.
#
# 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.
#
# Red Hat trademarks are not licensed under GPLv2. No permission is
# granted to use or replicate Red Hat trademarks that are incorporated
# in this software or its documentation.
import re
import os.path
import shutil
from tito.builder.main import BuilderBase
from tito.config_object import ConfigObject
from tito.common import error_out, debug, get_spec_version_and_release, \
get_class_by_name
class FetchBuilder(ConfigObject, BuilderBase):
"""
A separate Builder class for projects whose source is not in git. Source
is fetched via a configurable strategy, which also determines what version
and release to insert into the spec file.
Cannot build past tags.
"""
# TODO: test only for now, setup a tagger to fetch sources and store in git annex,
# then we can do official builds as well.
REQUIRED_ARGS = []
def __init__(self, name=None, tag=None, build_dir=None,
config=None, user_config=None,
args=None, **kwargs):
BuilderBase.__init__(self, name=name, build_dir=build_dir,
config=config,
user_config=user_config, args=args, **kwargs)
if tag:
error_out("FetchBuilder does not support building specific tags.")
if not config.has_option("builder",
"fetch_strategy"):
print("WARNING: no fetch_strategy specified in tito.props"
", assuming ArgSourceStrategy.")
if not config.has_section("builder"):
config.add_section("builder")
config.set('builder', 'fetch_strategy',
'tito.builder.fetch.ArgSourceStrategy')
self.build_tag = '%s-%s' % (self.project_name,
get_spec_version_and_release(self.start_dir, '%s.spec' % self.project_name))
def tgz(self):
self.ran_tgz = True
self._create_build_dirs()
print("Fetching sources...")
source_strat_class = get_class_by_name(self.config.get(
'builder', 'fetch_strategy'))
source_strat = source_strat_class(self)
source_strat.fetch()
self.sources = source_strat.sources
self.spec_file = source_strat.spec_file
def _get_rpmbuild_dir_options(self):
return ('--define "_topdir %s" --define "_sourcedir %s" --define "_builddir %s" '
'--define "_srcrpmdir %s" --define "_rpmdir %s" ' % (
self.rpmbuild_dir,
self.rpmbuild_sourcedir, self.rpmbuild_builddir,
self.rpmbuild_basedir, self.rpmbuild_basedir))
class SourceStrategy(object):
"""
Base class for source strategies. These are responsible for fetching the
sources the builder will use, and determining what version/release we're
building.
This is created and run in the tgz step of the builder. It will be passed
a reference to the builder calling it, which will be important for accessing
a lot of required information.
Ideally sources and the spec file to be used should be copied into
builder.rpmbuild_sourcedir, which will be cleaned up automatically after
the builder runs.
"""
def __init__(self, builder):
"""
Defines fields that should be set when a sub-class runs fetch.
"""
self.builder = builder
# Full path to the spec file we'll actually use to build, should be a
# copy, never a live spec file in a git repo as sometimes it will be
# modified:
self.spec_file = None
# Will contain the full path to each source we gather:
self.sources = []
# The version we're building:
self.version = None
# The release we're building:
self.release = None
def fetch(self):
raise NotImplementedError()
class ArgSourceStrategy(SourceStrategy):
"""
Assumes the builder was passed an explicit argument specifying which source
file(s) to use.
"""
def fetch(self):
# Assuming we're still in the start directory, get the absolute path
# to all sources specified:
# TODO: support passing of multiple sources here.
# TODO: error out if not present
manual_sources = [self.builder.args['source'][0]]
debug("Got sources: %s" % manual_sources)
# Copy the live spec from our starting location. Unlike most builders,
# we are not using a copy from a past git commit.
self.spec_file = os.path.join(self.builder.rpmbuild_sourcedir,
'%s.spec' % self.builder.project_name)
shutil.copyfile(
os.path.join(self.builder.start_dir, '%s.spec' %
self.builder.project_name),
self.spec_file)
print(" %s.spec" % self.builder.project_name)
# TODO: Make this a configurable strategy:
i = 0
replacements = []
for s in manual_sources:
base_name = os.path.basename(s)
dest_filepath = os.path.join(self.builder.rpmbuild_sourcedir,
base_name)
shutil.copyfile(s, dest_filepath)
self.sources.append(dest_filepath)
# Add a line to replace in the spec for each source:
source_regex = re.compile("^(source%s:\s*)(.+)$" % i, re.IGNORECASE)
new_line = "Source%s: %s\n" % (i, base_name)
replacements.append((source_regex, new_line))
# Replace version and release in spec:
version_regex = re.compile("^(version:\s*)(.+)$", re.IGNORECASE)
release_regex = re.compile("^(release:\s*)(.+)$", re.IGNORECASE)
(self.version, self.release) = self._get_version_and_release()
print("Building version: %s" % self.version)
print("Building release: %s" % self.release)
replacements.append((version_regex, "Version: %s\n" % self.version))
replacements.append((release_regex, "Release: %s\n" % self.release))
self.replace_in_spec(replacements)
def _get_version_and_release(self):
"""
Get the version and release from the builder.
Sources are configured at this point.
"""
# Assuming source0 is a tar.gz we can extract a version and possibly
# release from:
base_name = os.path.basename(self.sources[0])
debug("Extracting version/release from: %s" % base_name)
# usually a source tarball won't have a release, that is an RPM concept.
# Don't forget dist!
release = "1%{?dist}"
# Example filename: tito-0.4.18.tar.gz:
simple_version_re = re.compile(".*-(.*).(tar.gz|tgz|zip|bz2)")
match = re.search(simple_version_re, base_name)
if match:
version = match.group(1)
else:
error_out("Unable to determine version from file: %s" % base_name)
return (version, release)
def replace_in_spec(self, replacements):
"""
Replace lines in the spec file using the given replacements.
Replacements are a tuple of a regex to look for, and a new line to
substitute in when the regex matches.
Replaces all lines with one pass through the file.
"""
in_f = open(self.spec_file, 'r')
out_f = open(self.spec_file + ".new", 'w')
for line in in_f.readlines():
for line_regex, new_line in replacements:
match = re.match(line_regex, line)
if match:
line = new_line
out_f.write(line)
in_f.close()
out_f.close()
shutil.move(self.spec_file + ".new", self.spec_file)

1374
fws_tito/builder/main.py Normal file

File diff suppressed because it is too large Load Diff