summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/orm/models.py
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2016-07-21 14:43:25 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-07-26 08:10:35 +0100
commit853450befcf2cb998e0b89b5b6c1caa4d0429761 (patch)
tree103e9002cedef757294a54656088bb4ca4c75b1a /bitbake/lib/toaster/orm/models.py
parent20f939f2420636e5971378d964ac53a938178bff (diff)
downloadpoky-853450befcf2cb998e0b89b5b6c1caa4d0429761.tar.gz
bitbake: toaster: models Remove LayerSource models and replace with enum
We had a lot of complexity around different layer sources to allow for multiple sources and different priorities for these source. This was implemented using rigged abstract classes which represented the different layer sources when in fact just an enum/flag on the layer_version object is sufficient for our needs. Remove the LayerSourcePriority object as this is not needed. We no longer have a problem of multiple layers coming from multiple sources so this is not needed. Two migrations are added to first remove the child models which represented layersources. Then a second migration is needed to remove the LayerSource model it's self as Django can't understand the non-standard base class dependency. Triggering this issue: https://docs.djangoproject.com/en/1.8/topics/migrations/#dependencies Clean up a number of flake8 warnings in classes which were modified. [YOCTO #9853] (Bitbake rev: 26624740418de95adb1f4a970a30a5f1149ebb79) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/orm/models.py')
-rw-r--r--bitbake/lib/toaster/orm/models.py481
1 files changed, 103 insertions, 378 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 048399f34d..1daec9c25a 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -22,7 +22,7 @@
22from __future__ import unicode_literals 22from __future__ import unicode_literals
23 23
24from django.db import models, IntegrityError 24from django.db import models, IntegrityError
25from django.db.models import F, Q, Avg, Max, Sum, Count 25from django.db.models import F, Q, Sum, Count
26from django.utils import timezone 26from django.utils import timezone
27from django.utils.encoding import force_bytes 27from django.utils.encoding import force_bytes
28 28
@@ -117,39 +117,48 @@ class ToasterSetting(models.Model):
117 def __unicode__(self): 117 def __unicode__(self):
118 return "Setting %s = %s" % (self.name, self.value) 118 return "Setting %s = %s" % (self.name, self.value)
119 119
120
120class ProjectManager(models.Manager): 121class ProjectManager(models.Manager):
121 def create_project(self, name, release): 122 def create_project(self, name, release):
122 if release is not None: 123 if release is not None:
123 prj = self.model(name = name, bitbake_version = release.bitbake_version, release = release) 124 prj = self.model(name=name,
125 bitbake_version=release.bitbake_version,
126 release=release)
124 else: 127 else:
125 prj = self.model(name = name, bitbake_version = None, release = None) 128 prj = self.model(name=name,
129 bitbake_version=None,
130 release=None)
126 131
127 prj.save() 132 prj.save()
128 133
129 for defaultconf in ToasterSetting.objects.filter(name__startswith="DEFCONF_"): 134 for defaultconf in ToasterSetting.objects.filter(
135 name__startswith="DEFCONF_"):
130 name = defaultconf.name[8:] 136 name = defaultconf.name[8:]
131 ProjectVariable.objects.create( project = prj, 137 ProjectVariable.objects.create(project=prj,
132 name = name, 138 name=name,
133 value = defaultconf.value) 139 value=defaultconf.value)
134 140
135 if release is None: 141 if release is None:
136 return prj 142 return prj
137 143
138 for rdl in release.releasedefaultlayer_set.all(): 144 for rdl in release.releasedefaultlayer_set.all():
139 try: 145 lv = Layer_Version.objects.filter(
140 lv = Layer_Version.objects.filter(layer__name = rdl.layer_name, up_branch__name = release.branch_name)[0].get_equivalents_wpriority(prj)[0] 146 layer__name=rdl.layer_name,
141 ProjectLayer.objects.create( project = prj, 147 up_branch__name=release.branch_name).first()
142 layercommit = lv, 148
143 optional = False ) 149 if lv:
144 except IndexError: 150 ProjectLayer.objects.create(project=prj,
145 # we may have no valid layer version objects, and that's ok 151 layercommit=lv,
146 pass 152 optional=False)
153 else:
154 logger.warning("Default project layer %s not found" %
155 rdl.layer_name)
147 156
148 return prj 157 return prj
149 158
150 # return single object with is_default = True 159 # return single object with is_default = True
151 def get_or_create_default_project(self): 160 def get_or_create_default_project(self):
152 projects = super(ProjectManager, self).filter(is_default = True) 161 projects = super(ProjectManager, self).filter(is_default=True)
153 162
154 if len(projects) > 1: 163 if len(projects) > 1:
155 raise Exception('Inconsistent project data: multiple ' + 164 raise Exception('Inconsistent project data: multiple ' +
@@ -157,7 +166,8 @@ class ProjectManager(models.Manager):
157 elif len(projects) < 1: 166 elif len(projects) < 1:
158 options = { 167 options = {
159 'name': 'Command line builds', 168 'name': 'Command line builds',
160 'short_description': 'Project for builds started outside Toaster', 169 'short_description':
170 'Project for builds started outside Toaster',
161 'is_default': True 171 'is_default': True
162 } 172 }
163 project = Project.objects.create(**options) 173 project = Project.objects.create(**options)
@@ -1126,21 +1136,27 @@ class Target_Installed_Package(models.Model):
1126 target = models.ForeignKey(Target) 1136 target = models.ForeignKey(Target)
1127 package = models.ForeignKey(Package, related_name='buildtargetlist_package') 1137 package = models.ForeignKey(Package, related_name='buildtargetlist_package')
1128 1138
1139
1129class Package_File(models.Model): 1140class Package_File(models.Model):
1130 package = models.ForeignKey(Package, related_name='buildfilelist_package') 1141 package = models.ForeignKey(Package, related_name='buildfilelist_package')
1131 path = models.FilePathField(max_length=255, blank=True) 1142 path = models.FilePathField(max_length=255, blank=True)
1132 size = models.IntegerField() 1143 size = models.IntegerField()
1133 1144
1145
1134class Recipe(models.Model): 1146class Recipe(models.Model):
1135 search_allowed_fields = ['name', 'version', 'file_path', 'section', 'summary', 'description', 'license', 'layer_version__layer__name', 'layer_version__branch', 'layer_version__commit', 'layer_version__local_path', 'layer_version__layer_source__name'] 1147 search_allowed_fields = ['name', 'version', 'file_path', 'section',
1148 'summary', 'description', 'license',
1149 'layer_version__layer__name',
1150 'layer_version__branch', 'layer_version__commit',
1151 'layer_version__local_path',
1152 'layer_version__layer_source']
1136 1153
1137 layer_source = models.ForeignKey('LayerSource', default = None, null = True) # from where did we get this recipe 1154 up_date = models.DateTimeField(null=True, default=None)
1138 up_id = models.IntegerField(null = True, default = None) # id of entry in the source
1139 up_date = models.DateTimeField(null = True, default = None)
1140 1155
1141 name = models.CharField(max_length=100, blank=True) # pn 1156 name = models.CharField(max_length=100, blank=True)
1142 version = models.CharField(max_length=100, blank=True) # pv 1157 version = models.CharField(max_length=100, blank=True)
1143 layer_version = models.ForeignKey('Layer_Version', related_name='recipe_layer_version') 1158 layer_version = models.ForeignKey('Layer_Version',
1159 related_name='recipe_layer_version')
1144 summary = models.TextField(blank=True) 1160 summary = models.TextField(blank=True)
1145 description = models.TextField(blank=True) 1161 description = models.TextField(blank=True)
1146 section = models.CharField(max_length=100, blank=True) 1162 section = models.CharField(max_length=100, blank=True)
@@ -1151,13 +1167,6 @@ class Recipe(models.Model):
1151 pathflags = models.CharField(max_length=200, blank=True) 1167 pathflags = models.CharField(max_length=200, blank=True)
1152 is_image = models.BooleanField(default=False) 1168 is_image = models.BooleanField(default=False)
1153 1169
1154 def get_layersource_view_url(self):
1155 if self.layer_source is None:
1156 return ""
1157
1158 url = self.layer_source.get_object_view(self.layer_version.up_branch, "recipes", self.name)
1159 return url
1160
1161 def __unicode__(self): 1170 def __unicode__(self):
1162 return "Recipe " + self.name + ":" + self.version 1171 return "Recipe " + self.name + ":" + self.version
1163 1172
@@ -1203,8 +1212,6 @@ class Recipe_Dependency(models.Model):
1203 1212
1204class Machine(models.Model): 1213class Machine(models.Model):
1205 search_allowed_fields = ["name", "description", "layer_version__layer__name"] 1214 search_allowed_fields = ["name", "description", "layer_version__layer__name"]
1206 layer_source = models.ForeignKey('LayerSource', default = None, null = True) # from where did we get this machine
1207 up_id = models.IntegerField(null = True, default = None) # id of entry in the source
1208 up_date = models.DateTimeField(null = True, default = None) 1215 up_date = models.DateTimeField(null = True, default = None)
1209 1216
1210 layer_version = models.ForeignKey('Layer_Version') 1217 layer_version = models.ForeignKey('Layer_Version')
@@ -1219,293 +1226,9 @@ class Machine(models.Model):
1219 def __unicode__(self): 1226 def __unicode__(self):
1220 return "Machine " + self.name + "(" + self.description + ")" 1227 return "Machine " + self.name + "(" + self.description + ")"
1221 1228
1222 class Meta:
1223 unique_together = ("layer_source", "up_id")
1224
1225
1226from django.db.models.base import ModelBase
1227 1229
1228class InheritanceMetaclass(ModelBase):
1229 def __call__(cls, *args, **kwargs):
1230 obj = super(InheritanceMetaclass, cls).__call__(*args, **kwargs)
1231 return obj.get_object()
1232 1230
1233 1231
1234class LayerSource(models.Model):
1235 __metaclass__ = InheritanceMetaclass
1236
1237 class Meta:
1238 unique_together = (('sourcetype', 'apiurl'), )
1239
1240 TYPE_LOCAL = 0
1241 TYPE_LAYERINDEX = 1
1242 TYPE_IMPORTED = 2
1243 SOURCE_TYPE = (
1244 (TYPE_LOCAL, "local"),
1245 (TYPE_LAYERINDEX, "layerindex"),
1246 (TYPE_IMPORTED, "imported"),
1247 )
1248
1249 name = models.CharField(max_length=63, unique = True)
1250 sourcetype = models.IntegerField(choices=SOURCE_TYPE)
1251 apiurl = models.CharField(max_length=255, null=True, default=None)
1252
1253 def __init__(self, *args, **kwargs):
1254 super(LayerSource, self).__init__(*args, **kwargs)
1255 if self.sourcetype == LayerSource.TYPE_LOCAL:
1256 self.__class__ = LocalLayerSource
1257 elif self.sourcetype == LayerSource.TYPE_LAYERINDEX:
1258 self.__class__ = LayerIndexLayerSource
1259 elif self.sourcetype == LayerSource.TYPE_IMPORTED:
1260 self.__class__ = ImportedLayerSource
1261 elif self.sourcetype == None:
1262 raise Exception("Unknown LayerSource-derived class. If you added a new layer source type, fill out all code stubs.")
1263
1264
1265 def update(self):
1266 """
1267 Updates the local database information from the upstream layer source
1268 """
1269 raise Exception("Abstract, update() must be implemented by all LayerSource-derived classes (object is %s)" % str(vars(self)))
1270
1271 def save(self, *args, **kwargs):
1272 return super(LayerSource, self).save(*args, **kwargs)
1273
1274 def get_object(self):
1275 # preset an un-initilized object
1276 if None == self.name:
1277 self.name=""
1278 if None == self.apiurl:
1279 self.apiurl=""
1280 if None == self.sourcetype:
1281 self.sourcetype=LayerSource.TYPE_LOCAL
1282
1283 if self.sourcetype == LayerSource.TYPE_LOCAL:
1284 self.__class__ = LocalLayerSource
1285 elif self.sourcetype == LayerSource.TYPE_LAYERINDEX:
1286 self.__class__ = LayerIndexLayerSource
1287 elif self.sourcetype == LayerSource.TYPE_IMPORTED:
1288 self.__class__ = ImportedLayerSource
1289 else:
1290 raise Exception("Unknown LayerSource type. If you added a new layer source type, fill out all code stubs.")
1291 return self
1292
1293 def __unicode__(self):
1294 return "%s (%s)" % (self.name, self.sourcetype)
1295
1296
1297class LocalLayerSource(LayerSource):
1298 class Meta(LayerSource._meta.__class__):
1299 proxy = True
1300
1301 def __init__(self, *args, **kwargs):
1302 super(LocalLayerSource, self).__init__(args, kwargs)
1303 self.sourcetype = LayerSource.TYPE_LOCAL
1304
1305 def update(self):
1306 """
1307 Fetches layer, recipe and machine information from local repository
1308 """
1309 pass
1310
1311class ImportedLayerSource(LayerSource):
1312 class Meta(LayerSource._meta.__class__):
1313 proxy = True
1314
1315 def __init__(self, *args, **kwargs):
1316 super(ImportedLayerSource, self).__init__(args, kwargs)
1317 self.sourcetype = LayerSource.TYPE_IMPORTED
1318
1319 def update(self):
1320 """
1321 Fetches layer, recipe and machine information from local repository
1322 """
1323 pass
1324
1325
1326class LayerIndexLayerSource(LayerSource):
1327 class Meta(LayerSource._meta.__class__):
1328 proxy = True
1329
1330 def __init__(self, *args, **kwargs):
1331 super(LayerIndexLayerSource, self).__init__(args, kwargs)
1332 self.sourcetype = LayerSource.TYPE_LAYERINDEX
1333
1334 def get_object_view(self, branch, objectype, upid):
1335 return self.apiurl + "../branch/" + branch.name + "/" + objectype + "/?q=" + str(upid)
1336
1337 def update(self):
1338 """
1339 Fetches layer, recipe and machine information from remote repository
1340 """
1341 assert self.apiurl is not None
1342 from django.db import transaction, connection
1343
1344 import json
1345 import os
1346
1347 try:
1348 from urllib.request import urlopen, URLError
1349 from urllib.parse import urlparse
1350 except ImportError:
1351 from urllib2 import urlopen, URLError
1352 from urlparse import urlparse
1353
1354 proxy_settings = os.environ.get("http_proxy", None)
1355 oe_core_layer = 'openembedded-core'
1356
1357 def _get_json_response(apiurl = self.apiurl):
1358 _parsedurl = urlparse(apiurl)
1359 path = _parsedurl.path
1360
1361 try:
1362 res = urlopen(apiurl)
1363 except URLError as e:
1364 raise Exception("Failed to read %s: %s" % (path, e.reason))
1365
1366 return json.loads(res.read().decode('utf-8'))
1367
1368 # verify we can get the basic api
1369 try:
1370 apilinks = _get_json_response()
1371 except Exception as e:
1372 import traceback
1373 if proxy_settings is not None:
1374 logger.info("EE: Using proxy %s" % proxy_settings)
1375 logger.warning("EE: could not connect to %s, skipping update: %s\n%s" % (self.apiurl, e, traceback.format_exc()))
1376 return
1377
1378 # update branches; only those that we already have names listed in the
1379 # Releases table
1380 whitelist_branch_names = [rel.branch_name for rel in Release.objects.all()]
1381 if len(whitelist_branch_names) == 0:
1382 raise Exception("Failed to make list of branches to fetch")
1383
1384 logger.debug("Fetching branches")
1385 branches_info = _get_json_response(apilinks['branches']
1386 + "?filter=name:%s" % "OR".join(whitelist_branch_names))
1387 for bi in branches_info:
1388 b, created = Branch.objects.get_or_create(layer_source = self, name = bi['name'])
1389 b.up_id = bi['id']
1390 b.up_date = bi['updated']
1391 b.name = bi['name']
1392 b.short_description = bi['short_description']
1393 b.save()
1394
1395 # update layers
1396 layers_info = _get_json_response(apilinks['layerItems'])
1397
1398 for li in layers_info:
1399 # Special case for the openembedded-core layer
1400 if li['name'] == oe_core_layer:
1401 try:
1402 # If we have an existing openembedded-core for example
1403 # from the toasterconf.json augment the info using the
1404 # layerindex rather than duplicate it
1405 oe_core_l = Layer.objects.get(name=oe_core_layer)
1406 # Take ownership of the layer as now coming from the
1407 # layerindex
1408 oe_core_l.layer_source = self
1409 oe_core_l.up_id = li['id']
1410 oe_core_l.summary = li['summary']
1411 oe_core_l.description = li['description']
1412 oe_core_l.save()
1413 continue
1414
1415 except Layer.DoesNotExist:
1416 pass
1417
1418 l, created = Layer.objects.get_or_create(layer_source = self, name = li['name'])
1419 l.up_id = li['id']
1420 l.up_date = li['updated']
1421 l.vcs_url = li['vcs_url']
1422 l.vcs_web_url = li['vcs_web_url']
1423 l.vcs_web_tree_base_url = li['vcs_web_tree_base_url']
1424 l.vcs_web_file_base_url = li['vcs_web_file_base_url']
1425 l.summary = li['summary']
1426 l.description = li['description']
1427 l.save()
1428
1429 # update layerbranches/layer_versions
1430 logger.debug("Fetching layer information")
1431 layerbranches_info = _get_json_response(apilinks['layerBranches']
1432 + "?filter=branch:%s" % "OR".join(map(lambda x: str(x.up_id), [i for i in Branch.objects.filter(layer_source = self) if i.up_id is not None] ))
1433 )
1434
1435 for lbi in layerbranches_info:
1436 lv, created = Layer_Version.objects.get_or_create(layer_source = self,
1437 up_id = lbi['id'],
1438 layer=Layer.objects.get(layer_source = self, up_id = lbi['layer'])
1439 )
1440
1441 lv.up_date = lbi['updated']
1442 lv.up_branch = Branch.objects.get(layer_source = self, up_id = lbi['branch'])
1443 lv.branch = lbi['actual_branch']
1444 lv.commit = lbi['actual_branch']
1445 lv.dirpath = lbi['vcs_subdir']
1446 lv.save()
1447
1448 # update layer dependencies
1449 layerdependencies_info = _get_json_response(apilinks['layerDependencies'])
1450 dependlist = {}
1451 for ldi in layerdependencies_info:
1452 try:
1453 lv = Layer_Version.objects.get(layer_source = self, up_id = ldi['layerbranch'])
1454 except Layer_Version.DoesNotExist as e:
1455 continue
1456
1457 if lv not in dependlist:
1458 dependlist[lv] = []
1459 try:
1460 dependlist[lv].append(Layer_Version.objects.get(layer_source = self, layer__up_id = ldi['dependency'], up_branch = lv.up_branch))
1461 except Layer_Version.DoesNotExist:
1462 logger.warning("Cannot find layer version (ls:%s), up_id:%s lv:%s" % (self, ldi['dependency'], lv))
1463
1464 for lv in dependlist:
1465 LayerVersionDependency.objects.filter(layer_version = lv).delete()
1466 for lvd in dependlist[lv]:
1467 LayerVersionDependency.objects.get_or_create(layer_version = lv, depends_on = lvd)
1468
1469
1470 # update machines
1471 logger.debug("Fetching machine information")
1472 machines_info = _get_json_response(apilinks['machines']
1473 + "?filter=layerbranch:%s" % "OR".join(map(lambda x: str(x.up_id), Layer_Version.objects.filter(layer_source = self)))
1474 )
1475
1476 for mi in machines_info:
1477 mo, created = Machine.objects.get_or_create(layer_source = self, up_id = mi['id'], layer_version = Layer_Version.objects.get(layer_source = self, up_id = mi['layerbranch']))
1478 mo.up_date = mi['updated']
1479 mo.name = mi['name']
1480 mo.description = mi['description']
1481 mo.save()
1482
1483 # update recipes; paginate by layer version / layer branch
1484 logger.debug("Fetching target information")
1485 recipes_info = _get_json_response(apilinks['recipes']
1486 + "?filter=layerbranch:%s" % "OR".join(map(lambda x: str(x.up_id), Layer_Version.objects.filter(layer_source = self)))
1487 )
1488 for ri in recipes_info:
1489 try:
1490 ro, created = Recipe.objects.get_or_create(layer_source = self, up_id = ri['id'], layer_version = Layer_Version.objects.get(layer_source = self, up_id = ri['layerbranch']))
1491 ro.up_date = ri['updated']
1492 ro.name = ri['pn']
1493 ro.version = ri['pv']
1494 ro.summary = ri['summary']
1495 ro.description = ri['description']
1496 ro.section = ri['section']
1497 ro.license = ri['license']
1498 ro.homepage = ri['homepage']
1499 ro.bugtracker = ri['bugtracker']
1500 ro.file_path = ri['filepath'] + "/" + ri['filename']
1501 if 'inherits' in ri:
1502 ro.is_image = 'image' in ri['inherits'].split()
1503 else: # workaround for old style layer index
1504 ro.is_image = "-image-" in ri['pn']
1505 ro.save()
1506 except IntegrityError as e:
1507 logger.debug("Failed saving recipe, ignoring: %s (%s:%s)" % (e, ro.layer_version, ri['filepath']+"/"+ri['filename']))
1508 ro.delete()
1509 1232
1510class BitbakeVersion(models.Model): 1233class BitbakeVersion(models.Model):
1511 1234
@@ -1529,87 +1252,98 @@ class Release(models.Model):
1529 def __unicode__(self): 1252 def __unicode__(self):
1530 return "%s (%s)" % (self.name, self.branch_name) 1253 return "%s (%s)" % (self.name, self.branch_name)
1531 1254
1532class ReleaseLayerSourcePriority(models.Model):
1533 """ Each release selects layers from the set up layer sources, ordered by priority """
1534 release = models.ForeignKey("Release")
1535 layer_source = models.ForeignKey("LayerSource")
1536 priority = models.IntegerField(default = 0)
1537
1538 def __unicode__(self):
1539 return "%s-%s:%d" % (self.release.name, self.layer_source.name, self.priority)
1540 class Meta:
1541 unique_together = (('release', 'layer_source'),)
1542
1543
1544class ReleaseDefaultLayer(models.Model): 1255class ReleaseDefaultLayer(models.Model):
1545 release = models.ForeignKey(Release) 1256 release = models.ForeignKey(Release)
1546 layer_name = models.CharField(max_length=100, default="") 1257 layer_name = models.CharField(max_length=100, default="")
1547 1258
1548 1259
1549# Branch class is synced with layerindex.Branch, branches can only come from remote layer indexes 1260# Branch class is synced with layerindex.Branch, branches can only come
1261# from remote layer indexes
1550class Branch(models.Model): 1262class Branch(models.Model):
1551 layer_source = models.ForeignKey('LayerSource', null = True, default = True) 1263 # id of branch in the layerindex
1552 up_id = models.IntegerField(null = True, default = None) # id of branch in the source 1264 up_date = models.DateTimeField(null=True, default=None)
1553 up_date = models.DateTimeField(null = True, default = None)
1554 1265
1555 name = models.CharField(max_length=50) 1266 name = models.CharField(max_length=50)
1556 short_description = models.CharField(max_length=50, blank=True) 1267 short_description = models.CharField(max_length=50, blank=True)
1557 1268
1558 class Meta: 1269 class Meta:
1559 verbose_name_plural = "Branches" 1270 verbose_name_plural = "Branches"
1560 unique_together = (('layer_source', 'name'),('layer_source', 'up_id'))
1561 1271
1562 def __unicode__(self): 1272 def __unicode__(self):
1563 return self.name 1273 return self.name
1564 1274
1565 1275
1566# Layer class synced with layerindex.LayerItem 1276class LayerSource(object):
1277 """ Where the layer metadata came from """
1278 TYPE_LOCAL = 0
1279 TYPE_LAYERINDEX = 1
1280 TYPE_IMPORTED = 2
1281 TYPE_BUILD = 3
1282
1283 SOURCE_TYPE = (
1284 (TYPE_LOCAL, "local"),
1285 (TYPE_LAYERINDEX, "layerindex"),
1286 (TYPE_IMPORTED, "imported"),
1287 (TYPE_BUILD, "build"),
1288 )
1289
1290
1567class Layer(models.Model): 1291class Layer(models.Model):
1568 layer_source = models.ForeignKey(LayerSource, null = True, default = None) # from where did we got this layer 1292
1569 up_id = models.IntegerField(null = True, default = None) # id of layer in the remote source 1293 up_date = models.DateTimeField(null=True, default=timezone.now)
1570 up_date = models.DateTimeField(null = True, default = None)
1571 1294
1572 name = models.CharField(max_length=100) 1295 name = models.CharField(max_length=100)
1573 layer_index_url = models.URLField() 1296 layer_index_url = models.URLField()
1574 vcs_url = GitURLField(default = None, null = True) 1297 vcs_url = GitURLField(default=None, null=True)
1575 vcs_web_url = models.URLField(null = True, default = None) 1298 vcs_web_url = models.URLField(null=True, default=None)
1576 vcs_web_tree_base_url = models.URLField(null = True, default = None) 1299 vcs_web_tree_base_url = models.URLField(null=True, default=None)
1577 vcs_web_file_base_url = models.URLField(null = True, default = None) 1300 vcs_web_file_base_url = models.URLField(null=True, default=None)
1578 1301
1579 summary = models.TextField(help_text='One-line description of the layer', null = True, default = None) 1302 summary = models.TextField(help_text='One-line description of the layer',
1580 description = models.TextField(null = True, default = None) 1303 null=True, default=None)
1304 description = models.TextField(null=True, default=None)
1581 1305
1582 def __unicode__(self): 1306 def __unicode__(self):
1583 return "%s / %s " % (self.name, self.layer_source) 1307 return "%s / %s " % (self.name, self.summary)
1584
1585 class Meta:
1586 unique_together = (("layer_source", "up_id"), ("layer_source", "name"))
1587 1308
1588 1309
1589# LayerCommit class is synced with layerindex.LayerBranch
1590class Layer_Version(models.Model): 1310class Layer_Version(models.Model):
1591 """ 1311 """
1592 A Layer_Version either belongs to a single project or no project 1312 A Layer_Version either belongs to a single project or no project
1593 """ 1313 """
1594 search_allowed_fields = ["layer__name", "layer__summary", "layer__description", "layer__vcs_url", "dirpath", "up_branch__name", "commit", "branch"] 1314 search_allowed_fields = ["layer__name", "layer__summary",
1595 build = models.ForeignKey(Build, related_name='layer_version_build', default = None, null = True) 1315 "layer__description", "layer__vcs_url",
1316 "dirpath", "up_branch__name", "commit", "branch"]
1317
1318 build = models.ForeignKey(Build, related_name='layer_version_build',
1319 default=None, null=True)
1320
1596 layer = models.ForeignKey(Layer, related_name='layer_version_layer') 1321 layer = models.ForeignKey(Layer, related_name='layer_version_layer')
1597 1322
1598 layer_source = models.ForeignKey(LayerSource, null = True, default = None) # from where did we get this Layer Version 1323 layer_source = models.IntegerField(choices=LayerSource.SOURCE_TYPE,
1599 up_id = models.IntegerField(null = True, default = None) # id of layerbranch in the remote source 1324 default=0)
1600 up_date = models.DateTimeField(null = True, default = None) 1325
1601 up_branch = models.ForeignKey(Branch, null = True, default = None) 1326 up_date = models.DateTimeField(null=True, default=timezone.now)
1602 1327
1603 branch = models.CharField(max_length=80) # LayerBranch.actual_branch 1328 # layerindex specific field
1604 commit = models.CharField(max_length=100) # LayerBranch.vcs_last_rev 1329 up_branch = models.ForeignKey(Branch, null=True, default=None)
1605 dirpath = models.CharField(max_length=255, null = True, default = None) # LayerBranch.vcs_subdir
1606 priority = models.IntegerField(default = 0) # if -1, this is a default layer
1607 1330
1608 local_path = models.FilePathField(max_length=1024, default = "/") # where this layer was checked-out 1331 branch = models.CharField(max_length=80)
1332 commit = models.CharField(max_length=100)
1333 # If the layer is in a subdir
1334 dirpath = models.CharField(max_length=255, null=True, default=None)
1609 1335
1610 project = models.ForeignKey('Project', null = True, default = None) # Set if this layer is project-specific; always set for imported layers, and project-set branches 1336 # if -1, this is a default layer
1337 priority = models.IntegerField(default=0)
1611 1338
1612 # code lifted, with adaptations, from the layerindex-web application https://git.yoctoproject.org/cgit/cgit.cgi/layerindex-web/ 1339 # where this layer exists on the filesystem
1340 local_path = models.FilePathField(max_length=1024, default="/")
1341
1342 # Set if this layer is restricted to a particular project
1343 project = models.ForeignKey('Project', null=True, default=None)
1344
1345 # code lifted, with adaptations, from the layerindex-web application
1346 # https://git.yoctoproject.org/cgit/cgit.cgi/layerindex-web/
1613 def _handle_url_path(self, base_url, path): 1347 def _handle_url_path(self, base_url, path):
1614 import re, posixpath 1348 import re, posixpath
1615 if base_url: 1349 if base_url:
@@ -1651,18 +1385,14 @@ class Layer_Version(models.Model):
1651 def get_vcs_file_link_url(self, file_path=""): 1385 def get_vcs_file_link_url(self, file_path=""):
1652 if self.layer.vcs_web_file_base_url is None: 1386 if self.layer.vcs_web_file_base_url is None:
1653 return None 1387 return None
1654 return self._handle_url_path(self.layer.vcs_web_file_base_url, file_path) 1388 return self._handle_url_path(self.layer.vcs_web_file_base_url,
1389 file_path)
1655 1390
1656 def get_vcs_dirpath_link_url(self): 1391 def get_vcs_dirpath_link_url(self):
1657 if self.layer.vcs_web_tree_base_url is None: 1392 if self.layer.vcs_web_tree_base_url is None:
1658 return None 1393 return None
1659 return self._handle_url_path(self.layer.vcs_web_tree_base_url, '') 1394 return self._handle_url_path(self.layer.vcs_web_tree_base_url, '')
1660 1395
1661 def get_equivalents_wpriority(self, project):
1662 layer_versions = project.get_all_compatible_layer_versions()
1663 filtered = layer_versions.filter(layer__name = self.layer.name)
1664 return filtered.order_by("-layer_source__releaselayersourcepriority__priority")
1665
1666 def get_vcs_reference(self): 1396 def get_vcs_reference(self):
1667 if self.branch is not None and len(self.branch) > 0: 1397 if self.branch is not None and len(self.branch) > 0:
1668 return self.branch 1398 return self.branch
@@ -1695,20 +1425,15 @@ class Layer_Version(models.Model):
1695 return sorted(result, key=lambda x: x.layer.name) 1425 return sorted(result, key=lambda x: x.layer.name)
1696 1426
1697 def __unicode__(self): 1427 def __unicode__(self):
1698 return "%d %s (VCS %s, Project %s)" % (self.pk, str(self.layer), self.get_vcs_reference(), self.build.project if self.build is not None else "No project") 1428 return ("id %d belongs to layer: %s" % (self.pk, self.layer.name))
1699 1429
1700 class Meta:
1701 unique_together = ("layer_source", "up_id")
1702 1430
1703class LayerVersionDependency(models.Model): 1431class LayerVersionDependency(models.Model):
1704 layer_source = models.ForeignKey(LayerSource, null = True, default = None) # from where did we got this layer
1705 up_id = models.IntegerField(null = True, default = None) # id of layerbranch in the remote source
1706
1707 layer_version = models.ForeignKey(Layer_Version, related_name="dependencies")
1708 depends_on = models.ForeignKey(Layer_Version, related_name="dependees")
1709 1432
1710 class Meta: 1433 layer_version = models.ForeignKey(Layer_Version,
1711 unique_together = ("layer_source", "up_id") 1434 related_name="dependencies")
1435 depends_on = models.ForeignKey(Layer_Version,
1436 related_name="dependees")
1712 1437
1713class ProjectLayer(models.Model): 1438class ProjectLayer(models.Model):
1714 project = models.ForeignKey(Project) 1439 project = models.ForeignKey(Project)