diff options
7 files changed, 748 insertions, 22 deletions
diff --git a/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py b/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py new file mode 100644 index 0000000000..9e483f5dac --- /dev/null +++ b/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | # -*- coding: utf-8 -*- | ||
| 2 | from south.utils import datetime_utils as datetime | ||
| 3 | from south.db import db | ||
| 4 | from south.v2 import SchemaMigration | ||
| 5 | from django.db import models | ||
| 6 | |||
| 7 | |||
| 8 | class Migration(SchemaMigration): | ||
| 9 | |||
| 10 | def forwards(self, orm): | ||
| 11 | # Adding field 'ProjectLayer.optional' | ||
| 12 | db.add_column(u'orm_projectlayer', 'optional', | ||
| 13 | self.gf('django.db.models.fields.BooleanField')(default=True), | ||
| 14 | keep_default=False) | ||
| 15 | |||
| 16 | # Adding field 'ProjectTarget.task' | ||
| 17 | db.add_column(u'orm_projecttarget', 'task', | ||
| 18 | self.gf('django.db.models.fields.CharField')(max_length=100, null=True), | ||
| 19 | keep_default=False) | ||
| 20 | |||
| 21 | |||
| 22 | def backwards(self, orm): | ||
| 23 | # Deleting field 'ProjectLayer.optional' | ||
| 24 | db.delete_column(u'orm_projectlayer', 'optional') | ||
| 25 | |||
| 26 | # Deleting field 'ProjectTarget.task' | ||
| 27 | db.delete_column(u'orm_projecttarget', 'task') | ||
| 28 | |||
| 29 | |||
| 30 | models = { | ||
| 31 | u'orm.build': { | ||
| 32 | 'Meta': {'object_name': 'Build'}, | ||
| 33 | 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | ||
| 34 | 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 35 | 'completed_on': ('django.db.models.fields.DateTimeField', [], {}), | ||
| 36 | 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}), | ||
| 37 | 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 38 | 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 39 | 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 40 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 41 | 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 42 | 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}), | ||
| 43 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}), | ||
| 44 | 'started_on': ('django.db.models.fields.DateTimeField', [], {}), | ||
| 45 | 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 46 | 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}) | ||
| 47 | }, | ||
| 48 | u'orm.helptext': { | ||
| 49 | 'Meta': {'object_name': 'HelpText'}, | ||
| 50 | 'area': ('django.db.models.fields.IntegerField', [], {}), | ||
| 51 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}), | ||
| 52 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 53 | 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 54 | 'text': ('django.db.models.fields.TextField', [], {}) | ||
| 55 | }, | ||
| 56 | u'orm.layer': { | ||
| 57 | 'Meta': {'object_name': 'Layer'}, | ||
| 58 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 59 | 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}), | ||
| 60 | 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}), | ||
| 61 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
| 62 | }, | ||
| 63 | u'orm.layer_version': { | ||
| 64 | 'Meta': {'object_name': 'Layer_Version'}, | ||
| 65 | 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | ||
| 66 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}), | ||
| 67 | 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 68 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 69 | 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}), | ||
| 70 | 'priority': ('django.db.models.fields.IntegerField', [], {}) | ||
| 71 | }, | ||
| 72 | u'orm.logmessage': { | ||
| 73 | 'Meta': {'object_name': 'LogMessage'}, | ||
| 74 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}), | ||
| 75 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 76 | 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 77 | 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), | ||
| 78 | 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}), | ||
| 79 | 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}), | ||
| 80 | 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'}) | ||
| 81 | }, | ||
| 82 | u'orm.package': { | ||
| 83 | 'Meta': {'object_name': 'Package'}, | ||
| 84 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}), | ||
| 85 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
| 86 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 87 | 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}), | ||
| 88 | 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 89 | 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}), | ||
| 90 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 91 | 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}), | ||
| 92 | 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}), | ||
| 93 | 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}), | ||
| 94 | 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 95 | 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), | ||
| 96 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) | ||
| 97 | }, | ||
| 98 | u'orm.package_dependency': { | ||
| 99 | 'Meta': {'object_name': 'Package_Dependency'}, | ||
| 100 | 'dep_type': ('django.db.models.fields.IntegerField', [], {}), | ||
| 101 | 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}), | ||
| 102 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 103 | 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}), | ||
| 104 | 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'}) | ||
| 105 | }, | ||
| 106 | u'orm.package_file': { | ||
| 107 | 'Meta': {'object_name': 'Package_File'}, | ||
| 108 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 109 | 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}), | ||
| 110 | 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}), | ||
| 111 | 'size': ('django.db.models.fields.IntegerField', [], {}) | ||
| 112 | }, | ||
| 113 | u'orm.project': { | ||
| 114 | 'Meta': {'object_name': 'Project'}, | ||
| 115 | 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}), | ||
| 116 | 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
| 117 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 118 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 119 | 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), | ||
| 120 | 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), | ||
| 121 | 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}) | ||
| 122 | }, | ||
| 123 | u'orm.projectlayer': { | ||
| 124 | 'Meta': {'object_name': 'ProjectLayer'}, | ||
| 125 | 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}), | ||
| 126 | 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}), | ||
| 127 | 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}), | ||
| 128 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 129 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 130 | 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
| 131 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}) | ||
| 132 | }, | ||
| 133 | u'orm.projecttarget': { | ||
| 134 | 'Meta': {'object_name': 'ProjectTarget'}, | ||
| 135 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 136 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}), | ||
| 137 | 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 138 | 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}) | ||
| 139 | }, | ||
| 140 | u'orm.projectvariable': { | ||
| 141 | 'Meta': {'object_name': 'ProjectVariable'}, | ||
| 142 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 143 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 144 | 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}), | ||
| 145 | 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
| 146 | }, | ||
| 147 | u'orm.recipe': { | ||
| 148 | 'Meta': {'object_name': 'Recipe'}, | ||
| 149 | 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), | ||
| 150 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
| 151 | 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}), | ||
| 152 | 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}), | ||
| 153 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 154 | 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}), | ||
| 155 | 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), | ||
| 156 | 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), | ||
| 157 | 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), | ||
| 158 | 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), | ||
| 159 | 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}) | ||
| 160 | }, | ||
| 161 | u'orm.recipe_dependency': { | ||
| 162 | 'Meta': {'object_name': 'Recipe_Dependency'}, | ||
| 163 | 'dep_type': ('django.db.models.fields.IntegerField', [], {}), | ||
| 164 | 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}), | ||
| 165 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 166 | 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"}) | ||
| 167 | }, | ||
| 168 | u'orm.target': { | ||
| 169 | 'Meta': {'object_name': 'Target'}, | ||
| 170 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}), | ||
| 171 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 172 | 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 173 | 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
| 174 | 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}), | ||
| 175 | 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
| 176 | }, | ||
| 177 | u'orm.target_file': { | ||
| 178 | 'Meta': {'object_name': 'Target_File'}, | ||
| 179 | 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}), | ||
| 180 | 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
| 181 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 182 | 'inodetype': ('django.db.models.fields.IntegerField', [], {}), | ||
| 183 | 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
| 184 | 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}), | ||
| 185 | 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}), | ||
| 186 | 'size': ('django.db.models.fields.IntegerField', [], {}), | ||
| 187 | 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}), | ||
| 188 | 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"}) | ||
| 189 | }, | ||
| 190 | u'orm.target_image_file': { | ||
| 191 | 'Meta': {'object_name': 'Target_Image_File'}, | ||
| 192 | 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}), | ||
| 193 | 'file_size': ('django.db.models.fields.IntegerField', [], {}), | ||
| 194 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 195 | 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"}) | ||
| 196 | }, | ||
| 197 | u'orm.target_installed_package': { | ||
| 198 | 'Meta': {'object_name': 'Target_Installed_Package'}, | ||
| 199 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 200 | 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}), | ||
| 201 | 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"}) | ||
| 202 | }, | ||
| 203 | u'orm.task': { | ||
| 204 | 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'}, | ||
| 205 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}), | ||
| 206 | 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}), | ||
| 207 | 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), | ||
| 208 | 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}), | ||
| 209 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 210 | 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 211 | 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}), | ||
| 212 | 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}), | ||
| 213 | 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), | ||
| 214 | 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), | ||
| 215 | 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}), | ||
| 216 | 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}), | ||
| 217 | 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 218 | 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}), | ||
| 219 | 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), | ||
| 220 | 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
| 221 | 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
| 222 | 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 223 | 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}) | ||
| 224 | }, | ||
| 225 | u'orm.task_dependency': { | ||
| 226 | 'Meta': {'object_name': 'Task_Dependency'}, | ||
| 227 | 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}), | ||
| 228 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 229 | 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"}) | ||
| 230 | }, | ||
| 231 | u'orm.variable': { | ||
| 232 | 'Meta': {'object_name': 'Variable'}, | ||
| 233 | 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}), | ||
| 234 | 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
| 235 | 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
| 236 | 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), | ||
| 237 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 238 | 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
| 239 | 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'}) | ||
| 240 | }, | ||
| 241 | u'orm.variablehistory': { | ||
| 242 | 'Meta': {'object_name': 'VariableHistory'}, | ||
| 243 | 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}), | ||
| 244 | u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
| 245 | 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), | ||
| 246 | 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}), | ||
| 247 | 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}), | ||
| 248 | 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"}) | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | complete_apps = ['orm'] \ No newline at end of file | ||
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py index 9b7387a8af..f19a4370c8 100644 --- a/bitbake/lib/toaster/orm/models.py +++ b/bitbake/lib/toaster/orm/models.py | |||
| @@ -37,13 +37,15 @@ class ProjectManager(models.Manager): | |||
| 37 | name = "meta", | 37 | name = "meta", |
| 38 | giturl = "git://git.yoctoproject.org/poky", | 38 | giturl = "git://git.yoctoproject.org/poky", |
| 39 | commit = branch, | 39 | commit = branch, |
| 40 | dirpath = "meta") | 40 | dirpath = "meta", |
| 41 | optional = False) | ||
| 41 | 42 | ||
| 42 | ProjectLayer.objects.create(project = prj, | 43 | ProjectLayer.objects.create(project = prj, |
| 43 | name = "meta-yocto", | 44 | name = "meta-yocto", |
| 44 | giturl = "git://git.yoctoproject.org/poky", | 45 | giturl = "git://git.yoctoproject.org/poky", |
| 45 | commit = branch, | 46 | commit = branch, |
| 46 | dirpath = "meta-yocto") | 47 | dirpath = "meta-yocto", |
| 48 | optional = False) | ||
| 47 | 49 | ||
| 48 | return prj | 50 | return prj |
| 49 | 51 | ||
| @@ -116,6 +118,7 @@ class Build(models.Model): | |||
| 116 | class ProjectTarget(models.Model): | 118 | class ProjectTarget(models.Model): |
| 117 | project = models.ForeignKey(Project) | 119 | project = models.ForeignKey(Project) |
| 118 | target = models.CharField(max_length=100) | 120 | target = models.CharField(max_length=100) |
| 121 | task = models.CharField(max_length=100, null=True) | ||
| 119 | 122 | ||
| 120 | @python_2_unicode_compatible | 123 | @python_2_unicode_compatible |
| 121 | class Target(models.Model): | 124 | class Target(models.Model): |
| @@ -392,6 +395,7 @@ class ProjectLayer(models.Model): | |||
| 392 | giturl = models.CharField(max_length = 254) | 395 | giturl = models.CharField(max_length = 254) |
| 393 | commit = models.CharField(max_length = 254) | 396 | commit = models.CharField(max_length = 254) |
| 394 | dirpath = models.CharField(max_length = 254) | 397 | dirpath = models.CharField(max_length = 254) |
| 398 | optional = models.BooleanField(default = True) | ||
| 395 | 399 | ||
| 396 | class Layer(models.Model): | 400 | class Layer(models.Model): |
| 397 | name = models.CharField(max_length=100) | 401 | name = models.CharField(max_length=100) |
diff --git a/bitbake/lib/toaster/toastergui/static/css/default.css b/bitbake/lib/toaster/toastergui/static/css/default.css index 2c283feccf..778d8b8456 100644 --- a/bitbake/lib/toaster/toastergui/static/css/default.css +++ b/bitbake/lib/toaster/toastergui/static/css/default.css | |||
| @@ -116,17 +116,31 @@ select { width: auto; } | |||
| 116 | /* make tables Chrome-happy (me, not so much) */ | 116 | /* make tables Chrome-happy (me, not so much) */ |
| 117 | #otable { table-layout: fixed; word-wrap: break-word; } | 117 | #otable { table-layout: fixed; word-wrap: break-word; } |
| 118 | 118 | ||
| 119 | 119 | /* Configuration styles */ | |
| 120 | 120 | .icon-trash { color: #B94A48; font-size: 16px; padding-left: 2px; } | |
| 121 | 121 | .icon-trash:hover { color: #943A38; text-decoration: none; cursor: pointer; } | |
| 122 | 122 | .icon-pencil, .icon-download-alt { font-size: 16px; color: #0088CC; padding-left: 2px; } | |
| 123 | 123 | .icon-pencil:hover, .icon-download-alt:hover { color: #005580; text-decoration: none; cursor: pointer; } | |
| 124 | 124 | .configuration-list li { line-height: 35px; font-size: 21px; font-weight: 200; } | |
| 125 | 125 | .configuration-list { font-size: 16px; margin-bottom: 1.5em; } | |
| 126 | 126 | .configuration-list i { font-size: 16px; } | |
| 127 | 127 | /*.configuration-layers { height: 135px; overflow: scroll; }*/ | |
| 128 | 128 | .counter { font-weight: normal; } | |
| 129 | 129 | .well-alert { background-color: #FCF8E3; border: 1px solid #FBEED5; border-radius: 4px; } | |
| 130 | 130 | .well-alert > .lead { color: #C09853; padding-bottom: .75em; } | |
| 131 | 131 | .configuration-alert { margin-bottom: 0px; padding: 8px 14px; } | |
| 132 | 132 | .configuration-alert p { margin-bottom: 0px; } | |
| 133 | fieldset { padding-left: 19px; } | ||
| 134 | .project-form { margin-top: 10px; } | ||
| 135 | .add-layers .btn-block + .btn-block { margin-top: 0px; } | ||
| 136 | input.huge { font-size: 17.5px; padding: 11px 19px; } | ||
| 137 | .build-form { margin-bottom: 0px; padding-left: 20px; } | ||
| 138 | a code { color: #0088CC; } | ||
| 139 | a code:hover { color: #005580; } | ||
| 140 | .localconf { font-size: 17.5px; margin-top: 40px; } | ||
| 141 | .localconf code { font-size: 17.5px; } | ||
| 142 | #add-layer-dependencies { margin-top: 5px; } | ||
| 143 | .artifact { width: 9em; } | ||
| 144 | .control-group { margin-bottom: 0px; } | ||
| 145 | #project-details form { margin: 0px; } | ||
| 146 | dd form { margin: 10px 0 0 0; } | ||
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html index 1407d641d5..9ef249aab3 100644 --- a/bitbake/lib/toaster/toastergui/templates/base.html +++ b/bitbake/lib/toaster/toastergui/templates/base.html | |||
| @@ -65,6 +65,10 @@ function reload_params(params) { | |||
| 65 | <i class="icon-caret-down"></i> | 65 | <i class="icon-caret-down"></i> |
| 66 | </button> | 66 | </button> |
| 67 | <ul class="dropdown-menu"> | 67 | <ul class="dropdown-menu"> |
| 68 | {% for prj in projects %} | ||
| 69 | <li><a href="{% url 'project' prj.id %}">{{prj.name}}</a></li> | ||
| 70 | {% endfor %} | ||
| 71 | <li><hr/></li> | ||
| 68 | <li><a href="#">Clone project</a></li> | 72 | <li><a href="#">Clone project</a></li> |
| 69 | <li><a href="#">Export project</a></li> | 73 | <li><a href="#">Export project</a></li> |
| 70 | <li><a href="#">Import project</a></li> | 74 | <li><a href="#">Import project</a></li> |
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html index 71adb54431..c859f6bcd1 100644 --- a/bitbake/lib/toaster/toastergui/templates/project.html +++ b/bitbake/lib/toaster/toastergui/templates/project.html | |||
| @@ -3,4 +3,360 @@ | |||
| 3 | {% load humanize %} | 3 | {% load humanize %} |
| 4 | {% block pagecontent %} | 4 | {% block pagecontent %} |
| 5 | 5 | ||
| 6 | <script> | ||
| 7 | |||
| 8 | var buildrequests = []; | ||
| 9 | |||
| 10 | function targetInPage(targetname) { | ||
| 11 | return targetname in $("ul#target-list > li > a").map(function (i, x) {return x.text}); | ||
| 12 | } | ||
| 13 | |||
| 14 | function setEventHandlers() { | ||
| 15 | $("i#del-target-icon").unbind().click(function (evt) { | ||
| 16 | console.log("del target", evt.target.attributes["x-data"].value); | ||
| 17 | postEditAjaxRequest({"targetDel": evt.target.attributes["x-data"].value}); | ||
| 18 | }); | ||
| 19 | $("button#add-target-button").unbind().click( function (evt) { | ||
| 20 | if ( $("input#target")[0].value.length == 0) { | ||
| 21 | alert("cannot add empty target"); | ||
| 22 | return; | ||
| 23 | } | ||
| 24 | postEditAjaxRequest({"targetAdd" : $("input#target")[0].value}); | ||
| 25 | }); | ||
| 26 | } | ||
| 27 | |||
| 28 | function onEditPageUpdate(data) { | ||
| 29 | // update targets | ||
| 30 | var i; var orightml = ""; | ||
| 31 | |||
| 32 | $("span#target-count").html(data.targets.length); | ||
| 33 | for (i = 0; i < data.targets.length; i++) { | ||
| 34 | if (! targetInPage(data.targets[i].target)) { | ||
| 35 | orightml += '<li><a href="#">'+data.targets[i].target; | ||
| 36 | if (data.targets[i].task != "" && data.targets[i].task !== null) { | ||
| 37 | orightml += " ("+data.targets[i].task+")"; | ||
| 38 | } | ||
| 39 | orightml += '</a><i title="" data-original-title="" class="icon-trash" id="del-target-icon" x-data="'+data.targets[i].pk+'"></i></li>'; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | $("ul#target-list").html(orightml); | ||
| 44 | |||
| 45 | // update recent builds | ||
| 46 | |||
| 47 | setEventHandlers(); | ||
| 48 | } | ||
| 49 | |||
| 50 | function onEditAjaxSuccess(data, textstatus) { | ||
| 51 | console.log("XHR returned:", data, "(" + textstatus + ")"); | ||
| 52 | if (data.error != "ok") { | ||
| 53 | alert("error on request:\n" + data.error); | ||
| 54 | return; | ||
| 55 | } | ||
| 56 | onEditPageUpdate(data); | ||
| 57 | } | ||
| 58 | |||
| 59 | function onEditAjaxError(jqXHR, textstatus, error) { | ||
| 60 | alert("XHR errored:\n" + error + "\n(" + textstatus + ")"); | ||
| 61 | } | ||
| 62 | |||
| 63 | function postEditAjaxRequest(reqdata) { | ||
| 64 | var ajax = $.ajax({ | ||
| 65 | type:"POST", | ||
| 66 | data: $.param(reqdata), | ||
| 67 | url:"{% url 'xhr_projectedit' project.id%}", | ||
| 68 | headers: { 'X-CSRFToken': $.cookie("csrftoken")}, | ||
| 69 | success: onEditAjaxSuccess, | ||
| 70 | error: onEditAjaxError, | ||
| 71 | }) | ||
| 72 | } | ||
| 73 | |||
| 74 | $(document).ready(function () { | ||
| 75 | setEventHandlers(); | ||
| 76 | }); | ||
| 77 | |||
| 78 | </script> | ||
| 79 | |||
| 80 | |||
| 81 | <div class="page-header"> | ||
| 82 | <h1> | ||
| 83 | {{project.name}} | ||
| 84 | {% if project.build_set.all.count == 0 %} | ||
| 85 | <small>No builds yet</small> | ||
| 86 | {% else %} | ||
| 87 | <small><a href="#">{{project.build_set.all.count}} builds</a></small> | ||
| 88 | {% endif %} | ||
| 89 | </h1> | ||
| 90 | </div> | ||
| 91 | |||
| 92 | |||
| 93 | <div class="well"> | ||
| 94 | <!--div class="control-group error"--> | ||
| 95 | <button id="build-all-button" class="btn btn-primary btn-large">Build all added targets</button> | ||
| 96 | <div class="input-append build-form controls"> | ||
| 97 | <input class="huge input-xxlarge" placeholder="Or enter the target you want to build" autocomplete="off" data-minlength="1" data-autocomplete="off" data-provide="typeahead" data-source="" type="text"> | ||
| 98 | <button id="build-button" class="btn btn-large" disabled="">Build</button> | ||
| 99 | </div> | ||
| 100 | <script> | ||
| 101 | /* Provide XHR calls for the "build" buttons.*/ | ||
| 102 | $("button#build-all-button").click( function (evt) { | ||
| 103 | var ajax = $.ajax({ | ||
| 104 | type:"POST", | ||
| 105 | url:"{% url 'xhr_projectbuild' project.id %}", | ||
| 106 | headers: { 'X-CSRFToken': $.cookie("csrftoken")}, | ||
| 107 | success: function (data, textstatus) { | ||
| 108 | if (data.error != "ok") { | ||
| 109 | alert("XHR fail: " + data.error ); | ||
| 110 | } | ||
| 111 | }, | ||
| 112 | error: function (jqXHR, textstatus, error) { alert("XHR errored:" + error + "(" + textstatus + ")"); }, | ||
| 113 | }) | ||
| 114 | }); | ||
| 115 | |||
| 116 | </script> | ||
| 117 | <!--span class="help-inline">This target is not provided <br />by any of your added layers | ||
| 118 | <i class="icon-question-sign get-help get-help-red" title="Review your list of added layers to make sure one of them provides core-image-xyz. Clicking on a layer name will give you all the information Toaster has about the layer"></i> | ||
| 119 | </span> | ||
| 120 | </div--> | ||
| 121 | </div> | ||
| 122 | |||
| 123 | <div id="meta-tizen-alert" class="alert alert-info lead air" style="display:none;"> | ||
| 124 | <button type="button" class="close" data-dismiss="alert">?</button> | ||
| 125 | You have added <strong>6</strong> layers: <a href="#">meta-tizen</a> and its dependencies (<a href="#">meta-efl</a>, <a href="#">meta-intel</a>, <a href="#">meta-multimedia</a>, <a href="#">meta-oe</a> and <a href="#">meta-ruby</a>). | ||
| 126 | </div> | ||
| 127 | |||
| 128 | |||
| 129 | |||
| 130 | |||
| 131 | |||
| 132 | {% if builds|length > 0 or buildrequests|length > 0 %} | ||
| 133 | <h2 class="air">Recent Builds</h2> | ||
| 134 | |||
| 135 | <div id="scheduled-builds"> | ||
| 136 | {% for br in buildrequests %} | ||
| 137 | <div class="alert {% if br.0.state == br.0.REQ_FAILED%}alert-error{%else%}alert-info{%endif%}" id="build-request"> | ||
| 138 | <div class="row-fluid"> | ||
| 139 | <div class="lead span4"> | ||
| 140 | <span> | ||
| 141 | {{br.0.brtarget_set.all.0.target}} {%if br.brtarget_set.all.count > 1%}(+ {{br.brtarget_set.all.count|add:"-1"}}){%endif%} {{br.1.machine.value}} (Created {{br.0.created}}) | ||
| 142 | </span> | ||
| 143 | </div> | ||
| 144 | <div class="span2"> | ||
| 145 | {{br.0.get_state_display}} | ||
| 146 | </div> | ||
| 147 | <div class="span8"> | ||
| 148 | {% if br.state == br.REQ_FAILED%} | ||
| 149 | {% for bre in br.0.brerror_set.all %} {{bre.errmsg}} ({{bre.errtype}}) <br/><hr/><code>{{bre.traceback}}</code>{%endfor%} | ||
| 150 | {%endif%} | ||
| 151 | </div> | ||
| 152 | |||
| 153 | </div> | ||
| 154 | </div> | ||
| 155 | |||
| 156 | {% endfor %} | ||
| 157 | |||
| 158 | </div> | ||
| 159 | |||
| 160 | |||
| 161 | |||
| 162 | <!-- Lifted from build.html --> | ||
| 163 | {% for build in builds %} | ||
| 164 | <div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-error{%else%}alert-info{%endif%}"> | ||
| 165 | <div class="row-fluid"> | ||
| 166 | <div class="lead span5"> | ||
| 167 | {%if build.outcome == build.SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif build.outcome == build.FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%} | ||
| 168 | {%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %} | ||
| 169 | <a href="{%url 'builddashboard' build.pk%}" class="{%if build.outcome == build.SUCCEEDED %}success{%else%}error{%endif%}"> | ||
| 170 | {% endif %} | ||
| 171 | <span data-toggle="tooltip" {%if build.target_set.all.count > 1%}title="Targets: {%for target in build.target_set.all%}{{target.target}} {%endfor%}"{%endif%}>{{build.target_set.all.0.target}} {%if build.target_set.all.count > 1%}(+ {{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|naturaltime}})</span> | ||
| 172 | {%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %} | ||
| 173 | </a> | ||
| 174 | {% endif %} | ||
| 175 | </div> | ||
| 176 | {%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %} | ||
| 177 | <div class="span2 lead"> | ||
| 178 | {% if build.errors_no %} | ||
| 179 | <i class="icon-minus-sign red"></i> <a href="{%url 'builddashboard' build.pk%}#errors" class="error">{{build.errors_no}} error{{build.errors_no|pluralize}}</a> | ||
| 180 | {% endif %} | ||
| 181 | </div> | ||
| 182 | <div class="span2 lead"> | ||
| 183 | {% if build.warnings_no %} | ||
| 184 | <i class="icon-warning-sign yellow"></i> <a href="{%url 'builddashboard' build.pk%}#warnings" class="warning">{{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a> | ||
| 185 | {% endif %} | ||
| 186 | </div > | ||
| 187 | <div class="lead pull-right"> | ||
| 188 | Build time: <a href="{% url 'buildtime' build.pk %}">{{ build.timespent|sectohms }}</a> | ||
| 189 | </div> | ||
| 190 | {%endif%}{%if build.outcome == build.IN_PROGRESS %} | ||
| 191 | <div class="span4"> | ||
| 192 | <div class="progress" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete"> | ||
| 193 | <div style="width: {{build.completeper}}%;" class="bar"></div> | ||
| 194 | </div> | ||
| 195 | </div> | ||
| 196 | <div class="lead pull-right">ETA: in {{build.eta|naturaltime}}</div> | ||
| 197 | {%endif%} | ||
| 198 | </div> | ||
| 199 | </div> | ||
| 200 | {% endfor %} | ||
| 201 | <!-- end of lift--> | ||
| 202 | {%endif%} | ||
| 203 | |||
| 204 | <h2 class="air">Project configuration</h2> | ||
| 205 | |||
| 206 | <div class="row-fluid"> | ||
| 207 | |||
| 208 | <div id="layer-container" class="well well-transparent span4"> | ||
| 209 | <h3> | ||
| 210 | Add layers | ||
| 211 | <i data-original-title="OpenEmbedded organises metadata into modules called 'layers'. Layers allow you to isolate different types of customizations from each other. <a href='http://www.yoctoproject.org/docs/1.6.1/dev-manual/dev-manual.html#understanding-and-creating-layers' target='_blank'>More on layers</a>" class="icon-question-sign get-help heading-help" title=""></i> | ||
| 212 | </h3> | ||
| 213 | <form style="margin-top:20px;"> | ||
| 214 | <div class="input-append"> | ||
| 215 | <input class="input-xlarge" id="layer" autocomplete="off" placeholder="Type a layer name" data-provide="typeahead" data-source="" data-minlength="1" data-autocomplete="off" type="text"> | ||
| 216 | <button id="add-layer" class="btn" disabled="">Add</button> | ||
| 217 | </div> | ||
| 218 | <div id="import-alert" class="alert alert-info" style="display:none;"> | ||
| 219 | Toaster does not know about this layer. Please <a href="#">import it</a> | ||
| 220 | </div> | ||
| 221 | <div id="dependency-alert" class="alert alert-info" style="display:none;"> | ||
| 222 | <p><strong>meta-tizen</strong> depends on the layers below. Check the ones you want to add: </p> | ||
| 223 | <ul class="unstyled"> | ||
| 224 | <li> | ||
| 225 | <label class="checkbox"> | ||
| 226 | <input checked="checked" type="checkbox"> | ||
| 227 | meta-efl | ||
| 228 | </label> | ||
| 229 | </li> | ||
| 230 | <li> | ||
| 231 | <label class="checkbox"> | ||
| 232 | <input checked="checked" type="checkbox"> | ||
| 233 | meta-intel | ||
| 234 | </label> | ||
| 235 | </li> | ||
| 236 | <li> | ||
| 237 | <label class="checkbox"> | ||
| 238 | <input checked="checked" type="checkbox"> | ||
| 239 | meta-multimedia | ||
| 240 | </label> | ||
| 241 | </li> | ||
| 242 | <li> | ||
| 243 | <label class="checkbox"> | ||
| 244 | <input checked="checked" type="checkbox"> | ||
| 245 | meta-oe | ||
| 246 | </label> | ||
| 247 | </li> | ||
| 248 | <li> | ||
| 249 | <label class="checkbox"> | ||
| 250 | <input checked="checked" type="checkbox"> | ||
| 251 | meta-ruby | ||
| 252 | </label> | ||
| 253 | </li> | ||
| 254 | </ul> | ||
| 255 | <button id="add-layer-dependencies" class="btn btn-info add-layer">Add layers</button> | ||
| 256 | </div> | ||
| 257 | |||
| 258 | <p><a href="#">Import your layer</a> | <a href="#">View all layers</a></p> | ||
| 259 | </form> | ||
| 260 | |||
| 261 | <h4 class="air"> | ||
| 262 | Added layers | ||
| 263 | <span class="muted counter">{{project.projectlayer_set.count}}</span> | ||
| 264 | <i data-original-title="Your added layers will be listed in this same order in your <code>bblayers.conf</code> file" class="icon-question-sign get-help heading-help" title=""></i> | ||
| 265 | </h4> | ||
| 266 | <ul class="unstyled configuration-list"> | ||
| 267 | {% for pl in project.projectlayer_set.all %} | ||
| 268 | <li> | ||
| 269 | <a href="#">{{pl.name}} (<span class="layer-version">{{pl.giturl}}</span>)</a> | ||
| 270 | {% if pl.optional %} | ||
| 271 | <i title="" data-original-title="" class="icon-trash" id="del-layer-icon" x-data="{{pl.pk}}"></i> | ||
| 272 | {% endif %} | ||
| 273 | </li> | ||
| 274 | {% endfor %} | ||
| 275 | </ul> | ||
| 276 | </div> | ||
| 277 | |||
| 278 | <div id="target-container" class="well well-transparent span4"> | ||
| 279 | <h3> | ||
| 280 | Add targets | ||
| 281 | <i data-original-title="A target is what you want to build, usually an image recipe that produces a root file system" class="icon-question-sign get-help heading-help" title=""></i> | ||
| 282 | </h3> | ||
| 283 | <form style="margin-top:20px;"> | ||
| 284 | <div class="input-append"> | ||
| 285 | <input id="target" class="input-xlarge" autocomplete="off" placeholder="Type a target name" data-provide="typeahead" data-source="" data-minlength="1" data-autocomplete="off" type="text"> | ||
| 286 | <button id="add-target-button" class="btn" type="button">Add</button> | ||
| 287 | </div> | ||
| 288 | |||
| 289 | <p><a href="#" class="link">View all targets</a></p> | ||
| 290 | </form> | ||
| 291 | <h4 class="air"> | ||
| 292 | Added targets | ||
| 293 | <span id="target-count" class="muted counter">{{project.projecttarget_set.count}}</span> | ||
| 294 | </h4> | ||
| 295 | <ul class="unstyled configuration-list" id="target-list"> | ||
| 296 | {% for target in project.projecttarget_set.all %} | ||
| 297 | {% if target %} | ||
| 298 | <li> | ||
| 299 | <a href="#">{{target.target}}{% if target.task%} (target.task){%endif%}</a> | ||
| 300 | {% if target.notprovided %} | ||
| 301 | <i title="" data-original-title="" id="msg1" class="icon-exclamation-sign get-help-yellow" data-title="<strong>Target may not be provided</strong>" data-content="From the layer information it currently has, Toaster thinks this target is not provided by any of your added layers. If a target is not provided by one of your added layers, the build will fail.<h5>What Toaster suggests</h5><p>The <a href='#'>meta-abc</a> and <a href='#'>meta-efg</a> layers provide core-image-notprovided. You could add one of them to your project.</p><button class='btn btn-block'>Add meta-abc</button><button class='btn btn-block'>Add meta-efg</button><button id='dismiss1' class='btn btn-block btn-info'>Stop showing this message</button>"></i> | ||
| 302 | {% elif target.notknown %} | ||
| 303 | <i title="" data-original-title="" id="msg2" class="icon-exclamation-sign get-help-yellow" data-title="<strong>Target may not be provided</strong>" data-content="From the layer information it currently has, Toaster thinks this target is not provided by any of your added layers. If a target is not provided by one of your added layers, the build will fail.<h5>What Toaster suggests</h5><p>Review your added layers to make sure one of them provides core-image-unknown. Clicking on a layer name will give you all the information Toaster has about the layer. </p> <button class='btn btn-block btn-info'>Stop showing this message</button>"></i> | ||
| 304 | {% endif %} | ||
| 305 | <i title="" data-original-title="" class="icon-trash" id="del-target-icon" x-data="{{target.pk}}"></i> | ||
| 306 | </li> | ||
| 307 | {% endif %} | ||
| 308 | {% endfor %} | ||
| 309 | |||
| 310 | |||
| 311 | </ul> | ||
| 312 | </div> | ||
| 313 | |||
| 314 | <div class="well well-transparent span4"> | ||
| 315 | <h3> | ||
| 316 | Set machine | ||
| 317 | <i data-original-title="The machine is the hardware for which you want to build. You can only set one machine per project" class="icon-question-sign get-help heading-help" title=""></i> | ||
| 318 | </h3> | ||
| 319 | <p class="lead"> | ||
| 320 | {{machine}} | ||
| 321 | <i title="" data-original-title="" class="icon-pencil"></i> | ||
| 322 | </p> | ||
| 323 | <h3> | ||
| 324 | Set distro | ||
| 325 | <i data-original-title="When you build an image using the Yocto Project and do not alter the distro, you are creating a Poky distribution" class="icon-question-sign get-help heading-help" title=""></i> | ||
| 326 | </h3> | ||
| 327 | <p class="lead"> | ||
| 328 | {{distro}} | ||
| 329 | <i title="" data-original-title="" class="icon-pencil"></i> | ||
| 330 | </p> | ||
| 331 | <p class="localconf"> | ||
| 332 | <a href="#" class="link">Edit the <code>local.conf</code> file</a> | ||
| 333 | <i data-original-title="The <code>local.conf</code> file is where other project configuration options are set. Pretty much any configuration option can be set in this file. Each option, like everything else in the build system, is a variable - value pair" class="icon-question-sign get-help heading-help" title=""></i> | ||
| 334 | </p> | ||
| 335 | </div> | ||
| 336 | </div> | ||
| 337 | |||
| 338 | <h2>Project details</h2> | ||
| 339 | |||
| 340 | <div class="well well-transparent"> | ||
| 341 | <h3>Project name</h3> | ||
| 342 | <p class="lead"> | ||
| 343 | {{project.name}} | ||
| 344 | <i title="" data-original-title="" class="icon-pencil"></i> | ||
| 345 | </p> | ||
| 346 | <h3>Project owner</h3> | ||
| 347 | <p class="lead"> | ||
| 348 | {{puser.username}} | ||
| 349 | <i title="" data-original-title="" class="icon-pencil"></i> | ||
| 350 | </p> | ||
| 351 | <h3>Owner's email</h3> | ||
| 352 | <p class="lead"> | ||
| 353 | {{puser.email}} | ||
| 354 | <i title="" data-original-title="" class="icon-pencil"></i> | ||
| 355 | </p> | ||
| 356 | <h3>Yocto Project version</h3> | ||
| 357 | <p class="lead"> | ||
| 358 | {{project.branch}} - {{project.short_description}} | ||
| 359 | <i title="" data-original-title="" class="icon-pencil"></i> | ||
| 360 | </p> | ||
| 361 | </div> | ||
| 6 | {% endblock %} | 362 | {% endblock %} |
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 0d7a4c35fa..7c4f894b9c 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
| @@ -69,6 +69,9 @@ urlpatterns = patterns('toastergui.views', | |||
| 69 | # project URLs | 69 | # project URLs |
| 70 | url(r'^newproject/$', 'newproject', name='newproject'), | 70 | url(r'^newproject/$', 'newproject', name='newproject'), |
| 71 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), | 71 | url(r'^project/(?P<pid>\d+)/$', 'project', name='project'), |
| 72 | url(r'^xhr_projectbuild/(?P<pid>\d+)/$', 'xhr_projectbuild', name='xhr_projectbuild'), | ||
| 73 | url(r'^xhr_projectedit/(?P<pid>\d+)/$', 'xhr_projectedit', name='xhr_projectedit'), | ||
| 74 | |||
| 72 | 75 | ||
| 73 | # default redirection | 76 | # default redirection |
| 74 | url(r'^$', RedirectView.as_view( url= 'builds/')), | 77 | url(r'^$', RedirectView.as_view( url= 'builds/')), |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index f9e8e51688..bd65c08b06 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -30,7 +30,7 @@ from orm.models import Target_Installed_Package, Target_File, Target_Image_File | |||
| 30 | from django.views.decorators.cache import cache_control | 30 | from django.views.decorators.cache import cache_control |
| 31 | from django.core.urlresolvers import reverse | 31 | from django.core.urlresolvers import reverse |
| 32 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | 32 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
| 33 | from django.http import HttpResponseBadRequest | 33 | from django.http import HttpResponseBadRequest, HttpResponseNotFound |
| 34 | from django.utils import timezone | 34 | from django.utils import timezone |
| 35 | from datetime import timedelta | 35 | from datetime import timedelta |
| 36 | from django.utils import formats | 36 | from django.utils import formats |
| @@ -1761,8 +1761,6 @@ def image_information_dir(request, build_id, target_id, packagefile_id): | |||
| 1761 | 1761 | ||
| 1762 | 1762 | ||
| 1763 | import toastermain.settings | 1763 | import toastermain.settings |
| 1764 | def managedcontextprocessor(request): | ||
| 1765 | return { "MANAGED" : toastermain.settings.MANAGED } | ||
| 1766 | 1764 | ||
| 1767 | 1765 | ||
| 1768 | # we have a set of functions if we're in managed mode, or | 1766 | # we have a set of functions if we're in managed mode, or |
| @@ -1773,7 +1771,8 @@ if toastermain.settings.MANAGED: | |||
| 1773 | from django.contrib.auth import authenticate, login | 1771 | from django.contrib.auth import authenticate, login |
| 1774 | from django.contrib.auth.decorators import login_required | 1772 | from django.contrib.auth.decorators import login_required |
| 1775 | 1773 | ||
| 1776 | from orm.models import Project | 1774 | from orm.models import Project, ProjectLayer, ProjectTarget, ProjectVariable |
| 1775 | from bldcontrol.models import BuildRequest | ||
| 1777 | 1776 | ||
| 1778 | import traceback | 1777 | import traceback |
| 1779 | 1778 | ||
| @@ -1831,19 +1830,113 @@ if toastermain.settings.MANAGED: | |||
| 1831 | else: | 1830 | else: |
| 1832 | context['alert'] = str(e) | 1831 | context['alert'] = str(e) |
| 1833 | return render(request, template, context) | 1832 | return render(request, template, context) |
| 1833 | |||
| 1834 | raise Exception("Invalid HTTP method for this page") | 1834 | raise Exception("Invalid HTTP method for this page") |
| 1835 | 1835 | ||
| 1836 | # Shows the edit project page | 1836 | # Shows the edit project page |
| 1837 | def project(request, pid): | 1837 | def project(request, pid): |
| 1838 | template = "project.html" | 1838 | template = "project.html" |
| 1839 | context = {} | 1839 | try: |
| 1840 | prj = Project.objects.get(id = pid) | ||
| 1841 | except Project.DoesNotExist: | ||
| 1842 | return HttpResponseNotFound("<h1>Project id " + pid + " is unavailable</h1>") | ||
| 1843 | |||
| 1844 | try: | ||
| 1845 | puser = User.objects.get(id = prj.user_id) | ||
| 1846 | except User.DoesNotExist: | ||
| 1847 | puser = None | ||
| 1848 | |||
| 1849 | context = { | ||
| 1850 | "project" : prj, | ||
| 1851 | #"buildrequests" : prj.buildrequest_set.filter(state=BuildRequest.REQ_QUEUED), | ||
| 1852 | "buildrequests" : map(lambda x: (x, {"machine" : x.brvariable_set.filter(name="MACHINE")[0]}), prj.buildrequest_set.order_by("-pk")), | ||
| 1853 | "builds" : prj.build_set.all(), | ||
| 1854 | "puser": puser, | ||
| 1855 | } | ||
| 1856 | try: | ||
| 1857 | context["machine"] = prj.projectvariable_set.get(name="MACHINE").value | ||
| 1858 | except ProjectVariable.DoesNotExist: | ||
| 1859 | context["machine"] = "-- not set yet" | ||
| 1860 | |||
| 1861 | try: | ||
| 1862 | context["distro"] = prj.projectvariable_set.get(name="DISTRO").value | ||
| 1863 | except ProjectVariable.DoesNotExist: | ||
| 1864 | context["distro"] = "-- not set yet" | ||
| 1865 | |||
| 1866 | |||
| 1840 | return render(request, template, context) | 1867 | return render(request, template, context) |
| 1841 | 1868 | ||
| 1869 | import json | ||
| 1870 | |||
| 1871 | def xhr_projectbuild(request, pid): | ||
| 1872 | try: | ||
| 1873 | if request.method != "POST": | ||
| 1874 | raise BadParameterException("invalid method") | ||
| 1875 | prj = Project.objects.get(id = pid) | ||
| 1876 | |||
| 1877 | if prj.projecttarget_set.count() == 0: | ||
| 1878 | raise BadParameterException("no targets selected") | ||
| 1879 | |||
| 1880 | br = prj.schedule_build() | ||
| 1881 | return HttpResponse(json.dumps({"error":"ok", | ||
| 1882 | "brtarget" : map(lambda x: x.target, br.brtarget_set.all()), | ||
| 1883 | "machine" : br.brvariable_set.get(name="MACHINE").value, | ||
| 1884 | |||
| 1885 | }), content_type = "application/json") | ||
| 1886 | except Exception as e: | ||
| 1887 | return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") | ||
| 1888 | |||
| 1889 | def xhr_projectedit(request, pid): | ||
| 1890 | try: | ||
| 1891 | prj = Project.objects.get(id = pid) | ||
| 1892 | # add targets | ||
| 1893 | if 'targetAdd' in request.POST: | ||
| 1894 | for t in request.POST['targetAdd'].strip().split(" "): | ||
| 1895 | if ":" in t: | ||
| 1896 | target, task = t.split(":") | ||
| 1897 | else: | ||
| 1898 | target = t | ||
| 1899 | task = "" | ||
| 1900 | |||
| 1901 | pt, created = ProjectTarget.objects.get_or_create(project = prj, target = target, task = task) | ||
| 1902 | # remove targets | ||
| 1903 | if 'targetDel' in request.POST: | ||
| 1904 | for t in request.POST['targetDel'].strip().split(" "): | ||
| 1905 | pt = ProjectTarget.objects.get(pk = int(t)).delete() | ||
| 1906 | |||
| 1907 | # add layers | ||
| 1908 | |||
| 1909 | # remove layers | ||
| 1910 | |||
| 1911 | # return all project settings | ||
| 1912 | return HttpResponse(json.dumps( { | ||
| 1913 | "error": "ok", | ||
| 1914 | "layers": map(lambda x: (x.name, x.giturl), prj.projectlayer_set.all()), | ||
| 1915 | "targets" : map(lambda x: {"target" : x.target, "task" : x.task, "pk": x.pk}, prj.projecttarget_set.all()), | ||
| 1916 | "variables": map(lambda x: (x.name, x.value), prj.projectvariable_set.all()), | ||
| 1917 | }), content_type = "application/json") | ||
| 1918 | |||
| 1919 | except Exception as e: | ||
| 1920 | return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") | ||
| 1921 | |||
| 1842 | 1922 | ||
| 1843 | else: | 1923 | else: |
| 1844 | # these are pages that are NOT available in interactive mode | 1924 | # these are pages that are NOT available in interactive mode |
| 1925 | def managedcontextprocessor(request): | ||
| 1926 | return { | ||
| 1927 | "projects": [], | ||
| 1928 | "MANAGED" : toastermain.settings.MANAGED | ||
| 1929 | } | ||
| 1930 | |||
| 1845 | def newproject(request): | 1931 | def newproject(request): |
| 1846 | raise Exception("page not available in interactive mode") | 1932 | raise Exception("page not available in interactive mode") |
| 1847 | 1933 | ||
| 1848 | def project(request): | 1934 | def project(request, pid): |
| 1935 | raise Exception("page not available in interactive mode") | ||
| 1936 | |||
| 1937 | def xhr_projectbuild(request, pid): | ||
| 1849 | raise Exception("page not available in interactive mode") | 1938 | raise Exception("page not available in interactive mode") |
| 1939 | |||
| 1940 | def xhr_projectedit(request, pid): | ||
| 1941 | raise Exception("page not available in interactive mode") | ||
| 1942 | |||
