diff --git a/NEWS b/NEWS
index b2b6e437..f5d0fc29 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,8 @@
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
- switch to python3 in osc-wrapper and make python3 explicit
diff --git a/osc/commandline.py b/osc/commandline.py
index 92e8c4ad..9180f925 100644
--- a/osc/commandline.py
+++ b/osc/commandline.py
@@ -219,7 +219,7 @@ class Osc(cmdln.Cmdln):
return help
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
Initialize an existing directory to be a working copy of an
@@ -238,11 +238,25 @@ class Osc(cmdln.Cmdln):
usage:
osc init PRJ
osc init PRJ PAC
+ osc init PRJ PAC SCM_URL
${cmd_option_list}
"""
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:
Project.init_project(apiurl, os.curdir, project, conf.config['do_package_tracking'],
getPackageList=False)
@@ -708,6 +722,20 @@ class Osc(cmdln.Cmdln):
else:
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.option('-u', '--unset', action='store_true',
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)
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))
+ if scm_url != None:
+ return
+
# all packages
for package in meta_get_packagelist(apiurl, project):
if opts.output_dir is not None:
@@ -6677,10 +6715,14 @@ Please submit there instead, or use --nodevelproject to force direct submission.
project = None
try:
project = store_read_project(os.curdir)
+ if project == opts.alternative_project:
+ opts.alternative_project = None
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
- if project == opts.alternative_project:
- opts.alternative_project = None
if len(args) == 0 and is_package_dir(os.curdir):
# build env not specified, just read from last build attempt
diff --git a/osc/conf.py b/osc/conf.py
index ded53264..b1e3c3ab 100644
--- a/osc/conf.py
+++ b/osc/conf.py
@@ -134,6 +134,7 @@ DEFAULTS = {'apiurl': 'https://api.opensuse.org',
'build-vm-user': '', # optional for VM builds
'build-kernel': '', # 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()),
'builtin_signature_check': '1', # by default use builtin check for verify pkgs
diff --git a/osc/core.py b/osc/core.py
index 10cbabc3..d4ef6719 100644
--- a/osc/core.py
+++ b/osc/core.py
@@ -685,6 +685,7 @@ class Project:
self.progress_obj = progress_obj
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)
dirty_files = []
@@ -725,7 +726,7 @@ class Project:
global store
dirty_files = []
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',)
for fname in req_storefiles:
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)
rev = None
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():
try:
rev = show_upstream_xsrcmd5(p.apiurl, p.prjname, p.name, revision=p.rev)
@@ -1137,7 +1142,7 @@ class Project:
return '\n'.join(r)
@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
if not os.path.exists(dir):
@@ -1152,6 +1157,9 @@ class Project:
store_write_project(dir, project)
store_write_apiurl(dir, apiurl)
+ if scm_url:
+ store_write_string(dir, '_scm', scm_url + '\n')
+ package_tracking = None
if package_tracking:
store_write_initial_packages(dir, project, [])
return Project(dir, getPackageList, progress_obj, wc_check)
@@ -1174,6 +1182,7 @@ class Package:
self.storedir = os.path.join(self.absdir, store)
self.progress_obj = progress_obj
self.size_limit = size_limit
+ self.scm_url = store_read_scmurl(self.dir)
if size_limit and size_limit == 0:
self.size_limit = None
@@ -1198,6 +1207,8 @@ class Package:
def wc_check(self):
dirty_files = []
+ if self.scm_url:
+ return dirty_files
for fname in self.filenamelist:
if not os.path.exists(os.path.join(self.storedir, fname)) and not fname in self.skipped:
dirty_files.append(fname)
@@ -1774,6 +1785,20 @@ class Package:
called).
"""
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_root = files_tree.getroot()
@@ -1784,10 +1809,10 @@ class Package:
self.linkinfo.read(files_tree_root.find('linkinfo'))
self.serviceinfo = DirectoryServiceinfo()
self.serviceinfo.read(files_tree_root.find('serviceinfo'))
-
self.filenamelist = []
self.filelist = []
self.skipped = []
+
for node in files_tree_root.findall('entry'):
try:
f = File(node.get('name'),
@@ -2491,7 +2516,7 @@ rev: %s
self.write_addlist()
@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
if not os.path.exists(dir):
@@ -2509,7 +2534,10 @@ rev: %s
store_write_string(dir, '_meta_mode', '')
if size_limit:
store_write_string(dir, '_size_limit', str(size_limit) + '\n')
- store_write_string(dir, '_files', '' + '\n')
+ if scm_url:
+ store_write_string(dir, '_scm', scm_url + '\n')
+ else:
+ store_write_string(dir, '_files', '' + '\n')
store_write_string(dir, '_osclib_version', __store_version__ + '\n')
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')
if not is_package_dir(dir):
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):
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
+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):
m = show_package_meta(apiurl, prj, pac)
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
# 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
if expand_link:
@@ -6583,6 +6640,21 @@ def store_read_package(dir):
raise oscerr.NoWorkingCopy(msg)
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):
global store