update_layer.py: use new-style transaction API

The old transaction API has been removed in Django 1.8 and was
deprecated at 1.6. There's no explicit open transaction, commit or
rollback now - we just wrap the layer operations in
"with transaction.atomic()"; if we need to roll back we just raise a
"dummy" exception.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
This commit is contained in:
Paul Eggleton 2016-06-07 23:15:46 +12:00 committed by Aníbal Limón
parent 3df2b1c5d9
commit 3d6dc8f35a

View File

@ -34,6 +34,10 @@ except ImportError:
sys.exit(1) sys.exit(1)
class DryRunRollbackException(Exception):
pass
def check_machine_conf(path, subdir_start): def check_machine_conf(path, subdir_start):
subpath = path[len(subdir_start):] subpath = path[len(subdir_start):]
res = conf_re.match(subpath) res = conf_re.match(subpath)
@ -187,429 +191,422 @@ def main():
# why won't they just fix that?!) # why won't they just fix that?!)
tinfoil.config_data.setVar('LICENSE', '') tinfoil.config_data.setVar('LICENSE', '')
transaction.enter_transaction_management()
transaction.managed(True)
try: try:
layer = utils.get_layer(options.layer) with transaction.atomic():
urldir = layer.get_fetch_dir() layer = utils.get_layer(options.layer)
repodir = os.path.join(fetchdir, urldir) urldir = layer.get_fetch_dir()
repodir = os.path.join(fetchdir, urldir)
layerbranch = layer.get_layerbranch(options.branch) layerbranch = layer.get_layerbranch(options.branch)
branchname = options.branch branchname = options.branch
branchdesc = options.branch branchdesc = options.branch
if layerbranch:
if layerbranch.actual_branch:
branchname = layerbranch.actual_branch
branchdesc = "%s (%s)" % (options.branch, branchname)
# Collect repo info
repo = git.Repo(repodir)
assert repo.bare == False
try:
if options.nocheckout:
topcommit = repo.commit('HEAD')
else:
topcommit = repo.commit('origin/%s' % branchname)
except:
if layerbranch: if layerbranch:
logger.error("Failed update of layer %s - branch %s no longer exists" % (layer.name, branchdesc)) if layerbranch.actual_branch:
else: branchname = layerbranch.actual_branch
logger.info("Skipping update of layer %s - branch %s doesn't exist" % (layer.name, branchdesc)) branchdesc = "%s (%s)" % (options.branch, branchname)
transaction.rollback()
sys.exit(1)
newbranch = False
if not layerbranch:
# LayerBranch doesn't exist for this branch, create it
newbranch = True
layerbranch = LayerBranch()
layerbranch.layer = layer
layerbranch.branch = branch
layerbranch_source = layer.get_layerbranch('master')
if not layerbranch_source:
layerbranch_source = layer.get_layerbranch(None)
if layerbranch_source:
layerbranch.vcs_subdir = layerbranch_source.vcs_subdir
layerbranch.save()
if layerbranch_source:
for maintainer in layerbranch_source.layermaintainer_set.all():
maintainer.pk = None
maintainer.id = None
maintainer.layerbranch = layerbranch
maintainer.save()
for dep in layerbranch_source.dependencies_set.all():
dep.pk = None
dep.id = None
dep.layerbranch = layerbranch
dep.save()
if layerbranch.vcs_subdir and not options.nocheckout:
# Find latest commit in subdirectory
# A bit odd to do it this way but apparently there's no other way in the GitPython API
topcommit = next(repo.iter_commits('origin/%s' % branchname, paths=layerbranch.vcs_subdir), None)
if not topcommit:
# This will error out if the directory is completely invalid or had never existed at this point
# If it previously existed but has since been deleted, you will get the revision where it was
# deleted - so we need to handle that case separately later
if newbranch:
logger.info("Skipping update of layer %s for branch %s - subdirectory %s does not exist on this branch" % (layer.name, branchdesc, layerbranch.vcs_subdir))
elif layerbranch.vcs_subdir:
logger.error("Subdirectory for layer %s does not exist on branch %s - if this is legitimate, the layer branch record should be deleted" % (layer.name, branchdesc))
else:
logger.error("Failed to get last revision for layer %s on branch %s" % (layer.name, branchdesc))
transaction.rollback()
sys.exit(1)
layerdir = os.path.join(repodir, layerbranch.vcs_subdir)
layerdir_start = os.path.normpath(layerdir) + os.sep
layerrecipes = Recipe.objects.filter(layerbranch=layerbranch)
layermachines = Machine.objects.filter(layerbranch=layerbranch)
layerappends = BBAppend.objects.filter(layerbranch=layerbranch)
layerclasses = BBClass.objects.filter(layerbranch=layerbranch)
if layerbranch.vcs_last_rev != topcommit.hexsha or options.reload:
# Check out appropriate branch
if not options.nocheckout:
out = utils.runcmd("git checkout origin/%s" % branchname, repodir, logger=logger)
out = utils.runcmd("git clean -f -x", repodir, logger=logger)
if layerbranch.vcs_subdir and not os.path.exists(layerdir):
if newbranch:
logger.info("Skipping update of layer %s for branch %s - subdirectory %s does not exist on this branch" % (layer.name, branchdesc, layerbranch.vcs_subdir))
else:
logger.error("Subdirectory for layer %s does not exist on branch %s - if this is legitimate, the layer branch record should be deleted" % (layer.name, branchdesc))
transaction.rollback()
sys.exit(1)
if not os.path.exists(os.path.join(layerdir, 'conf/layer.conf')):
logger.error("conf/layer.conf not found for layer %s - is subdirectory set correctly?" % layer.name)
transaction.rollback()
sys.exit(1)
logger.info("Collecting data for layer %s on branch %s" % (layer.name, branchdesc))
# Collect repo info
repo = git.Repo(repodir)
assert repo.bare == False
try: try:
config_data_copy = recipeparse.setup_layer(tinfoil.config_data, fetchdir, layerdir, layer, layerbranch) if options.nocheckout:
except recipeparse.RecipeParseError as e: topcommit = repo.commit('HEAD')
logger.error(str(e)) else:
transaction.rollback() topcommit = repo.commit('origin/%s' % branchname)
except:
if layerbranch:
logger.error("Failed update of layer %s - branch %s no longer exists" % (layer.name, branchdesc))
else:
logger.info("Skipping update of layer %s - branch %s doesn't exist" % (layer.name, branchdesc))
sys.exit(1) sys.exit(1)
if layerbranch.vcs_last_rev and not options.reload: newbranch = False
if not layerbranch:
# LayerBranch doesn't exist for this branch, create it
newbranch = True
layerbranch = LayerBranch()
layerbranch.layer = layer
layerbranch.branch = branch
layerbranch_source = layer.get_layerbranch('master')
if not layerbranch_source:
layerbranch_source = layer.get_layerbranch(None)
if layerbranch_source:
layerbranch.vcs_subdir = layerbranch_source.vcs_subdir
layerbranch.save()
if layerbranch_source:
for maintainer in layerbranch_source.layermaintainer_set.all():
maintainer.pk = None
maintainer.id = None
maintainer.layerbranch = layerbranch
maintainer.save()
for dep in layerbranch_source.dependencies_set.all():
dep.pk = None
dep.id = None
dep.layerbranch = layerbranch
dep.save()
if layerbranch.vcs_subdir and not options.nocheckout:
# Find latest commit in subdirectory
# A bit odd to do it this way but apparently there's no other way in the GitPython API
topcommit = next(repo.iter_commits('origin/%s' % branchname, paths=layerbranch.vcs_subdir), None)
if not topcommit:
# This will error out if the directory is completely invalid or had never existed at this point
# If it previously existed but has since been deleted, you will get the revision where it was
# deleted - so we need to handle that case separately later
if newbranch:
logger.info("Skipping update of layer %s for branch %s - subdirectory %s does not exist on this branch" % (layer.name, branchdesc, layerbranch.vcs_subdir))
elif layerbranch.vcs_subdir:
logger.error("Subdirectory for layer %s does not exist on branch %s - if this is legitimate, the layer branch record should be deleted" % (layer.name, branchdesc))
else:
logger.error("Failed to get last revision for layer %s on branch %s" % (layer.name, branchdesc))
sys.exit(1)
layerdir = os.path.join(repodir, layerbranch.vcs_subdir)
layerdir_start = os.path.normpath(layerdir) + os.sep
layerrecipes = Recipe.objects.filter(layerbranch=layerbranch)
layermachines = Machine.objects.filter(layerbranch=layerbranch)
layerappends = BBAppend.objects.filter(layerbranch=layerbranch)
layerclasses = BBClass.objects.filter(layerbranch=layerbranch)
if layerbranch.vcs_last_rev != topcommit.hexsha or options.reload:
# Check out appropriate branch
if not options.nocheckout:
out = utils.runcmd("git checkout origin/%s" % branchname, repodir, logger=logger)
out = utils.runcmd("git clean -f -x", repodir, logger=logger)
if layerbranch.vcs_subdir and not os.path.exists(layerdir):
if newbranch:
logger.info("Skipping update of layer %s for branch %s - subdirectory %s does not exist on this branch" % (layer.name, branchdesc, layerbranch.vcs_subdir))
else:
logger.error("Subdirectory for layer %s does not exist on branch %s - if this is legitimate, the layer branch record should be deleted" % (layer.name, branchdesc))
sys.exit(1)
if not os.path.exists(os.path.join(layerdir, 'conf/layer.conf')):
logger.error("conf/layer.conf not found for layer %s - is subdirectory set correctly?" % layer.name)
sys.exit(1)
logger.info("Collecting data for layer %s on branch %s" % (layer.name, branchdesc))
try: try:
diff = repo.commit(layerbranch.vcs_last_rev).diff(topcommit) config_data_copy = recipeparse.setup_layer(tinfoil.config_data, fetchdir, layerdir, layer, layerbranch)
except Exception as e: except recipeparse.RecipeParseError as e:
logger.warn("Unable to get diff from last commit hash for layer %s - falling back to slow update: %s" % (layer.name, str(e))) logger.error(str(e))
diff = None sys.exit(1)
else:
diff = None
# We handle recipes specially to try to preserve the same id if layerbranch.vcs_last_rev and not options.reload:
# when recipe upgrades happen (so that if a user bookmarks a try:
# recipe page it remains valid) diff = repo.commit(layerbranch.vcs_last_rev).diff(topcommit)
layerrecipes_delete = [] except Exception as e:
layerrecipes_add = [] logger.warn("Unable to get diff from last commit hash for layer %s - falling back to slow update: %s" % (layer.name, str(e)))
diff = None
# Check if any paths should be ignored because there are layers within this layer
removedirs = []
for root, dirs, files in os.walk(layerdir):
for diritem in dirs:
if os.path.exists(os.path.join(root, diritem, 'conf', 'layer.conf')):
removedirs.append(os.path.join(root, diritem) + os.sep)
if diff:
# Apply git changes to existing recipe list
if layerbranch.vcs_subdir:
subdir_start = os.path.normpath(layerbranch.vcs_subdir) + os.sep
else: else:
subdir_start = "" diff = None
updatedrecipes = set() # We handle recipes specially to try to preserve the same id
dirtyrecipes = set() # when recipe upgrades happen (so that if a user bookmarks a
other_deletes = [] # recipe page it remains valid)
other_adds = [] layerrecipes_delete = []
for diffitem in diff.iter_change_type('R'): layerrecipes_add = []
oldpath = diffitem.a_blob.path
newpath = diffitem.b_blob.path
skip = False
for removedir in removedirs:
# FIXME what about files moved into removedirs?
if oldpath.startswith(removedir):
skip = True
break
if skip:
continue
if oldpath.startswith(subdir_start):
(oldtypename, oldfilepath, oldfilename) = recipeparse.detect_file_type(oldpath, subdir_start)
(newtypename, newfilepath, newfilename) = recipeparse.detect_file_type(newpath, subdir_start)
if oldtypename != newtypename:
# This is most likely to be a .inc file renamed to a .bb - and since
# there may be another recipe deleted at the same time we probably want
# to consider that, so just treat it as a delete and an add
logger.debug("Treating rename of %s to %s as a delete and add (since type changed)" % (oldpath, newpath))
other_deletes.append(diffitem)
other_adds.append(diffitem)
elif oldtypename == 'recipe':
results = layerrecipes.filter(filepath=oldfilepath).filter(filename=oldfilename)
if len(results):
recipe = results[0]
logger.debug("Rename recipe %s to %s" % (recipe, newpath))
recipe.filepath = newfilepath
recipe.filename = newfilename
recipe.save()
update_recipe_file(config_data_copy, os.path.join(layerdir, newfilepath), recipe, layerdir_start, repodir)
updatedrecipes.add(os.path.join(oldfilepath, oldfilename))
updatedrecipes.add(os.path.join(newfilepath, newfilename))
else:
logger.warn("Renamed recipe %s could not be found" % oldpath)
other_adds.append(diffitem)
elif oldtypename == 'bbappend':
results = layerappends.filter(filepath=oldfilepath).filter(filename=oldfilename)
if len(results):
logger.debug("Rename bbappend %s to %s" % (results[0], newfilepath))
results[0].filepath = newfilepath
results[0].filename = newfilename
results[0].save()
else:
logger.warn("Renamed bbappend %s could not be found" % oldpath)
other_adds.append(diffitem)
elif oldtypename == 'machine':
results = layermachines.filter(name=oldfilename)
if len(results):
logger.debug("Rename machine %s to %s" % (results[0], newfilename))
results[0].name = newfilename
results[0].save()
else:
logger.warn("Renamed machine %s could not be found" % oldpath)
other_adds.append(diffitem)
elif oldtypename == 'bbclass':
results = layerclasses.filter(name=oldfilename)
if len(results):
logger.debug("Rename class %s to %s" % (results[0], newfilename))
results[0].name = newfilename
results[0].save()
else:
logger.warn("Renamed class %s could not be found" % oldpath)
other_adds.append(diffitem)
deps = RecipeFileDependency.objects.filter(layerbranch=layerbranch).filter(path=oldpath) # Check if any paths should be ignored because there are layers within this layer
for dep in deps: removedirs = []
dirtyrecipes.add(dep.recipe) for root, dirs, files in os.walk(layerdir):
for diritem in dirs:
if os.path.exists(os.path.join(root, diritem, 'conf', 'layer.conf')):
removedirs.append(os.path.join(root, diritem) + os.sep)
if diff:
# Apply git changes to existing recipe list
for diffitem in itertools.chain(diff.iter_change_type('D'), other_deletes): if layerbranch.vcs_subdir:
path = diffitem.a_blob.path subdir_start = os.path.normpath(layerbranch.vcs_subdir) + os.sep
if path.startswith(subdir_start): else:
subdir_start = ""
updatedrecipes = set()
dirtyrecipes = set()
other_deletes = []
other_adds = []
for diffitem in diff.iter_change_type('R'):
oldpath = diffitem.a_blob.path
newpath = diffitem.b_blob.path
skip = False skip = False
for removedir in removedirs: for removedir in removedirs:
if path.startswith(removedir): # FIXME what about files moved into removedirs?
if oldpath.startswith(removedir):
skip = True skip = True
break break
if skip: if skip:
continue continue
(typename, filepath, filename) = recipeparse.detect_file_type(path, subdir_start) if oldpath.startswith(subdir_start):
if typename == 'recipe': (oldtypename, oldfilepath, oldfilename) = recipeparse.detect_file_type(oldpath, subdir_start)
values = layerrecipes.filter(filepath=filepath).filter(filename=filename).values('id', 'filepath', 'filename', 'pn') (newtypename, newfilepath, newfilename) = recipeparse.detect_file_type(newpath, subdir_start)
if len(values): if oldtypename != newtypename:
layerrecipes_delete.append(values[0]) # This is most likely to be a .inc file renamed to a .bb - and since
logger.debug("Mark %s for deletion" % values[0]) # there may be another recipe deleted at the same time we probably want
updatedrecipes.add(os.path.join(values[0]['filepath'], values[0]['filename'])) # to consider that, so just treat it as a delete and an add
else: logger.debug("Treating rename of %s to %s as a delete and add (since type changed)" % (oldpath, newpath))
logger.warn("Deleted recipe %s could not be found" % path) other_deletes.append(diffitem)
elif typename == 'bbappend': other_adds.append(diffitem)
layerappends.filter(filepath=filepath).filter(filename=filename).delete() elif oldtypename == 'recipe':
elif typename == 'machine': results = layerrecipes.filter(filepath=oldfilepath).filter(filename=oldfilename)
layermachines.filter(name=filename).delete() if len(results):
elif typename == 'bbclass': recipe = results[0]
layerclasses.filter(name=filename).delete() logger.debug("Rename recipe %s to %s" % (recipe, newpath))
recipe.filepath = newfilepath
recipe.filename = newfilename
recipe.save()
update_recipe_file(config_data_copy, os.path.join(layerdir, newfilepath), recipe, layerdir_start, repodir)
updatedrecipes.add(os.path.join(oldfilepath, oldfilename))
updatedrecipes.add(os.path.join(newfilepath, newfilename))
else:
logger.warn("Renamed recipe %s could not be found" % oldpath)
other_adds.append(diffitem)
elif oldtypename == 'bbappend':
results = layerappends.filter(filepath=oldfilepath).filter(filename=oldfilename)
if len(results):
logger.debug("Rename bbappend %s to %s" % (results[0], newfilepath))
results[0].filepath = newfilepath
results[0].filename = newfilename
results[0].save()
else:
logger.warn("Renamed bbappend %s could not be found" % oldpath)
other_adds.append(diffitem)
elif oldtypename == 'machine':
results = layermachines.filter(name=oldfilename)
if len(results):
logger.debug("Rename machine %s to %s" % (results[0], newfilename))
results[0].name = newfilename
results[0].save()
else:
logger.warn("Renamed machine %s could not be found" % oldpath)
other_adds.append(diffitem)
elif oldtypename == 'bbclass':
results = layerclasses.filter(name=oldfilename)
if len(results):
logger.debug("Rename class %s to %s" % (results[0], newfilename))
results[0].name = newfilename
results[0].save()
else:
logger.warn("Renamed class %s could not be found" % oldpath)
other_adds.append(diffitem)
for diffitem in itertools.chain(diff.iter_change_type('A'), other_adds): deps = RecipeFileDependency.objects.filter(layerbranch=layerbranch).filter(path=oldpath)
path = diffitem.b_blob.path for dep in deps:
if path.startswith(subdir_start): dirtyrecipes.add(dep.recipe)
skip = False
for removedir in removedirs:
if path.startswith(removedir):
skip = True
break
if skip:
continue
(typename, filepath, filename) = recipeparse.detect_file_type(path, subdir_start)
if typename == 'recipe':
layerrecipes_add.append(os.path.join(repodir, path))
logger.debug("Mark %s for addition" % path)
updatedrecipes.add(os.path.join(filepath, filename))
elif typename == 'bbappend':
append = BBAppend()
append.layerbranch = layerbranch
append.filename = filename
append.filepath = filepath
append.save()
elif typename == 'machine':
machine = Machine()
machine.layerbranch = layerbranch
machine.name = filename
update_machine_conf_file(os.path.join(repodir, path), machine)
machine.save()
elif typename == 'bbclass':
bbclass = BBClass()
bbclass.layerbranch = layerbranch
bbclass.name = filename
bbclass.save()
for diffitem in diff.iter_change_type('M'):
path = diffitem.a_blob.path for diffitem in itertools.chain(diff.iter_change_type('D'), other_deletes):
if path.startswith(subdir_start): path = diffitem.a_blob.path
skip = False if path.startswith(subdir_start):
for removedir in removedirs: skip = False
if path.startswith(removedir): for removedir in removedirs:
skip = True if path.startswith(removedir):
break skip = True
if skip: break
continue if skip:
(typename, filepath, filename) = recipeparse.detect_file_type(path, subdir_start) continue
if typename == 'recipe': (typename, filepath, filename) = recipeparse.detect_file_type(path, subdir_start)
logger.debug("Mark %s for update" % path) if typename == 'recipe':
results = layerrecipes.filter(filepath=filepath).filter(filename=filename)[:1] values = layerrecipes.filter(filepath=filepath).filter(filename=filename).values('id', 'filepath', 'filename', 'pn')
if results: if len(values):
recipe = results[0] layerrecipes_delete.append(values[0])
update_recipe_file(config_data_copy, os.path.join(layerdir, filepath), recipe, layerdir_start, repodir) logger.debug("Mark %s for deletion" % values[0])
recipe.save() updatedrecipes.add(os.path.join(values[0]['filepath'], values[0]['filename']))
updatedrecipes.add(recipe.full_path()) else:
elif typename == 'machine': logger.warn("Deleted recipe %s could not be found" % path)
results = layermachines.filter(name=filename) elif typename == 'bbappend':
if results: layerappends.filter(filepath=filepath).filter(filename=filename).delete()
machine = results[0] elif typename == 'machine':
layermachines.filter(name=filename).delete()
elif typename == 'bbclass':
layerclasses.filter(name=filename).delete()
for diffitem in itertools.chain(diff.iter_change_type('A'), other_adds):
path = diffitem.b_blob.path
if path.startswith(subdir_start):
skip = False
for removedir in removedirs:
if path.startswith(removedir):
skip = True
break
if skip:
continue
(typename, filepath, filename) = recipeparse.detect_file_type(path, subdir_start)
if typename == 'recipe':
layerrecipes_add.append(os.path.join(repodir, path))
logger.debug("Mark %s for addition" % path)
updatedrecipes.add(os.path.join(filepath, filename))
elif typename == 'bbappend':
append = BBAppend()
append.layerbranch = layerbranch
append.filename = filename
append.filepath = filepath
append.save()
elif typename == 'machine':
machine = Machine()
machine.layerbranch = layerbranch
machine.name = filename
update_machine_conf_file(os.path.join(repodir, path), machine) update_machine_conf_file(os.path.join(repodir, path), machine)
machine.save() machine.save()
elif typename == 'bbclass':
bbclass = BBClass()
bbclass.layerbranch = layerbranch
bbclass.name = filename
bbclass.save()
deps = RecipeFileDependency.objects.filter(layerbranch=layerbranch).filter(path=path) for diffitem in diff.iter_change_type('M'):
for dep in deps: path = diffitem.a_blob.path
dirtyrecipes.add(dep.recipe) if path.startswith(subdir_start):
skip = False
for recipe in dirtyrecipes:
if not recipe.full_path() in updatedrecipes:
update_recipe_file(config_data_copy, os.path.join(layerdir, recipe.filepath), recipe, layerdir_start, repodir)
else:
# Collect recipe data from scratch
layerrecipe_fns = []
if options.fullreload:
layerrecipes.delete()
else:
# First, check which recipes still exist
layerrecipe_values = layerrecipes.values('id', 'filepath', 'filename', 'pn')
for v in layerrecipe_values:
root = os.path.join(layerdir, v['filepath'])
fullpath = os.path.join(root, v['filename'])
preserve = True
if os.path.exists(fullpath):
for removedir in removedirs: for removedir in removedirs:
if fullpath.startswith(removedir): if path.startswith(removedir):
preserve = False skip = True
break break
else: if skip:
preserve = False continue
(typename, filepath, filename) = recipeparse.detect_file_type(path, subdir_start)
if typename == 'recipe':
logger.debug("Mark %s for update" % path)
results = layerrecipes.filter(filepath=filepath).filter(filename=filename)[:1]
if results:
recipe = results[0]
update_recipe_file(config_data_copy, os.path.join(layerdir, filepath), recipe, layerdir_start, repodir)
recipe.save()
updatedrecipes.add(recipe.full_path())
elif typename == 'machine':
results = layermachines.filter(name=filename)
if results:
machine = results[0]
update_machine_conf_file(os.path.join(repodir, path), machine)
machine.save()
if preserve: deps = RecipeFileDependency.objects.filter(layerbranch=layerbranch).filter(path=path)
# Recipe still exists, update it for dep in deps:
results = layerrecipes.filter(id=v['id'])[:1] dirtyrecipes.add(dep.recipe)
recipe = results[0]
update_recipe_file(config_data_copy, root, recipe, layerdir_start, repodir)
else:
# Recipe no longer exists, mark it for later on
layerrecipes_delete.append(v)
layerrecipe_fns.append(fullpath)
layermachines.delete() for recipe in dirtyrecipes:
layerappends.delete() if not recipe.full_path() in updatedrecipes:
layerclasses.delete() update_recipe_file(config_data_copy, os.path.join(layerdir, recipe.filepath), recipe, layerdir_start, repodir)
for root, dirs, files in os.walk(layerdir):
if '.git' in dirs:
dirs.remove('.git')
for diritem in dirs[:]:
fullpath = os.path.join(root, diritem) + os.sep
if fullpath in removedirs:
dirs.remove(diritem)
for f in files:
fullpath = os.path.join(root, f)
(typename, _, filename) = recipeparse.detect_file_type(fullpath, layerdir_start)
if typename == 'recipe':
if fullpath not in layerrecipe_fns:
layerrecipes_add.append(fullpath)
elif typename == 'bbappend':
append = BBAppend()
append.layerbranch = layerbranch
append.filename = f
append.filepath = os.path.relpath(root, layerdir)
append.save()
elif typename == 'machine':
machine = Machine()
machine.layerbranch = layerbranch
machine.name = filename
update_machine_conf_file(fullpath, machine)
machine.save()
elif typename == 'bbclass':
bbclass = BBClass()
bbclass.layerbranch = layerbranch
bbclass.name = filename
bbclass.save()
for added in layerrecipes_add:
# This is good enough without actually parsing the file
(pn, pv) = split_recipe_fn(added)
oldid = -1
for deleted in layerrecipes_delete:
if deleted['pn'] == pn:
oldid = deleted['id']
layerrecipes_delete.remove(deleted)
break
if oldid > -1:
# Reclaim a record we would have deleted
results = Recipe.objects.filter(id=oldid)[:1]
recipe = results[0]
logger.debug("Reclaim %s for %s %s" % (recipe, pn, pv))
else: else:
# Create new record # Collect recipe data from scratch
logger.debug("Add new recipe %s" % added)
recipe = Recipe()
recipe.layerbranch = layerbranch
recipe.filename = os.path.basename(added)
root = os.path.dirname(added)
recipe.filepath = os.path.relpath(root, layerdir)
update_recipe_file(config_data_copy, root, recipe, layerdir_start, repodir)
recipe.save()
for deleted in layerrecipes_delete: layerrecipe_fns = []
logger.debug("Delete %s" % deleted) if options.fullreload:
results = Recipe.objects.filter(id=deleted['id'])[:1] layerrecipes.delete()
recipe = results[0] else:
recipe.delete() # First, check which recipes still exist
layerrecipe_values = layerrecipes.values('id', 'filepath', 'filename', 'pn')
for v in layerrecipe_values:
root = os.path.join(layerdir, v['filepath'])
fullpath = os.path.join(root, v['filename'])
preserve = True
if os.path.exists(fullpath):
for removedir in removedirs:
if fullpath.startswith(removedir):
preserve = False
break
else:
preserve = False
# Save repo info if preserve:
layerbranch.vcs_last_rev = topcommit.hexsha # Recipe still exists, update it
layerbranch.vcs_last_commit = datetime.fromtimestamp(topcommit.committed_date) results = layerrecipes.filter(id=v['id'])[:1]
else: recipe = results[0]
logger.info("Layer %s is already up-to-date for branch %s" % (layer.name, branchdesc)) update_recipe_file(config_data_copy, root, recipe, layerdir_start, repodir)
else:
# Recipe no longer exists, mark it for later on
layerrecipes_delete.append(v)
layerrecipe_fns.append(fullpath)
layerbranch.vcs_last_fetch = datetime.now() layermachines.delete()
layerbranch.save() layerappends.delete()
layerclasses.delete()
for root, dirs, files in os.walk(layerdir):
if '.git' in dirs:
dirs.remove('.git')
for diritem in dirs[:]:
fullpath = os.path.join(root, diritem) + os.sep
if fullpath in removedirs:
dirs.remove(diritem)
for f in files:
fullpath = os.path.join(root, f)
(typename, _, filename) = recipeparse.detect_file_type(fullpath, layerdir_start)
if typename == 'recipe':
if fullpath not in layerrecipe_fns:
layerrecipes_add.append(fullpath)
elif typename == 'bbappend':
append = BBAppend()
append.layerbranch = layerbranch
append.filename = f
append.filepath = os.path.relpath(root, layerdir)
append.save()
elif typename == 'machine':
machine = Machine()
machine.layerbranch = layerbranch
machine.name = filename
update_machine_conf_file(fullpath, machine)
machine.save()
elif typename == 'bbclass':
bbclass = BBClass()
bbclass.layerbranch = layerbranch
bbclass.name = filename
bbclass.save()
for added in layerrecipes_add:
# This is good enough without actually parsing the file
(pn, pv) = split_recipe_fn(added)
oldid = -1
for deleted in layerrecipes_delete:
if deleted['pn'] == pn:
oldid = deleted['id']
layerrecipes_delete.remove(deleted)
break
if oldid > -1:
# Reclaim a record we would have deleted
results = Recipe.objects.filter(id=oldid)[:1]
recipe = results[0]
logger.debug("Reclaim %s for %s %s" % (recipe, pn, pv))
else:
# Create new record
logger.debug("Add new recipe %s" % added)
recipe = Recipe()
recipe.layerbranch = layerbranch
recipe.filename = os.path.basename(added)
root = os.path.dirname(added)
recipe.filepath = os.path.relpath(root, layerdir)
update_recipe_file(config_data_copy, root, recipe, layerdir_start, repodir)
recipe.save()
for deleted in layerrecipes_delete:
logger.debug("Delete %s" % deleted)
results = Recipe.objects.filter(id=deleted['id'])[:1]
recipe = results[0]
recipe.delete()
# Save repo info
layerbranch.vcs_last_rev = topcommit.hexsha
layerbranch.vcs_last_commit = datetime.fromtimestamp(topcommit.committed_date)
else:
logger.info("Layer %s is already up-to-date for branch %s" % (layer.name, branchdesc))
layerbranch.vcs_last_fetch = datetime.now()
layerbranch.save()
if options.dryrun:
raise DryRunRollbackException()
if options.dryrun:
transaction.rollback()
else:
transaction.commit()
except KeyboardInterrupt: except KeyboardInterrupt:
transaction.rollback()
logger.warn("Update interrupted, changes to %s rolled back" % layer.name) logger.warn("Update interrupted, changes to %s rolled back" % layer.name)
sys.exit(254) sys.exit(254)
except SystemExit:
raise
except DryRunRollbackException:
pass
except: except:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
transaction.rollback()
finally:
transaction.leave_transaction_management()
shutil.rmtree(tempdir) shutil.rmtree(tempdir)
sys.exit(0) sys.exit(0)