1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-12-26 09:56:13 +01:00

Merge pull request #1012 from adrianschroeter/obs_git

initial obs-git support
This commit is contained in:
Marco Strigl 2022-05-24 11:39:45 +02:00 committed by GitHub
commit c3d535c3b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 130 additions and 12 deletions

5
NEWS
View File

@ -1,5 +1,8 @@
0.178.0 0.178.0
- - EXPERIMENTAL: git repository handling
* init command is working inside of a git repository
* downloadassets command fetches references assets from build description
* checkout is cloning from git
0.177.0 0.177.0
- switch to python3 in osc-wrapper and make python3 explicit - switch to python3 in osc-wrapper and make python3 explicit

View File

@ -219,7 +219,7 @@ class Osc(cmdln.Cmdln):
return help return help
return cmdln.Cmdln._help_preprocess_cmd_usage(self, help, cmdname) return cmdln.Cmdln._help_preprocess_cmd_usage(self, help, cmdname)
def do_init(self, subcmd, opts, project, package=None): def do_init(self, subcmd, opts, project, package=None, scm_url=None):
"""${cmd_name}: Initialize a directory as working copy """${cmd_name}: Initialize a directory as working copy
Initialize an existing directory to be a working copy of an Initialize an existing directory to be a working copy of an
@ -238,11 +238,25 @@ class Osc(cmdln.Cmdln):
usage: usage:
osc init PRJ osc init PRJ
osc init PRJ PAC osc init PRJ PAC
osc init PRJ PAC SCM_URL
${cmd_option_list} ${cmd_option_list}
""" """
apiurl = self.get_api_url() apiurl = self.get_api_url()
if not scm_url:
scm_url = show_scmsync(apiurl, project, package)
if scm_url:
if package:
Package.init_package(apiurl, project, package, os.curdir, scm_url=scm_url)
print('Initializing %s (Project: %s, Package: %s) as git repository' % (os.curdir, project, package))
else:
Project.init_project(apiurl, os.curdir, project, conf.config['do_package_tracking'],
getPackageList=False, scm_url=scm_url)
print('Initializing %s (Project: %s) as scm repository' % (os.curdir, project))
return
if not package: if not package:
Project.init_project(apiurl, os.curdir, project, conf.config['do_package_tracking'], Project.init_project(apiurl, os.curdir, project, conf.config['do_package_tracking'],
getPackageList=False) getPackageList=False)
@ -708,6 +722,20 @@ class Osc(cmdln.Cmdln):
else: else:
print(devprj) print(devprj)
@cmdln.alias('ca')
def do_cleanassets(self, subcmd, opts, *args):
"""${cmd_name}: Clean all previous downloaded assets.
This is useful to prepare a new git commit.
"""
clean_assets(".")
@cmdln.alias('da')
def do_downloadassets(self, subcmd, opts, *args):
"""${cmd_name}: Download all assets referenced in the build descriptions
"""
download_assets(".")
@cmdln.alias('sdp') @cmdln.alias('sdp')
@cmdln.option('-u', '--unset', action='store_true', @cmdln.option('-u', '--unset', action='store_true',
help='remove devel project') help='remove devel project')
@ -4682,9 +4710,19 @@ Please submit there instead, or use --nodevelproject to force direct submission.
# check if the project does exist (show_project_meta will throw an exception) # check if the project does exist (show_project_meta will throw an exception)
show_project_meta(apiurl, project) show_project_meta(apiurl, project)
Project.init_project(apiurl, prj_dir, project, conf.config['do_package_tracking']) scm_url = show_scmsync(apiurl, project)
if scm_url != None:
if not os.path.isfile('/usr/lib/obs/service/obs_scm_bridge'):
raise oscerr.OscIOError(None, 'Install the obs-scm-bridge package to work on packages managed in scm (git)!')
os.putenv("OSC_VERSION", get_osc_version())
run_external(['/usr/lib/obs/service/obs_scm_bridge', '--outdir', prj_dir, '--url', scm_url])
Project.init_project(apiurl, prj_dir, project, conf.config['do_package_tracking'], scm_url=scm_url)
print(statfrmt('A', prj_dir)) print(statfrmt('A', prj_dir))
if scm_url != None:
return
# all packages # all packages
for package in meta_get_packagelist(apiurl, project): for package in meta_get_packagelist(apiurl, project):
if opts.output_dir is not None: if opts.output_dir is not None:
@ -6677,10 +6715,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
project = None project = None
try: try:
project = store_read_project(os.curdir) project = store_read_project(os.curdir)
if project == opts.alternative_project:
opts.alternative_project = None
except oscerr.NoWorkingCopy: except oscerr.NoWorkingCopy:
# This may be a project managed entirely via git?
if os.path.isdir(os.curdir + "/../.osc") and os.path.isdir(os.curdir + "/../.git"):
project = store_read_project(os.curdir + "/..")
opts.alternative_project = project
pass pass
if project == opts.alternative_project:
opts.alternative_project = None
if len(args) == 0 and is_package_dir(os.curdir): if len(args) == 0 and is_package_dir(os.curdir):
# build env not specified, just read from last build attempt # build env not specified, just read from last build attempt

