mirror of
https://github.com/openSUSE/osc.git
synced 2025-01-14 09:36:21 +01:00
support source services better:
* offer updating version from server * executing them locally on update or build
This commit is contained in:
parent
5f9127cd6c
commit
c2cee79679
3
NEWS
3
NEWS
@ -1,5 +1,8 @@
|
|||||||
|
|
||||||
0.122
|
0.122
|
||||||
|
- option to download server side generated _service:* files on update
|
||||||
|
- support for running source services locally. Happens by default on source update
|
||||||
|
and build.
|
||||||
|
|
||||||
0.121.1
|
0.121.1
|
||||||
- fixed creation of new ~/.oscrc files
|
- fixed creation of new ~/.oscrc files
|
||||||
|
@ -1520,8 +1520,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
|
|
||||||
if opts.unexpand_link: expand_link = False
|
if opts.unexpand_link: expand_link = False
|
||||||
else: expand_link = True
|
else: expand_link = True
|
||||||
if opts.source_service_files: service_file = True
|
if opts.source_service_files: service_files = True
|
||||||
else: service_file = False
|
else: service_files = False
|
||||||
|
|
||||||
args = slash_split(args)
|
args = slash_split(args)
|
||||||
project = package = filename = None
|
project = package = filename = None
|
||||||
@ -1554,7 +1554,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
if opts.current_dir: project_dir = None
|
if opts.current_dir: project_dir = None
|
||||||
|
|
||||||
checkout_package(apiurl, project, package,
|
checkout_package(apiurl, project, package,
|
||||||
rev, expand_link=expand_link, prj_dir=project_dir, service_file=service_file)
|
rev, expand_link=expand_link, prj_dir=project_dir, service_files=service_files)
|
||||||
|
|
||||||
elif project:
|
elif project:
|
||||||
prj_dir = project
|
prj_dir = project
|
||||||
@ -1573,13 +1573,13 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
for package in meta_get_packagelist(apiurl, project):
|
for package in meta_get_packagelist(apiurl, project):
|
||||||
try:
|
try:
|
||||||
checkout_package(apiurl, project, package,
|
checkout_package(apiurl, project, package,
|
||||||
expand_link = expand_link, prj_dir = prj_dir, service_file = service_file)
|
expand_link = expand_link, prj_dir = prj_dir, service_files = service_files)
|
||||||
except oscerr.LinkExpandError, e:
|
except oscerr.LinkExpandError, e:
|
||||||
print >>sys.stderr, 'Link cannot be expanded:\n', e
|
print >>sys.stderr, 'Link cannot be expanded:\n', e
|
||||||
print >>sys.stderr, 'Use "osc repairlink" for fixing merge conflicts:\n'
|
print >>sys.stderr, 'Use "osc repairlink" for fixing merge conflicts:\n'
|
||||||
# check out in unexpanded form at least
|
# check out in unexpanded form at least
|
||||||
checkout_package(apiurl, project, package,
|
checkout_package(apiurl, project, package,
|
||||||
expand_link = False, prj_dir = prj_dir, service_file = service_file)
|
expand_link = False, prj_dir = prj_dir, service_files = service_files)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise oscerr.WrongArgs('Missing argument.\n\n' \
|
raise oscerr.WrongArgs('Missing argument.\n\n' \
|
||||||
@ -1856,6 +1856,8 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
help='if a package is an expanded link, update to the raw _link file')
|
help='if a package is an expanded link, update to the raw _link file')
|
||||||
@cmdln.option('-e', '--expand-link', action='store_true',
|
@cmdln.option('-e', '--expand-link', action='store_true',
|
||||||
help='if a package is a link, update to the expanded sources')
|
help='if a package is a link, update to the expanded sources')
|
||||||
|
@cmdln.option('-s', '--source-service-files', action='store_true',
|
||||||
|
help='Use server side generated sources instead of local generation.' )
|
||||||
@cmdln.alias('up')
|
@cmdln.alias('up')
|
||||||
def do_update(self, subcmd, opts, *args):
|
def do_update(self, subcmd, opts, *args):
|
||||||
"""${cmd_name}: Update a working copy
|
"""${cmd_name}: Update a working copy
|
||||||
@ -1889,6 +1891,9 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
raise oscerr.WrongOptions('Sorry, the options --expand-link, --unexpand-link and '
|
raise oscerr.WrongOptions('Sorry, the options --expand-link, --unexpand-link and '
|
||||||
'--revision are mutually exclusive.')
|
'--revision are mutually exclusive.')
|
||||||
|
|
||||||
|
if opts.source_service_files: service_files = True
|
||||||
|
else: service_files = False
|
||||||
|
|
||||||
args = parseargs(args)
|
args = parseargs(args)
|
||||||
arg_list = args[:]
|
arg_list = args[:]
|
||||||
|
|
||||||
@ -1944,7 +1949,7 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
'copy has local modifications. Please remove them ' \
|
'copy has local modifications. Please remove them ' \
|
||||||
'and try again'
|
'and try again'
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
p.update(rev)
|
p.update(rev, service_files)
|
||||||
rev = None
|
rev = None
|
||||||
|
|
||||||
|
|
||||||
@ -2523,6 +2528,11 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
if not arg_platform in platforms:
|
if not arg_platform in platforms:
|
||||||
raise oscerr.WrongArgs('%s is not a valid platform, use one of: %s' % (arg_platform, ", ".join(platforms)))
|
raise oscerr.WrongArgs('%s is not a valid platform, use one of: %s' % (arg_platform, ", ".join(platforms)))
|
||||||
|
|
||||||
|
# check for source services
|
||||||
|
if os.listdir('.').count("_service"):
|
||||||
|
p = Package('.')
|
||||||
|
p.run_source_services()
|
||||||
|
|
||||||
descr = [ i for i in os.listdir('.') if i.endswith('.spec') or i.endswith('.dsc') ]
|
descr = [ i for i in os.listdir('.') if i.endswith('.spec') or i.endswith('.dsc') ]
|
||||||
# FIXME:
|
# FIXME:
|
||||||
# * request repos from server and select by build type.
|
# * request repos from server and select by build type.
|
||||||
|
74
osc/core.py
74
osc/core.py
@ -208,6 +208,53 @@ class File:
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class Serviceinfo:
|
||||||
|
"""Source service content
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
"""creates an empty serviceinfo instance"""
|
||||||
|
self.commands = None
|
||||||
|
|
||||||
|
def read(self, serviceinfo_node):
|
||||||
|
"""read in the source services <services> element passed as
|
||||||
|
elementtree node.
|
||||||
|
"""
|
||||||
|
if serviceinfo_node == None:
|
||||||
|
return
|
||||||
|
self.commands = []
|
||||||
|
services = serviceinfo_node.findall('service')
|
||||||
|
|
||||||
|
for service in services:
|
||||||
|
name = service.get('name')
|
||||||
|
try:
|
||||||
|
for param in service.findall('param'):
|
||||||
|
option = param.get('name', None)
|
||||||
|
value = param.text
|
||||||
|
name += " --" + option + " '" + value + "'"
|
||||||
|
self.commands.append(name)
|
||||||
|
except:
|
||||||
|
msg = 'invalid service format:\n%s' % ET.tostring(root)
|
||||||
|
raise oscerr.APIError(msg)
|
||||||
|
|
||||||
|
def execute(self, dir):
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
for call in self.commands:
|
||||||
|
temp_dir = tempfile.mkdtemp()
|
||||||
|
name = call.split(None, 1)[0]
|
||||||
|
if not os.path.exists("/usr/lib/obs/service/"+name):
|
||||||
|
msg = "ERROR: service is not installed !"
|
||||||
|
msg += "Can maybe solved with: zypper in obs-server-" + name
|
||||||
|
raise oscerr.APIError(msg)
|
||||||
|
c = "/usr/lib/obs/service/" + call + " --outdir " + temp_dir
|
||||||
|
ret = subprocess.call(c, shell=True)
|
||||||
|
if ret != 0:
|
||||||
|
print "ERROR: service call failed: " + c
|
||||||
|
|
||||||
|
for file in os.listdir(temp_dir):
|
||||||
|
os.rename( os.path.join(temp_dir, file), os.path.join(dir, "_service:"+name+":"+file) )
|
||||||
|
os.rmdir(temp_dir)
|
||||||
|
|
||||||
class Linkinfo:
|
class Linkinfo:
|
||||||
"""linkinfo metadata (which is part of the xml representing a directory
|
"""linkinfo metadata (which is part of the xml representing a directory
|
||||||
"""
|
"""
|
||||||
@ -423,7 +470,7 @@ class Project:
|
|||||||
else:
|
else:
|
||||||
print 'unsupported state'
|
print 'unsupported state'
|
||||||
|
|
||||||
def update(self, pacs = (), expand_link=False, unexpand_link=False):
|
def update(self, pacs = (), expand_link=False, unexpand_link=False, service_files=False):
|
||||||
if len(pacs):
|
if len(pacs):
|
||||||
for pac in pacs:
|
for pac in pacs:
|
||||||
Package(os.path.join(self.dir, pac)).update()
|
Package(os.path.join(self.dir, pac)).update()
|
||||||
@ -465,7 +512,7 @@ class Project:
|
|||||||
elif p.islink() and p.isexpanded():
|
elif p.islink() and p.isexpanded():
|
||||||
rev = p.latest_rev();
|
rev = p.latest_rev();
|
||||||
print 'Updating %s' % p.name
|
print 'Updating %s' % p.name
|
||||||
p.update(rev)
|
p.update(rev, service_files)
|
||||||
elif state == 'D':
|
elif state == 'D':
|
||||||
# TODO: Package::update has to fixed to behave like svn does
|
# TODO: Package::update has to fixed to behave like svn does
|
||||||
if pac in self.pacs_broken:
|
if pac in self.pacs_broken:
|
||||||
@ -1191,7 +1238,7 @@ rev: %s
|
|||||||
upstream_rev = show_upstream_rev(self.apiurl, self.prjname, self.name)
|
upstream_rev = show_upstream_rev(self.apiurl, self.prjname, self.name)
|
||||||
return upstream_rev
|
return upstream_rev
|
||||||
|
|
||||||
def update(self, rev = None):
|
def update(self, rev = None, service_files = False):
|
||||||
# save filelist and (modified) status before replacing the meta file
|
# save filelist and (modified) status before replacing the meta file
|
||||||
saved_filenames = self.filenamelist
|
saved_filenames = self.filenamelist
|
||||||
saved_modifiedfiles = [ f for f in self.filenamelist if self.status(f) == 'M' ]
|
saved_modifiedfiles = [ f for f in self.filenamelist if self.status(f) == 'M' ]
|
||||||
@ -1206,7 +1253,7 @@ rev: %s
|
|||||||
pathn = getTransActPath(self.dir)
|
pathn = getTransActPath(self.dir)
|
||||||
|
|
||||||
for filename in saved_filenames:
|
for filename in saved_filenames:
|
||||||
if filename in disappeared:
|
if not filename.startswith('_service:') and filename in disappeared:
|
||||||
print statfrmt('D', os.path.join(pathn, filename))
|
print statfrmt('D', os.path.join(pathn, filename))
|
||||||
# keep file if it has local modifications
|
# keep file if it has local modifications
|
||||||
if oldp.status(filename) == ' ':
|
if oldp.status(filename) == ' ':
|
||||||
@ -1216,7 +1263,9 @@ rev: %s
|
|||||||
for filename in self.filenamelist:
|
for filename in self.filenamelist:
|
||||||
|
|
||||||
state = self.status(filename)
|
state = self.status(filename)
|
||||||
if state == 'M' and self.findfilebyname(filename).md5 == oldp.findfilebyname(filename).md5:
|
if not service_files and filename.startswith('_service:'):
|
||||||
|
pass
|
||||||
|
elif state == 'M' and self.findfilebyname(filename).md5 == oldp.findfilebyname(filename).md5:
|
||||||
# no merge necessary... local file is changed, but upstream isn't
|
# no merge necessary... local file is changed, but upstream isn't
|
||||||
pass
|
pass
|
||||||
elif state == 'M' and filename in saved_modifiedfiles:
|
elif state == 'M' and filename in saved_modifiedfiles:
|
||||||
@ -1238,12 +1287,21 @@ rev: %s
|
|||||||
elif state == ' ':
|
elif state == ' ':
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
self.update_local_pacmeta()
|
self.update_local_pacmeta()
|
||||||
|
|
||||||
#print ljust(p.name, 45), 'At revision %s.' % p.rev
|
#print ljust(p.name, 45), 'At revision %s.' % p.rev
|
||||||
print 'At revision %s.' % self.rev
|
print 'At revision %s.' % self.rev
|
||||||
|
|
||||||
|
if not service_files:
|
||||||
|
self.run_source_services()
|
||||||
|
|
||||||
|
def run_source_services(self):
|
||||||
|
if self.filenamelist.count('_service'):
|
||||||
|
service = ET.parse(os.path.join(self.absdir, '_service')).getroot()
|
||||||
|
si = Serviceinfo()
|
||||||
|
si.read(service)
|
||||||
|
si.execute(self.absdir)
|
||||||
|
|
||||||
def prepare_filelist(self):
|
def prepare_filelist(self):
|
||||||
"""Prepare a list of files, which will be processed by process_filelist
|
"""Prepare a list of files, which will be processed by process_filelist
|
||||||
method. This allows easy modifications of a file list in commit
|
method. This allows easy modifications of a file list in commit
|
||||||
@ -2762,7 +2820,7 @@ def make_dir(apiurl, project, package, pathname=None, prj_dir=None):
|
|||||||
|
|
||||||
def checkout_package(apiurl, project, package,
|
def checkout_package(apiurl, project, package,
|
||||||
revision=None, pathname=None, prj_obj=None,
|
revision=None, pathname=None, prj_obj=None,
|
||||||
expand_link=False, prj_dir=None, service_file=None):
|
expand_link=False, prj_dir=None, service_files=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# the project we're in might be deleted.
|
# the project we're in might be deleted.
|
||||||
@ -2800,7 +2858,7 @@ def checkout_package(apiurl, project, package,
|
|||||||
p = Package(package)
|
p = Package(package)
|
||||||
|
|
||||||
for filename in p.filenamelist:
|
for filename in p.filenamelist:
|
||||||
if service_file or not filename.startswith('_service:'):
|
if service_files or not filename.startswith('_service:'):
|
||||||
p.updatefile(filename, revision)
|
p.updatefile(filename, revision)
|
||||||
#print 'A ', os.path.join(project, package, filename)
|
#print 'A ', os.path.join(project, package, filename)
|
||||||
print statfrmt('A', os.path.join(pathname, filename))
|
print statfrmt('A', os.path.join(pathname, filename))
|
||||||
|
Loading…
Reference in New Issue
Block a user