mirror of
https://github.com/peridotbuild/pv2.git
synced 2024-11-21 12:41:26 +00:00
Add module importer and git example
* Add ModuleImport class to import module repos * Add import_git.py example of using GitImport
This commit is contained in:
parent
edd6b41608
commit
60e210aaa6
32
examples/import_git.py
Normal file
32
examples/import_git.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import pv2.importer as importutil
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Importer")
|
||||||
|
|
||||||
|
parser.add_argument('--srpm', type=str, required=True)
|
||||||
|
parser.add_argument('--source-giturl', type=str, required=True)
|
||||||
|
parser.add_argument('--source-gitorg', type=str, required=True)
|
||||||
|
parser.add_argument('--branch', type=str, required=True)
|
||||||
|
parser.add_argument('--giturl', type=str, required=True)
|
||||||
|
parser.add_argument('--gitorg', type=str, required=False, default='rpms')
|
||||||
|
parser.add_argument('--dest-branch', type=str, required=False, default='')
|
||||||
|
parser.add_argument('--release', type=str, required=False, default='')
|
||||||
|
parser.add_argument('--distprefix', type=str, required=False, default='el')
|
||||||
|
parser.add_argument('--upstream-lookaside', type=str, required=True)
|
||||||
|
results = parser.parse_args()
|
||||||
|
classy = importutil.GitImport(
|
||||||
|
results.srpm,
|
||||||
|
source_git_url_path=results.source_giturl,
|
||||||
|
source_git_org_path=results.source_gitorg,
|
||||||
|
git_url_path=results.giturl,
|
||||||
|
org=results.gitorg,
|
||||||
|
release=results.release,
|
||||||
|
branch=results.branch,
|
||||||
|
dest_branch=results.dest_branch,
|
||||||
|
upstream_lookaside=results.upstream_lookaside,
|
||||||
|
distprefix=results.distprefix
|
||||||
|
)
|
||||||
|
|
||||||
|
classy.pkg_import()
|
@ -6,7 +6,7 @@ Import a source RPM into a git forge using pv2
|
|||||||
import argparse
|
import argparse
|
||||||
import pv2.importer as importutil
|
import pv2.importer as importutil
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="ISO Compose")
|
parser = argparse.ArgumentParser(description="Importer")
|
||||||
|
|
||||||
parser.add_argument('--giturl', type=str, required=True)
|
parser.add_argument('--giturl', type=str, required=True)
|
||||||
parser.add_argument('--branch', type=str, required=True)
|
parser.add_argument('--branch', type=str, required=True)
|
||||||
|
@ -7,4 +7,4 @@ This assists packagers by taking input as srpm or git location, importing and
|
|||||||
tagging it as appropriate.
|
tagging it as appropriate.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .operation import Import, SrpmImport, GitImport
|
from .operation import Import, SrpmImport, GitImport, ModuleImport
|
||||||
|
@ -8,14 +8,24 @@ import os
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import string
|
import string
|
||||||
|
import datetime
|
||||||
from pv2.util import gitutil, fileutil, rpmutil, processor, generic
|
from pv2.util import gitutil, fileutil, rpmutil, processor, generic
|
||||||
from pv2.util import error as err
|
from pv2.util import error as err
|
||||||
from pv2.util import constants as const
|
from pv2.util import constants as const
|
||||||
|
|
||||||
|
#try:
|
||||||
|
# import gi
|
||||||
|
# gi.require_version('Modulemd', '2.0')
|
||||||
|
# from gi.repository import Modulemd
|
||||||
|
# HAS_GI = True
|
||||||
|
#except ImportError:
|
||||||
|
# HAS_GI = False
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Import',
|
'Import',
|
||||||
'SrpmImport',
|
'SrpmImport',
|
||||||
'GitImport'
|
'GitImport',
|
||||||
|
'ModuleImport'
|
||||||
]
|
]
|
||||||
# todo: add in logging and replace print with log
|
# todo: add in logging and replace print with log
|
||||||
|
|
||||||
@ -223,6 +233,35 @@ class Import:
|
|||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise err.FileNotFound(f'{directory} could not be deleted. Please check. {exc}')
|
raise err.FileNotFound(f'{directory} could not be deleted. Please check. {exc}')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_module_stream_name(source_branch):
|
||||||
|
"""
|
||||||
|
Returns a branch name for modules
|
||||||
|
"""
|
||||||
|
regex = r'stream-([a-zA-Z0-9_\.]+)-([a-zA-Z0-9_\.]+)'
|
||||||
|
regex_search = re.search(regex, source_branch)
|
||||||
|
return regex_search.group(2)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_module_stream_version(release, source_branch, timestamp):
|
||||||
|
"""
|
||||||
|
Returns a code of major, minor, micro version if applicable
|
||||||
|
"""
|
||||||
|
if 'rhel' not in source_branch:
|
||||||
|
return f'{release}'
|
||||||
|
|
||||||
|
regex = r'rhel-([0-9]+)\.([0-9]+)\.([0-9]+)'
|
||||||
|
regex_search = re.search(regex, source_branch)
|
||||||
|
minor_version = regex_search.group(2)
|
||||||
|
micro_version = regex_search.group(3)
|
||||||
|
if len(regex_search.group(2)) == 1:
|
||||||
|
minor_version = f'0{regex_search.group(2)}'
|
||||||
|
|
||||||
|
if len(regex_search.group(3)) == 1:
|
||||||
|
micro_version = f'0{regex_search.group(3)}'
|
||||||
|
|
||||||
|
return f'{release}{minor_version}{micro_version}'
|
||||||
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
class SrpmImport(Import):
|
class SrpmImport(Import):
|
||||||
"""
|
"""
|
||||||
@ -534,7 +573,8 @@ class GitImport(Import):
|
|||||||
# it'll be a module. Since this should always be the case, we'll change
|
# it'll be a module. Since this should always be the case, we'll change
|
||||||
# dest_branch to be: {dest_branch}-stream-{stream_name}
|
# dest_branch to be: {dest_branch}-stream-{stream_name}
|
||||||
if "stream" in source_branch:
|
if "stream" in source_branch:
|
||||||
dest_branch = self.__get_module_stream_branch_name(source_branch, dest_branch)
|
_stream_name = self.get_module_stream_name(source_branch)
|
||||||
|
dest_branch = f'{dest_branch}-stream-{_stream_name}'
|
||||||
distmarker = self.dist_tag.lstrip('.')
|
distmarker = self.dist_tag.lstrip('.')
|
||||||
_dist_tag = f'.module+{distmarker}+1010+deadbeef'
|
_dist_tag = f'.module+{distmarker}+1010+deadbeef'
|
||||||
|
|
||||||
@ -676,15 +716,6 @@ class GitImport(Import):
|
|||||||
substitute = template.substitute(dict_template)
|
substitute = template.substitute(dict_template)
|
||||||
return substitute
|
return substitute
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def __get_module_stream_branch_name(source_branch, dest_branch):
|
|
||||||
"""
|
|
||||||
Returns a branch name for modules
|
|
||||||
"""
|
|
||||||
regex = r'stream-([a-zA-Z0-9_\.]+)-([a-zA-Z0-9_\.]+)'
|
|
||||||
regex_search = re.search(regex, source_branch)
|
|
||||||
return f'{dest_branch}-stream-{regex_search.group(2)}'
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rpm_name(self):
|
def rpm_name(self):
|
||||||
"""
|
"""
|
||||||
@ -755,3 +786,234 @@ class GitImport(Import):
|
|||||||
Returns destination local lookaside
|
Returns destination local lookaside
|
||||||
"""
|
"""
|
||||||
return self.__dest_lookaside
|
return self.__dest_lookaside
|
||||||
|
|
||||||
|
class ModuleImport(Import):
|
||||||
|
"""
|
||||||
|
Imports module repos
|
||||||
|
"""
|
||||||
|
# This needs to clone whatever is there, find if there's a SOURCES
|
||||||
|
# directory, if not make it. Make changes to the YAML to point to the
|
||||||
|
# destination branch, copy it to SOURCES, make a metadata file.
|
||||||
|
# pylint: disable=too-many-arguments
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
module: str,
|
||||||
|
source_git_url_path: str,
|
||||||
|
source_git_org_path: str,
|
||||||
|
git_url_path: str,
|
||||||
|
release: str,
|
||||||
|
branch: str,
|
||||||
|
source_git_protocol: str = 'https',
|
||||||
|
dest_branch: str = '',
|
||||||
|
distprefix: str = 'el',
|
||||||
|
git_user: str = 'git',
|
||||||
|
org: str = 'modules'
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Init the class
|
||||||
|
"""
|
||||||
|
#if not HAS_GI:
|
||||||
|
# raise err.GenericError('This class cannot be loaded due to missing modules.')
|
||||||
|
|
||||||
|
self.__module = module
|
||||||
|
self.__release = release
|
||||||
|
# pylint: disable=line-too-long
|
||||||
|
self.__source_git_url = f'{source_git_protocol}://{source_git_url_path}/{source_git_org_path}/{module}.git'
|
||||||
|
self.__git_url = f'ssh://{git_user}@{git_url_path}/{org}/{module}.git'
|
||||||
|
self.__dist_prefix = distprefix
|
||||||
|
self.__dist_tag = f'.{distprefix}{release}'
|
||||||
|
self.__branch = branch
|
||||||
|
self.__dest_branch = branch
|
||||||
|
self.__current_time = datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S')
|
||||||
|
|
||||||
|
if len(dest_branch) > 0:
|
||||||
|
self.__dest_branch = dest_branch
|
||||||
|
|
||||||
|
if "stream" not in self.__branch:
|
||||||
|
raise err.ConfigurationError('Source branch does not contain stream')
|
||||||
|
|
||||||
|
self.__stream_name = self.get_module_stream_name(branch)
|
||||||
|
|
||||||
|
def module_import(self):
|
||||||
|
"""
|
||||||
|
Actually perform the import.
|
||||||
|
"""
|
||||||
|
check_source_repo = gitutil.lsremote(self.source_git_url)
|
||||||
|
check_dest_repo = gitutil.lsremote(self.dest_git_url)
|
||||||
|
source_git_repo_path = f'/var/tmp/{self.module_name}-source'
|
||||||
|
dest_git_repo_path = f'/var/tmp/{self.module_name}'
|
||||||
|
modulemd_file = f'{source_git_repo_path}/{self.module_name}.yaml'
|
||||||
|
metadata_file = f'{dest_git_repo_path}/.{self.module_name}.metadata'
|
||||||
|
source_branch = self.source_branch
|
||||||
|
dest_branch = self.dest_branch
|
||||||
|
_dist_tag = self.dist_tag
|
||||||
|
stream_name = self.stream_name
|
||||||
|
repo_tags = []
|
||||||
|
|
||||||
|
# If the upstream repo doesn't report anything, exit.
|
||||||
|
if not check_source_repo:
|
||||||
|
raise err.GitInitError('Upstream git repo does not exist')
|
||||||
|
|
||||||
|
dest_branch = f'{dest_branch}-stream-{stream_name}'
|
||||||
|
module_version = self.get_module_stream_version(self.release,
|
||||||
|
source_branch,
|
||||||
|
self.datestamp)
|
||||||
|
nsvc = f'{self.module_name}-{stream_name}-{module_version}.deadbeef'
|
||||||
|
import_tag = generic.safe_encoding(
|
||||||
|
f'imports/{dest_branch}/{nsvc}'
|
||||||
|
)
|
||||||
|
commit_msg = f'import {nsvc}'
|
||||||
|
|
||||||
|
print(f'Cloning upstream: {self.module_name}')
|
||||||
|
source_repo = gitutil.clone(
|
||||||
|
git_url_path=self.source_git_url,
|
||||||
|
repo_name=self.module_name,
|
||||||
|
to_path=source_git_repo_path,
|
||||||
|
branch=source_branch
|
||||||
|
)
|
||||||
|
|
||||||
|
if check_dest_repo:
|
||||||
|
ref_check = f'refs/heads/{dest_branch}' in check_dest_repo
|
||||||
|
print(f'Cloning: {self.module_name}')
|
||||||
|
if ref_check:
|
||||||
|
dest_repo = gitutil.clone(
|
||||||
|
git_url_path=self.dest_git_url,
|
||||||
|
repo_name=self.module_name,
|
||||||
|
to_path=dest_git_repo_path,
|
||||||
|
branch=dest_branch
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
dest_repo = gitutil.clone(
|
||||||
|
git_url_path=self.dest_git_url,
|
||||||
|
repo_name=self.module_name,
|
||||||
|
to_path=dest_git_repo_path,
|
||||||
|
branch=None
|
||||||
|
)
|
||||||
|
gitutil.checkout(dest_repo, branch=dest_branch, orphan=True)
|
||||||
|
self.remove_everything(dest_repo.working_dir)
|
||||||
|
for tag_name in dest_repo.tags:
|
||||||
|
repo_tags.append(tag_name.name)
|
||||||
|
else:
|
||||||
|
print('Repo may not exist or is private. Try to import anyway.')
|
||||||
|
dest_repo = gitutil.init(
|
||||||
|
git_url_path=self.dest_git_url,
|
||||||
|
repo_name=self.module_name,
|
||||||
|
to_path=dest_git_repo_path,
|
||||||
|
branch=dest_branch
|
||||||
|
)
|
||||||
|
|
||||||
|
# We'd normally look for similar tags. But the date time is always
|
||||||
|
# going to change, so we're skipping that part.
|
||||||
|
|
||||||
|
if not os.path.exists(f'{dest_git_repo_path}/SOURCES'):
|
||||||
|
try:
|
||||||
|
os.makedirs(f'{dest_git_repo_path}/SOURCES')
|
||||||
|
except Exception as exc:
|
||||||
|
raise err.GenericError(f'Directory could not be created: {exc}')
|
||||||
|
|
||||||
|
# We eventually want to do it this way.
|
||||||
|
#if Version(Modulemd.get_version()) < Version("2.11"):
|
||||||
|
# source_modulemd = Modulemd.ModuleStream.read_file(
|
||||||
|
# modulemd_file,
|
||||||
|
# True,
|
||||||
|
# self.module_name
|
||||||
|
# )
|
||||||
|
#else:
|
||||||
|
# source_modulemd = Modulemd.read_packager_file(modulemd_file,
|
||||||
|
# self.module_name,
|
||||||
|
# stream_name)
|
||||||
|
#components = source_modulemd.get_rpm_component_names()
|
||||||
|
#for component in components:
|
||||||
|
# change = source_modulemd.get_rpm_component(component)
|
||||||
|
# change.set_ref(dest_branch)
|
||||||
|
|
||||||
|
with open(modulemd_file, 'r') as module_yaml:
|
||||||
|
content = module_yaml.read()
|
||||||
|
content_new = re.sub('ref:\s+(.*)', f'ref: {dest_branch}', content)
|
||||||
|
module_yaml.close()
|
||||||
|
|
||||||
|
# Write to the root
|
||||||
|
with open(f'{dest_git_repo_path}/{self.module_name}.yaml', 'w') as module_yaml:
|
||||||
|
module_yaml.write(content_new)
|
||||||
|
module_yaml.close()
|
||||||
|
|
||||||
|
# Write to the sources, should be the same content
|
||||||
|
with open(f'{dest_git_repo_path}/SOURCES/modulemd.src.txt', 'w') as module_yaml:
|
||||||
|
module_yaml.write(content_new)
|
||||||
|
module_yaml.close()
|
||||||
|
|
||||||
|
self.generate_metadata(dest_git_repo_path, self.module_name, {})
|
||||||
|
gitutil.add_all(dest_repo)
|
||||||
|
verify = dest_repo.is_dirty()
|
||||||
|
if verify:
|
||||||
|
gitutil.commit(dest_repo, commit_msg)
|
||||||
|
ref = gitutil.tag(dest_repo, import_tag, commit_msg)
|
||||||
|
gitutil.push(dest_repo, ref=ref)
|
||||||
|
self.perform_cleanup([source_git_repo_path, dest_git_repo_path])
|
||||||
|
return True
|
||||||
|
print('Nothing to push')
|
||||||
|
self.perform_cleanup([source_git_repo_path, dest_git_repo_path])
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def module_name(self):
|
||||||
|
"""
|
||||||
|
Returns the module name
|
||||||
|
"""
|
||||||
|
return self.__module
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source_branch(self):
|
||||||
|
"""
|
||||||
|
Returns the starting branch
|
||||||
|
"""
|
||||||
|
return self.__branch
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dest_branch(self):
|
||||||
|
"""
|
||||||
|
Returns the starting branch
|
||||||
|
"""
|
||||||
|
return self.__dest_branch
|
||||||
|
|
||||||
|
@property
|
||||||
|
def source_git_url(self):
|
||||||
|
"""
|
||||||
|
Returns the source git url
|
||||||
|
"""
|
||||||
|
return self.__source_git_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dest_git_url(self):
|
||||||
|
"""
|
||||||
|
Returns the destination git url
|
||||||
|
"""
|
||||||
|
return self.__git_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dist_tag(self):
|
||||||
|
"""
|
||||||
|
Returns the dist tag
|
||||||
|
"""
|
||||||
|
return self.__dist_tag
|
||||||
|
|
||||||
|
@property
|
||||||
|
def datestamp(self):
|
||||||
|
"""
|
||||||
|
Returns a date time stamp
|
||||||
|
"""
|
||||||
|
return self.__current_time
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stream_name(self):
|
||||||
|
"""
|
||||||
|
Returns the stream name
|
||||||
|
"""
|
||||||
|
return self.__stream_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def release(self):
|
||||||
|
"""
|
||||||
|
Returns the release
|
||||||
|
"""
|
||||||
|
return self.__release
|
||||||
|
Loading…
Reference in New Issue
Block a user