View File

@ -134,6 +134,7 @@ DEFAULTS = {'apiurl': 'https://api.opensuse.org',
'build-vm-user': '', # optional for VM builds 'build-vm-user': '', # optional for VM builds
'build-kernel': '', # optional for VM builds 'build-kernel': '', # optional for VM builds
'build-initrd': '', # optional for VM builds 'build-initrd': '', # optional for VM builds
'download-assets-cmd': '/usr/lib/build/download_assets', # optional for scm/git based builds
'build-jobs': str(_get_processors()), 'build-jobs': str(_get_processors()),
'builtin_signature_check': '1', # by default use builtin check for verify pkgs 'builtin_signature_check': '1', # by default use builtin check for verify pkgs

View File

@ -685,6 +685,7 @@ class Project:
self.progress_obj = progress_obj self.progress_obj = progress_obj
self.name = store_read_project(self.dir) self.name = store_read_project(self.dir)
self.scm_url = store_read_scmurl(self.dir)
self.apiurl = store_read_apiurl(self.dir, defaulturl=not wc_check) self.apiurl = store_read_apiurl(self.dir, defaulturl=not wc_check)
dirty_files = [] dirty_files = []
@ -725,7 +726,7 @@ class Project:
global store global store
dirty_files = [] dirty_files = []
req_storefiles = Project.REQ_STOREFILES req_storefiles = Project.REQ_STOREFILES
if conf.config['do_package_tracking']: if conf.config['do_package_tracking'] and self.scm_url == None:
req_storefiles += ('_packages',) req_storefiles += ('_packages',)
for fname in req_storefiles: for fname in req_storefiles:
if not os.path.exists(os.path.join(self.absdir, store, fname)): if not os.path.exists(os.path.join(self.absdir, store, fname)):
@ -959,7 +960,11 @@ class Project:
p = Package(os.path.join(self.dir, pac), progress_obj=self.progress_obj) p = Package(os.path.join(self.dir, pac), progress_obj=self.progress_obj)
rev = None rev = None
needs_update = True needs_update = True
if expand_link and p.islink() and not p.isexpanded(): if p.scm_url != None:
# git managed.
print("Skipping git managed package ", pac)
continue
elif expand_link and p.islink() and not p.isexpanded():
if p.haslinkerror(): if p.haslinkerror():
try: try:
rev = show_upstream_xsrcmd5(p.apiurl, p.prjname, p.name, revision=p.rev) rev = show_upstream_xsrcmd5(p.apiurl, p.prjname, p.name, revision=p.rev)
@ -1137,7 +1142,7 @@ class Project:
return '\n'.join(r) return '\n'.join(r)
@staticmethod @staticmethod
def init_project(apiurl, dir, project, package_tracking=True, getPackageList=True, progress_obj=None, wc_check=True): def init_project(apiurl, dir, project, package_tracking=True, getPackageList=True, progress_obj=None, wc_check=True, scm_url=None):
global store global store
if not os.path.exists(dir): if not os.path.exists(dir):
@ -1152,6 +1157,9 @@ class Project:
store_write_project(dir, project) store_write_project(dir, project)
store_write_apiurl(dir, apiurl) store_write_apiurl(dir, apiurl)
if scm_url:
store_write_string(dir, '_scm', scm_url + '\n')
package_tracking = None
if package_tracking: if package_tracking:
store_write_initial_packages(dir, project, []) store_write_initial_packages(dir, project, [])
return Project(dir, getPackageList, progress_obj, wc_check) return Project(dir, getPackageList, progress_obj, wc_check)
@ -1174,6 +1182,7 @@ class Package:
self.storedir = os.path.join(self.absdir, store) self.storedir = os.path.join(self.absdir, store)
self.progress_obj = progress_obj self.progress_obj = progress_obj
self.size_limit = size_limit self.size_limit = size_limit
self.scm_url = store_read_scmurl(self.dir)
if size_limit and size_limit == 0: if size_limit and size_limit == 0:
self.size_limit = None self.size_limit = None
@ -1198,6 +1207,8 @@ class Package:
def wc_check(self): def wc_check(self):
dirty_files = [] dirty_files = []
if self.scm_url:
return dirty_files
for fname in self.filenamelist: for fname in self.filenamelist:
if not os.path.exists(os.path.join(self.storedir, fname)) and not fname in self.skipped: if not os.path.exists(os.path.join(self.storedir, fname)) and not fname in self.skipped:
dirty_files.append(fname) dirty_files.append(fname)
@ -1774,6 +1785,20 @@ class Package:
called). called).
""" """
import fnmatch import fnmatch
if self.scm_url:
self.filenamelist = []
self.filelist = []
self.skipped = []
self.to_be_added = []
self.to_be_deleted = []
self.in_conflict = []
self.linkrepair = None
self.rev = None
self.srcmd5 = None
self.linkinfo = None
self.serviceinfo = None
return
files_tree = read_filemeta(self.dir) files_tree = read_filemeta(self.dir)
files_tree_root = files_tree.getroot() files_tree_root = files_tree.getroot()
@ -1784,10 +1809,10 @@ class Package:
self.linkinfo.read(files_tree_root.find('linkinfo')) self.linkinfo.read(files_tree_root.find('linkinfo'))
self.serviceinfo = DirectoryServiceinfo() self.serviceinfo = DirectoryServiceinfo()
self.serviceinfo.read(files_tree_root.find('serviceinfo')) self.serviceinfo.read(files_tree_root.find('serviceinfo'))
self.filenamelist = [] self.filenamelist = []
self.filelist = [] self.filelist = []
self.skipped = [] self.skipped = []
for node in files_tree_root.findall('entry'): for node in files_tree_root.findall('entry'):
try: try:
f = File(node.get('name'), f = File(node.get('name'),
@ -2491,7 +2516,7 @@ rev: %s
self.write_addlist() self.write_addlist()
@staticmethod @staticmethod
def init_package(apiurl, project, package, dir, size_limit=None, meta=False, progress_obj=None): def init_package(apiurl, project, package, dir, size_limit=None, meta=False, progress_obj=None, scm_url=None):
global store global store
if not os.path.exists(dir): if not os.path.exists(dir):
@ -2509,7 +2534,10 @@ rev: %s
store_write_string(dir, '_meta_mode', '') store_write_string(dir, '_meta_mode', '')
if size_limit: if size_limit:
store_write_string(dir, '_size_limit', str(size_limit) + '\n') store_write_string(dir, '_size_limit', str(size_limit) + '\n')
store_write_string(dir, '_files', '<directory />' + '\n') if scm_url:
store_write_string(dir, '_scm', scm_url + '\n')
else:
store_write_string(dir, '_files', '<directory />' + '\n')
store_write_string(dir, '_osclib_version', __store_version__ + '\n') store_write_string(dir, '_osclib_version', __store_version__ + '\n')
return Package(dir, progress_obj=progress_obj, size_limit=size_limit) return Package(dir, progress_obj=progress_obj, size_limit=size_limit)
@ -3255,6 +3283,8 @@ def read_filemeta(dir):
filesmeta = os.path.join(dir, store, '_files') filesmeta = os.path.join(dir, store, '_files')
if not is_package_dir(dir): if not is_package_dir(dir):
raise oscerr.NoWorkingCopy(msg) raise oscerr.NoWorkingCopy(msg)
if os.path.isfile(os.path.join(dir, store, '_scm')):
raise oscerr.NoWorkingCopy("Is managed via scm")
if not os.path.isfile(filesmeta): if not os.path.isfile(filesmeta):
raise oscerr.NoWorkingCopy('%s (%s does not exist)' % (msg, filesmeta)) raise oscerr.NoWorkingCopy('%s (%s does not exist)' % (msg, filesmeta))
@ -3610,6 +3640,23 @@ def show_attribute_meta(apiurl, prj, pac, subpac, attribute, with_defaults, with
raise raise
def clean_assets(directory):
return run_external(conf.config['download-assets-cmd'], '--clean', directory)
def download_assets(directory):
return run_external(conf.config['download-assets-cmd'], '--unpack', '--noassetdir', directory)
def show_scmsync(apiurl, prj, pac=None):
if pac:
m = show_package_meta(apiurl, prj, pac)
else:
m = show_project_meta(apiurl, prj)
node = ET.fromstring(b''.join(m)).find('scmsync')
if node is None:
return None
else:
return node.text
def show_devel_project(apiurl, prj, pac): def show_devel_project(apiurl, prj, pac):
m = show_package_meta(apiurl, prj, pac) m = show_package_meta(apiurl, prj, pac)
node = ET.fromstring(b''.join(m)).find('devel') node = ET.fromstring(b''.join(m)).find('devel')
@ -5123,7 +5170,17 @@ def checkout_package(apiurl, project, package,
# before we create directories and stuff, check if the package actually # before we create directories and stuff, check if the package actually
# exists # exists
show_package_meta(apiurl, quote_plus(project), quote_plus(package), meta) meta_data = b''.join(show_package_meta(apiurl, quote_plus(project), quote_plus(package)))
root = ET.fromstring(meta_data)
if root.find('scmsync') != None and root.find('scmsync').text != None:
if not os.path.isfile('/usr/lib/obs/service/obs_scm_bridge'):
raise oscerr.OscIOError(None, 'Install the obs-scm-bridge package to work on packages managed in scm (git)!')
scm_url = root.find('scmsync').text
directory = make_dir(apiurl, project, package, pathname, prj_dir, conf.config['do_package_tracking'], outdir)
os.putenv("OSC_VERSION", get_osc_version())
run_external(['/usr/lib/obs/service/obs_scm_bridge', '--outdir', directory, '--url', scm_url])
Package.init_package(apiurl, project, package, directory, size_limit, meta, progress_obj, scm_url)
return
isfrozen = False isfrozen = False
if expand_link: if expand_link:
@ -6583,6 +6640,21 @@ def store_read_package(dir):
raise oscerr.NoWorkingCopy(msg) raise oscerr.NoWorkingCopy(msg)
return p return p
def store_read_scmurl(dir):
global store
url_file = os.path.join(dir, store, '_scm')
if not os.path.exists(url_file):
return
try:
p = open(url_file).readlines()[0].strip()
except IOError:
msg = 'Error: \'%s\' is not an osc package working copy' % os.path.abspath(dir)
if os.path.exists(os.path.join(dir, '.svn')):
msg += '\nTry svn instead of osc.'
raise oscerr.NoWorkingCopy(msg)
return p
def store_read_apiurl(dir, defaulturl=True): def store_read_apiurl(dir, defaulturl=True):
global store global store