summaryrefslogtreecommitdiffstats
path: root/yocto-poky/bitbake
diff options
context:
space:
mode:
Diffstat (limited to 'yocto-poky/bitbake')
-rw-r--r--yocto-poky/bitbake/LICENSE2
-rwxr-xr-xyocto-poky/bitbake/bin/bitbake2
-rwxr-xr-xyocto-poky/bitbake/bin/bitbake-layers2
-rwxr-xr-xyocto-poky/bitbake/bin/bitbake-prserv2
-rwxr-xr-xyocto-poky/bitbake/bin/bitbake-worker12
-rwxr-xr-xyocto-poky/bitbake/bin/bitdoc2
-rwxr-xr-xyocto-poky/bitbake/bin/image-writer2
-rwxr-xr-xyocto-poky/bitbake/bin/toaster344
-rw-r--r--yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml37
-rw-r--r--yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml1
-rw-r--r--yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml12
-rw-r--r--yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml114
-rw-r--r--yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml20
-rw-r--r--yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml2
-rw-r--r--yocto-poky/bitbake/lib/bb/__init__.py18
-rw-r--r--yocto-poky/bitbake/lib/bb/build.py55
-rw-r--r--yocto-poky/bitbake/lib/bb/cache.py31
-rw-r--r--yocto-poky/bitbake/lib/bb/checksum.py49
-rw-r--r--yocto-poky/bitbake/lib/bb/codeparser.py34
-rw-r--r--yocto-poky/bitbake/lib/bb/command.py1
-rw-r--r--yocto-poky/bitbake/lib/bb/cooker.py141
-rw-r--r--yocto-poky/bitbake/lib/bb/cookerdata.py11
-rw-r--r--yocto-poky/bitbake/lib/bb/data.py48
-rw-r--r--yocto-poky/bitbake/lib/bb/data_smart.py29
-rw-r--r--yocto-poky/bitbake/lib/bb/event.py15
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/__init__.py240
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/git.py21
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/gitsm.py9
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/local.py1
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/npm.py284
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/osc.py12
-rw-r--r--yocto-poky/bitbake/lib/bb/fetch2/wget.py118
-rwxr-xr-xyocto-poky/bitbake/lib/bb/main.py22
-rw-r--r--yocto-poky/bitbake/lib/bb/methodpool.py15
-rw-r--r--yocto-poky/bitbake/lib/bb/parse/__init__.py4
-rw-r--r--yocto-poky/bitbake/lib/bb/parse/ast.py77
-rw-r--r--yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py23
-rw-r--r--yocto-poky/bitbake/lib/bb/persist_data.py1
-rw-r--r--yocto-poky/bitbake/lib/bb/providers.py105
-rw-r--r--yocto-poky/bitbake/lib/bb/runqueue.py119
-rw-r--r--yocto-poky/bitbake/lib/bb/server/__init__.py3
-rw-r--r--yocto-poky/bitbake/lib/bb/server/process.py14
-rw-r--r--yocto-poky/bitbake/lib/bb/server/xmlrpc.py18
-rw-r--r--yocto-poky/bitbake/lib/bb/siggen.py111
-rw-r--r--yocto-poky/bitbake/lib/bb/taskdata.py45
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/codeparser.py7
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/data.py13
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/fetch.py145
-rw-r--r--yocto-poky/bitbake/lib/bb/tests/utils.py24
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py367
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py437
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/builder.py1475
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py455
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py341
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py163
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py90
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py51
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py159
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py891
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py645
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py903
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py128
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py561
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py669
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py355
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py335
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py85
-rwxr-xr-xyocto-poky/bitbake/lib/bb/ui/hob.py109
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/knotty.py62
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/puccho.py425
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/toasterui.py109
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/uievent.py30
-rw-r--r--yocto-poky/bitbake/lib/bb/ui/uihelper.py41
-rw-r--r--yocto-poky/bitbake/lib/bb/utils.py104
-rw-r--r--yocto-poky/bitbake/lib/prserv/db.py8
-rw-r--r--yocto-poky/bitbake/lib/prserv/serv.py45
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcollector/urls.py1
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/bbcontroller.py96
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py301
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py113
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0001_initial.py265
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto_20160120_1250.py19
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto__add_field_buildenvironment_sourcedir__add_field_buildenvironment.py106
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_add_cancelling_state.py19
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_auto__add_field_brlayer_dirpath.py99
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0004_loadinitialdata.py104
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0005_auto__add_brerror.py112
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0006_auto__add_brbitbake.py128
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0007_auto__add_field_buildrequest_environment__chg_field_buildrequest_build.py145
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0008_brarchive.py138
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0009_auto__add_field_brlayer_layer_version.py180
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/models.py43
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/sshbecontroller.py179
-rw-r--r--yocto-poky/bitbake/lib/toaster/bldcontrol/tests.py40
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.gitignore10
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.travis.yml50
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/LICENSE21
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/README.rst156
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/aggregate_if.py164
-rwxr-xr-xyocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/runtests.py48
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/setup.py33
-rw-r--r--yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/tox.ini198
-rwxr-xr-xyocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py164
-rwxr-xr-xyocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py662
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0001_initial.py902
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0002_auto__add_field_build_timespent.py180
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0002_customimagerecipe.py24
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0003_customimagepackage.py24
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0003_timespent.py182
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0004_auto__add_field_package_installed_name.py181
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0004_provides.py27
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0005_auto__add_target_image_file__add_target_file__add_field_variablehistor.py281
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0005_task_field_separation.py48
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py19
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0006_auto__add_field_target_image_size__add_field_target_license_manifest_p.py235
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0007_auto__add_helptext.py214
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0008_auto__chg_field_variablehistory_operation__chg_field_recipe_descriptio.py225
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0009_auto__add_projectvariable__add_projectlayer__add_projecttarget__add_pr.py286
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py257
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0011_auto__add_field_projectlayer_dirpath.py242
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py252
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0013_auto__add_release__add_layerversiondependency__add_unique_layerversion.py710
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0014_auto__chg_field_package_summary__chg_field_layer_summary__chg_field_re.py336
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0015_auto__add_field_layer_vcs_web_url__add_field_layer_vcs_web_tree_base_u.py336
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0016_auto__add_field_release_helptext__chg_field_release_branch__add_index_.py359
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py396
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0018_auto__add_field_layer_version_project.py331
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py342
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0020_auto__add_field_layer_version_local_path__add_field_recipe_pathflags__.py361
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0021_auto__chg_field_build_project__chg_field_project_bitbake_version__chg_.py371
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0022_auto__add_field_target_task__add_field_layer_version_local_path__del_f.py343
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0023_auto__del_field_build_warnings_no__del_field_build_errors_no__del_fiel.py353
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0024_auto__add_field_recipe_is_image.py338
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0025_auto__add_field_project_is_default.py346
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0026_set_default_project.py374
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0027_auto__add_customimagerecipe__add_unique_customimagerecipe_name_project.py375
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/migrations/0028_auto__chg_field_logmessage_message.py345
-rw-r--r--yocto-poky/bitbake/lib/toaster/orm/models.py560
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/__init__.py0
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/README41
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/__init__.py0
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/selenium_helpers.py204
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_all_builds_page.py143
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_all_projects_page.py214
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py251
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_js_unit_tests.py57
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_landing_page.py108
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py160
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_project_builds_page.py168
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_project_page.py59
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/browser/test_sample.py41
-rw-r--r--yocto-poky/bitbake/lib/toaster/tests/toaster-tests-requirements.txt1
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/api.py110
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/fixtures/toastergui-unittest-data.xml446
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/css/default.css8
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/css/qunit-1.18.0.css1
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/base.js229
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js276
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js30
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js8
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js17
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js89
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js95
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage.js49
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js148
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js39
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js90
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/qunit-1.18.0.js347
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/recipedetails.js51
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js349
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/tablefilter.py292
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/tables.py1063
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/base.html144
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuilddetailpage.html11
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuildpage.html213
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html3
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/basetable_top.html4
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/builddashboard.html25
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/builds-toastertable.html48
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/builds.html119
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/customise_btn.html14
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/customrecipe.html193
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/editcustomimage_modal.html71
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/importlayer.html2
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/js-unit-tests.html4
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/landing.html10
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/layer_btn.html2
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/layerdetails.html8
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/machine_btn.html12
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/mrb_section.html108
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage.html44
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage_modal.html48
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/pkg_add_rm_btn.html50
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/project.html21
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html56
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds.html11
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/projectconf.html186
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html36
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/projects.html92
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/projecttopbar.html34
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/recipe.html28
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/recipedetails.html177
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html14
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html14
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/task.html23
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/tasks.html22
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html4
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable.html13
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templates/unavailable_artifact.html13
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/templatetags/objects_to_dictionaries_filter.py35
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/tests.py859
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/urls.py44
-rwxr-xr-xyocto-poky/bitbake/lib/toaster/toastergui/views.py1200
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastergui/widgets.py112
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastermain/management/commands/checksocket.py69
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastermain/management/commands/get-dburl.py9
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastermain/settings.py23
-rw-r--r--yocto-poky/bitbake/lib/toaster/toastermain/urls.py11
-rw-r--r--yocto-poky/bitbake/toaster-requirements.txt3
219 files changed, 11063 insertions, 23572 deletions
diff --git a/yocto-poky/bitbake/LICENSE b/yocto-poky/bitbake/LICENSE
index 350140c93..a57f9a419 100644
--- a/yocto-poky/bitbake/LICENSE
+++ b/yocto-poky/bitbake/LICENSE
@@ -8,3 +8,5 @@ Foundation and individual contributors.
* Twitter Bootstrap (including Glyphicons), redistributed under the Apache License 2.0.
* jQuery is redistributed under the MIT license.
+
+* QUnit is redistributed under the MIT license.
diff --git a/yocto-poky/bitbake/bin/bitbake b/yocto-poky/bitbake/bin/bitbake
index 981b2c0de..b03683e12 100755
--- a/yocto-poky/bitbake/bin/bitbake
+++ b/yocto-poky/bitbake/bin/bitbake
@@ -35,7 +35,7 @@ except RuntimeError as exc:
from bb import cookerdata
from bb.main import bitbake_main, BitBakeConfigParameters, BBMainException
-__version__ = "1.28.0"
+__version__ = "1.30.0"
if __name__ == "__main__":
if __version__ != bb.__version__:
diff --git a/yocto-poky/bitbake/bin/bitbake-layers b/yocto-poky/bitbake/bin/bitbake-layers
index fb130444b..d47a6690e 100755
--- a/yocto-poky/bitbake/bin/bitbake-layers
+++ b/yocto-poky/bitbake/bin/bitbake-layers
@@ -1068,5 +1068,5 @@ if __name__ == "__main__":
except Exception:
ret = 1
import traceback
- traceback.print_exc(5)
+ traceback.print_exc()
sys.exit(ret)
diff --git a/yocto-poky/bitbake/bin/bitbake-prserv b/yocto-poky/bitbake/bin/bitbake-prserv
index a8d7acb4c..03821446b 100755
--- a/yocto-poky/bitbake/bin/bitbake-prserv
+++ b/yocto-poky/bitbake/bin/bitbake-prserv
@@ -50,6 +50,6 @@ if __name__ == "__main__":
except Exception:
ret = 1
import traceback
- traceback.print_exc(5)
+ traceback.print_exc()
sys.exit(ret)
diff --git a/yocto-poky/bitbake/bin/bitbake-worker b/yocto-poky/bitbake/bin/bitbake-worker
index 3390f637e..767a1c033 100755
--- a/yocto-poky/bitbake/bin/bitbake-worker
+++ b/yocto-poky/bitbake/bin/bitbake-worker
@@ -18,7 +18,7 @@ if len(sys.argv) != 2 or not sys.argv[1].startswith("decafbad"):
sys.exit(1)
profiling = False
-if sys.argv[1] == "decafbadbad":
+if sys.argv[1].startswith("decafbadbad"):
profiling = True
try:
import cProfile as profile
@@ -202,6 +202,8 @@ def fork_off_task(cfg, data, workerdata, fn, task, taskname, appends, taskdepdat
the_data = bb.cache.Cache.loadDataFull(fn, appends, data)
the_data.setVar('BB_TASKHASH', workerdata["runq_hash"][task])
+ bb.utils.set_process_name("%s:%s" % (the_data.getVar("PN", True), taskname.replace("do_", "")))
+
# exported_vars() returns a generator which *cannot* be passed to os.environ.update()
# successfully. We also need to unset anything from the environment which shouldn't be there
exports = bb.data.exported_vars(the_data)
@@ -296,12 +298,16 @@ class BitbakeWorker(object):
signal.signal(signal.SIGTERM, self.sigterm_exception)
# Let SIGHUP exit as SIGTERM
signal.signal(signal.SIGHUP, self.sigterm_exception)
+ if "beef" in sys.argv[1]:
+ bb.utils.set_process_name("Worker (Fakeroot)")
+ else:
+ bb.utils.set_process_name("Worker")
def sigterm_exception(self, signum, stackframe):
if signum == signal.SIGTERM:
- bb.warn("Worker recieved SIGTERM, shutting down...")
+ bb.warn("Worker received SIGTERM, shutting down...")
elif signum == signal.SIGHUP:
- bb.warn("Worker recieved SIGHUP, shutting down...")
+ bb.warn("Worker received SIGHUP, shutting down...")
self.handle_finishnow(None)
signal.signal(signal.SIGTERM, signal.SIG_DFL)
os.kill(os.getpid(), signal.SIGTERM)
diff --git a/yocto-poky/bitbake/bin/bitdoc b/yocto-poky/bitbake/bin/bitdoc
index 576d88b57..defb3dd37 100755
--- a/yocto-poky/bitbake/bin/bitdoc
+++ b/yocto-poky/bitbake/bin/bitdoc
@@ -462,7 +462,7 @@ def main():
state_group = 2
for key in bb.data.keys(documentation):
- data = documentation.getVarFlag(key, "doc")
+ data = documentation.getVarFlag(key, "doc", False)
if not data:
continue
diff --git a/yocto-poky/bitbake/bin/image-writer b/yocto-poky/bitbake/bin/image-writer
index 7d7116780..e30ab45e3 100755
--- a/yocto-poky/bitbake/bin/image-writer
+++ b/yocto-poky/bitbake/bin/image-writer
@@ -119,4 +119,4 @@ if __name__ == '__main__':
gtk.main()
except Exception:
import traceback
- traceback.print_exc(3)
+ traceback.print_exc()
diff --git a/yocto-poky/bitbake/bin/toaster b/yocto-poky/bitbake/bin/toaster
index 2c3432c24..70c66d2c2 100755
--- a/yocto-poky/bitbake/bin/toaster
+++ b/yocto-poky/bitbake/bin/toaster
@@ -1,5 +1,8 @@
-#!/bin/sh
-# (c) 2013 Intel Corp.
+#!/bin/echo ERROR: This script needs to be sourced. Please run as .
+
+# toaster - shell script to start Toaster
+
+# Copyright (C) 2013-2015 Intel Corp.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -12,32 +15,24 @@
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
+# along with this program. If not, see http://www.gnu.org/licenses/.
-# This script can be run in two modes.
-
-# When used with "source", from a build directory,
-# it enables toaster event logging and starts the bitbake resident server.
-# use as: source toaster [start|stop] [noweb] [noui]
-
-# When it is called as a stand-alone script, it starts just the
-# web server, and the building shall be done through the web interface.
-# As script, it will not return to the command prompt. Stop with Ctrl-C.
+# Usage: source toaster [start|stop]
+# [webport=<port>] [noui] [noweb]
# Helper function to kill a background toaster development server
webserverKillAll()
{
local pidfile
- for pidfile in ${BUILDDIR}/.toastermain.pid; do
+ for pidfile in ${BUILDDIR}/.toastermain.pid ${BUILDDIR}/.runbuilds.pid; do
if [ -f ${pidfile} ]; then
pid=`cat ${pidfile}`
while kill -0 $pid 2>/dev/null; do
kill -SIGTERM -$pid 2>/dev/null
sleep 1
- # Kill processes if they are still running - may happen in interactive shells
+ # Kill processes if they are still running - may happen
+ # in interactive shells
ps fux | grep "python.*manage.py runserver" | awk '{print $2}' | xargs kill
done
rm ${pidfile}
@@ -55,35 +50,15 @@ webserverStartAll()
retval=0
# you can always add a superuser later via
- # python bitbake/lib/toaster/manage.py python manage.py createsuperuser --username=<ME>
- python $BBBASEDIR/lib/toaster/manage.py syncdb --noinput || retval=1
-
- python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=2
-
- if [ $retval -eq 1 ]; then
- echo "Failed db sync, aborting system start" 1>&2
- return $retval
- fi
-
- python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=1
-
- if [ $retval -eq 1 ]; then
- printf "\nError on orm migration, rolling back...\n"
- python $BBBASEDIR/lib/toaster/manage.py migrate orm 0001_initial --fake
- return $retval
- fi
-
- python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol || retval=1
+ # ../bitbake/lib/toaster/manage.py createsuperuser --username=<ME>
+ $MANAGE migrate --noinput || retval=1
if [ $retval -eq 1 ]; then
- printf "\nError on bldcontrol migration, rolling back...\n"
- python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol 0001_initial --fake
+ echo "Failed migrations, aborting system start" 1>&2
return $retval
fi
- if [ "$TOASTER_MANAGED" = '1' ]; then
- python $BBBASEDIR/lib/toaster/manage.py checksettings --traceback || retval=1
- fi
+ $MANAGE checksettings --traceback || retval=1
if [ $retval -eq 1 ]; then
printf "\nError while checking settings; aborting\n"
@@ -92,7 +67,9 @@ webserverStartAll()
echo "Starting webserver..."
- python $BBBASEDIR/lib/toaster/manage.py runserver "0.0.0.0:$WEB_PORT" </dev/null >>${BUILDDIR}/toaster_web.log 2>&1 & echo $! >${BUILDDIR}/.toastermain.pid
+ $MANAGE runserver "0.0.0.0:$WEB_PORT" \
+ </dev/null >>${BUILDDIR}/toaster_web.log 2>&1 \
+ & echo $! >${BUILDDIR}/.toastermain.pid
sleep 1
@@ -106,16 +83,6 @@ webserverStartAll()
return $retval
}
-# Helper functions to add a special configuration file
-
-addtoConfiguration()
-{
- file=$1
- shift
- echo "#Created by toaster start script" > ${BUILDDIR}/conf/$file
- for var in "$@"; do echo $var >> ${BUILDDIR}/conf/$file; done
-}
-
INSTOPSYSTEM=0
# define the stop command
@@ -128,45 +95,34 @@ stop_system()
kill `cat ${BUILDDIR}/.toasterui.pid` 2>/dev/null
rm ${BUILDDIR}/.toasterui.pid
fi
- BBSERVER=0.0.0.0:-1 bitbake -m
- unset BBSERVER
webserverKillAll
- # force stop any misbehaving bitbake server
- lsof bitbake.lock | awk '{print $2}' | grep "[0-9]\+" | xargs -n1 -r kill
+ # unset exported variables
+ unset DATABASE_URL
+ unset TOASTER_CONF
+ unset TOASTER_DIR
+ unset BITBAKE_UI
+ unset BBBASEDIR
trap - SIGHUP
#trap - SIGCHLD
INSTOPSYSTEM=0
}
-check_pidbyfile() {
- [ -e $1 ] && kill -0 `cat $1` 2>/dev/null
-}
-
-
-notify_chldexit() {
- if [ $NOTOASTERUI -eq 0 ]; then
- check_pidbyfile ${BUILDDIR}/.toasterui.pid && return
- stop_system
- fi
-}
-
-
verify_prereq() {
- # Verify prerequisites
-
- if ! echo "import django; print (1,) == django.VERSION[0:1] and django.VERSION[1:2][0] in (6,)" | python 2>/dev/null | grep True >/dev/null; then
- printf "This program needs Django 1.6. Please install with\n\npip install django==1.6\n"
+ # Verify Django version
+ reqfile=$(python -c "import os; print os.path.realpath('$BBBASEDIR/toaster-requirements.txt')")
+ exp='s/Django\([><=]\+\)\([^,]\+\),\([><=]\+\)\(.\+\)/'
+ exp=$exp'import sys,django;version=django.get_version().split(".");'
+ exp=$exp'sys.exit(not (version \1 "\2".split(".") and version \3 "\4".split(".")))/p'
+ if ! sed -n "$exp" $reqfile | python - ; then
+ req=`grep ^Django $reqfile`
+ echo "This program needs $req"
+ echo "Please install with pip install -r $reqfile"
return 2
fi
- if ! echo "import south; print reduce(lambda x, y: 2 if x==2 else 0 if x == 0 else y, map(lambda x: 1+cmp(x[1]-x[0],0), zip([0,8,4], map(int,south.__version__.split(\".\"))))) > 0" | python 2>/dev/null | grep True >/dev/null; then
- printf "This program needs South 0.8.4. Please install with\n\npip install south==0.8.4\n"
- return 2
- fi
return 0
}
-
# read command line parameters
if [ -n "$BASH_SOURCE" ] ; then
TOASTER=${BASH_SOURCE}
@@ -176,33 +132,42 @@ else
TOASTER=$0
fi
-[ `basename \"$0\"` = `basename \"${TOASTER}\"` ] && TOASTER_MANAGED=1
+export BBBASEDIR=`dirname $TOASTER`/..
+MANAGE=$BBBASEDIR/lib/toaster/manage.py
+OEROOT=`dirname $TOASTER`/../..
-BBBASEDIR=`dirname $TOASTER`/..
-
-RUNNING=0
-
-NOTOASTERUI=0
-WEBSERVER=1
-TOASTER_BRBE=""
-if [ "$WEB_PORT" = "" ]; then
- WEB_PORT="8000"
-fi
# this is the configuraton file we are using for toaster
-# note default is assuming yocto. Override this if you are
-# running in a pure OE environment and use the toasterconf.json
-# in meta/conf/toasterconf.json
-# note: for future there are a number of relative path assumptions
-# in the local layers that currently prevent using an arbitrary
-# toasterconf.json
+# we are using the same logic that oe-setup-builddir uses
+# (based on TEMPLATECONF and .templateconf) to determine
+# which toasterconf.json to use.
+# note: There are a number of relative path assumptions
+# in the local layers that currently make using an arbitrary
+# toasterconf.json difficult.
+
+. $OEROOT/.templateconf
+if [ -n "$TEMPLATECONF" ]; then
+ if [ ! -d "$TEMPLATECONF" ]; then
+ # Allow TEMPLATECONF=meta-xyz/conf as a shortcut
+ if [ -d "$OEROOT/$TEMPLATECONF" ]; then
+ TEMPLATECONF="$OEROOT/$TEMPLATECONF"
+ fi
+ if [ ! -d "$TEMPLATECONF" ]; then
+ echo >&2 "Error: '$TEMPLATECONF' must be a directory containing toasterconf.json"
+ return 1
+ fi
+ fi
+fi
+
if [ "$TOASTER_CONF" = "" ]; then
- TOASTER_CONF="$(dirname $TOASTER)/../../meta-yocto/conf/toasterconf.json"
+ TOASTER_CONF="$TEMPLATECONF/toasterconf.json"
export TOASTER_CONF=$(python -c "import os; print os.path.realpath('$TOASTER_CONF')")
fi
+
if [ ! -f $TOASTER_CONF ]; then
- echo "$TOASTER_CONF configuration file not found. set TOASTER_CONF to specify a path"
- [ "$TOASTER_MANAGED" = '1' ] && exit 1 || return 1
+ echo "$TOASTER_CONF configuration file not found. Set TOASTER_CONF to specify file or fix .templateconf"
+ return 1
fi
+
# this defines the dir toaster will use for
# 1) clones of layers (in _toaster_clones )
# 2) the build dir (in build)
@@ -212,102 +177,31 @@ fi
# make sure that the toaster.sqlite file doesn't default to `pwd` like it currently does.
export TOASTER_DIR=`pwd`
-
-NOBROWSER=0
-
+WEBSERVER=1
+WEB_PORT="8000"
+unset CMD
for param in $*; do
case $param in
- noui )
- NOTOASTERUI=1
- ;;
noweb )
WEBSERVER=0
;;
- nobrowser )
- NOBROWSER=1
+ start )
+ CMD=$param
;;
- brbe=* )
- TOASTER_BRBE=$'\n'"TOASTER_BRBE=\""${param#*=}"\""
+ stop )
+ CMD=$param
;;
webport=*)
WEB_PORT="${param#*=}"
esac
done
-if [ "$TOASTER_MANAGED" = '1' ]; then
- # We are called as standalone. We refuse to run in a build environment - we need the interactive mode for that.
- # Start just the web server, point the web browser to the interface, and start any Django services.
-
- if ! verify_prereq; then
- echo "Error: Could not verify that the needed dependencies are installed. Please use virtualenv and pip to install dependencies listed in toaster-requirements.txt" 1>&2
- exit 1
- fi
-
- if [ -n "$BUILDDIR" ]; then
- printf "Error: It looks like you sourced oe-init-build-env. Toaster cannot start in build mode from an oe-core build environment.\n You should be starting Toaster from a new terminal window.\n" 1>&2
- exit 1
- fi
-
- # Define a fake builddir where only the pid files are actually created. No real builds will take place here.
- BUILDDIR=/tmp/toaster_$$
- if [ -d "$BUILDDIR" ]; then
- echo "Previous toaster run directory $BUILDDIR found, cowardly refusing to start. Please remove the directory when that toaster instance is over" 2>&1
- exit 1
- fi
-
- mkdir -p "$BUILDDIR"
-
- RUNNING=1
- trap_ctrlc() {
- echo "** Stopping system"
- webserverKillAll
- RUNNING=0
- }
-
- do_cleanup() {
- find "$BUILDDIR" -type f | xargs rm
- rmdir "$BUILDDIR"
- }
- cleanup() {
- if grep -ir error "$BUILDDIR" >/dev/null; then
- if grep -irn "That port is already in use" "$BUILDDIR"; then
- echo "You can use the \"webport=PORTNUMBER\" parameter to start Toaster on a different port (port $WEB_PORT is already in use)"
- do_cleanup
- else
- printf "\nErrors found in the Toaster log files present in '$BUILDDIR'. Directory will not be cleaned.\n Please review the errors and notify toaster@yoctoproject.org or submit a bug https://bugzilla.yoctoproject.org/enter_bug.cgi?product=Toaster"
- fi
- else
- echo "No errors found, removing the run directory '$BUILDDIR'"
- do_cleanup
- fi
- }
- export TOASTER_MANAGED=1
- if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
- echo "Failed to start the web server, stopping" 1>&2
- cleanup
- exit 1
- fi
- if [ $WEBSERVER -gt 0 ] && [ $NOBROWSER -eq 0 ] ; then
- echo "Starting browser..."
- xdg-open http://127.0.0.1:$WEB_PORT/ >/dev/null 2>&1 &
- fi
- trap trap_ctrlc 2
- echo "Toaster is now running. You can stop it with Ctrl-C"
- while [ $RUNNING -gt 0 ]; do
- python $BBBASEDIR/lib/toaster/manage.py runbuilds 2>&1 | tee -a "$BUILDDIR/toaster.log"
- sleep 1
- done
- cleanup
- echo "**** Exit"
- exit 0
-fi
-
-
-if ! verify_prereq; then
- echo "Error: Could not verify that the needed dependencies are installed. Please use virtualenv and pip to install dependencies listed in toaster-requirements.txt" 1>&2
+if [ `basename \"$0\"` = `basename \"${TOASTER}\"` ]; then
+ echo "Error: This script needs to be sourced. Please run as . $TOASTER"
return 1
fi
+verify_prereq || return 1
# We make sure we're running in the current shell and in a good environment
if [ -z "$BUILDDIR" ] || ! which bitbake >/dev/null 2>&1 ; then
@@ -315,11 +209,23 @@ if [ -z "$BUILDDIR" ] || ! which bitbake >/dev/null 2>&1 ; then
return 2
fi
+# this defines the dir toaster will use for
+# 1) clones of layers (in _toaster_clones )
+# 2) the build dir (in build)
+# 3) the sqlite db if that is being used.
+# 4) pid's we need to clean up on exit/shutdown
+# note: for future. in order to make this an arbitrary directory, we need to
+# make sure that the toaster.sqlite file doesn't default to `pwd`
+# like it currently does.
+export TOASTER_DIR=`dirname $BUILDDIR`
# Determine the action. If specified by arguments, fine, if not, toggle it
-if [ "$1" = 'start' ] || [ "$1" = 'stop' ]; then
- CMD="$1"
-else
+if [ "$CMD" = "start" ] ; then
+ if [ -n "$BBSERVER" ]; then
+ echo " Toaster is already running. Exiting..."
+ return 1
+fi
+elif [ "$CMD" = "" ]; then
if [ -z "$BBSERVER" ]; then
CMD="start"
else
@@ -329,70 +235,42 @@ fi
echo "The system will $CMD."
-# Make sure it's safe to run by checking bitbake lock
-
-lock=1
-if [ -e $BUILDDIR/bitbake.lock ]; then
- python -c "import fcntl; fcntl.flock(open(\"$BUILDDIR/bitbake.lock\"), fcntl.LOCK_EX|fcntl.LOCK_NB)" 2>/dev/null || lock=0
-fi
-
-if [ ${CMD} = 'start' ] && [ $lock -eq 0 ]; then
- echo "Error: bitbake lock state error. File locks show that the system is on." 1>&2
- echo "Please wait for the current build to finish, stop and then start the system again." 1>&2
- return 3
-fi
-
-if [ ${CMD} = 'start' ] && [ -e $BUILDDIR/.toastermain.pid ] && kill -0 `cat $BUILDDIR/.toastermain.pid`; then
- echo "Warning: bitbake appears to be dead, but the Toaster web server is running. Something fishy is going on." 1>&2
- echo "Cleaning up the web server to start from a clean slate."
- webserverKillAll
-fi
-
-
# Execute the commands
case $CMD in
start )
- start_success=1
- addtoConfiguration toaster.conf "INHERIT+=\"toaster buildhistory\"" $TOASTER_BRBE
- if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
- echo "Failed ${CMD}."
- return 4
- fi
- unset BBSERVER
- PREREAD=""
- if [ -e ${BUILDDIR}/conf/toaster-pre.conf ]; then
- rm ${BUILDDIR}/conf/toaster-pre.conf
+ # check if addr:port is not in use
+ if [ "$CMD" == 'start' ]; then
+ $MANAGE checksocket "0.0.0.0:$WEB_PORT" || return 1
fi
- bitbake $PREREAD --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0
- if [ $? -ne 0 ]; then
- start_success=0
- echo "Bitbake server start failed"
- else
- export BBSERVER=0.0.0.0:-1
- if [ $NOTOASTERUI -eq 0 ]; then # we start the TOASTERUI only if not inhibited
- bitbake --observe-only -u toasterui >>${BUILDDIR}/toaster_ui.log 2>&1 & echo $! >${BUILDDIR}/.toasterui.pid
- fi
+
+ # kill Toaster web server if it's alive
+ if [ -e $BUILDDIR/.toastermain.pid ] && kill -0 `cat $BUILDDIR/.toastermain.pid`; then
+ echo "Warning: bitbake appears to be dead, but the Toaster web server is running." 1>&2
+ echo " Something fishy is going on." 1>&2
+ echo "Cleaning up the web server to start from a clean slate."
+ webserverKillAll
fi
- if [ $start_success -eq 1 ]; then
- # set fail safe stop system on terminal exit
- trap stop_system SIGHUP
- echo "Successful ${CMD}."
- return 0
- else
- # failed start, do stop
- stop_system
+
+ # Create configuration file
+ conf=${BUILDDIR}/conf/local.conf
+ line='INHERIT+="toaster buildhistory"'
+ grep -q "$line" $conf || echo $line >> $conf
+
+ if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
echo "Failed ${CMD}."
- return 1
+ return 4
fi
- # stop system on terminal exit
- set -o monitor
+ export BITBAKE_UI='toasterui'
+ export DATABASE_URL=`$MANAGE get-dburl`
+ $MANAGE runbuilds & echo $! >${BUILDDIR}/.runbuilds.pid
+ # set fail safe stop system on terminal exit
trap stop_system SIGHUP
- #trap notify_chldexit SIGCHLD
+ echo "Successful ${CMD}."
+ return 0
;;
stop )
stop_system
echo "Successful ${CMD}."
;;
esac
-
diff --git a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
index fa52e2989..b1b72e0aa 100644
--- a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
+++ b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-execution.xml
@@ -42,9 +42,9 @@
<literallayout class='monospaced'>
$ grep processor /proc/cpuinfo
</literallayout>
- This command returns the number of processors, which takes into
- account hyper-threading.
- Thus, a quad-core build host with hyper-threading most likely
+ This command returns the number of processors, which takes into
+ account hyper-threading.
+ Thus, a quad-core build host with hyper-threading most likely
shows eight processors, which is the value you would then assign to
<filename>BB_NUMBER_THREADS</filename>.
</para>
@@ -116,16 +116,35 @@
Prior to parsing configuration files, Bitbake looks
at certain variables, including:
<itemizedlist>
- <listitem><para><link linkend='var-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link></para></listitem>
- <listitem><para><link linkend='var-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link></para></listitem>
- <listitem><para><link linkend='var-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link></para></listitem>
+ <listitem><para>
+ <link linkend='var-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>
+ </para></listitem>
+ <listitem><para>
+ <link linkend='var-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link>
+ </para></listitem>
+ <listitem><para>
+ <link linkend='var-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link>
+ </para></listitem>
+ <listitem><para>
+ <link linkend='var-BB_ORIGENV'><filename>BB_ORIGENV</filename></link>
+ </para></listitem>
<listitem><para>
<link linkend='var-BITBAKE_UI'><filename>BITBAKE_UI</filename></link>
</para></listitem>
</itemizedlist>
- You can find information on how to pass environment variables into the BitBake
- execution environment in the
- "<link linkend='passing-information-into-the-build-task-environment'>Passing Information Into the Build Task Environment</link>" section.
+ The first four variables in this list relate to how BitBake treats shell
+ environment variables during task execution.
+ By default, BitBake cleans the environment variables and provides tight
+ control over the shell execution environment.
+ However, through the use of these first four variables, you can
+ apply your control regarding the
+ environment variables allowed to be used by BitBake in the shell
+ during execution of tasks.
+ See the
+ "<link linkend='passing-information-into-the-build-task-environment'>Passing Information Into the Build Task Environment</link>"
+ section and the information about these variables in the
+ variable glossary for more information on how they work and
+ on how to use them.
</para>
<para>
diff --git a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
index f3628cf6b..f6d82b4f3 100644
--- a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
+++ b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-hello.xml
@@ -47,7 +47,6 @@
-rw-rw-r--. 1 wmat wmat 849 Nov 26 04:55 HEADER
drwxrwxr-x. 5 wmat wmat 4096 Jan 31 13:44 lib
-rw-rw-r--. 1 wmat wmat 195 Nov 26 04:55 MANIFEST.in
- -rwxrwxr-x. 1 wmat wmat 3195 Jan 31 11:57 setup.py
-rw-rw-r--. 1 wmat wmat 2887 Nov 26 04:55 TODO
</literallayout>
</para>
diff --git a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
index 2188655de..7a37edd50 100644
--- a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
+++ b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-intro.xml
@@ -471,7 +471,7 @@
Following is the usage and syntax for BitBake:
<literallayout class='monospaced'>
$ bitbake -h
- Usage: bitbake [options] [recipename/target ...]
+ Usage: bitbake [options] [recipename/target recipe:do_task ...]
Executes the specified task (default is 'build') for a given set of target recipes (.bb files).
It is assumed there is a conf/bblayers.conf available in cwd or in BBPATH which
@@ -529,9 +529,11 @@
-l DEBUG_DOMAINS, --log-domains=DEBUG_DOMAINS
Show debug logging for the specified logging domains
-P, --profile Profile the command and save reports.
- -u UI, --ui=UI The user interface to use (e.g. knotty, hob, depexp).
+ -u UI, --ui=UI The user interface to use (depexp, goggle, hob, knotty
+ or ncurses - default knotty).
-t SERVERTYPE, --servertype=SERVERTYPE
- Choose which server to use, process or xmlrpc.
+ Choose which server type to use (process or xmlrpc -
+ default process).
--token=XMLRPCTOKEN Specify the connection token to be used when
connecting to a remote server.
--revisions-changed Set the exit code depending on whether upstream
@@ -546,6 +548,10 @@
-m, --kill-server Terminate the remote server.
--observe-only Connect to a server as an observing-only client.
--status-only Check the status of the remote bitbake server.
+ -w WRITEEVENTLOG, --write-log=WRITEEVENTLOG
+ Writes the event log of the build to a bitbake event
+ json file. Use '' (empty string) to assign the name
+ automatically.
</literallayout>
</para>
</section>
diff --git a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
index 1b9d80010..6329cd6e4 100644
--- a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
+++ b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-metadata.xml
@@ -379,6 +379,12 @@
You can use <filename>OVERRIDES</filename> to conditionally select
a specific version of a variable and to conditionally
append or prepend the value of a variable.
+ <note>
+ Overrides can only use lower-case characters.
+ Additionally, underscores are not permitted in override names
+ as they are used to separate overrides from each other and
+ from the variable name.
+ </note>
<itemizedlist>
<listitem><para><emphasis>Selecting a Variable:</emphasis>
The <filename>OVERRIDES</filename> variable is
@@ -603,8 +609,13 @@
BitBake uses the
<link linkend='var-BBPATH'><filename>BBPATH</filename></link>
variable to locate needed include and class files.
- The <filename>BBPATH</filename> variable is analogous to
- the environment variable <filename>PATH</filename>.
+ Additionally, BitBake searches the current directory for
+ <filename>include</filename> and <filename>require</filename>
+ directives.
+ <note>
+ The <filename>BBPATH</filename> variable is analogous to
+ the environment variable <filename>PATH</filename>.
+ </note>
</para>
<para>
@@ -652,6 +663,51 @@
after the "inherit" statement.
</note>
</para>
+
+ <para>
+ If necessary, it is possible to inherit a class
+ conditionally by using
+ a variable expression after the <filename>inherit</filename>
+ statement.
+ Here is an example:
+ <literallayout class='monospaced'>
+ inherit ${VARNAME}
+ </literallayout>
+ If <filename>VARNAME</filename> is going to be set, it needs
+ to be set before the <filename>inherit</filename> statement
+ is parsed.
+ One way to achieve a conditional inherit in this case is to use
+ overrides:
+ <literallayout class='monospaced'>
+ VARIABLE = ""
+ VARIABLE_someoverride = "myclass"
+ </literallayout>
+ </para>
+
+ <para>
+ Another method is by using anonymous Python.
+ Here is an example:
+ <literallayout class='monospaced'>
+ python () {
+ if condition == value:
+ d.setVar('VARIABLE', 'myclass')
+ else:
+ d.setVar('VARIABLE', '')
+ }
+ </literallayout>
+ </para>
+
+ <para>
+ Alternatively, you could use an in-line Python expression
+ in the following form:
+ <literallayout class='monospaced'>
+ inherit ${@'classname' if condition else ''}
+ inherit ${@functionname(params)}
+ </literallayout>
+ In all cases, if the expression evaluates to an empty
+ string, the statement does not trigger a syntax error
+ because it becomes a no-op.
+ </para>
</section>
<section id='include-directive'>
@@ -759,6 +815,16 @@
<filename>INHERIT</filename> to inherit a class effectively
inherits the class globally (i.e. for all recipes).
</note>
+ If you want to use the directive to inherit
+ multiple classes, you can provide them on the same line in the
+ <filename>local.conf</filename> file.
+ Use spaces to separate the classes.
+ The following example shows how to inherit both the
+ <filename>autotools</filename> and <filename>pkgconfig</filename>
+ classes:
+ <literallayout class='monospaced'>
+ inherit autotools pkgconfig
+ </literallayout>
</para>
</section>
</section>
@@ -840,6 +906,18 @@
is a global variable and is always automatically
available.
</para>
+
+ <note>
+ Variable expressions (e.g. <filename>${X}</filename>) are no
+ longer expanded within Python functions.
+ This behavior is intentional in order to allow you to freely
+ set variable values to expandable expressions without having
+ them expanded prematurely.
+ If you do wish to expand a variable within a Python function,
+ use <filename>d.getVar("X", True)</filename>.
+ Or, for more complicated expressions, use
+ <filename>d.expand()</filename>.
+ </note>
</section>
<section id='python-functions'>
@@ -1107,10 +1185,18 @@
<title>Passing Information Into the Build Task Environment</title>
<para>
- When running a task, BitBake tightly controls the execution
+ When running a task, BitBake tightly controls the shell execution
environment of the build tasks to make
sure unwanted contamination from the build machine cannot
influence the build.
+ <note>
+ By default, BitBake cleans the environment to include only those
+ things exported or listed in its whitelist to ensure that the build
+ environment is reproducible and consistent.
+ You can prevent this "cleaning" by setting the
+ <link linkend='var-BB_PRESERVE_ENV'><filename>BB_PRESERVE_ENV</filename></link>
+ variable.
+ </note>
Consequently, if you do want something to get passed into the
build task environment, you must take these two steps:
<orderedlist>
@@ -1118,14 +1204,16 @@
Tell BitBake to load what you want from the environment
into the datastore.
You can do so through the
+ <link linkend='var-BB_ENV_WHITELIST'><filename>BB_ENV_WHITELIST</filename></link>
+ and
<link linkend='var-BB_ENV_EXTRAWHITE'><filename>BB_ENV_EXTRAWHITE</filename></link>
- variable.
+ variables.
For example, assume you want to prevent the build system from
accessing your <filename>$HOME/.ccache</filename>
directory.
- The following command tells BitBake to load
- <filename>CCACHE_DIR</filename> from the environment into
- the datastore:
+ The following command "whitelists" the environment variable
+ <filename>CCACHE_DIR</filename> causing BitBack to allow that
+ variable into the datastore:
<literallayout class='monospaced'>
export BB_ENV_EXTRAWHITE="$BB_ENV_EXTRAWHITE CCACHE_DIR"
</literallayout></para></listitem>
@@ -1174,12 +1262,6 @@
The previous example returns <filename>BAR</filename> from the original
execution environment.
</para>
-
- <para>
- By default, BitBake cleans the environment to include only those
- things exported or listed in its whitelist to ensure that the build
- environment is reproducible and consistent.
- </para>
</section>
</section>
@@ -1234,6 +1316,8 @@
</para></listitem>
<listitem><para><emphasis>dirs:</emphasis>
Directories that should be created before the task runs.
+ The last directory listed will be used as the work directory
+ for the task.
</para></listitem>
<listitem><para><emphasis>lockfiles:</emphasis>
Specifies one or more lockfiles to lock while the task
@@ -1765,6 +1849,10 @@
<entry align="left"><filename>d.delVarFlags("X")</filename></entry>
<entry align="left">Deletes all the flags for the variable "X".</entry>
</row>
+ <row>
+ <entry align="left"><filename>d.expand(expression)</filename></entry>
+ <entry align="left">Expands variable references in the specified string expression.</entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
diff --git a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
index e5aeffcff..ae7e4cee8 100644
--- a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
+++ b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual-ref-variables.xml
@@ -1142,14 +1142,14 @@
to "hide" these <filename>.bb</filename> and
<filename>.bbappend</filename> files.
BitBake ignores any recipe or recipe append files that
- match the expression.
+ match any of the expressions.
It is as if BitBake does not see them at all.
Consequently, matching files are not parsed or otherwise
used by BitBake.</para>
<para>
- The value you provide is passed to Python's regular
+ The values you provide are passed to Python's regular
expression compiler.
- The expression is compared against the full paths to
+ The expressions are compared against the full paths to
the files.
For complete syntax information, see Python's
documentation at
@@ -1165,18 +1165,16 @@
BBMASK = "meta-ti/recipes-misc/"
</literallayout>
If you want to mask out multiple directories or recipes,
- use the vertical bar to separate the regular expression
- fragments.
+ you can specify multiple regular expression fragments.
This next example masks out multiple directories and
individual recipes:
<literallayout class='monospaced'>
- BBMASK = "meta-ti/recipes-misc/|meta-ti/recipes-ti/packagegroup/"
- BBMASK .= "|.*meta-oe/recipes-support/"
- BBMASK .= "|.*openldap"
- BBMASK .= "|.*opencv"
- BBMASK .= "|.*lzma"
+ BBMASK += "/meta-ti/recipes-misc/ meta-ti/recipes-ti/packagegroup/"
+ BBMASK += "/meta-oe/recipes-support/"
+ BBMASK += "/meta-foo/.*/openldap"
+ BBMASK += "opencv.*\.bbappend"
+ BBMASK += "lzma"
</literallayout>
- Notice how the vertical bar is used to append the fragments.
<note>
When specifying a directory name, use the trailing
slash character to ensure you match just that directory
diff --git a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
index 7fff933be..4aef4e72f 100644
--- a/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
+++ b/yocto-poky/bitbake/doc/bitbake-user-manual/bitbake-user-manual.xml
@@ -56,7 +56,7 @@
-->
<copyright>
- <year>2004-2015</year>
+ <year>2004-2016</year>
<holder>Richard Purdie</holder>
<holder>Chris Larson</holder>
<holder>and Phil Blundell</holder>
diff --git a/yocto-poky/bitbake/lib/bb/__init__.py b/yocto-poky/bitbake/lib/bb/__init__.py
index ac62d262c..502ad839e 100644
--- a/yocto-poky/bitbake/lib/bb/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/__init__.py
@@ -21,7 +21,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-__version__ = "1.28.0"
+__version__ = "1.30.0"
import sys
if sys.version_info < (2, 7, 3):
@@ -70,6 +70,8 @@ logger = logging.getLogger("BitBake")
logger.addHandler(NullHandler())
logger.setLevel(logging.DEBUG - 2)
+mainlogger = logging.getLogger("BitBake.Main")
+
# This has to be imported after the setLoggerClass, as the import of bb.msg
# can result in construction of the various loggers.
import bb.msg
@@ -79,26 +81,26 @@ sys.modules['bb.fetch'] = sys.modules['bb.fetch2']
# Messaging convenience functions
def plain(*args):
- logger.plain(''.join(args))
+ mainlogger.plain(''.join(args))
def debug(lvl, *args):
if isinstance(lvl, basestring):
- logger.warn("Passed invalid debug level '%s' to bb.debug", lvl)
+ mainlogger.warn("Passed invalid debug level '%s' to bb.debug", lvl)
args = (lvl,) + args
lvl = 1
- logger.debug(lvl, ''.join(args))
+ mainlogger.debug(lvl, ''.join(args))
def note(*args):
- logger.info(''.join(args))
+ mainlogger.info(''.join(args))
def warn(*args):
- logger.warn(''.join(args))
+ mainlogger.warn(''.join(args))
def error(*args, **kwargs):
- logger.error(''.join(args), extra=kwargs)
+ mainlogger.error(''.join(args), extra=kwargs)
def fatal(*args, **kwargs):
- logger.critical(''.join(args), extra=kwargs)
+ mainlogger.critical(''.join(args), extra=kwargs)
raise BBHandledException()
def deprecated(func, name=None, advice=""):
diff --git a/yocto-poky/bitbake/lib/bb/build.py b/yocto-poky/bitbake/lib/bb/build.py
index 22428a649..db5072cb4 100644
--- a/yocto-poky/bitbake/lib/bb/build.py
+++ b/yocto-poky/bitbake/lib/bb/build.py
@@ -156,7 +156,12 @@ class LogTee(object):
def flush(self):
self.outfile.flush()
-def exec_func(func, d, dirs = None):
+#
+# pythonexception allows the python exceptions generated to be raised
+# as the real exceptions (not FuncFailed) and without a backtrace at the
+# origin of the failure.
+#
+def exec_func(func, d, dirs = None, pythonexception=False):
"""Execute a BB 'function'"""
body = d.getVar(func, False)
@@ -224,22 +229,18 @@ def exec_func(func, d, dirs = None):
with bb.utils.fileslocked(lockfiles):
if ispython:
- exec_func_python(func, d, runfile, cwd=adir)
+ exec_func_python(func, d, runfile, cwd=adir, pythonexception=pythonexception)
else:
exec_func_shell(func, d, runfile, cwd=adir)
_functionfmt = """
-def {function}(d):
-{body}
-
{function}(d)
"""
logformatter = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
-def exec_func_python(func, d, runfile, cwd=None):
+def exec_func_python(func, d, runfile, cwd=None, pythonexception=False):
"""Execute a python BB 'function'"""
- bbfile = d.getVar('FILE', True)
- code = _functionfmt.format(function=func, body=d.getVar(func, True))
+ code = _functionfmt.format(function=func)
bb.utils.mkdirhier(os.path.dirname(runfile))
with open(runfile, 'w') as script:
bb.data.emit_func_python(func, script, d)
@@ -254,11 +255,18 @@ def exec_func_python(func, d, runfile, cwd=None):
bb.debug(2, "Executing python function %s" % func)
try:
- comp = utils.better_compile(code, func, bbfile)
- utils.better_exec(comp, {"d": d}, code, bbfile)
+ text = "def %s(d):\n%s" % (func, d.getVar(func, False))
+ fn = d.getVarFlag(func, "filename", False)
+ lineno = int(d.getVarFlag(func, "lineno", False))
+ bb.methodpool.insert_method(func, text, fn, lineno - 1)
+
+ comp = utils.better_compile(code, func, "exec_python_func() autogenerated")
+ utils.better_exec(comp, {"d": d}, code, "exec_python_func() autogenerated", pythonexception=pythonexception)
except (bb.parse.SkipRecipe, bb.build.FuncFailed):
raise
except:
+ if pythonexception:
+ raise
raise FuncFailed(func, None)
finally:
bb.debug(2, "Python function %s finished" % func)
@@ -277,9 +285,8 @@ bb_exit_handler() {
case $ret in
0) ;;
*) case $BASH_VERSION in
- "") echo "WARNING: exit code $ret from a shell command.";;
- *) echo "WARNING: ${BASH_SOURCE[0]}:${BASH_LINENO[0]} exit $ret from
- \"$BASH_COMMAND\"";;
+ "") echo "WARNING: exit code $ret from a shell command.";;
+ *) echo "WARNING: ${BASH_SOURCE[0]}:${BASH_LINENO[0]} exit $ret from '$BASH_COMMAND'";;
esac
exit $ret
esac
@@ -319,7 +326,7 @@ exit $ret
os.chmod(runfile, 0775)
cmd = runfile
- if d.getVarFlag(func, 'fakeroot'):
+ if d.getVarFlag(func, 'fakeroot', False):
fakerootcmd = d.getVar('FAKEROOT', True)
if fakerootcmd:
cmd = [fakerootcmd, runfile]
@@ -394,7 +401,7 @@ def _exec_task(fn, task, d, quieterr):
Execution of a task involves a bit more setup than executing a function,
running it with its own local metadata, and with some useful variables set.
"""
- if not d.getVarFlag(task, 'task'):
+ if not d.getVarFlag(task, 'task', False):
event.fire(TaskInvalid(task, d), d)
logger.error("No such task: %s" % task)
return 1
@@ -533,7 +540,7 @@ def _exec_task(fn, task, d, quieterr):
bb.utils.remove(loglink)
event.fire(TaskSucceeded(task, logfn, localdata), localdata)
- if not localdata.getVarFlag(task, 'nostamp') and not localdata.getVarFlag(task, 'selfstamp'):
+ if not localdata.getVarFlag(task, 'nostamp', False) and not localdata.getVarFlag(task, 'selfstamp', False):
make_stamp(task, localdata)
return 0
@@ -541,7 +548,7 @@ def _exec_task(fn, task, d, quieterr):
def exec_task(fn, task, d, profile = False):
try:
quieterr = False
- if d.getVarFlag(task, "quieterrors") is not None:
+ if d.getVarFlag(task, "quieterrors", False) is not None:
quieterr = True
if profile:
@@ -582,10 +589,10 @@ def stamp_internal(taskname, d, file_name, baseonly=False):
taskflagname = taskname.replace("_setscene", "")
if file_name:
- stamp = d.stamp_base[file_name].get(taskflagname) or d.stamp[file_name]
+ stamp = d.stamp[file_name]
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
else:
- stamp = d.getVarFlag(taskflagname, 'stamp-base', True) or d.getVar('STAMP', True)
+ stamp = d.getVar('STAMP', True)
file_name = d.getVar('BB_FILENAME', True)
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
@@ -616,10 +623,10 @@ def stamp_cleanmask_internal(taskname, d, file_name):
taskflagname = taskname.replace("_setscene", "")
if file_name:
- stamp = d.stamp_base_clean[file_name].get(taskflagname) or d.stampclean[file_name]
+ stamp = d.stampclean[file_name]
extrainfo = d.stamp_extrainfo[file_name].get(taskflagname) or ""
else:
- stamp = d.getVarFlag(taskflagname, 'stamp-base-clean', True) or d.getVar('STAMPCLEAN', True)
+ stamp = d.getVar('STAMPCLEAN', True)
file_name = d.getVar('BB_FILENAME', True)
extrainfo = d.getVarFlag(taskflagname, 'stamp-extra-info', True) or ""
@@ -746,7 +753,7 @@ def addtask(task, before, after, d):
bbtasks.append(task)
d.setVar('__BBTASKS', bbtasks)
- existing = d.getVarFlag(task, "deps") or []
+ existing = d.getVarFlag(task, "deps", False) or []
if after is not None:
# set up deps for function
for entry in after.split():
@@ -756,7 +763,7 @@ def addtask(task, before, after, d):
if before is not None:
# set up things that depend on this func
for entry in before.split():
- existing = d.getVarFlag(entry, "deps") or []
+ existing = d.getVarFlag(entry, "deps", False) or []
if task not in existing:
d.setVarFlag(entry, "deps", [task] + existing)
@@ -771,7 +778,7 @@ def deltask(task, d):
d.delVarFlag(task, 'deps')
for bbtask in d.getVar('__BBTASKS', False) or []:
- deps = d.getVarFlag(bbtask, 'deps') or []
+ deps = d.getVarFlag(bbtask, 'deps', False) or []
if task in deps:
deps.remove(task)
d.setVarFlag(bbtask, 'deps', deps)
diff --git a/yocto-poky/bitbake/lib/bb/cache.py b/yocto-poky/bitbake/lib/bb/cache.py
index ab09b08b5..af5b9fbc6 100644
--- a/yocto-poky/bitbake/lib/bb/cache.py
+++ b/yocto-poky/bitbake/lib/bb/cache.py
@@ -43,7 +43,7 @@ except ImportError:
logger.info("Importing cPickle failed. "
"Falling back to a very slow implementation.")
-__cache_version__ = "148"
+__cache_version__ = "149"
def getCacheFile(path, filename, data_hash):
return os.path.join(path, filename + "." + data_hash)
@@ -85,8 +85,8 @@ class RecipeInfoCommon(object):
return out_dict
@classmethod
- def getvar(cls, var, metadata):
- return metadata.getVar(var, True) or ''
+ def getvar(cls, var, metadata, expand = True):
+ return metadata.getVar(var, expand) or ''
class CoreRecipeInfo(RecipeInfoCommon):
@@ -99,7 +99,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.timestamp = bb.parse.cached_mtime(filename)
self.variants = self.listvar('__VARIANTS', metadata) + ['']
self.appends = self.listvar('__BBAPPEND', metadata)
- self.nocache = self.getvar('__BB_DONT_CACHE', metadata)
+ self.nocache = self.getvar('BB_DONT_CACHE', metadata)
self.skipreason = self.getvar('__SKIPPED', metadata)
if self.skipreason:
@@ -129,8 +129,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.not_world = self.getvar('EXCLUDE_FROM_WORLD', metadata)
self.stamp = self.getvar('STAMP', metadata)
self.stampclean = self.getvar('STAMPCLEAN', metadata)
- self.stamp_base = self.flaglist('stamp-base', self.tasks, metadata)
- self.stamp_base_clean = self.flaglist('stamp-base-clean', self.tasks, metadata)
self.stamp_extrainfo = self.flaglist('stamp-extra-info', self.tasks, metadata)
self.file_checksums = self.flaglist('file-checksums', self.tasks, metadata, True)
self.packages_dynamic = self.listvar('PACKAGES_DYNAMIC', metadata)
@@ -142,10 +140,11 @@ class CoreRecipeInfo(RecipeInfoCommon):
self.rprovides_pkg = self.pkgvar('RPROVIDES', self.packages, metadata)
self.rdepends_pkg = self.pkgvar('RDEPENDS', self.packages, metadata)
self.rrecommends_pkg = self.pkgvar('RRECOMMENDS', self.packages, metadata)
- self.inherits = self.getvar('__inherit_cache', metadata)
+ self.inherits = self.getvar('__inherit_cache', metadata, expand=False)
self.fakerootenv = self.getvar('FAKEROOTENV', metadata)
self.fakerootdirs = self.getvar('FAKEROOTDIRS', metadata)
self.fakerootnoenv = self.getvar('FAKEROOTNOENV', metadata)
+ self.extradepsfunc = self.getvar('calculate_extra_depends', metadata)
@classmethod
def init_cacheData(cls, cachedata):
@@ -158,8 +157,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.stamp = {}
cachedata.stampclean = {}
- cachedata.stamp_base = {}
- cachedata.stamp_base_clean = {}
cachedata.stamp_extrainfo = {}
cachedata.file_checksums = {}
cachedata.fn_provides = {}
@@ -183,6 +180,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.fakerootenv = {}
cachedata.fakerootnoenv = {}
cachedata.fakerootdirs = {}
+ cachedata.extradepsfunc = {}
def add_cacheData(self, cachedata, fn):
cachedata.task_deps[fn] = self.task_deps
@@ -192,8 +190,6 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.pkg_dp[fn] = self.defaultpref
cachedata.stamp[fn] = self.stamp
cachedata.stampclean[fn] = self.stampclean
- cachedata.stamp_base[fn] = self.stamp_base
- cachedata.stamp_base_clean[fn] = self.stamp_base_clean
cachedata.stamp_extrainfo[fn] = self.stamp_extrainfo
cachedata.file_checksums[fn] = self.file_checksums
@@ -220,7 +216,8 @@ class CoreRecipeInfo(RecipeInfoCommon):
rprovides += self.rprovides_pkg[package]
for rprovide in rprovides:
- cachedata.rproviders[rprovide].append(fn)
+ if fn not in cachedata.rproviders[rprovide]:
+ cachedata.rproviders[rprovide].append(fn)
for package in self.packages_dynamic:
cachedata.packages_dynamic[package].append(fn)
@@ -251,6 +248,7 @@ class CoreRecipeInfo(RecipeInfoCommon):
cachedata.fakerootenv[fn] = self.fakerootenv
cachedata.fakerootnoenv[fn] = self.fakerootnoenv
cachedata.fakerootdirs[fn] = self.fakerootdirs
+ cachedata.extradepsfunc[fn] = self.extradepsfunc
@@ -757,13 +755,14 @@ class MultiProcessCache(object):
self.cachedata = self.create_cachedata()
self.cachedata_extras = self.create_cachedata()
- def init_cache(self, d):
+ def init_cache(self, d, cache_file_name=None):
cachedir = (d.getVar("PERSISTENT_DIR", True) or
d.getVar("CACHE", True))
if cachedir in [None, '']:
return
bb.utils.mkdirhier(cachedir)
- self.cachefile = os.path.join(cachedir, self.__class__.cache_file_name)
+ self.cachefile = os.path.join(cachedir,
+ cache_file_name or self.__class__.cache_file_name)
logger.debug(1, "Using cache in '%s'", self.cachefile)
glf = bb.utils.lockfile(self.cachefile + ".lock")
@@ -787,7 +786,7 @@ class MultiProcessCache(object):
data = [{}]
return data
- def save_extras(self, d):
+ def save_extras(self):
if not self.cachefile:
return
@@ -817,7 +816,7 @@ class MultiProcessCache(object):
if h not in dest[j]:
dest[j][h] = source[j][h]
- def save_merge(self, d):
+ def save_merge(self):
if not self.cachefile:
return
diff --git a/yocto-poky/bitbake/lib/bb/checksum.py b/yocto-poky/bitbake/lib/bb/checksum.py
index 514ff0b1e..2ec964d73 100644
--- a/yocto-poky/bitbake/lib/bb/checksum.py
+++ b/yocto-poky/bitbake/lib/bb/checksum.py
@@ -15,6 +15,8 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+import glob
+import operator
import os
import stat
import bb.utils
@@ -88,3 +90,50 @@ class FileChecksumCache(MultiProcessCache):
dest[0][h] = source[0][h]
else:
dest[0][h] = source[0][h]
+
+ def get_checksums(self, filelist, pn):
+ """Get checksums for a list of files"""
+
+ def checksum_file(f):
+ try:
+ checksum = self.get_checksum(f)
+ except OSError as e:
+ bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
+ return None
+ return checksum
+
+ def checksum_dir(pth):
+ # Handle directories recursively
+ dirchecksums = []
+ for root, dirs, files in os.walk(pth):
+ for name in files:
+ fullpth = os.path.join(root, name)
+ checksum = checksum_file(fullpth)
+ if checksum:
+ dirchecksums.append((fullpth, checksum))
+ return dirchecksums
+
+ checksums = []
+ for pth in filelist.split():
+ exist = pth.split(":")[1]
+ if exist == "False":
+ continue
+ pth = pth.split(":")[0]
+ if '*' in pth:
+ # Handle globs
+ for f in glob.glob(pth):
+ if os.path.isdir(f):
+ if not os.path.islink(f):
+ checksums.extend(checksum_dir(f))
+ else:
+ checksum = checksum_file(f)
+ checksums.append((f, checksum))
+ elif os.path.isdir(pth):
+ if not os.path.islink(pth):
+ checksums.extend(checksum_dir(pth))
+ else:
+ checksum = checksum_file(pth)
+ checksums.append((pth, checksum))
+
+ checksums.sort(key=operator.itemgetter(1))
+ return checksums
diff --git a/yocto-poky/bitbake/lib/bb/codeparser.py b/yocto-poky/bitbake/lib/bb/codeparser.py
index 82a3af4e0..3ee4d5622 100644
--- a/yocto-poky/bitbake/lib/bb/codeparser.py
+++ b/yocto-poky/bitbake/lib/bb/codeparser.py
@@ -28,6 +28,10 @@ def check_indent(codestr):
return codestr
if codestr[i-1] == "\t" or codestr[i-1] == " ":
+ if codestr[0] == "\n":
+ # Since we're adding a line, we need to remove one line of any empty padding
+ # to ensure line numbers are correct
+ codestr = codestr[1:]
return "if 1:\n" + codestr
return codestr
@@ -144,6 +148,10 @@ class CodeParserCache(MultiProcessCache):
return cacheline
def init_cache(self, d):
+ # Check if we already have the caches
+ if self.pythoncache:
+ return
+
MultiProcessCache.init_cache(self, d)
# cachedata gets re-assigned in the parent
@@ -159,11 +167,11 @@ codeparsercache = CodeParserCache()
def parser_cache_init(d):
codeparsercache.init_cache(d)
-def parser_cache_save(d):
- codeparsercache.save_extras(d)
+def parser_cache_save():
+ codeparsercache.save_extras()
-def parser_cache_savemerge(d):
- codeparsercache.save_merge(d)
+def parser_cache_savemerge():
+ codeparsercache.save_merge()
Logger = logging.getLoggerClass()
class BufferedLogger(Logger):
@@ -213,6 +221,17 @@ class PythonParser():
self.references.add(node.args[0].s)
else:
self.warn(node.func, node.args[0])
+ elif name and name.endswith(".expand"):
+ if isinstance(node.args[0], ast.Str):
+ value = node.args[0].s
+ d = bb.data.init()
+ parser = d.expandWithRefs(value, self.name)
+ self.references |= parser.references
+ self.execs |= parser.execs
+ for varname in parser.contains:
+ if varname not in self.contains:
+ self.contains[varname] = set()
+ self.contains[varname] |= parser.contains[varname]
elif name in self.execfuncs:
if isinstance(node.args[0], ast.Str):
self.var_execs.add(node.args[0].s)
@@ -235,6 +254,7 @@ class PythonParser():
break
def __init__(self, name, log):
+ self.name = name
self.var_execs = set()
self.contains = {}
self.execs = set()
@@ -244,7 +264,7 @@ class PythonParser():
self.unhandled_message = "in call of %s, argument '%s' is not a string literal"
self.unhandled_message = "while parsing %s, %s" % (name, self.unhandled_message)
- def parse_python(self, node):
+ def parse_python(self, node, lineno=0, filename="<string>"):
if not node or not node.strip():
return
@@ -266,7 +286,9 @@ class PythonParser():
self.contains[i] = set(codeparsercache.pythoncacheextras[h].contains[i])
return
- code = compile(check_indent(str(node)), "<string>", "exec",
+ # We can't add to the linenumbers for compile, we can pad to the correct number of blank lines though
+ node = "\n" * int(lineno) + node
+ code = compile(check_indent(str(node)), filename, "exec",
ast.PyCF_ONLY_AST)
for n in ast.walk(code):
diff --git a/yocto-poky/bitbake/lib/bb/command.py b/yocto-poky/bitbake/lib/bb/command.py
index 74106d143..0559ffc07 100644
--- a/yocto-poky/bitbake/lib/bb/command.py
+++ b/yocto-poky/bitbake/lib/bb/command.py
@@ -279,6 +279,7 @@ class CommandsSync:
mask = params[3]
return bb.event.set_UIHmask(handlerNum, llevel, debug_domains, mask)
setEventMask.needconfig = False
+ setEventMask.readonly = True
def setFeatures(self, command, params):
"""
diff --git a/yocto-poky/bitbake/lib/bb/cooker.py b/yocto-poky/bitbake/lib/bb/cooker.py
index 4df88818f..9b565fc37 100644
--- a/yocto-poky/bitbake/lib/bb/cooker.py
+++ b/yocto-poky/bitbake/lib/bb/cooker.py
@@ -67,6 +67,14 @@ class CollectionError(bb.BBHandledException):
class state:
initial, parsing, running, shutdown, forceshutdown, stopped, error = range(7)
+ @classmethod
+ def get_name(cls, code):
+ for name in dir(cls):
+ value = getattr(cls, name)
+ if type(value) == type(cls.initial) and value == code:
+ return name
+ raise ValueError("Invalid status code: %s" % code)
+
class SkippedPackage:
def __init__(self, info = None, reason = None):
@@ -136,6 +144,10 @@ class BBCooker:
self.watcher.bbwatchedfiles = []
self.notifier = pyinotify.Notifier(self.watcher, self.notifications)
+ # If being called by something like tinfoil, we need to clean cached data
+ # which may now be invalid
+ bb.parse.__mtime_cache = {}
+ bb.parse.BBHandler.cached_statements = {}
self.initConfigurationData()
@@ -189,13 +201,13 @@ class BBCooker:
def config_notifications(self, event):
if not event.pathname in self.configwatcher.bbwatchedfiles:
return
- if not event.path in self.inotify_modified_files:
- self.inotify_modified_files.append(event.path)
+ if not event.pathname in self.inotify_modified_files:
+ self.inotify_modified_files.append(event.pathname)
self.baseconfig_valid = False
def notifications(self, event):
- if not event.path in self.inotify_modified_files:
- self.inotify_modified_files.append(event.path)
+ if not event.pathname in self.inotify_modified_files:
+ self.inotify_modified_files.append(event.pathname)
self.parsecache_valid = False
def add_filewatch(self, deps, watcher=None):
@@ -234,9 +246,9 @@ class BBCooker:
def sigterm_exception(self, signum, stackframe):
if signum == signal.SIGTERM:
- bb.warn("Cooker recieved SIGTERM, shutting down...")
+ bb.warn("Cooker received SIGTERM, shutting down...")
elif signum == signal.SIGHUP:
- bb.warn("Cooker recieved SIGHUP, shutting down...")
+ bb.warn("Cooker received SIGHUP, shutting down...")
self.state = state.forceshutdown
def setFeatures(self, features):
@@ -645,7 +657,7 @@ class BBCooker:
data.expandKeys(envdata)
for e in envdata.keys():
if data.getVarFlag( e, 'python', envdata ):
- logger.plain("\npython %s () {\n%s}\n", e, envdata.getVar(e, True))
+ logger.plain("\npython %s () {\n%s}\n", e, envdata.getVar(e, False))
def buildTaskData(self, pkgs_to_build, task, abort, allowincomplete=False):
@@ -717,8 +729,15 @@ class BBCooker:
depend_tree["packages"] = {}
depend_tree["rdepends-pkg"] = {}
depend_tree["rrecs-pkg"] = {}
+ depend_tree['providermap'] = {}
depend_tree["layer-priorities"] = self.recipecache.bbfile_config_priorities
+ for name, fn in taskdata.get_providermap().iteritems():
+ pn = self.recipecache.pkg_fn[fn]
+ if name != pn:
+ version = "%s:%s-%s" % self.recipecache.pkg_pepvpr[fn]
+ depend_tree['providermap'][name] = (pn, version)
+
for task in xrange(len(rq.rqdata.runq_fnid)):
taskname = rq.rqdata.runq_task[task]
fnid = rq.rqdata.runq_fnid[task]
@@ -893,7 +912,7 @@ class BBCooker:
logger.info("PN build list saved to 'pn-buildlist'")
for pn in depgraph["depends"]:
for depend in depgraph["depends"][pn]:
- print('"%s" -> "%s"' % (pn, depend), file=depends_file)
+ print('"%s" -> "%s" [style=solid]' % (pn, depend), file=depends_file)
for pn in depgraph["rdepends-pn"]:
for rdepend in depgraph["rdepends-pn"][pn]:
print('"%s" -> "%s" [style=dashed]' % (pn, rdepend), file=depends_file)
@@ -911,13 +930,13 @@ class BBCooker:
else:
print('"%s" [label="%s(%s) %s\\n%s"]' % (package, package, pn, version, fn), file=depends_file)
for depend in depgraph["depends"][pn]:
- print('"%s" -> "%s"' % (package, depend), file=depends_file)
+ print('"%s" -> "%s" [style=solid]' % (package, depend), file=depends_file)
for package in depgraph["rdepends-pkg"]:
for rdepend in depgraph["rdepends-pkg"][package]:
print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
for package in depgraph["rrecs-pkg"]:
for rdepend in depgraph["rrecs-pkg"][package]:
- print('"%s" -> "%s" [style=dashed]' % (package, rdepend), file=depends_file)
+ print('"%s" -> "%s" [style=dotted]' % (package, rdepend), file=depends_file)
print("}", file=depends_file)
logger.info("Package dependencies saved to 'package-depends.dot'")
@@ -1019,22 +1038,21 @@ class BBCooker:
def findFilesMatchingInDir(self, filepattern, directory):
"""
- Searches for files matching the regex 'pattern' which are children of
+ Searches for files containing the substring 'filepattern' which are children of
'directory' in each BBPATH. i.e. to find all rootfs package classes available
to BitBake one could call findFilesMatchingInDir(self, 'rootfs_', 'classes')
or to find all machine configuration files one could call:
- findFilesMatchingInDir(self, 'conf/machines', 'conf')
+ findFilesMatchingInDir(self, '.conf', 'conf/machine')
"""
matches = []
- p = re.compile(re.escape(filepattern))
bbpaths = self.data.getVar('BBPATH', True).split(':')
for path in bbpaths:
dirpath = os.path.join(path, directory)
if os.path.exists(dirpath):
for root, dirs, files in os.walk(dirpath):
for f in files:
- if p.search(f):
+ if filepattern in f:
matches.append(f)
if matches:
@@ -1072,7 +1090,7 @@ class BBCooker:
for pfn in self.recipecache.pkg_fn:
inherits = self.recipecache.inherits.get(pfn, None)
- if inherits and inherits.count(klass) > 0:
+ if inherits and klass in inherits:
pkg_list.append(self.recipecache.pkg_fn[pfn])
return pkg_list
@@ -1095,28 +1113,6 @@ class BBCooker:
tree = self.generatePkgDepTreeData(pkgs, 'build')
bb.event.fire(bb.event.TargetsTreeGenerated(tree), self.data)
- def buildWorldTargetList(self):
- """
- Build package list for "bitbake world"
- """
- parselog.debug(1, "collating packages for \"world\"")
- for f in self.recipecache.possible_world:
- terminal = True
- pn = self.recipecache.pkg_fn[f]
-
- for p in self.recipecache.pn_provides[pn]:
- if p.startswith('virtual/'):
- parselog.debug(2, "World build skipping %s due to %s provider starting with virtual/", f, p)
- terminal = False
- break
- for pf in self.recipecache.providers[p]:
- if self.recipecache.pkg_fn[pf] != pn:
- parselog.debug(2, "World build skipping %s due to both us and %s providing %s", f, pf, p)
- terminal = False
- break
- if terminal:
- self.recipecache.world_target.add(pn)
-
def interactiveMode( self ):
"""Drop off into a shell"""
try:
@@ -1353,7 +1349,7 @@ class BBCooker:
failures += len(exc.args)
retval = False
except SystemExit as exc:
- self.command.finishAsyncCommand()
+ self.command.finishAsyncCommand(str(exc))
return False
if not retval:
@@ -1389,7 +1385,7 @@ class BBCooker:
failures += len(exc.args)
retval = False
except SystemExit as exc:
- self.command.finishAsyncCommand()
+ self.command.finishAsyncCommand(str(exc))
return False
if not retval:
@@ -1437,14 +1433,21 @@ class BBCooker:
dump = {}
for k in self.data.keys():
try:
- v = self.data.getVar(k, True)
+ expand = True
+ flags = self.data.getVarFlags(k)
+ if flags and "func" in flags and "python" in flags:
+ expand = False
+ v = self.data.getVar(k, expand)
if not k.startswith("__") and not isinstance(v, bb.data_smart.DataSmart):
dump[k] = {
'v' : v ,
'history' : self.data.varhistory.variable(k),
}
for d in flaglist:
- dump[k][d] = self.data.getVarFlag(k, d)
+ if flags and d in flags:
+ dump[k][d] = flags[d]
+ else:
+ dump[k][d] = None
except Exception as e:
print(e)
return dump
@@ -1506,6 +1509,8 @@ class BBCooker:
# reload files for which we got notifications
for p in self.inotify_modified_files:
bb.parse.update_cache(p)
+ if p in bb.parse.BBHandler.cached_statements:
+ del bb.parse.BBHandler.cached_statements[p]
self.inotify_modified_files = []
if not self.baseconfig_valid:
@@ -1577,7 +1582,7 @@ class BBCooker:
parselog.warn("Explicit target \"%s\" is in ASSUME_PROVIDED, ignoring" % pkg)
if 'world' in pkgs_to_build:
- self.buildWorldTargetList()
+ bb.providers.buildWorldTargetList(self.recipecache)
pkgs_to_build.remove('world')
for t in self.recipecache.world_target:
pkgs_to_build.append(t)
@@ -1643,6 +1648,9 @@ class BBCooker:
else:
self.state = state.shutdown
+ if self.parser:
+ self.parser.shutdown(clean=not force, force=force)
+
def finishcommand(self):
self.state = state.initial
@@ -1760,18 +1768,32 @@ class CookerCollectFiles(object):
globbed = glob.glob(f)
if not globbed and os.path.exists(f):
globbed = [f]
- for g in globbed:
+ # glob gives files in order on disk. Sort to be deterministic.
+ for g in sorted(globbed):
if g not in newfiles:
newfiles.append(g)
bbmask = config.getVar('BBMASK', True)
if bbmask:
+ # First validate the individual regular expressions and ignore any
+ # that do not compile
+ bbmasks = []
+ for mask in bbmask.split():
+ try:
+ re.compile(mask)
+ bbmasks.append(mask)
+ except sre_constants.error:
+ collectlog.critical("BBMASK contains an invalid regular expression, ignoring: %s" % mask)
+
+ # Then validate the combined regular expressions. This should never
+ # fail, but better safe than sorry...
+ bbmask = "|".join(bbmasks)
try:
bbmask_compiled = re.compile(bbmask)
except sre_constants.error:
- collectlog.critical("BBMASK is not a valid regular expression, ignoring.")
- return list(newfiles), 0
+ collectlog.critical("BBMASK is not a valid regular expression, ignoring: %s" % bbmask)
+ bbmask = None
bbfiles = []
bbappend = []
@@ -1948,9 +1970,17 @@ class Parser(multiprocessing.Process):
def parse(self, filename, appends, caches_array):
try:
+ # Record the filename we're parsing into any events generated
+ def parse_filter(self, record):
+ record.taskpid = bb.event.worker_pid
+ record.fn = filename
+ return True
+
# Reset our environment and handlers to the original settings
bb.utils.set_context(self.context.copy())
bb.event.set_class_handlers(self.handlers.copy())
+ bb.event.LogHandler.filter = parse_filter
+
return True, bb.cache.Cache.parse(filename, appends, self.cfg, caches_array)
except Exception as exc:
tb = sys.exc_info()[2]
@@ -1981,8 +2011,6 @@ class CookerParser(object):
self.total = len(filelist)
self.current = 0
- self.num_processes = int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
- multiprocessing.cpu_count())
self.process_names = []
self.bb_cache = bb.cache.Cache(self.cfgdata, self.cfghash, cooker.caches_array)
@@ -1997,6 +2025,9 @@ class CookerParser(object):
self.toparse = self.total - len(self.fromcache)
self.progress_chunk = max(self.toparse / 100, 1)
+ self.num_processes = min(int(self.cfgdata.getVar("BB_NUMBER_PARSE_THREADS", True) or
+ multiprocessing.cpu_count()), len(self.willparse))
+
self.start()
self.haveshutdown = False
@@ -2007,8 +2038,9 @@ class CookerParser(object):
bb.event.fire(bb.event.ParseStarted(self.toparse), self.cfgdata)
def init():
Parser.cfg = self.cfgdata
- multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, args=(self.cfgdata,), exitpriority=1)
- multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, args=(self.cfgdata,), exitpriority=1)
+ bb.utils.set_process_name(multiprocessing.current_process().name)
+ multiprocessing.util.Finalize(None, bb.codeparser.parser_cache_save, exitpriority=1)
+ multiprocessing.util.Finalize(None, bb.fetch.fetcher_parse_save, exitpriority=1)
self.feeder_quit = multiprocessing.Queue(maxsize=1)
self.parser_quit = multiprocessing.Queue(maxsize=self.num_processes)
@@ -2040,7 +2072,7 @@ class CookerParser(object):
bb.event.fire(event, self.cfgdata)
self.feeder_quit.put(None)
for process in self.processes:
- self.jobs.put(None)
+ self.parser_quit.put(None)
else:
self.feeder_quit.put('cancel')
@@ -2061,8 +2093,8 @@ class CookerParser(object):
sync = threading.Thread(target=self.bb_cache.sync)
sync.start()
multiprocessing.util.Finalize(None, sync.join, exitpriority=-100)
- bb.codeparser.parser_cache_savemerge(self.cooker.data)
- bb.fetch.fetcher_parse_done(self.cooker.data)
+ bb.codeparser.parser_cache_savemerge()
+ bb.fetch.fetcher_parse_done()
if self.cooker.configuration.profile:
profiles = []
for i in self.process_names:
@@ -2125,11 +2157,6 @@ class CookerParser(object):
logger.error('ExpansionError during parsing %s: %s', value.recipe, str(exc))
self.shutdown(clean=False)
return False
- except SyntaxError as exc:
- self.error += 1
- logger.error('Unable to parse %s', exc.recipe)
- self.shutdown(clean=False)
- return False
except Exception as exc:
self.error += 1
etype, value, tb = sys.exc_info()
diff --git a/yocto-poky/bitbake/lib/bb/cookerdata.py b/yocto-poky/bitbake/lib/bb/cookerdata.py
index 671c0cb0e..50259a9a0 100644
--- a/yocto-poky/bitbake/lib/bb/cookerdata.py
+++ b/yocto-poky/bitbake/lib/bb/cookerdata.py
@@ -137,6 +137,7 @@ class CookerConfiguration(object):
self.force = False
self.profile = False
self.nosetscene = False
+ self.setsceneonly = False
self.invalidate_stamp = False
self.dump_signatures = []
self.dry_run = False
@@ -181,7 +182,7 @@ def catch_parse_error(func):
parselog.critical(traceback.format_exc())
parselog.critical("Unable to parse %s: %s" % (fn, exc))
sys.exit(1)
- except (bb.parse.ParseError, bb.data_smart.ExpansionError) as exc:
+ except bb.data_smart.ExpansionError as exc:
import traceback
bbdir = os.path.dirname(__file__) + os.sep
@@ -192,6 +193,8 @@ def catch_parse_error(func):
if not fn.startswith(bbdir):
break
parselog.critical("Unable to parse %s", fn, exc_info=(exc_class, exc, tb))
+ except bb.parse.ParseError as exc:
+ parselog.critical(str(exc))
sys.exit(1)
return wrapped
@@ -289,6 +292,8 @@ class CookerDataBuilder(object):
parselog.debug(2, "Adding layer %s", layer)
if 'HOME' in approved and '~' in layer:
layer = os.path.expanduser(layer)
+ if layer.endswith('/'):
+ layer = layer.rstrip('/')
data.setVar('LAYERDIR', layer)
data = parse_config_file(os.path.join(layer, "conf", "layer.conf"), data)
data.expandVarref('LAYERDIR')
@@ -317,7 +322,9 @@ class CookerDataBuilder(object):
# Nomally we only register event handlers at the end of parsing .bb files
# We register any handlers we've found so far here...
for var in data.getVar('__BBHANDLERS', False) or []:
- bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask", True) or "").split())
+ handlerfn = data.getVarFlag(var, "filename", False)
+ handlerln = int(data.getVarFlag(var, "lineno", False))
+ bb.event.register(var, data.getVar(var, False), (data.getVarFlag(var, "eventmask", True) or "").split(), handlerfn, handlerln)
if data.getVar("BB_WORKERCONTEXT", False) is None:
bb.fetch.fetcher_init(data)
diff --git a/yocto-poky/bitbake/lib/bb/data.py b/yocto-poky/bitbake/lib/bb/data.py
index f6415a467..dbc6dea68 100644
--- a/yocto-poky/bitbake/lib/bb/data.py
+++ b/yocto-poky/bitbake/lib/bb/data.py
@@ -107,7 +107,7 @@ def setVarFlag(var, flag, flagvalue, d):
def getVarFlag(var, flag, d):
"""Gets given flag from given var"""
- return d.getVarFlag(var, flag)
+ return d.getVarFlag(var, flag, False)
def delVarFlag(var, flag, d):
"""Removes a given flag from the variable's flags"""
@@ -182,12 +182,12 @@ def inheritFromOS(d, savedenv, permitted):
def emit_var(var, o=sys.__stdout__, d = init(), all=False):
"""Emit a variable to be sourced by a shell."""
- if d.getVarFlag(var, "python"):
+ if d.getVarFlag(var, "python", False):
return False
- export = d.getVarFlag(var, "export")
- unexport = d.getVarFlag(var, "unexport")
- func = d.getVarFlag(var, "func")
+ export = d.getVarFlag(var, "export", False)
+ unexport = d.getVarFlag(var, "unexport", False)
+ func = d.getVarFlag(var, "func", False)
if not all and not export and not unexport and not func:
return False
@@ -227,6 +227,7 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
if func:
# NOTE: should probably check for unbalanced {} within the var
+ val = val.rstrip('\n')
o.write("%s() {\n%s\n}\n" % (varExpanded, val))
return 1
@@ -244,7 +245,7 @@ def emit_var(var, o=sys.__stdout__, d = init(), all=False):
def emit_env(o=sys.__stdout__, d = init(), all=False):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
- isfunc = lambda key: bool(d.getVarFlag(key, "func"))
+ isfunc = lambda key: bool(d.getVarFlag(key, "func", False))
keys = sorted((key for key in d.keys() if not key.startswith("__")), key=isfunc)
grouped = groupby(keys, isfunc)
for isfunc, keys in grouped:
@@ -253,8 +254,8 @@ def emit_env(o=sys.__stdout__, d = init(), all=False):
def exported_keys(d):
return (key for key in d.keys() if not key.startswith('__') and
- d.getVarFlag(key, 'export') and
- not d.getVarFlag(key, 'unexport'))
+ d.getVarFlag(key, 'export', False) and
+ not d.getVarFlag(key, 'unexport', False))
def exported_vars(d):
for key in exported_keys(d):
@@ -269,7 +270,7 @@ def exported_vars(d):
def emit_func(func, o=sys.__stdout__, d = init()):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
- keys = (key for key in d.keys() if not key.startswith("__") and not d.getVarFlag(key, "func"))
+ keys = (key for key in d.keys() if not key.startswith("__") and not d.getVarFlag(key, "func", False))
for key in keys:
emit_var(key, o, d, False)
@@ -283,7 +284,7 @@ def emit_func(func, o=sys.__stdout__, d = init()):
seen |= deps
newdeps = set()
for dep in deps:
- if d.getVarFlag(dep, "func") and not d.getVarFlag(dep, "python"):
+ if d.getVarFlag(dep, "func", False) and not d.getVarFlag(dep, "python", False):
emit_var(dep, o, d, False) and o.write('\n')
newdeps |= bb.codeparser.ShellParser(dep, logger).parse_shell(d.getVar(dep, True))
newdeps |= set((d.getVarFlag(dep, "vardeps", True) or "").split())
@@ -297,7 +298,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
"""Emits all items in the data store in a format such that it can be sourced by a shell."""
def write_func(func, o, call = False):
- body = d.getVar(func, True)
+ body = d.getVar(func, False)
if not body.startswith("def"):
body = _functionfmt.format(function=func, body=body)
@@ -307,7 +308,7 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
write_func(func, o, True)
pp = bb.codeparser.PythonParser(func, logger)
- pp.parse_python(d.getVar(func, True))
+ pp.parse_python(d.getVar(func, False))
newdeps = pp.execs
newdeps |= set((d.getVarFlag(func, "vardeps", True) or "").split())
seen = set()
@@ -316,10 +317,10 @@ def emit_func_python(func, o=sys.__stdout__, d = init()):
seen |= deps
newdeps = set()
for dep in deps:
- if d.getVarFlag(dep, "func") and d.getVarFlag(dep, "python"):
+ if d.getVarFlag(dep, "func", False) and d.getVarFlag(dep, "python", False):
write_func(dep, o)
pp = bb.codeparser.PythonParser(dep, logger)
- pp.parse_python(d.getVar(dep, True))
+ pp.parse_python(d.getVar(dep, False))
newdeps |= pp.execs
newdeps |= set((d.getVarFlag(dep, "vardeps", True) or "").split())
newdeps -= seen
@@ -338,7 +339,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
deps |= parser.references
deps = deps | (keys & parser.execs)
return deps, value
- varflags = d.getVarFlags(key, ["vardeps", "vardepvalue", "vardepsexclude", "vardepvalueexclude", "postfuncs", "prefuncs"]) or {}
+ varflags = d.getVarFlags(key, ["vardeps", "vardepvalue", "vardepsexclude", "vardepvalueexclude", "postfuncs", "prefuncs", "lineno", "filename"]) or {}
vardeps = varflags.get("vardeps")
value = d.getVar(key, False)
@@ -361,27 +362,27 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
value = varflags.get("vardepvalue")
elif varflags.get("func"):
if varflags.get("python"):
- parsedvar = d.expandWithRefs(value, key)
parser = bb.codeparser.PythonParser(key, logger)
- if parsedvar.value and "\t" in parsedvar.value:
+ if value and "\t" in value:
logger.warn("Variable %s contains tabs, please remove these (%s)" % (key, d.getVar("FILE", True)))
- parser.parse_python(parsedvar.value)
+ parser.parse_python(value, filename=varflags.get("filename"), lineno=varflags.get("lineno"))
deps = deps | parser.references
+ deps = deps | (keys & parser.execs)
value = handle_contains(value, parser.contains, d)
else:
parsedvar = d.expandWithRefs(value, key)
parser = bb.codeparser.ShellParser(key, logger)
parser.parse_shell(parsedvar.value)
deps = deps | shelldeps
+ deps = deps | parsedvar.references
+ deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
+ value = handle_contains(value, parsedvar.contains, d)
if vardeps is None:
parser.log.flush()
if "prefuncs" in varflags:
deps = deps | set(varflags["prefuncs"].split())
if "postfuncs" in varflags:
deps = deps | set(varflags["postfuncs"].split())
- deps = deps | parsedvar.references
- deps = deps | (keys & parser.execs) | (keys & parsedvar.execs)
- value = handle_contains(value, parsedvar.contains, d)
else:
parser = d.expandWithRefs(value, key)
deps |= parser.references
@@ -406,7 +407,8 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
deps |= set((vardeps or "").split())
deps -= set(varflags.get("vardepsexclude", "").split())
except Exception as e:
- raise bb.data_smart.ExpansionError(key, None, e)
+ bb.warn("Exception during build_dependencies for %s" % key)
+ raise
return deps, value
#bb.note("Variable %s references %s and calls %s" % (key, str(deps), str(execs)))
#d.setVarFlag(key, "vardeps", deps)
@@ -414,7 +416,7 @@ def build_dependencies(key, keys, shelldeps, varflagsexcl, d):
def generate_dependencies(d):
keys = set(key for key in d if not key.startswith("__"))
- shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export") and not d.getVarFlag(key, "unexport"))
+ shelldeps = set(key for key in d.getVar("__exportlist", False) if d.getVarFlag(key, "export", False) and not d.getVarFlag(key, "unexport", False))
varflagsexcl = d.getVar('BB_SIGNATURE_EXCLUDE_FLAGS', True)
deps = {}
diff --git a/yocto-poky/bitbake/lib/bb/data_smart.py b/yocto-poky/bitbake/lib/bb/data_smart.py
index 70558c15a..fa1e79427 100644
--- a/yocto-poky/bitbake/lib/bb/data_smart.py
+++ b/yocto-poky/bitbake/lib/bb/data_smart.py
@@ -40,7 +40,7 @@ logger = logging.getLogger("BitBake.Data")
__setvar_keyword__ = ["_append", "_prepend", "_remove"]
__setvar_regexp__ = re.compile('(?P<base>.*?)(?P<keyword>_append|_prepend|_remove)(_(?P<add>.*))?$')
-__expand_var_regexp__ = re.compile(r"\${[^{}@\n\t ]+}")
+__expand_var_regexp__ = re.compile(r"\${[^{}@\n\t :]+}")
__expand_python_regexp__ = re.compile(r"\${@.+?}")
def infer_caller_details(loginfo, parent = False, varval = True):
@@ -147,7 +147,7 @@ class DataContext(dict):
def __missing__(self, key):
value = self.metadata.getVar(key, True)
- if value is None or self.metadata.getVarFlag(key, 'func'):
+ if value is None or self.metadata.getVarFlag(key, 'func', False):
raise KeyError(key)
else:
return value
@@ -384,7 +384,12 @@ class DataSmart(MutableMapping):
olds = s
try:
s = __expand_var_regexp__.sub(varparse.var_sub, s)
- s = __expand_python_regexp__.sub(varparse.python_sub, s)
+ try:
+ s = __expand_python_regexp__.sub(varparse.python_sub, s)
+ except SyntaxError as e:
+ # Likely unmatched brackets, just don't expand the expression
+ if e.msg != "EOL while scanning string literal":
+ raise
if s == olds:
break
except ExpansionError:
@@ -475,7 +480,7 @@ class DataSmart(MutableMapping):
base = match.group('base')
keyword = match.group("keyword")
override = match.group('add')
- l = self.getVarFlag(base, keyword) or []
+ l = self.getVarFlag(base, keyword, False) or []
l.append([value, override])
self.setVarFlag(base, keyword, l, ignore=True)
# And cause that to be recorded:
@@ -547,7 +552,7 @@ class DataSmart(MutableMapping):
# aka pay the cookie monster
override = var[var.rfind('_')+1:]
shortvar = var[:var.rfind('_')]
- while override:
+ while override and override.islower():
if shortvar not in self.overridedata:
self.overridedata[shortvar] = []
if [var, override] not in self.overridedata[shortvar]:
@@ -561,7 +566,7 @@ class DataSmart(MutableMapping):
if len(shortvar) == 0:
override = None
- def getVar(self, var, expand=False, noweakdefault=False, parsing=False):
+ def getVar(self, var, expand, noweakdefault=False, parsing=False):
return self.getVarFlag(var, "_content", expand, noweakdefault, parsing)
def renameVar(self, key, newkey, **loginfo):
@@ -577,11 +582,11 @@ class DataSmart(MutableMapping):
self.setVar(newkey, val, ignore=True, parsing=True)
for i in (__setvar_keyword__):
- src = self.getVarFlag(key, i)
+ src = self.getVarFlag(key, i, False)
if src is None:
continue
- dest = self.getVarFlag(newkey, i) or []
+ dest = self.getVarFlag(newkey, i, False) or []
dest.extend(src)
self.setVarFlag(newkey, i, dest, ignore=True)
@@ -621,7 +626,7 @@ class DataSmart(MutableMapping):
if '_' in var:
override = var[var.rfind('_')+1:]
shortvar = var[:var.rfind('_')]
- while override:
+ while override and override.islower():
try:
if shortvar in self.overridedata:
# Force CoW by recreating the list first
@@ -658,7 +663,7 @@ class DataSmart(MutableMapping):
self.dict["__exportlist"]["_content"] = set()
self.dict["__exportlist"]["_content"].add(var)
- def getVarFlag(self, var, flag, expand=False, noweakdefault=False, parsing=False):
+ def getVarFlag(self, var, flag, expand, noweakdefault=False, parsing=False):
local_var = self._findVar(var)
value = None
if flag == "_content" and var in self.overridedata and not parsing:
@@ -687,7 +692,7 @@ class DataSmart(MutableMapping):
match = active[a]
del active[a]
if match:
- value = self.getVar(match)
+ value = self.getVar(match, False)
if local_var is not None and value is None:
if flag in local_var:
@@ -957,7 +962,7 @@ class DataSmart(MutableMapping):
if key == "__BBANONFUNCS":
for i in bb_list:
- value = d.getVar(i, True) or ""
+ value = d.getVar(i, False) or ""
data.update({i:value})
data_str = str([(k, data[k]) for k in sorted(data.keys())])
diff --git a/yocto-poky/bitbake/lib/bb/event.py b/yocto-poky/bitbake/lib/bb/event.py
index 366bc4188..5ffe89eae 100644
--- a/yocto-poky/bitbake/lib/bb/event.py
+++ b/yocto-poky/bitbake/lib/bb/event.py
@@ -31,6 +31,7 @@ except ImportError:
import logging
import atexit
import traceback
+import ast
import bb.utils
import bb.compat
import bb.exceptions
@@ -177,7 +178,7 @@ def fire_from_worker(event, d):
fire_ui_handlers(event, d)
noop = lambda _: None
-def register(name, handler, mask=None):
+def register(name, handler, mask=None, filename=None, lineno=None):
"""Register an Event handler"""
# already registered
@@ -189,7 +190,15 @@ def register(name, handler, mask=None):
if isinstance(handler, basestring):
tmp = "def %s(e):\n%s" % (name, handler)
try:
- code = compile(tmp, "%s(e)" % name, "exec")
+ code = bb.methodpool.compile_cache(tmp)
+ if not code:
+ if filename is None:
+ filename = "%s(e)" % name
+ code = compile(tmp, filename, "exec", ast.PyCF_ONLY_AST)
+ if lineno is not None:
+ ast.increment_lineno(code, lineno-1)
+ code = compile(code, filename, "exec")
+ bb.methodpool.compile_cache_add(tmp, code)
except SyntaxError:
logger.error("Unable to register event handler '%s':\n%s", name,
''.join(traceback.format_exc(limit=0)))
@@ -595,6 +604,8 @@ class LogHandler(logging.Handler):
etype, value, tb = record.exc_info
if hasattr(tb, 'tb_next'):
tb = list(bb.exceptions.extract_traceback(tb, context=3))
+ # Need to turn the value into something the logging system can pickle
+ value = str(value)
record.bb_exc_info = (etype, value, tb)
record.exc_info = None
fire(record, None)
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/__init__.py b/yocto-poky/bitbake/lib/bb/fetch2/__init__.py
index a9c044b6a..1fa67020c 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/__init__.py
@@ -29,11 +29,9 @@ from __future__ import absolute_import
from __future__ import print_function
import os, re
import signal
-import glob
import logging
import urllib
import urlparse
-import operator
import bb.persist_data, bb.utils
import bb.checksum
from bb import data
@@ -329,7 +327,7 @@ class URI(object):
def path(self, path):
self._path = path
- if re.compile("^/").match(path):
+ if not path or re.compile("^/").match(path):
self.relative = False
else:
self.relative = True
@@ -377,9 +375,12 @@ def decodeurl(url):
if locidx != -1 and type.lower() != 'file':
host = location[:locidx]
path = location[locidx:]
- else:
+ elif type.lower() == 'file':
host = ""
path = location
+ else:
+ host = location
+ path = ""
if user:
m = re.compile('(?P<user>[^:]+)(:?(?P<pswd>.*))').match(user)
if m:
@@ -515,13 +516,13 @@ def fetcher_init(d):
if hasattr(m, "init"):
m.init(d)
-def fetcher_parse_save(d):
- _checksum_cache.save_extras(d)
+def fetcher_parse_save():
+ _checksum_cache.save_extras()
-def fetcher_parse_done(d):
- _checksum_cache.save_merge(d)
+def fetcher_parse_done():
+ _checksum_cache.save_merge()
-def fetcher_compare_revisions(d):
+def fetcher_compare_revisions():
"""
Compare the revisions in the persistant cache with current values and
return true/false on whether they've changed.
@@ -574,10 +575,10 @@ def verify_checksum(ud, d, precomputed={}):
else:
sha256data = bb.utils.sha256_file(ud.localpath)
- if ud.method.recommends_checksum(ud):
+ if ud.method.recommends_checksum(ud) and not ud.md5_expected and not ud.sha256_expected:
# If strict checking enabled and neither sum defined, raise error
strict = d.getVar("BB_STRICT_CHECKSUM", True) or "0"
- if (strict == "1") and not (ud.md5_expected or ud.sha256_expected):
+ if strict == "1":
logger.error('No checksum specified for %s, please add at least one to the recipe:\n'
'SRC_URI[%s] = "%s"\nSRC_URI[%s] = "%s"' %
(ud.localpath, ud.md5_name, md5data,
@@ -585,34 +586,22 @@ def verify_checksum(ud, d, precomputed={}):
raise NoChecksumError('Missing SRC_URI checksum', ud.url)
# Log missing sums so user can more easily add them
- if not ud.md5_expected:
- logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
- 'SRC_URI[%s] = "%s"',
- ud.localpath, ud.md5_name, md5data)
-
- if not ud.sha256_expected:
- logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
- 'SRC_URI[%s] = "%s"',
- ud.localpath, ud.sha256_name, sha256data)
-
- md5mismatch = False
- sha256mismatch = False
-
- if ud.md5_expected != md5data:
- md5mismatch = True
-
- if ud.sha256_expected != sha256data:
- sha256mismatch = True
+ logger.warn('Missing md5 SRC_URI checksum for %s, consider adding to the recipe:\n'
+ 'SRC_URI[%s] = "%s"',
+ ud.localpath, ud.md5_name, md5data)
+ logger.warn('Missing sha256 SRC_URI checksum for %s, consider adding to the recipe:\n'
+ 'SRC_URI[%s] = "%s"',
+ ud.localpath, ud.sha256_name, sha256data)
# We want to alert the user if a checksum is defined in the recipe but
# it does not match.
msg = ""
mismatch = False
- if md5mismatch and ud.md5_expected:
+ if ud.md5_expected and ud.md5_expected != md5data:
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'md5', md5data, ud.md5_expected)
mismatch = True;
- if sha256mismatch and ud.sha256_expected:
+ if ud.sha256_expected and ud.sha256_expected != sha256data:
msg = msg + "\nFile: '%s' has %s checksum %s when %s was expected" % (ud.localpath, 'sha256', sha256data, ud.sha256_expected)
mismatch = True;
@@ -637,6 +626,9 @@ def verify_donestamp(ud, d, origud=None):
Returns True, if the donestamp exists and is valid, False otherwise. When
returning False, any existing done stamps are removed.
"""
+ if not ud.needdonestamp:
+ return True
+
if not os.path.exists(ud.donestamp):
return False
@@ -685,7 +677,8 @@ def verify_donestamp(ud, d, origud=None):
# incorrect stamp file.
logger.warn("Checksum mismatch for local file %s\n"
"Cleaning and trying again." % ud.localpath)
- rename_bad_checksum(ud, e.checksum)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
bb.utils.remove(ud.donestamp)
return False
@@ -695,6 +688,9 @@ def update_stamp(ud, d):
donestamp is file stamp indicating the whole fetching is done
this function update the stamp after verifying the checksum
"""
+ if not ud.needdonestamp:
+ return
+
if os.path.exists(ud.donestamp):
# Touch the done stamp file to show active use of the download
try:
@@ -703,11 +699,21 @@ def update_stamp(ud, d):
# Errors aren't fatal here
pass
else:
- checksums = verify_checksum(ud, d)
- # Store the checksums for later re-verification against the recipe
- with open(ud.donestamp, "wb") as cachefile:
- p = pickle.Pickler(cachefile, pickle.HIGHEST_PROTOCOL)
- p.dump(checksums)
+ try:
+ checksums = verify_checksum(ud, d)
+ # Store the checksums for later re-verification against the recipe
+ with open(ud.donestamp, "wb") as cachefile:
+ p = pickle.Pickler(cachefile, pickle.HIGHEST_PROTOCOL)
+ p.dump(checksums)
+ except ChecksumError as e:
+ # Checksums failed to verify, trigger re-download and remove the
+ # incorrect stamp file.
+ logger.warn("Checksum mismatch for local file %s\n"
+ "Cleaning and trying again." % ud.localpath)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
+ bb.utils.remove(ud.donestamp)
+ raise
def subprocess_setup():
# Python installs a SIGPIPE handler by default. This is usually not what
@@ -718,7 +724,7 @@ def subprocess_setup():
def get_autorev(d):
# only not cache src rev in autorev case
if d.getVar('BB_SRCREV_POLICY', True) != "cache":
- d.setVar('__BB_DONT_CACHE', '1')
+ d.setVar('BB_DONT_CACHE', '1')
return "AUTOINC"
def get_srcrev(d, method_name='sortable_revision'):
@@ -920,6 +926,10 @@ def rename_bad_checksum(ud, suffix):
def try_mirror_url(fetch, origud, ud, ld, check = False):
# Return of None or a value means we're finished
# False means try another url
+
+ if ud.lockfile and ud.lockfile != origud.lockfile:
+ lf = bb.utils.lockfile(ud.lockfile)
+
try:
if check:
found = ud.method.checkstatus(fetch, ud, ld)
@@ -946,8 +956,9 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
if origud.mirrortarball and os.path.basename(ud.localpath) == os.path.basename(origud.mirrortarball) \
and os.path.basename(ud.localpath) != os.path.basename(origud.localpath):
# Create donestamp in old format to avoid triggering a re-download
- bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
- open(ud.donestamp, 'w').close()
+ if ud.donestamp:
+ bb.utils.mkdirhier(os.path.dirname(ud.donestamp))
+ open(ud.donestamp, 'w').close()
dest = os.path.join(dldir, os.path.basename(ud.localpath))
if not os.path.exists(dest):
os.symlink(ud.localpath, dest)
@@ -973,7 +984,8 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
if isinstance(e, ChecksumError):
logger.warn("Mirror checksum failure for url %s (original url: %s)\nCleaning and trying again." % (ud.url, origud.url))
logger.warn(str(e))
- rename_bad_checksum(ud, e.checksum)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
elif isinstance(e, NoChecksumError):
raise
else:
@@ -984,6 +996,10 @@ def try_mirror_url(fetch, origud, ud, ld, check = False):
except UnboundLocalError:
pass
return False
+ finally:
+ if ud.lockfile and ud.lockfile != origud.lockfile:
+ bb.utils.unlockfile(lf)
+
def try_mirrors(fetch, d, origud, mirrors, check = False):
"""
@@ -1014,7 +1030,7 @@ def trusted_network(d, url):
return True
pkgname = d.expand(d.getVar('PN', False))
- trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname)
+ trusted_hosts = d.getVarFlag('BB_ALLOWED_NETWORKS', pkgname, False)
if not trusted_hosts:
trusted_hosts = d.getVar('BB_ALLOWED_NETWORKS', True)
@@ -1028,6 +1044,7 @@ def trusted_network(d, url):
if not network:
return True
+ network = network.split(':')[0]
network = network.lower()
for host in trusted_hosts.split(" "):
@@ -1120,48 +1137,7 @@ def get_file_checksums(filelist, pn):
it proceeds
"""
-
- def checksum_file(f):
- try:
- checksum = _checksum_cache.get_checksum(f)
- except OSError as e:
- bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
- return None
- return checksum
-
- def checksum_dir(pth):
- # Handle directories recursively
- dirchecksums = []
- for root, dirs, files in os.walk(pth):
- for name in files:
- fullpth = os.path.join(root, name)
- checksum = checksum_file(fullpth)
- if checksum:
- dirchecksums.append((fullpth, checksum))
- return dirchecksums
-
- checksums = []
- for pth in filelist.split():
- exist = pth.split(":")[1]
- if exist == "False":
- continue
- pth = pth.split(":")[0]
- if '*' in pth:
- # Handle globs
- for f in glob.glob(pth):
- if os.path.isdir(f):
- checksums.extend(checksum_dir(f))
- else:
- checksum = checksum_file(f)
- checksums.append((f, checksum))
- elif os.path.isdir(pth):
- checksums.extend(checksum_dir(pth))
- else:
- checksum = checksum_file(pth)
- checksums.append((pth, checksum))
-
- checksums.sort(key=operator.itemgetter(1))
- return checksums
+ return _checksum_cache.get_checksums(filelist, pn)
class FetchData(object):
@@ -1171,6 +1147,7 @@ class FetchData(object):
def __init__(self, url, d, localonly = False):
# localpath is the location of a downloaded result. If not set, the file is local.
self.donestamp = None
+ self.needdonestamp = True
self.localfile = ""
self.localpath = None
self.lockfile = None
@@ -1197,13 +1174,13 @@ class FetchData(object):
elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
self.md5_expected = None
else:
- self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name)
+ self.md5_expected = d.getVarFlag("SRC_URI", self.md5_name, True)
if self.sha256_name in self.parm:
self.sha256_expected = self.parm[self.sha256_name]
elif self.type not in ["http", "https", "ftp", "ftps", "sftp"]:
self.sha256_expected = None
else:
- self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name)
+ self.sha256_expected = d.getVarFlag("SRC_URI", self.sha256_name, True)
self.ignore_checksums = False
self.names = self.parm.get("name",'default').split(',')
@@ -1235,13 +1212,20 @@ class FetchData(object):
self.localpath = self.method.localpath(self, d)
dldir = d.getVar("DL_DIR", True)
+
+ if not self.needdonestamp:
+ return
+
# Note: .done and .lock files should always be in DL_DIR whereas localpath may not be.
if self.localpath and self.localpath.startswith(dldir):
basepath = self.localpath
elif self.localpath:
basepath = dldir + os.sep + os.path.basename(self.localpath)
- else:
+ elif self.basepath or self.basename:
basepath = dldir + os.sep + (self.basepath or self.basename)
+ else:
+ bb.fatal("Can't determine lock path for url %s" % url)
+
self.donestamp = basepath + '.done'
self.lockfile = basepath + '.lock'
@@ -1355,6 +1339,11 @@ class FetchMethod(object):
iterate = False
file = urldata.localpath
+ # Localpath can't deal with 'dir/*' entries, so it converts them to '.',
+ # but it must be corrected back for local files copying
+ if urldata.basename == '*' and file.endswith('/.'):
+ file = '%s/%s' % (file.rstrip('/.'), urldata.path)
+
try:
unpack = bb.utils.to_boolean(urldata.parm.get('unpack'), True)
except ValueError as exc:
@@ -1407,51 +1396,40 @@ class FetchMethod(object):
cmd = 'rpm2cpio.sh %s | cpio -id' % (file)
elif file.endswith('.deb') or file.endswith('.ipk'):
cmd = 'ar -p %s data.tar.gz | zcat | tar --no-same-owner -xpf -' % file
+ elif file.endswith('.tar.7z'):
+ cmd = '7z x -so %s | tar xf - ' % file
+ elif file.endswith('.7z'):
+ cmd = '7za x -y %s 1>/dev/null' % file
+
+ # If 'subdir' param exists, create a dir and use it as destination for unpack cmd
+ if 'subdir' in urldata.parm:
+ unpackdir = '%s/%s' % (rootdir, urldata.parm.get('subdir'))
+ bb.utils.mkdirhier(unpackdir)
+ else:
+ unpackdir = rootdir
if not unpack or not cmd:
# If file == dest, then avoid any copies, as we already put the file into dest!
- dest = os.path.join(rootdir, os.path.basename(file))
- if (file != dest) and not (os.path.exists(dest) and os.path.samefile(file, dest)):
- if os.path.isdir(file):
- # If for example we're asked to copy file://foo/bar, we need to unpack the result into foo/bar
- basepath = getattr(urldata, "basepath", None)
- destdir = "."
- if basepath and basepath.endswith("/"):
- basepath = basepath.rstrip("/")
- elif basepath:
- basepath = os.path.dirname(basepath)
- if basepath and basepath.find("/") != -1:
- destdir = basepath[:basepath.rfind('/')]
- destdir = destdir.strip('/')
- if destdir != "." and not os.access("%s/%s" % (rootdir, destdir), os.F_OK):
- os.makedirs("%s/%s" % (rootdir, destdir))
- cmd = 'cp -fpPR %s %s/%s/' % (file, rootdir, destdir)
- #cmd = 'tar -cf - -C "%d" -ps . | tar -xf - -C "%s/%s/"' % (file, rootdir, destdir)
- else:
- # The "destdir" handling was specifically done for FILESPATH
- # items. So, only do so for file:// entries.
- if urldata.type == "file" and urldata.path.find("/") != -1:
- destdir = urldata.path.rsplit("/", 1)[0]
- if urldata.parm.get('subdir') != None:
- destdir = urldata.parm.get('subdir') + "/" + destdir
- else:
- if urldata.parm.get('subdir') != None:
- destdir = urldata.parm.get('subdir')
- else:
- destdir = "."
- bb.utils.mkdirhier("%s/%s" % (rootdir, destdir))
- cmd = 'cp -f %s %s/%s/' % (file, rootdir, destdir)
+ dest = os.path.join(unpackdir, os.path.basename(file))
+ if file != dest and not (os.path.exists(dest) and os.path.samefile(file, dest)):
+ destdir = '.'
+ # For file:// entries all intermediate dirs in path must be created at destination
+ if urldata.type == "file":
+ # Trailing '/' does a copying to wrong place
+ urlpath = urldata.path.rstrip('/')
+ # Want files places relative to cwd so no leading '/'
+ urlpath = urlpath.lstrip('/')
+ if urlpath.find("/") != -1:
+ destdir = urlpath.rsplit("/", 1)[0] + '/'
+ bb.utils.mkdirhier("%s/%s" % (unpackdir, destdir))
+ cmd = 'cp -fpPR %s %s' % (file, destdir)
if not cmd:
return
- # Change to subdir before executing command
+ # Change to unpackdir before executing command
save_cwd = os.getcwd();
- os.chdir(rootdir)
- if 'subdir' in urldata.parm:
- newdir = ("%s/%s" % (rootdir, urldata.parm.get('subdir')))
- bb.utils.mkdirhier(newdir)
- os.chdir(newdir)
+ os.chdir(unpackdir)
path = data.getVar('PATH', True)
if path:
@@ -1578,7 +1556,8 @@ class Fetch(object):
m = ud.method
localpath = ""
- lf = bb.utils.lockfile(ud.lockfile)
+ if ud.lockfile:
+ lf = bb.utils.lockfile(ud.lockfile)
try:
self.d.setVar("BB_NO_NETWORK", network)
@@ -1617,7 +1596,8 @@ class Fetch(object):
if isinstance(e, ChecksumError):
logger.warn("Checksum failure encountered with download of %s - will attempt other sources if available" % u)
logger.debug(1, str(e))
- rename_bad_checksum(ud, e.checksum)
+ if os.path.exists(ud.localpath):
+ rename_bad_checksum(ud, e.checksum)
elif isinstance(e, NoChecksumError):
raise
else:
@@ -1644,7 +1624,8 @@ class Fetch(object):
raise
finally:
- bb.utils.unlockfile(lf)
+ if ud.lockfile:
+ bb.utils.unlockfile(lf)
def checkstatus(self, urls=None):
"""
@@ -1686,9 +1667,6 @@ class Fetch(object):
ud = self.ud[u]
ud.setup_localpath(self.d)
- if self.d.expand(self.localpath) is None:
- continue
-
if ud.lockfile:
lf = bb.utils.lockfile(ud.lockfile)
@@ -1775,6 +1753,7 @@ from . import hg
from . import osc
from . import repo
from . import clearcase
+from . import npm
methods.append(local.Local())
methods.append(wget.Wget())
@@ -1791,3 +1770,4 @@ methods.append(hg.Hg())
methods.append(osc.Osc())
methods.append(repo.Repo())
methods.append(clearcase.ClearCase())
+methods.append(npm.Npm())
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/git.py b/yocto-poky/bitbake/lib/bb/fetch2/git.py
index 9bd87ad25..526668bc2 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/git.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/git.py
@@ -70,6 +70,7 @@ import errno
import os
import re
import bb
+import errno
from bb import data
from bb.fetch2 import FetchMethod
from bb.fetch2 import runfetchcmd
@@ -261,23 +262,7 @@ class Git(FetchMethod):
if ud.bareclone:
cloneflags += " --mirror"
- # Versions of git prior to 1.7.9.2 have issues where foo.git and foo get confused
- # and you end up with some horrible union of the two when you attempt to clone it
- # The least invasive workaround seems to be a symlink to the real directory to
- # fool git into ignoring any .git version that may also be present.
- #
- # The issue is fixed in more recent versions of git so we can drop this hack in future
- # when that version becomes common enough.
- clonedir = ud.clonedir
- if not ud.path.endswith(".git"):
- indirectiondir = destdir[:-1] + ".indirectionsymlink"
- if os.path.exists(indirectiondir):
- os.remove(indirectiondir)
- bb.utils.mkdirhier(os.path.dirname(indirectiondir))
- os.symlink(ud.clonedir, indirectiondir)
- clonedir = indirectiondir
-
- runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, cloneflags, clonedir, destdir), d)
+ runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, cloneflags, ud.clonedir, destdir), d)
os.chdir(destdir)
repourl = self._get_repo_url(ud)
runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, repourl), d)
@@ -379,7 +364,7 @@ class Git(FetchMethod):
"""
pupver = ('', '')
- tagregex = re.compile(d.getVar('GITTAGREGEX', True) or "(?P<pver>([0-9][\.|_]?)+)")
+ tagregex = re.compile(d.getVar('UPSTREAM_CHECK_GITTAGREGEX', True) or "(?P<pver>([0-9][\.|_]?)+)")
try:
output = self._lsremote(ud, d, "refs/tags/*")
except bb.fetch2.FetchError or bb.fetch2.NetworkAccess:
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py b/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py
index 0392e48d1..752f1d3c1 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/gitsm.py
@@ -110,8 +110,7 @@ class GitSM(Git):
os.chdir(tmpclonedir)
runfetchcmd(ud.basecmd + " reset --hard", d)
runfetchcmd(ud.basecmd + " checkout " + ud.revisions[ud.names[0]], d)
- runfetchcmd(ud.basecmd + " submodule init", d)
- runfetchcmd(ud.basecmd + " submodule update", d)
+ runfetchcmd(ud.basecmd + " submodule update --init --recursive", d)
self._set_relative_paths(tmpclonedir)
runfetchcmd("sed " + gitdir + "/config -i -e 's/bare.*=.*false/bare = true/'", d)
os.rename(gitdir, ud.clonedir,)
@@ -131,7 +130,5 @@ class GitSM(Git):
os.chdir(ud.destdir)
submodules = self.uses_submodules(ud, d)
if submodules:
- runfetchcmd("cp -r " + ud.clonedir + "/modules " + ud.destdir + "/.git/", d)
- runfetchcmd(ud.basecmd + " submodule init", d)
- runfetchcmd(ud.basecmd + " submodule update", d)
-
+ runfetchcmd(ud.basecmd + " checkout " + ud.revisions[ud.names[0]], d)
+ runfetchcmd(ud.basecmd + " submodule update --init --recursive", d)
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/local.py b/yocto-poky/bitbake/lib/bb/fetch2/local.py
index 2d921f7e5..303a52b63 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/local.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/local.py
@@ -45,6 +45,7 @@ class Local(FetchMethod):
ud.decodedurl = urllib.unquote(ud.url.split("://")[1].split(";")[0])
ud.basename = os.path.basename(ud.decodedurl)
ud.basepath = ud.decodedurl
+ ud.needdonestamp = False
return
def localpath(self, urldata, d):
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/npm.py b/yocto-poky/bitbake/lib/bb/fetch2/npm.py
new file mode 100644
index 000000000..e8d9b1109
--- /dev/null
+++ b/yocto-poky/bitbake/lib/bb/fetch2/npm.py
@@ -0,0 +1,284 @@
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+"""
+BitBake 'Fetch' NPM implementation
+
+The NPM fetcher is used to retrieve files from the npmjs repository
+
+Usage in the recipe:
+
+ SRC_URI = "npm://registry.npmjs.org/;name=${PN};version=${PV}"
+ Suported SRC_URI options are:
+
+ - name
+ - version
+
+ npm://registry.npmjs.org/${PN}/-/${PN}-${PV}.tgz would become npm://registry.npmjs.org;name=${PN};ver=${PV}
+ The fetcher all triggers off the existence of ud.localpath. If that exists and has the ".done" stamp, its assumed the fetch is good/done
+
+"""
+
+import os
+import sys
+import urllib
+import json
+import subprocess
+import signal
+import bb
+from bb import data
+from bb.fetch2 import FetchMethod
+from bb.fetch2 import FetchError
+from bb.fetch2 import ChecksumError
+from bb.fetch2 import runfetchcmd
+from bb.fetch2 import logger
+from bb.fetch2 import UnpackError
+from bb.fetch2 import ParameterError
+from distutils import spawn
+
+def subprocess_setup():
+ # Python installs a SIGPIPE handler by default. This is usually not what
+ # non-Python subprocesses expect.
+ # SIGPIPE errors are known issues with gzip/bash
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+
+class Npm(FetchMethod):
+
+ """Class to fetch urls via 'npm'"""
+ def init(self, d):
+ pass
+
+ def supports(self, ud, d):
+ """
+ Check to see if a given url can be fetched with npm
+ """
+ return ud.type in ['npm']
+
+ def debug(self, msg):
+ logger.debug(1, "NpmFetch: %s", msg)
+
+ def clean(self, ud, d):
+ logger.debug(2, "Calling cleanup %s" % ud.pkgname)
+ bb.utils.remove(ud.localpath, False)
+ bb.utils.remove(ud.pkgdatadir, True)
+ bb.utils.remove(ud.fullmirror, False)
+
+ def urldata_init(self, ud, d):
+ """
+ init NPM specific variable within url data
+ """
+ if 'downloadfilename' in ud.parm:
+ ud.basename = ud.parm['downloadfilename']
+ else:
+ ud.basename = os.path.basename(ud.path)
+
+ # can't call it ud.name otherwise fetcher base class will start doing sha1stuff
+ # TODO: find a way to get an sha1/sha256 manifest of pkg & all deps
+ ud.pkgname = ud.parm.get("name", None)
+ if not ud.pkgname:
+ raise ParameterError("NPM fetcher requires a name parameter", ud.url)
+ ud.version = ud.parm.get("version", None)
+ if not ud.version:
+ raise ParameterError("NPM fetcher requires a version parameter", ud.url)
+ ud.bbnpmmanifest = "%s-%s.deps.json" % (ud.pkgname, ud.version)
+ ud.registry = "http://%s" % (ud.url.replace('npm://', '', 1).split(';'))[0]
+ prefixdir = "npm/%s" % ud.pkgname
+ ud.pkgdatadir = d.expand("${DL_DIR}/%s" % prefixdir)
+ if not os.path.exists(ud.pkgdatadir):
+ bb.utils.mkdirhier(ud.pkgdatadir)
+ ud.localpath = d.expand("${DL_DIR}/npm/%s" % ud.bbnpmmanifest)
+
+ self.basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -O -t 2 -T 30 -nv --passive-ftp --no-check-certificate "
+ self.basecmd += " --directory-prefix=%s " % prefixdir
+
+ ud.write_tarballs = ((data.getVar("BB_GENERATE_MIRROR_TARBALLS", d, True) or "0") != "0")
+ ud.mirrortarball = 'npm_%s-%s.tar.xz' % (ud.pkgname, ud.version)
+ ud.fullmirror = os.path.join(d.getVar("DL_DIR", True), ud.mirrortarball)
+
+ def need_update(self, ud, d):
+ if os.path.exists(ud.localpath):
+ return False
+ return True
+
+ def _runwget(self, ud, d, command, quiet):
+ logger.debug(2, "Fetching %s using command '%s'" % (ud.url, command))
+ bb.fetch2.check_network_access(d, command)
+ runfetchcmd(command, d, quiet)
+
+ def _unpackdep(self, ud, pkg, data, destdir, dldir, d):
+ file = data[pkg]['tgz']
+ logger.debug(2, "file to extract is %s" % file)
+ if file.endswith('.tgz') or file.endswith('.tar.gz') or file.endswith('.tar.Z'):
+ cmd = 'tar xz --strip 1 --no-same-owner --warning=no-unknown-keyword -f %s/%s' % (dldir, file)
+ else:
+ bb.fatal("NPM package %s downloaded not a tarball!" % file)
+
+ # Change to subdir before executing command
+ save_cwd = os.getcwd()
+ if not os.path.exists(destdir):
+ os.makedirs(destdir)
+ os.chdir(destdir)
+ path = d.getVar('PATH', True)
+ if path:
+ cmd = "PATH=\"%s\" %s" % (path, cmd)
+ bb.note("Unpacking %s to %s/" % (file, os.getcwd()))
+ ret = subprocess.call(cmd, preexec_fn=subprocess_setup, shell=True)
+ os.chdir(save_cwd)
+
+ if ret != 0:
+ raise UnpackError("Unpack command %s failed with return value %s" % (cmd, ret), ud.url)
+
+ if 'deps' not in data[pkg]:
+ return
+ for dep in data[pkg]['deps']:
+ self._unpackdep(ud, dep, data[pkg]['deps'], "%s/node_modules/%s" % (destdir, dep), dldir, d)
+
+
+ def unpack(self, ud, destdir, d):
+ dldir = d.getVar("DL_DIR", True)
+ depdumpfile = "%s-%s.deps.json" % (ud.pkgname, ud.version)
+ with open("%s/npm/%s" % (dldir, depdumpfile)) as datafile:
+ workobj = json.load(datafile)
+ dldir = "%s/%s" % (os.path.dirname(ud.localpath), ud.pkgname)
+
+ self._unpackdep(ud, ud.pkgname, workobj, "%s/npmpkg" % destdir, dldir, d)
+
+ def _parse_view(self, output):
+ '''
+ Parse the output of npm view --json; the last JSON result
+ is assumed to be the one that we're interested in.
+ '''
+ pdata = None
+ outdeps = {}
+ datalines = []
+ bracelevel = 0
+ for line in output.splitlines():
+ if bracelevel:
+ datalines.append(line)
+ elif '{' in line:
+ datalines = []
+ datalines.append(line)
+ bracelevel = bracelevel + line.count('{') - line.count('}')
+ if datalines:
+ pdata = json.loads('\n'.join(datalines))
+ return pdata
+
+ def _getdependencies(self, pkg, data, version, d, ud, optional=False):
+ pkgfullname = pkg
+ if version != '*' and not '/' in version:
+ pkgfullname += "@'%s'" % version
+ logger.debug(2, "Calling getdeps on %s" % pkg)
+ fetchcmd = "npm view %s --json --registry %s" % (pkgfullname, ud.registry)
+ output = runfetchcmd(fetchcmd, d, True)
+ pdata = self._parse_view(output)
+ if not pdata:
+ raise FetchError("The command '%s' returned no output" % fetchcmd)
+ if optional:
+ pkg_os = pdata.get('os', None)
+ if pkg_os:
+ if not isinstance(pkg_os, list):
+ pkg_os = [pkg_os]
+ if 'linux' not in pkg_os or '!linux' in pkg_os:
+ logger.debug(2, "Skipping %s since it's incompatible with Linux" % pkg)
+ return
+ #logger.debug(2, "Output URL is %s - %s - %s" % (ud.basepath, ud.basename, ud.localfile))
+ outputurl = pdata['dist']['tarball']
+ data[pkg] = {}
+ data[pkg]['tgz'] = os.path.basename(outputurl)
+ self._runwget(ud, d, "%s %s" % (self.basecmd, outputurl), False)
+
+ dependencies = pdata.get('dependencies', {})
+ optionalDependencies = pdata.get('optionalDependencies', {})
+ depsfound = {}
+ optdepsfound = {}
+ data[pkg]['deps'] = {}
+ for dep in dependencies:
+ if dep in optionalDependencies:
+ optdepsfound[dep] = dependencies[dep]
+ else:
+ depsfound[dep] = dependencies[dep]
+ for dep, version in optdepsfound.iteritems():
+ self._getdependencies(dep, data[pkg]['deps'], version, d, ud, optional=True)
+ for dep, version in depsfound.iteritems():
+ self._getdependencies(dep, data[pkg]['deps'], version, d, ud)
+
+ def _getshrinkeddependencies(self, pkg, data, version, d, ud, lockdown, manifest):
+ logger.debug(2, "NPM shrinkwrap file is %s" % data)
+ outputurl = "invalid"
+ if ('resolved' not in data) or (not data['resolved'].startswith('http')):
+ # will be the case for ${PN}
+ fetchcmd = "npm view %s@%s dist.tarball --registry %s" % (pkg, version, ud.registry)
+ logger.debug(2, "Found this matching URL: %s" % str(fetchcmd))
+ outputurl = runfetchcmd(fetchcmd, d, True)
+ else:
+ outputurl = data['resolved']
+ self._runwget(ud, d, "%s %s" % (self.basecmd, outputurl), False)
+ manifest[pkg] = {}
+ manifest[pkg]['tgz'] = os.path.basename(outputurl).rstrip()
+ manifest[pkg]['deps'] = {}
+
+ if pkg in lockdown:
+ sha1_expected = lockdown[pkg][version]
+ sha1_data = bb.utils.sha1_file("npm/%s/%s" % (ud.pkgname, manifest[pkg]['tgz']))
+ if sha1_expected != sha1_data:
+ msg = "\nFile: '%s' has %s checksum %s when %s was expected" % (manifest[pkg]['tgz'], 'sha1', sha1_data, sha1_expected)
+ raise ChecksumError('Checksum mismatch!%s' % msg)
+ else:
+ logger.debug(2, "No lockdown data for %s@%s" % (pkg, version))
+
+ if 'dependencies' in data:
+ for obj in data['dependencies']:
+ logger.debug(2, "Found dep is %s" % str(obj))
+ self._getshrinkeddependencies(obj, data['dependencies'][obj], data['dependencies'][obj]['version'], d, ud, lockdown, manifest[pkg]['deps'])
+
+ def download(self, ud, d):
+ """Fetch url"""
+ jsondepobj = {}
+ shrinkobj = {}
+ lockdown = {}
+
+ if not os.listdir(ud.pkgdatadir) and os.path.exists(ud.fullmirror):
+ dest = d.getVar("DL_DIR", True)
+ bb.utils.mkdirhier(dest)
+ save_cwd = os.getcwd()
+ os.chdir(dest)
+ runfetchcmd("tar -xJf %s" % (ud.fullmirror), d)
+ os.chdir(save_cwd)
+ return
+
+ shwrf = d.getVar('NPM_SHRINKWRAP', True)
+ logger.debug(2, "NPM shrinkwrap file is %s" % shwrf)
+ try:
+ with open(shwrf) as datafile:
+ shrinkobj = json.load(datafile)
+ except:
+ logger.warn('Missing shrinkwrap file in NPM_SHRINKWRAP for %s, this will lead to unreliable builds!' % ud.pkgname)
+ lckdf = d.getVar('NPM_LOCKDOWN', True)
+ logger.debug(2, "NPM lockdown file is %s" % lckdf)
+ try:
+ with open(lckdf) as datafile:
+ lockdown = json.load(datafile)
+ except:
+ logger.warn('Missing lockdown file in NPM_LOCKDOWN for %s, this will lead to unreproducible builds!' % ud.pkgname)
+
+ if ('name' not in shrinkobj):
+ self._getdependencies(ud.pkgname, jsondepobj, ud.version, d, ud)
+ else:
+ self._getshrinkeddependencies(ud.pkgname, shrinkobj, ud.version, d, ud, lockdown, jsondepobj)
+
+ with open(ud.localpath, 'w') as outfile:
+ json.dump(jsondepobj, outfile)
+
+ def build_mirror_data(self, ud, d):
+ # Generate a mirror tarball if needed
+ if ud.write_tarballs and not os.path.exists(ud.fullmirror):
+ # it's possible that this symlink points to read-only filesystem with PREMIRROR
+ if os.path.islink(ud.fullmirror):
+ os.unlink(ud.fullmirror)
+
+ save_cwd = os.getcwd()
+ os.chdir(d.getVar("DL_DIR", True))
+ logger.info("Creating tarball of npm data")
+ runfetchcmd("tar -cJf %s npm/%s npm/%s" % (ud.fullmirror, ud.bbnpmmanifest, ud.pkgname), d)
+ runfetchcmd("touch %s.done" % (ud.fullmirror), d)
+ os.chdir(save_cwd)
+
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/osc.py b/yocto-poky/bitbake/lib/bb/fetch2/osc.py
index 3d8779682..d051dfdaf 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/osc.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/osc.py
@@ -34,13 +34,13 @@ class Osc(FetchMethod):
# Create paths to osc checkouts
relpath = self._strip_leading_slashes(ud.path)
- ud.pkgdir = os.path.join(data.expand('${OSCDIR}', d), ud.host)
+ ud.pkgdir = os.path.join(d.getVar('OSCDIR', True), ud.host)
ud.moddir = os.path.join(ud.pkgdir, relpath, ud.module)
if 'rev' in ud.parm:
ud.revision = ud.parm['rev']
else:
- pv = data.getVar("PV", d, 0)
+ pv = d.getVar("PV", False)
rev = bb.fetch2.srcrev_internal_helper(ud, d)
if rev and rev != True:
ud.revision = rev
@@ -84,7 +84,7 @@ class Osc(FetchMethod):
logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
- if os.access(os.path.join(data.expand('${OSCDIR}', d), ud.path, ud.module), os.R_OK):
+ if os.access(os.path.join(d.getVar('OSCDIR', True), ud.path, ud.module), os.R_OK):
oscupdatecmd = self._buildosccommand(ud, d, "update")
logger.info("Update "+ ud.url)
# update sources there
@@ -114,7 +114,7 @@ class Osc(FetchMethod):
Generate a .oscrc to be used for this run.
"""
- config_path = os.path.join(data.expand('${OSCDIR}', d), "oscrc")
+ config_path = os.path.join(d.getVar('OSCDIR', True), "oscrc")
if (os.path.exists(config_path)):
os.remove(config_path)
@@ -123,8 +123,8 @@ class Osc(FetchMethod):
f.write("apisrv = %s\n" % ud.host)
f.write("scheme = http\n")
f.write("su-wrapper = su -c\n")
- f.write("build-root = %s\n" % data.expand('${WORKDIR}', d))
- f.write("urllist = http://moblin-obs.jf.intel.com:8888/build/%(project)s/%(repository)s/%(buildarch)s/:full/%(name)s.rpm\n")
+ f.write("build-root = %s\n" % d.getVar('WORKDIR', True))
+ f.write("urllist = %s\n" % d.getVar("OSCURLLIST", True))
f.write("extra-pkgs = gzip\n")
f.write("\n")
f.write("[%s]\n" % ud.host)
diff --git a/yocto-poky/bitbake/lib/bb/fetch2/wget.py b/yocto-poky/bitbake/lib/bb/fetch2/wget.py
index bd2a8972a..8bc9e93ca 100644
--- a/yocto-poky/bitbake/lib/bb/fetch2/wget.py
+++ b/yocto-poky/bitbake/lib/bb/fetch2/wget.py
@@ -37,7 +37,9 @@ from bb.fetch2 import FetchMethod
from bb.fetch2 import FetchError
from bb.fetch2 import logger
from bb.fetch2 import runfetchcmd
+from bb.utils import export_proxies
from bs4 import BeautifulSoup
+from bs4 import SoupStrainer
class Wget(FetchMethod):
"""Class to fetch urls via 'wget'"""
@@ -61,6 +63,8 @@ class Wget(FetchMethod):
ud.basename = os.path.basename(ud.path)
ud.localfile = data.expand(urllib.unquote(ud.basename), d)
+ if not ud.localfile:
+ ud.localfile = data.expand(urllib.unquote(ud.host + ud.path).replace("/", "."), d)
self.basecmd = d.getVar("FETCHCMD_wget", True) or "/usr/bin/env wget -t 2 -T 30 -nv --passive-ftp --no-check-certificate"
@@ -218,54 +222,64 @@ class Wget(FetchMethod):
return resp
- def export_proxies(d):
- variables = ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY',
- 'ftp_proxy', 'FTP_PROXY', 'no_proxy', 'NO_PROXY']
- exported = False
-
- for v in variables:
- if v in os.environ.keys():
- exported = True
- else:
- v_proxy = d.getVar(v, True)
- if v_proxy is not None:
- os.environ[v] = v_proxy
- exported = True
-
- return exported
-
- def head_method(self):
- return "HEAD"
-
+ class HTTPMethodFallback(urllib2.BaseHandler):
+ """
+ Fallback to GET if HEAD is not allowed (405 HTTP error)
+ """
+ def http_error_405(self, req, fp, code, msg, headers):
+ fp.read()
+ fp.close()
+
+ newheaders = dict((k,v) for k,v in req.headers.items()
+ if k.lower() not in ("content-length", "content-type"))
+ return self.parent.open(urllib2.Request(req.get_full_url(),
+ headers=newheaders,
+ origin_req_host=req.get_origin_req_host(),
+ unverifiable=True))
+
+ """
+ Some servers (e.g. GitHub archives, hosted on Amazon S3) return 403
+ Forbidden when they actually mean 405 Method Not Allowed.
+ """
+ http_error_403 = http_error_405
+
+ """
+ Some servers (e.g. FusionForge) returns 406 Not Acceptable when they
+ actually mean 405 Method Not Allowed.
+ """
+ http_error_406 = http_error_405
+
+ class FixedHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
+ """
+ urllib2.HTTPRedirectHandler resets the method to GET on redirect,
+ when we want to follow redirects using the original method.
+ """
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
+ newreq = urllib2.HTTPRedirectHandler.redirect_request(self, req, fp, code, msg, headers, newurl)
+ newreq.get_method = lambda: req.get_method()
+ return newreq
exported_proxies = export_proxies(d)
+ handlers = [FixedHTTPRedirectHandler, HTTPMethodFallback]
+ if export_proxies:
+ handlers.append(urllib2.ProxyHandler())
+ handlers.append(CacheHTTPHandler())
# XXX: Since Python 2.7.9 ssl cert validation is enabled by default
# see PEP-0476, this causes verification errors on some https servers
# so disable by default.
import ssl
- ssl_context = None
if hasattr(ssl, '_create_unverified_context'):
- ssl_context = ssl._create_unverified_context()
-
- if exported_proxies == True and ssl_context is not None:
- opener = urllib2.build_opener(urllib2.ProxyHandler, CacheHTTPHandler,
- urllib2.HTTPSHandler(context=ssl_context))
- elif exported_proxies == False and ssl_context is not None:
- opener = urllib2.build_opener(CacheHTTPHandler,
- urllib2.HTTPSHandler(context=ssl_context))
- elif exported_proxies == True and ssl_context is None:
- opener = urllib2.build_opener(urllib2.ProxyHandler, CacheHTTPHandler)
- else:
- opener = urllib2.build_opener(CacheHTTPHandler)
-
- urllib2.Request.get_method = head_method
- urllib2.install_opener(opener)
-
- uri = ud.url.split(";")[0]
+ handlers.append(urllib2.HTTPSHandler(context=ssl._create_unverified_context()))
+ opener = urllib2.build_opener(*handlers)
try:
- urllib2.urlopen(uri)
- except:
+ uri = ud.url.split(";")[0]
+ r = urllib2.Request(uri)
+ r.get_method = lambda: "HEAD"
+ opener.open(r)
+ except urllib2.URLError as e:
+ # debug for now to avoid spamming the logs in e.g. remote sstate searches
+ logger.debug(2, "checkstatus() urlopen failed: %s" % e)
return False
return True
@@ -367,7 +381,7 @@ class Wget(FetchMethod):
version = ['', '', '']
bb.debug(3, "VersionURL: %s" % (url))
- soup = BeautifulSoup(self._fetch_index(url, ud, d))
+ soup = BeautifulSoup(self._fetch_index(url, ud, d), "html.parser", parse_only=SoupStrainer("a"))
if not soup:
bb.debug(3, "*** %s NO SOUP" % (url))
return ""
@@ -406,10 +420,10 @@ class Wget(FetchMethod):
version_dir = ['', '', '']
version = ['', '', '']
- dirver_regex = re.compile("(\D*)((\d+[\.\-_])+(\d+))")
+ dirver_regex = re.compile("(?P<pfx>\D*)(?P<ver>(\d+[\.\-_])+(\d+))")
s = dirver_regex.search(dirver)
if s:
- version_dir[1] = s.group(2)
+ version_dir[1] = s.group('ver')
else:
version_dir[1] = dirver
@@ -417,16 +431,26 @@ class Wget(FetchMethod):
ud.path.split(dirver)[0], ud.user, ud.pswd, {}])
bb.debug(3, "DirURL: %s, %s" % (dirs_uri, package))
- soup = BeautifulSoup(self._fetch_index(dirs_uri, ud, d))
+ soup = BeautifulSoup(self._fetch_index(dirs_uri, ud, d), "html.parser", parse_only=SoupStrainer("a"))
if not soup:
return version[1]
for line in soup.find_all('a', href=True):
s = dirver_regex.search(line['href'].strip("/"))
if s:
- version_dir_new = ['', s.group(2), '']
+ sver = s.group('ver')
+
+ # When prefix is part of the version directory it need to
+ # ensure that only version directory is used so remove previous
+ # directories if exists.
+ #
+ # Example: pfx = '/dir1/dir2/v' and version = '2.5' the expected
+ # result is v2.5.
+ spfx = s.group('pfx').split('/')[-1]
+
+ version_dir_new = ['', sver, '']
if self._vercmp(version_dir, version_dir_new) <= 0:
- dirver_new = s.group(1) + s.group(2)
+ dirver_new = spfx + sver
path = ud.path.replace(dirver, dirver_new, True) \
.split(package)[0]
uri = bb.fetch.encodeurl([ud.type, ud.host, path,
@@ -480,7 +504,7 @@ class Wget(FetchMethod):
self.suffix_regex_comp = re.compile(psuffix_regex)
# compile regex, can be specific by package or generic regex
- pn_regex = d.getVar('REGEX', True)
+ pn_regex = d.getVar('UPSTREAM_CHECK_REGEX', True)
if pn_regex:
package_custom_regex_comp = re.compile(pn_regex)
else:
@@ -516,7 +540,7 @@ class Wget(FetchMethod):
bb.debug(3, "latest_versionstring, regex: %s" % (package_regex.pattern))
uri = ""
- regex_uri = d.getVar("REGEX_URI", True)
+ regex_uri = d.getVar("UPSTREAM_CHECK_URI", True)
if not regex_uri:
path = ud.path.split(package)[0]
diff --git a/yocto-poky/bitbake/lib/bb/main.py b/yocto-poky/bitbake/lib/bb/main.py
index c8530fc3d..e30217369 100755
--- a/yocto-poky/bitbake/lib/bb/main.py
+++ b/yocto-poky/bitbake/lib/bb/main.py
@@ -219,6 +219,9 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
parser.add_option("", "--no-setscene", help = "Do not run any setscene tasks. sstate will be ignored and everything needed, built.",
action = "store_true", dest = "nosetscene", default = False)
+ parser.add_option("", "--setscene-only", help = "Only run setscene tasks, don't run any real tasks.",
+ action = "store_true", dest = "setsceneonly", default = False)
+
parser.add_option("", "--remote-server", help = "Connect to the specified server.",
action = "store", dest = "remote_server", default = False)
@@ -244,7 +247,7 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
if "BBTOKEN" in os.environ:
options.xmlrpctoken = os.environ["BBTOKEN"]
- if "BBEVENTLOG" is os.environ:
+ if "BBEVENTLOG" in os.environ:
options.writeeventlog = os.environ["BBEVENTLOG"]
# fill in proper log name if not supplied
@@ -279,12 +282,13 @@ class BitBakeConfigParameters(cookerdata.ConfigParameters):
def start_server(servermodule, configParams, configuration, features):
server = servermodule.BitBakeServer()
+ single_use = not configParams.server_only
if configParams.bind:
(host, port) = configParams.bind.split(':')
- server.initServer((host, int(port)))
+ server.initServer((host, int(port)), single_use)
configuration.interface = [ server.serverImpl.host, server.serverImpl.port ]
else:
- server.initServer()
+ server.initServer(single_use=single_use)
configuration.interface = []
try:
@@ -406,6 +410,13 @@ def bitbake_main(configParams, configuration):
except Exception as e:
bb.fatal("Could not connect to server %s: %s" % (configParams.remote_server, str(e)))
+ if configParams.kill_server:
+ server_connection.connection.terminateServer()
+ bb.event.ui_queue = []
+ return 0
+
+ server_connection.setupEventQueue()
+
# Restore the environment in case the UI needs it
for k in cleanedvars:
os.environ[k] = cleanedvars[k]
@@ -417,11 +428,6 @@ def bitbake_main(configParams, configuration):
server_connection.terminate()
return 0
- if configParams.kill_server:
- server_connection.connection.terminateServer()
- bb.event.ui_queue = []
- return 0
-
try:
return ui_module.main(server_connection.connection, server_connection.events, configParams)
finally:
diff --git a/yocto-poky/bitbake/lib/bb/methodpool.py b/yocto-poky/bitbake/lib/bb/methodpool.py
index bf2e9f554..49aed3338 100644
--- a/yocto-poky/bitbake/lib/bb/methodpool.py
+++ b/yocto-poky/bitbake/lib/bb/methodpool.py
@@ -19,11 +19,22 @@
from bb.utils import better_compile, better_exec
-def insert_method(modulename, code, fn):
+def insert_method(modulename, code, fn, lineno):
"""
Add code of a module should be added. The methods
will be simply added, no checking will be done
"""
- comp = better_compile(code, modulename, fn )
+ comp = better_compile(code, modulename, fn, lineno=lineno)
better_exec(comp, None, code, fn)
+compilecache = {}
+
+def compile_cache(code):
+ h = hash(code)
+ if h in compilecache:
+ return compilecache[h]
+ return None
+
+def compile_cache_add(code, compileobj):
+ h = hash(code)
+ compilecache[h] = compileobj
diff --git a/yocto-poky/bitbake/lib/bb/parse/__init__.py b/yocto-poky/bitbake/lib/bb/parse/__init__.py
index 67ec71f86..26ae7ead8 100644
--- a/yocto-poky/bitbake/lib/bb/parse/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/parse/__init__.py
@@ -161,8 +161,8 @@ def vars_from_file(mypkg, d):
def get_file_depends(d):
'''Return the dependent files'''
dep_files = []
- depends = d.getVar('__base_depends', True) or []
- depends = depends + (d.getVar('__depends', True) or [])
+ depends = d.getVar('__base_depends', False) or []
+ depends = depends + (d.getVar('__depends', False) or [])
for (fn, _) in depends:
dep_files.append(os.path.abspath(fn))
return " ".join(dep_files)
diff --git a/yocto-poky/bitbake/lib/bb/parse/ast.py b/yocto-poky/bitbake/lib/bb/parse/ast.py
index 11db1801b..5f55af5ef 100644
--- a/yocto-poky/bitbake/lib/bb/parse/ast.py
+++ b/yocto-poky/bitbake/lib/bb/parse/ast.py
@@ -83,7 +83,7 @@ class DataNode(AstNode):
def getFunc(self, key, data):
if 'flag' in self.groupd and self.groupd['flag'] != None:
- return data.getVarFlag(key, self.groupd['flag'], noweakdefault=True)
+ return data.getVarFlag(key, self.groupd['flag'], expand=False, noweakdefault=True)
else:
return data.getVar(key, False, noweakdefault=True, parsing=True)
@@ -141,24 +141,37 @@ class DataNode(AstNode):
class MethodNode(AstNode):
tr_tbl = string.maketrans('/.+-@%&', '_______')
- def __init__(self, filename, lineno, func_name, body):
+ def __init__(self, filename, lineno, func_name, body, python, fakeroot):
AstNode.__init__(self, filename, lineno)
self.func_name = func_name
self.body = body
+ self.python = python
+ self.fakeroot = fakeroot
def eval(self, data):
text = '\n'.join(self.body)
+ funcname = self.func_name
if self.func_name == "__anonymous":
funcname = ("__anon_%s_%s" % (self.lineno, self.filename.translate(MethodNode.tr_tbl)))
+ self.python = True
text = "def %s(d):\n" % (funcname) + text
- bb.methodpool.insert_method(funcname, text, self.filename)
+ bb.methodpool.insert_method(funcname, text, self.filename, self.lineno - len(self.body))
anonfuncs = data.getVar('__BBANONFUNCS', False) or []
anonfuncs.append(funcname)
data.setVar('__BBANONFUNCS', anonfuncs)
- data.setVar(funcname, text, parsing=True)
- else:
- data.setVarFlag(self.func_name, "func", 1)
- data.setVar(self.func_name, text, parsing=True)
+ if data.getVar(funcname, False):
+ # clean up old version of this piece of metadata, as its
+ # flags could cause problems
+ data.delVarFlag(funcname, 'python')
+ data.delVarFlag(funcname, 'fakeroot')
+ if self.python:
+ data.setVarFlag(funcname, "python", "1")
+ if self.fakeroot:
+ data.setVarFlag(funcname, "fakeroot", "1")
+ data.setVarFlag(funcname, "func", 1)
+ data.setVar(funcname, text, parsing=True)
+ data.setVarFlag(funcname, 'filename', self.filename)
+ data.setVarFlag(funcname, 'lineno', str(self.lineno - len(self.body)))
class PythonMethodNode(AstNode):
def __init__(self, filename, lineno, function, modulename, body):
@@ -172,31 +185,12 @@ class PythonMethodNode(AstNode):
# 'this' file. This means we will not parse methods from
# bb classes twice
text = '\n'.join(self.body)
- bb.methodpool.insert_method(self.modulename, text, self.filename)
+ bb.methodpool.insert_method(self.modulename, text, self.filename, self.lineno - len(self.body) - 1)
data.setVarFlag(self.function, "func", 1)
data.setVarFlag(self.function, "python", 1)
data.setVar(self.function, text, parsing=True)
-
-class MethodFlagsNode(AstNode):
- def __init__(self, filename, lineno, key, m):
- AstNode.__init__(self, filename, lineno)
- self.key = key
- self.m = m
-
- def eval(self, data):
- if data.getVar(self.key, False):
- # clean up old version of this piece of metadata, as its
- # flags could cause problems
- data.setVarFlag(self.key, 'python', None)
- data.setVarFlag(self.key, 'fakeroot', None)
- if self.m.group("py") is not None:
- data.setVarFlag(self.key, "python", "1")
- else:
- data.delVarFlag(self.key, "python")
- if self.m.group("fr") is not None:
- data.setVarFlag(self.key, "fakeroot", "1")
- else:
- data.delVarFlag(self.key, "fakeroot")
+ data.setVarFlag(self.function, 'filename', self.filename)
+ data.setVarFlag(self.function, 'lineno', str(self.lineno - len(self.body) - 1))
class ExportFuncsNode(AstNode):
def __init__(self, filename, lineno, fns, classname):
@@ -209,7 +203,7 @@ class ExportFuncsNode(AstNode):
for func in self.n:
calledfunc = self.classname + "_" + func
- if data.getVar(func, False) and not data.getVarFlag(func, 'export_func'):
+ if data.getVar(func, False) and not data.getVarFlag(func, 'export_func', False):
continue
if data.getVar(func, False):
@@ -217,13 +211,15 @@ class ExportFuncsNode(AstNode):
data.setVarFlag(func, 'func', None)
for flag in [ "func", "python" ]:
- if data.getVarFlag(calledfunc, flag):
- data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag))
+ if data.getVarFlag(calledfunc, flag, False):
+ data.setVarFlag(func, flag, data.getVarFlag(calledfunc, flag, False))
for flag in [ "dirs" ]:
- if data.getVarFlag(func, flag):
- data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag))
+ if data.getVarFlag(func, flag, False):
+ data.setVarFlag(calledfunc, flag, data.getVarFlag(func, flag, False))
+ data.setVarFlag(func, "filename", "autogenerated")
+ data.setVarFlag(func, "lineno", 1)
- if data.getVarFlag(calledfunc, "python"):
+ if data.getVarFlag(calledfunc, "python", False):
data.setVar(func, " bb.build.exec_func('" + calledfunc + "', d)\n", parsing=True)
else:
if "-" in self.classname:
@@ -278,15 +274,12 @@ def handleExport(statements, filename, lineno, m):
def handleData(statements, filename, lineno, groupd):
statements.append(DataNode(filename, lineno, groupd))
-def handleMethod(statements, filename, lineno, func_name, body):
- statements.append(MethodNode(filename, lineno, func_name, body))
+def handleMethod(statements, filename, lineno, func_name, body, python, fakeroot):
+ statements.append(MethodNode(filename, lineno, func_name, body, python, fakeroot))
def handlePythonMethod(statements, filename, lineno, funcname, modulename, body):
statements.append(PythonMethodNode(filename, lineno, funcname, modulename, body))
-def handleMethodFlags(statements, filename, lineno, key, m):
- statements.append(MethodFlagsNode(filename, lineno, key, m))
-
def handleExportFuncs(statements, filename, lineno, m, classname):
statements.append(ExportFuncsNode(filename, lineno, m.group(1), classname))
@@ -317,7 +310,9 @@ def finalize(fn, d, variant = None):
all_handlers = {}
for var in d.getVar('__BBHANDLERS', False) or []:
# try to add the handler
- bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask", True) or "").split())
+ handlerfn = d.getVarFlag(var, "filename", False)
+ handlerln = int(d.getVarFlag(var, "lineno", False))
+ bb.event.register(var, d.getVar(var, False), (d.getVarFlag(var, "eventmask", True) or "").split(), handlerfn, handlerln)
bb.event.fire(bb.event.RecipePreFinalise(fn), d)
diff --git a/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py b/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py
index ec097baf7..ef72c3700 100644
--- a/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py
+++ b/yocto-poky/bitbake/lib/bb/parse/parse_py/BBHandler.py
@@ -47,7 +47,6 @@ __addhandler_regexp__ = re.compile( r"addhandler\s+(.+)" )
__def_regexp__ = re.compile( r"def\s+(\w+).*:" )
__python_func_regexp__ = re.compile( r"(\s+.*)|(^$)" )
-
__infunc__ = []
__inpython__ = False
__body__ = []
@@ -55,15 +54,6 @@ __classname__ = ""
cached_statements = {}
-# We need to indicate EOF to the feeder. This code is so messy that
-# factoring it out to a close_parse_file method is out of question.
-# We will use the IN_PYTHON_EOF as an indicator to just close the method
-#
-# The two parts using it are tightly integrated anyway
-IN_PYTHON_EOF = -9999999999999
-
-
-
def supports(fn, d):
"""Return True if fn has a supported extension"""
return os.path.splitext(fn)[-1] in [".bb", ".bbclass", ".inc"]
@@ -110,7 +100,7 @@ def get_statements(filename, absolute_filename, base_name):
file.close()
if __inpython__:
# add a blank line to close out any python definition
- feeder(IN_PYTHON_EOF, "", filename, base_name, statements)
+ feeder(lineno, "", filename, base_name, statements, eof=True)
if filename.endswith(".bbclass") or filename.endswith(".inc"):
cached_statements[absolute_filename] = statements
@@ -171,12 +161,12 @@ def handle(fn, d, include):
return d
-def feeder(lineno, s, fn, root, statements):
+def feeder(lineno, s, fn, root, statements, eof=False):
global __func_start_regexp__, __inherit_regexp__, __export_func_regexp__, __addtask_regexp__, __addhandler_regexp__, __def_regexp__, __python_func_regexp__, __inpython__, __infunc__, __body__, bb, __residue__, __classname__
if __infunc__:
if s == '}':
__body__.append('')
- ast.handleMethod(statements, fn, lineno, __infunc__[0], __body__)
+ ast.handleMethod(statements, fn, lineno, __infunc__[0], __body__, __infunc__[3], __infunc__[4])
__infunc__ = []
__body__ = []
else:
@@ -185,7 +175,7 @@ def feeder(lineno, s, fn, root, statements):
if __inpython__:
m = __python_func_regexp__.match(s)
- if m and lineno != IN_PYTHON_EOF:
+ if m and not eof:
__body__.append(s)
return
else:
@@ -194,7 +184,7 @@ def feeder(lineno, s, fn, root, statements):
__body__ = []
__inpython__ = False
- if lineno == IN_PYTHON_EOF:
+ if eof:
return
if s and s[0] == '#':
@@ -221,8 +211,7 @@ def feeder(lineno, s, fn, root, statements):
m = __func_start_regexp__.match(s)
if m:
- __infunc__ = [m.group("func") or "__anonymous", fn, lineno]
- ast.handleMethodFlags(statements, fn, lineno, __infunc__[0], m)
+ __infunc__ = [m.group("func") or "__anonymous", fn, lineno, m.group("py") is not None, m.group("fr") is not None]
return
m = __def_regexp__.match(s)
diff --git a/yocto-poky/bitbake/lib/bb/persist_data.py b/yocto-poky/bitbake/lib/bb/persist_data.py
index 5795bc835..e45042324 100644
--- a/yocto-poky/bitbake/lib/bb/persist_data.py
+++ b/yocto-poky/bitbake/lib/bb/persist_data.py
@@ -201,6 +201,7 @@ class PersistData(object):
def connect(database):
connection = sqlite3.connect(database, timeout=5, isolation_level=None)
connection.execute("pragma synchronous = off;")
+ connection.text_factory = str
return connection
def persist(domain, d):
diff --git a/yocto-poky/bitbake/lib/bb/providers.py b/yocto-poky/bitbake/lib/bb/providers.py
index 637e1fab9..563a091fd 100644
--- a/yocto-poky/bitbake/lib/bb/providers.py
+++ b/yocto-poky/bitbake/lib/bb/providers.py
@@ -121,11 +121,14 @@ def findPreferredProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
preferred_file = None
preferred_ver = None
- localdata = data.createCopy(cfgData)
- localdata.setVar('OVERRIDES', "%s:pn-%s:%s" % (data.getVar('OVERRIDES', localdata), pn, pn))
- bb.data.update_data(localdata)
+ # pn can contain '_', e.g. gcc-cross-x86_64 and an override cannot
+ # hence we do this manually rather than use OVERRIDES
+ preferred_v = cfgData.getVar("PREFERRED_VERSION_pn-%s" % pn, True)
+ if not preferred_v:
+ preferred_v = cfgData.getVar("PREFERRED_VERSION_%s" % pn, True)
+ if not preferred_v:
+ preferred_v = cfgData.getVar("PREFERRED_VERSION", True)
- preferred_v = localdata.getVar('PREFERRED_VERSION', True)
if preferred_v:
m = re.match('(\d+:)*(.*)(_.*)*', preferred_v)
if m:
@@ -223,7 +226,7 @@ def findBestProvider(pn, cfgData, dataCache, pkg_pn = None, item = None):
def _filterProviders(providers, item, cfgData, dataCache):
"""
Take a list of providers and filter/reorder according to the
- environment variables and previous build results
+ environment variables
"""
eligible = []
preferred_versions = {}
@@ -280,7 +283,7 @@ def _filterProviders(providers, item, cfgData, dataCache):
def filterProviders(providers, item, cfgData, dataCache):
"""
Take a list of providers and filter/reorder according to the
- environment variables and previous build results
+ environment variables
Takes a "normal" target item
"""
@@ -308,38 +311,56 @@ def filterProviders(providers, item, cfgData, dataCache):
def filterProvidersRunTime(providers, item, cfgData, dataCache):
"""
Take a list of providers and filter/reorder according to the
- environment variables and previous build results
+ environment variables
Takes a "runtime" target item
"""
eligible = _filterProviders(providers, item, cfgData, dataCache)
- # Should use dataCache.preferred here?
- preferred = []
- preferred_vars = []
- pns = {}
- for p in eligible:
- pns[dataCache.pkg_fn[p]] = p
- for p in eligible:
- pn = dataCache.pkg_fn[p]
- provides = dataCache.pn_provides[pn]
- for provide in provides:
- prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide, True)
- #logger.debug(1, "checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
- if prefervar in pns and pns[prefervar] not in preferred:
- var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
- logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var)
- preferred_vars.append(var)
- pref = pns[prefervar]
- eligible.remove(pref)
- eligible = [pref] + eligible
- preferred.append(pref)
+ # First try and match any PREFERRED_RPROVIDER entry
+ prefervar = cfgData.getVar('PREFERRED_RPROVIDER_%s' % item, True)
+ foundUnique = False
+ if prefervar:
+ for p in eligible:
+ pn = dataCache.pkg_fn[p]
+ if prefervar == pn:
+ logger.verbose("selecting %s to satisfy %s due to PREFERRED_RPROVIDER", pn, item)
+ eligible.remove(p)
+ eligible = [p] + eligible
+ foundUnique = True
+ numberPreferred = 1
break
- numberPreferred = len(preferred)
+ # If we didn't find an RPROVIDER entry, try and infer the provider from PREFERRED_PROVIDER entries
+ # by looking through the provides of each eligible recipe and seeing if a PREFERRED_PROVIDER was set.
+ # This is most useful for virtual/ entries rather than having a RPROVIDER per entry.
+ if not foundUnique:
+ # Should use dataCache.preferred here?
+ preferred = []
+ preferred_vars = []
+ pns = {}
+ for p in eligible:
+ pns[dataCache.pkg_fn[p]] = p
+ for p in eligible:
+ pn = dataCache.pkg_fn[p]
+ provides = dataCache.pn_provides[pn]
+ for provide in provides:
+ prefervar = cfgData.getVar('PREFERRED_PROVIDER_%s' % provide, True)
+ #logger.debug(1, "checking PREFERRED_PROVIDER_%s (value %s) against %s", provide, prefervar, pns.keys())
+ if prefervar in pns and pns[prefervar] not in preferred:
+ var = "PREFERRED_PROVIDER_%s = %s" % (provide, prefervar)
+ logger.verbose("selecting %s to satisfy runtime %s due to %s", prefervar, item, var)
+ preferred_vars.append(var)
+ pref = pns[prefervar]
+ eligible.remove(pref)
+ eligible = [pref] + eligible
+ preferred.append(pref)
+ break
+
+ numberPreferred = len(preferred)
if numberPreferred > 1:
- logger.error("Trying to resolve runtime dependency %s resulted in conflicting PREFERRED_PROVIDER entries being found.\nThe providers found were: %s\nThe PREFERRED_PROVIDER entries resulting in this conflict were: %s", item, preferred, preferred_vars)
+ logger.error("Trying to resolve runtime dependency %s resulted in conflicting PREFERRED_PROVIDER entries being found.\nThe providers found were: %s\nThe PREFERRED_PROVIDER entries resulting in this conflict were: %s. You could set PREFERRED_RPROVIDER_%s" % (item, preferred, preferred_vars, item))
logger.debug(1, "sorted runtime providers for %s are: %s", item, eligible)
@@ -379,3 +400,29 @@ def getRuntimeProviders(dataCache, rdepend):
logger.debug(1, "Assuming %s is a dynamic package, but it may not exist" % rdepend)
return rproviders
+
+
+def buildWorldTargetList(dataCache):
+ """
+ Build package list for "bitbake world"
+ """
+ if dataCache.world_target:
+ return
+
+ logger.debug(1, "collating packages for \"world\"")
+ for f in dataCache.possible_world:
+ terminal = True
+ pn = dataCache.pkg_fn[f]
+
+ for p in dataCache.pn_provides[pn]:
+ if p.startswith('virtual/'):
+ logger.debug(2, "World build skipping %s due to %s provider starting with virtual/", f, p)
+ terminal = False
+ break
+ for pf in dataCache.providers[p]:
+ if dataCache.pkg_fn[pf] != pn:
+ logger.debug(2, "World build skipping %s due to both us and %s providing %s", f, pf, p)
+ terminal = False
+ break
+ if terminal:
+ dataCache.world_target.add(pn)
diff --git a/yocto-poky/bitbake/lib/bb/runqueue.py b/yocto-poky/bitbake/lib/bb/runqueue.py
index 878028aa9..e1b9b2e66 100644
--- a/yocto-poky/bitbake/lib/bb/runqueue.py
+++ b/yocto-poky/bitbake/lib/bb/runqueue.py
@@ -261,6 +261,13 @@ class RunQueueData:
taskname = self.runq_task[task] + task_name_suffix
return "%s, %s" % (fn, taskname)
+ def get_short_user_idstring(self, task, task_name_suffix = ""):
+ fn = self.taskData.fn_index[self.runq_fnid[task]]
+ pn = self.dataCache.pkg_fn[fn]
+ taskname = self.runq_task[task] + task_name_suffix
+ return "%s:%s" % (pn, taskname)
+
+
def get_task_id(self, fnid, taskname):
for listid in xrange(len(self.runq_fnid)):
if self.runq_fnid[listid] == fnid and self.runq_task[listid] == taskname:
@@ -634,23 +641,33 @@ class RunQueueData:
fnid = taskData.build_targets[targetid][0]
fn = taskData.fn_index[fnid]
- self.target_pairs.append((fn, target[1]))
+ task = target[1]
+ parents = False
+ if task.endswith('-'):
+ parents = True
+ task = task[:-1]
+
+ self.target_pairs.append((fn, task))
if fnid in taskData.failed_fnids:
continue
- if target[1] not in taskData.tasks_lookup[fnid]:
+ if task not in taskData.tasks_lookup[fnid]:
import difflib
- close_matches = difflib.get_close_matches(target[1], taskData.tasks_lookup[fnid], cutoff=0.7)
+ close_matches = difflib.get_close_matches(task, taskData.tasks_lookup[fnid], cutoff=0.7)
if close_matches:
extra = ". Close matches:\n %s" % "\n ".join(close_matches)
else:
extra = ""
- bb.msg.fatal("RunQueue", "Task %s does not exist for target %s%s" % (target[1], target[0], extra))
-
- listid = taskData.tasks_lookup[fnid][target[1]]
-
- mark_active(listid, 1)
+ bb.msg.fatal("RunQueue", "Task %s does not exist for target %s%s" % (task, target[0], extra))
+
+ # For tasks called "XXXX-", ony run their dependencies
+ listid = taskData.tasks_lookup[fnid][task]
+ if parents:
+ for i in self.runq_depends[listid]:
+ mark_active(i, 1)
+ else:
+ mark_active(listid, 1)
# Step C - Prune all inactive tasks
#
@@ -743,11 +760,72 @@ class RunQueueData:
seen_pn.append(pn)
else:
bb.fatal("Multiple versions of %s are due to be built (%s). Only one version of a given PN should be built in any given build. You likely need to set PREFERRED_VERSION_%s to select the correct version or don't depend on multiple versions." % (pn, " ".join(prov_list[prov]), pn))
- msg = "Multiple .bb files are due to be built which each provide %s (%s)." % (prov, " ".join(prov_list[prov]))
+ msg = "Multiple .bb files are due to be built which each provide %s:\n %s" % (prov, "\n ".join(prov_list[prov]))
+ #
+ # Construct a list of things which uniquely depend on each provider
+ # since this may help the user figure out which dependency is triggering this warning
+ #
+ msg += "\nA list of tasks depending on these providers is shown and may help explain where the dependency comes from."
+ deplist = {}
+ commondeps = None
+ for provfn in prov_list[prov]:
+ deps = set()
+ for task, fnid in enumerate(self.runq_fnid):
+ fn = taskData.fn_index[fnid]
+ if fn != provfn:
+ continue
+ for dep in self.runq_revdeps[task]:
+ fn = taskData.fn_index[self.runq_fnid[dep]]
+ if fn == provfn:
+ continue
+ deps.add(self.get_short_user_idstring(dep))
+ if not commondeps:
+ commondeps = set(deps)
+ else:
+ commondeps &= deps
+ deplist[provfn] = deps
+ for provfn in deplist:
+ msg += "\n%s has unique dependees:\n %s" % (provfn, "\n ".join(deplist[provfn] - commondeps))
+ #
+ # Construct a list of provides and runtime providers for each recipe
+ # (rprovides has to cover RPROVIDES, PACKAGES, PACKAGES_DYNAMIC)
+ #
+ msg += "\nIt could be that one recipe provides something the other doesn't and should. The following provider and runtime provider differences may be helpful."
+ provide_results = {}
+ rprovide_results = {}
+ commonprovs = None
+ commonrprovs = None
+ for provfn in prov_list[prov]:
+ provides = set(self.dataCache.fn_provides[provfn])
+ rprovides = set()
+ for rprovide in self.dataCache.rproviders:
+ if provfn in self.dataCache.rproviders[rprovide]:
+ rprovides.add(rprovide)
+ for package in self.dataCache.packages:
+ if provfn in self.dataCache.packages[package]:
+ rprovides.add(package)
+ for package in self.dataCache.packages_dynamic:
+ if provfn in self.dataCache.packages_dynamic[package]:
+ rprovides.add(package)
+ if not commonprovs:
+ commonprovs = set(provides)
+ else:
+ commonprovs &= provides
+ provide_results[provfn] = provides
+ if not commonrprovs:
+ commonrprovs = set(rprovides)
+ else:
+ commonrprovs &= rprovides
+ rprovide_results[provfn] = rprovides
+ #msg += "\nCommon provides:\n %s" % ("\n ".join(commonprovs))
+ #msg += "\nCommon rprovides:\n %s" % ("\n ".join(commonrprovs))
+ for provfn in prov_list[prov]:
+ msg += "\n%s has unique provides:\n %s" % (provfn, "\n ".join(provide_results[provfn] - commonprovs))
+ msg += "\n%s has unique rprovides:\n %s" % (provfn, "\n ".join(rprovide_results[provfn] - commonrprovs))
+
if self.warn_multi_bb:
logger.warn(msg)
else:
- msg += "\n This usually means one provides something the other doesn't and should."
logger.error(msg)
# Create a whitelist usable by the stamp checks
@@ -798,7 +876,7 @@ class RunQueueData:
invalidate_task(fn, st, True)
# Create and print to the logs a virtual/xxxx -> PN (fn) table
- virtmap = taskData.get_providermap()
+ virtmap = taskData.get_providermap(prefix="virtual/")
virtpnmap = {}
for v in virtmap:
virtpnmap[v] = self.dataCache.pkg_fn[virtmap[v]]
@@ -819,6 +897,7 @@ class RunQueueData:
procdep.append(self.taskData.fn_index[self.runq_fnid[dep]] + "." + self.runq_task[dep])
self.runq_hash[task] = bb.parse.siggen.get_taskhash(self.taskData.fn_index[self.runq_fnid[task]], self.runq_task[task], procdep, self.dataCache)
+ bb.parse.siggen.writeout_file_checksum_cache()
return len(self.runq_fnid)
def dump_data(self, taskQueue):
@@ -874,6 +953,7 @@ class RunQueue:
if self.cooker.configuration.profile:
magic = "decafbadbad"
if fakeroot:
+ magic = magic + "beef"
fakerootcmd = self.cfgData.getVar("FAKEROOTCMD", True)
fakerootenv = (self.cfgData.getVar("FAKEROOTBASEENV", True) or "").split()
env = os.environ.copy()
@@ -1067,9 +1147,12 @@ class RunQueue:
retval = self.rqexe.execute()
if self.state is runQueueRunInit:
- logger.info("Executing RunQueue Tasks")
- self.rqexe = RunQueueExecuteTasks(self)
- self.state = runQueueRunning
+ if self.cooker.configuration.setsceneonly:
+ self.state = runQueueComplete
+ else:
+ logger.info("Executing RunQueue Tasks")
+ self.rqexe = RunQueueExecuteTasks(self)
+ self.state = runQueueRunning
if self.state is runQueueRunning:
retval = self.rqexe.execute()
@@ -1388,7 +1471,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
self.runq_buildable.append(1)
else:
self.runq_buildable.append(0)
- if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered) and task not in self.rq.scenequeue_notcovered:
+ if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered):
self.rq.scenequeue_covered.add(task)
found = True
@@ -1399,7 +1482,7 @@ class RunQueueExecuteTasks(RunQueueExecute):
continue
logger.debug(1, 'Considering %s (%s): %s' % (task, self.rqdata.get_user_idstring(task), str(self.rqdata.runq_revdeps[task])))
- if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered) and task not in self.rq.scenequeue_notcovered:
+ if len(self.rqdata.runq_revdeps[task]) > 0 and self.rqdata.runq_revdeps[task].issubset(self.rq.scenequeue_covered):
found = True
self.rq.scenequeue_covered.add(task)
@@ -1708,6 +1791,7 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
sq_revdeps_new[point] = set()
if point in self.rqdata.runq_setscene:
sq_revdeps_new[point] = tasks
+ tasks = set()
for dep in self.rqdata.runq_depends[point]:
if point in sq_revdeps[dep]:
sq_revdeps[dep].remove(point)
@@ -2014,9 +2098,6 @@ class RunQueueExecuteScenequeue(RunQueueExecute):
self.rq.scenequeue_covered = set()
for task in oldcovered:
self.rq.scenequeue_covered.add(self.rqdata.runq_setscene[task])
- self.rq.scenequeue_notcovered = set()
- for task in self.scenequeue_notcovered:
- self.rq.scenequeue_notcovered.add(self.rqdata.runq_setscene[task])
logger.debug(1, 'We can skip tasks %s', sorted(self.rq.scenequeue_covered))
diff --git a/yocto-poky/bitbake/lib/bb/server/__init__.py b/yocto-poky/bitbake/lib/bb/server/__init__.py
index da5e48074..538a633fe 100644
--- a/yocto-poky/bitbake/lib/bb/server/__init__.py
+++ b/yocto-poky/bitbake/lib/bb/server/__init__.py
@@ -63,6 +63,9 @@ class BitBakeBaseServerConnection():
def terminate(self):
pass
+ def setupEventQueue(self):
+ pass
+
""" BitBakeBaseServer class is the common ancestor to all Bitbake servers
diff --git a/yocto-poky/bitbake/lib/bb/server/process.py b/yocto-poky/bitbake/lib/bb/server/process.py
index 5fca3508b..a3078a873 100644
--- a/yocto-poky/bitbake/lib/bb/server/process.py
+++ b/yocto-poky/bitbake/lib/bb/server/process.py
@@ -53,10 +53,12 @@ class ServerCommunicator():
while True:
# don't let the user ctrl-c while we're waiting for a response
try:
- if self.connection.poll(20):
- return self.connection.recv()
- else:
- bb.fatal("Timeout while attempting to communicate with bitbake server")
+ for idx in range(0,4): # 0, 1, 2, 3
+ if self.connection.poll(5):
+ return self.connection.recv()
+ else:
+ bb.warn("Timeout while attempting to communicate with bitbake server")
+ bb.fatal("Gave up; Too many tries: timeout while attempting to communicate with bitbake server")
except KeyboardInterrupt:
pass
@@ -106,6 +108,7 @@ class ProcessServer(Process, BaseImplServer):
# the UI and communicated to us
self.quitin.close()
signal.signal(signal.SIGINT, signal.SIG_IGN)
+ bb.utils.set_process_name("Cooker")
while not self.quit:
try:
if self.command_channel.poll():
@@ -212,6 +215,7 @@ class ProcessEventQueue(multiprocessing.queues.Queue):
def __init__(self, maxsize):
multiprocessing.queues.Queue.__init__(self, maxsize)
self.exit = False
+ bb.utils.set_process_name("ProcessEQueue")
def setexit(self):
self.exit = True
@@ -238,7 +242,7 @@ class ProcessEventQueue(multiprocessing.queues.Queue):
class BitBakeServer(BitBakeBaseServer):
- def initServer(self):
+ def initServer(self, single_use=True):
# establish communication channels. We use bidirectional pipes for
# ui <--> server command/response pairs
# and a queue for server -> ui event notifications
diff --git a/yocto-poky/bitbake/lib/bb/server/xmlrpc.py b/yocto-poky/bitbake/lib/bb/server/xmlrpc.py
index b7647c198..ace1cf646 100644
--- a/yocto-poky/bitbake/lib/bb/server/xmlrpc.py
+++ b/yocto-poky/bitbake/lib/bb/server/xmlrpc.py
@@ -97,10 +97,10 @@ class BitBakeServerCommands():
# we don't allow connections if the cooker is running
if (self.cooker.state in [bb.cooker.state.parsing, bb.cooker.state.running]):
- return None
+ return None, "Cooker is busy: %s" % bb.cooker.state.get_name(self.cooker.state)
self.event_handle = bb.event.register_UIHhandler(s, True)
- return self.event_handle
+ return self.event_handle, 'OK'
def unregisterEventHandler(self, handlerNum):
"""
@@ -186,13 +186,12 @@ class XMLRPCServer(SimpleXMLRPCServer, BaseImplServer):
# remove this when you're done with debugging
# allow_reuse_address = True
- def __init__(self, interface):
+ def __init__(self, interface, single_use=False):
"""
Constructor
"""
BaseImplServer.__init__(self)
- if (interface[1] == 0): # anonymous port, not getting reused
- self.single_use = True
+ self.single_use = single_use
# Use auto port configuration
if (interface[1] == -1):
interface = (interface[0], 0)
@@ -205,7 +204,6 @@ class XMLRPCServer(SimpleXMLRPCServer, BaseImplServer):
self.commands = BitBakeServerCommands(self)
self.autoregister_all_functions(self.commands, "")
self.interface = interface
- self.single_use = False
def addcooker(self, cooker):
BaseImplServer.addcooker(self, cooker)
@@ -302,7 +300,9 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
return None
self.transport.set_connection_token(token)
+ return self
+ def setupEventQueue(self):
self.events = uievent.BBUIEventQueue(self.connection, self.clientinfo)
for event in bb.event.ui_queue:
self.events.queue_event(event)
@@ -314,8 +314,6 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
# no need to log it here, the error shall be sent to the client
raise BaseException(error)
- return self
-
def removeClient(self):
if not self.observer_only:
self.connection.removeClient()
@@ -334,9 +332,9 @@ class BitBakeXMLRPCServerConnection(BitBakeBaseServerConnection):
pass
class BitBakeServer(BitBakeBaseServer):
- def initServer(self, interface = ("localhost", 0)):
+ def initServer(self, interface = ("localhost", 0), single_use = False):
self.interface = interface
- self.serverImpl = XMLRPCServer(interface)
+ self.serverImpl = XMLRPCServer(interface, single_use)
def detach(self):
daemonize.createDaemon(self.serverImpl.serve_forever, "bitbake-cookerdaemon.log")
diff --git a/yocto-poky/bitbake/lib/bb/siggen.py b/yocto-poky/bitbake/lib/bb/siggen.py
index 0352e4523..88fc0f1d5 100644
--- a/yocto-poky/bitbake/lib/bb/siggen.py
+++ b/yocto-poky/bitbake/lib/bb/siggen.py
@@ -4,6 +4,7 @@ import os
import re
import tempfile
import bb.data
+from bb.checksum import FileChecksumCache
logger = logging.getLogger('BitBake.SigGen')
@@ -37,6 +38,7 @@ class SignatureGenerator(object):
self.taskhash = {}
self.runtaskdeps = {}
self.file_checksum_values = {}
+ self.taints = {}
def finalise(self, fn, d, varient):
return
@@ -44,7 +46,8 @@ class SignatureGenerator(object):
def get_taskhash(self, fn, task, deps, dataCache):
return "0"
- def set_taskdata(self, hashes, deps, checksum):
+ def writeout_file_checksum_cache(self):
+ """Write/update the file checksum cache onto disk"""
return
def stampfile(self, stampbase, file_name, taskname, extrainfo):
@@ -63,10 +66,10 @@ class SignatureGenerator(object):
return
def get_taskdata(self):
- return (self.runtaskdeps, self.taskhash, self.file_checksum_values)
+ return (self.runtaskdeps, self.taskhash, self.file_checksum_values, self.taints)
def set_taskdata(self, data):
- self.runtaskdeps, self.taskhash, self.file_checksum_values = data
+ self.runtaskdeps, self.taskhash, self.file_checksum_values, self.taints = data
class SignatureGeneratorBasic(SignatureGenerator):
@@ -87,6 +90,12 @@ class SignatureGeneratorBasic(SignatureGenerator):
self.basewhitelist = set((data.getVar("BB_HASHBASE_WHITELIST", True) or "").split())
self.taskwhitelist = None
self.init_rundepcheck(data)
+ checksum_cache_file = data.getVar("BB_HASH_CHECKSUM_CACHE_FILE", True)
+ if checksum_cache_file:
+ self.checksum_cache = FileChecksumCache()
+ self.checksum_cache.init_cache(data, checksum_cache_file)
+ else:
+ self.checksum_cache = None
def init_rundepcheck(self, data):
self.taskwhitelist = data.getVar("BB_HASHTASK_WHITELIST", True) or None
@@ -146,7 +155,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
try:
taskdeps = self._build_data(fn, d)
except:
- bb.note("Error during finalise of %s" % fn)
+ bb.warn("Error during finalise of %s" % fn)
raise
#Slow but can be useful for debugging mismatched basehashes
@@ -178,8 +187,9 @@ class SignatureGeneratorBasic(SignatureGenerator):
k = fn + "." + task
data = dataCache.basetaskhash[k]
self.runtaskdeps[k] = []
- self.file_checksum_values[k] = {}
+ self.file_checksum_values[k] = []
recipename = dataCache.pkg_fn[fn]
+
for dep in sorted(deps, key=clean_basepath):
depname = dataCache.pkg_fn[self.pkgnameextract.search(dep).group('fn')]
if not self.rundep_check(fn, recipename, task, dep, depname, dataCache):
@@ -190,9 +200,12 @@ class SignatureGeneratorBasic(SignatureGenerator):
self.runtaskdeps[k].append(dep)
if task in dataCache.file_checksums[fn]:
- checksums = bb.fetch2.get_file_checksums(dataCache.file_checksums[fn][task], recipename)
+ if self.checksum_cache:
+ checksums = self.checksum_cache.get_checksums(dataCache.file_checksums[fn][task], recipename)
+ else:
+ checksums = bb.fetch2.get_file_checksums(dataCache.file_checksums[fn][task], recipename)
for (f,cs) in checksums:
- self.file_checksum_values[k][f] = cs
+ self.file_checksum_values[k].append((f,cs))
if cs:
data = data + cs
@@ -215,10 +228,22 @@ class SignatureGeneratorBasic(SignatureGenerator):
#d.setVar("BB_TASKHASH_task-%s" % task, taskhash[task])
return h
+ def writeout_file_checksum_cache(self):
+ """Write/update the file checksum cache onto disk"""
+ if self.checksum_cache:
+ self.checksum_cache.save_extras()
+ self.checksum_cache.save_merge()
+ else:
+ bb.fetch2.fetcher_parse_save()
+ bb.fetch2.fetcher_parse_done()
+
def dump_sigtask(self, fn, task, stampbase, runtime):
+
k = fn + "." + task
- if runtime == "customfile":
+ referencestamp = stampbase
+ if isinstance(runtime, str) and runtime.startswith("customfile"):
sigfile = stampbase
+ referencestamp = runtime[11:]
elif runtime and k in self.taskhash:
sigfile = stampbase + "." + task + ".sigdata" + "." + self.taskhash[k]
else:
@@ -227,6 +252,7 @@ class SignatureGeneratorBasic(SignatureGenerator):
bb.utils.mkdirhier(os.path.dirname(sigfile))
data = {}
+ data['task'] = task
data['basewhitelist'] = self.basewhitelist
data['taskwhitelist'] = self.taskwhitelist
data['taskdeps'] = self.taskdeps[fn][task]
@@ -242,12 +268,13 @@ class SignatureGeneratorBasic(SignatureGenerator):
if runtime and k in self.taskhash:
data['runtaskdeps'] = self.runtaskdeps[k]
- data['file_checksum_values'] = [(os.path.basename(f), cs) for f,cs in self.file_checksum_values[k].items()]
+ data['file_checksum_values'] = [(os.path.basename(f), cs) for f,cs in self.file_checksum_values[k]]
data['runtaskhashes'] = {}
for dep in data['runtaskdeps']:
data['runtaskhashes'][dep] = self.taskhash[dep]
+ data['taskhash'] = self.taskhash[k]
- taint = self.read_taint(fn, task, stampbase)
+ taint = self.read_taint(fn, task, referencestamp)
if taint:
data['taint'] = taint
@@ -269,6 +296,15 @@ class SignatureGeneratorBasic(SignatureGenerator):
pass
raise err
+ computed_basehash = calc_basehash(data)
+ if computed_basehash != self.basehash[k]:
+ bb.error("Basehash mismatch %s verses %s for %s" % (computed_basehash, self.basehash[k], k))
+ if k in self.taskhash:
+ computed_taskhash = calc_taskhash(data)
+ if computed_taskhash != self.taskhash[k]:
+ bb.error("Taskhash mismatch %s verses %s for %s" % (computed_taskhash, self.taskhash[k], k))
+
+
def dump_sigs(self, dataCache, options):
for fn in self.taskdeps:
for task in self.taskdeps[fn]:
@@ -308,7 +344,8 @@ def dump_this_task(outfile, d):
import bb.parse
fn = d.getVar("BB_FILENAME", True)
task = "do_" + d.getVar("BB_CURRENTTASK", True)
- bb.parse.siggen.dump_sigtask(fn, task, outfile, "customfile")
+ referencestamp = bb.build.stamp_internal(task, d, None, True)
+ bb.parse.siggen.dump_sigtask(fn, task, outfile, "customfile:" + referencestamp)
def clean_basepath(a):
b = a.rsplit("/", 2)[1] + a.rsplit("/", 2)[2]
@@ -485,6 +522,40 @@ def compare_sigfiles(a, b, recursecb = None):
return output
+def calc_basehash(sigdata):
+ task = sigdata['task']
+ basedata = sigdata['varvals'][task]
+
+ if basedata is None:
+ basedata = ''
+
+ alldeps = sigdata['taskdeps']
+ for dep in alldeps:
+ basedata = basedata + dep
+ val = sigdata['varvals'][dep]
+ if val is not None:
+ basedata = basedata + str(val)
+
+ return hashlib.md5(basedata).hexdigest()
+
+def calc_taskhash(sigdata):
+ data = sigdata['basehash']
+
+ for dep in sigdata['runtaskdeps']:
+ data = data + sigdata['runtaskhashes'][dep]
+
+ for c in sigdata['file_checksum_values']:
+ data = data + c[1]
+
+ if 'taint' in sigdata:
+ if 'nostamp:' in sigdata['taint']:
+ data = data + sigdata['taint'][8:]
+ else:
+ data = data + sigdata['taint']
+
+ return hashlib.md5(data).hexdigest()
+
+
def dump_sigfile(a):
output = []
@@ -518,17 +589,13 @@ def dump_sigfile(a):
if 'taint' in a_data:
output.append("Tainted (by forced/invalidated task): %s" % a_data['taint'])
- data = a_data['basehash']
- for dep in a_data['runtaskdeps']:
- data = data + a_data['runtaskhashes'][dep]
-
- for c in a_data['file_checksum_values']:
- data = data + c[1]
-
- if 'taint' in a_data:
- data = data + a_data['taint']
+ if 'task' in a_data:
+ computed_basehash = calc_basehash(a_data)
+ output.append("Computed base hash is %s and from file %s" % (computed_basehash, a_data['basehash']))
+ else:
+ output.append("Unable to compute base hash")
- h = hashlib.md5(data).hexdigest()
- output.append("Computed Hash is %s" % h)
+ computed_taskhash = calc_taskhash(a_data)
+ output.append("Computed task hash is %s" % computed_taskhash)
return output
diff --git a/yocto-poky/bitbake/lib/bb/taskdata.py b/yocto-poky/bitbake/lib/bb/taskdata.py
index 4d12b3325..9ae52d77d 100644
--- a/yocto-poky/bitbake/lib/bb/taskdata.py
+++ b/yocto-poky/bitbake/lib/bb/taskdata.py
@@ -172,6 +172,8 @@ class TaskData:
if fnid in self.tasks_fnid:
return
+ self.add_extra_deps(fn, dataCache)
+
for task in task_deps['tasks']:
# Work out task dependencies
@@ -242,6 +244,21 @@ class TaskData:
self.fail_fnid(fnid)
return
+ def add_extra_deps(self, fn, dataCache):
+ func = dataCache.extradepsfunc.get(fn, None)
+ if func:
+ bb.providers.buildWorldTargetList(dataCache)
+ pn = dataCache.pkg_fn[fn]
+ params = {'deps': dataCache.deps[fn],
+ 'world_target': dataCache.world_target,
+ 'pkg_pn': dataCache.pkg_pn,
+ 'self_pn': pn}
+ funcname = '_%s_calculate_extra_depends' % pn.replace('-', '_')
+ paramlist = ','.join(params.keys())
+ func = 'def %s(%s):\n%s\n\n%s(%s)' % (funcname, paramlist, func, funcname, paramlist)
+ bb.utils.better_exec(func, params)
+
+
def have_build_target(self, target):
"""
Have we a build target matching this name?
@@ -429,7 +446,14 @@ class TaskData:
return
if not item in dataCache.providers:
- bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=self.get_close_matches(item, dataCache.providers.keys())), cfgData)
+ close_matches = self.get_close_matches(item, dataCache.providers.keys())
+ # Is it in RuntimeProviders ?
+ all_p = bb.providers.getRuntimeProviders(dataCache, item)
+ for fn in all_p:
+ new = dataCache.pkg_fn[fn] + " RPROVIDES " + item
+ if new not in close_matches:
+ close_matches.append(new)
+ bb.event.fire(bb.event.NoProvider(item, dependees=self.get_dependees_str(item), reasons=self.get_reasons(item), close_matches=close_matches), cfgData)
raise bb.providers.NoProvider(item)
if self.have_build_target(item):
@@ -612,17 +636,16 @@ class TaskData:
break
# self.dump_data()
- def get_providermap(self):
- virts = []
- virtmap = {}
-
+ def get_providermap(self, prefix=None):
+ provmap = {}
for name in self.build_names_index:
- if name.startswith("virtual/"):
- virts.append(name)
- for v in virts:
- if self.have_build_target(v):
- virtmap[v] = self.fn_index[self.get_provider(v)[0]]
- return virtmap
+ if prefix and not name.startswith(prefix):
+ continue
+ if self.have_build_target(name):
+ provider = self.get_provider(name)
+ if provider:
+ provmap[name] = self.fn_index[provider[0]]
+ return provmap
def dump_data(self):
"""
diff --git a/yocto-poky/bitbake/lib/bb/tests/codeparser.py b/yocto-poky/bitbake/lib/bb/tests/codeparser.py
index 4454bc51e..bb820e403 100644
--- a/yocto-poky/bitbake/lib/bb/tests/codeparser.py
+++ b/yocto-poky/bitbake/lib/bb/tests/codeparser.py
@@ -293,7 +293,12 @@ bb.data.getVar(a(), d, False)
def test_python(self):
self.d.setVar("FOO", self.pydata)
self.setEmptyVars(["inexpand", "a", "test2", "test"])
- self.d.setVarFlags("FOO", {"func": True, "python": True})
+ self.d.setVarFlags("FOO", {
+ "func": True,
+ "python": True,
+ "lineno": 1,
+ "filename": "example.bb",
+ })
deps, values = bb.data.build_dependencies("FOO", set(self.d.keys()), set(), set(), self.d)
diff --git a/yocto-poky/bitbake/lib/bb/tests/data.py b/yocto-poky/bitbake/lib/bb/tests/data.py
index e9aab577f..12232305c 100644
--- a/yocto-poky/bitbake/lib/bb/tests/data.py
+++ b/yocto-poky/bitbake/lib/bb/tests/data.py
@@ -80,6 +80,11 @@ class DataExpansions(unittest.TestCase):
val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
self.assertEqual(str(val), "value_of_foo value_of_bar")
+ def test_python_unexpanded(self):
+ self.d.setVar("bar", "${unsetvar}")
+ val = self.d.expand("${@d.getVar('foo', True) + ' ${bar}'}")
+ self.assertEqual(str(val), "${@d.getVar('foo', True) + ' ${unsetvar}'}")
+
def test_python_snippet_syntax_error(self):
self.d.setVar("FOO", "${@foo = 5}")
self.assertRaises(bb.data_smart.ExpansionError, self.d.getVar, "FOO", True)
@@ -394,13 +399,13 @@ class TestFlags(unittest.TestCase):
self.d.setVarFlag("foo", "flag2", "value of flag2")
def test_setflag(self):
- self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
- self.assertEqual(self.d.getVarFlag("foo", "flag2"), "value of flag2")
+ self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
+ self.assertEqual(self.d.getVarFlag("foo", "flag2", False), "value of flag2")
def test_delflag(self):
self.d.delVarFlag("foo", "flag2")
- self.assertEqual(self.d.getVarFlag("foo", "flag1"), "value of flag1")
- self.assertEqual(self.d.getVarFlag("foo", "flag2"), None)
+ self.assertEqual(self.d.getVarFlag("foo", "flag1", False), "value of flag1")
+ self.assertEqual(self.d.getVarFlag("foo", "flag2", False), None)
class Contains(unittest.TestCase):
diff --git a/yocto-poky/bitbake/lib/bb/tests/fetch.py b/yocto-poky/bitbake/lib/bb/tests/fetch.py
index 94173c14a..4ba688bfe 100644
--- a/yocto-poky/bitbake/lib/bb/tests/fetch.py
+++ b/yocto-poky/bitbake/lib/bb/tests/fetch.py
@@ -228,7 +228,38 @@ class URITest(unittest.TestCase):
'params': {},
'query': {},
'relative': False
+ },
+ "http://somesite.net;someparam=1": {
+ 'uri': 'http://somesite.net;someparam=1',
+ 'scheme': 'http',
+ 'hostname': 'somesite.net',
+ 'port': None,
+ 'hostport': 'somesite.net',
+ 'path': '',
+ 'userinfo': '',
+ 'userinfo': '',
+ 'username': '',
+ 'password': '',
+ 'params': {"someparam" : "1"},
+ 'query': {},
+ 'relative': False
+ },
+ "file://somelocation;someparam=1": {
+ 'uri': 'file:somelocation;someparam=1',
+ 'scheme': 'file',
+ 'hostname': '',
+ 'port': None,
+ 'hostport': '',
+ 'path': 'somelocation',
+ 'userinfo': '',
+ 'userinfo': '',
+ 'username': '',
+ 'password': '',
+ 'params': {"someparam" : "1"},
+ 'query': {},
+ 'relative': True
}
+
}
def test_uri(self):
@@ -451,9 +482,7 @@ class FetcherLocalTest(FetcherTest):
def test_local_wildcard(self):
tree = self.fetchUnpack(['file://a', 'file://dir/*'])
- # FIXME: this is broken - it should return ['a', 'dir/c', 'dir/d', 'dir/subdir/e']
- # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=6128
- self.assertEqual(tree, ['a', 'b', 'dir/c', 'dir/d', 'dir/subdir/e'])
+ self.assertEqual(tree, ['a', 'dir/c', 'dir/d', 'dir/subdir/e'])
def test_local_dir(self):
tree = self.fetchUnpack(['file://a', 'file://dir'])
@@ -461,17 +490,15 @@ class FetcherLocalTest(FetcherTest):
def test_local_subdir(self):
tree = self.fetchUnpack(['file://dir/subdir'])
- # FIXME: this is broken - it should return ['dir/subdir/e']
- # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=6129
- self.assertEqual(tree, ['subdir/e'])
+ self.assertEqual(tree, ['dir/subdir/e'])
def test_local_subdir_file(self):
tree = self.fetchUnpack(['file://dir/subdir/e'])
self.assertEqual(tree, ['dir/subdir/e'])
def test_local_subdirparam(self):
- tree = self.fetchUnpack(['file://a;subdir=bar'])
- self.assertEqual(tree, ['bar/a'])
+ tree = self.fetchUnpack(['file://a;subdir=bar', 'file://dir;subdir=foo/moo'])
+ self.assertEqual(tree, ['bar/a', 'foo/moo/dir/c', 'foo/moo/dir/d', 'foo/moo/dir/subdir/e'])
def test_local_deepsubdirparam(self):
tree = self.fetchUnpack(['file://dir/subdir/e;subdir=bar'])
@@ -584,42 +611,49 @@ class FetcherNetworkTest(FetcherTest):
os.chdir(os.path.dirname(self.unpackdir))
fetcher.unpack(self.unpackdir)
- def test_trusted_network(self):
- # Ensure trusted_network returns False when the host IS in the list.
- url = "git://Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_wild_trusted_network(self):
- # Ensure trusted_network returns true when the *.host IS in the list.
- url = "git://Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_prefix_wild_trusted_network(self):
- # Ensure trusted_network returns true when the prefix matches *.host.
- url = "git://git.Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_two_prefix_wild_trusted_network(self):
- # Ensure trusted_network returns true when the prefix matches *.host.
- url = "git://something.git.Someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
- self.assertTrue(bb.fetch.trusted_network(self.d, url))
-
- def test_untrusted_network(self):
- # Ensure trusted_network returns False when the host is NOT in the list.
- url = "git://someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
- self.assertFalse(bb.fetch.trusted_network(self.d, url))
-
- def test_wild_untrusted_network(self):
- # Ensure trusted_network returns False when the host is NOT in the list.
- url = "git://*.someserver.org/foo;rev=1"
- self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
- self.assertFalse(bb.fetch.trusted_network(self.d, url))
+class TrustedNetworksTest(FetcherTest):
+ def test_trusted_network(self):
+ # Ensure trusted_network returns False when the host IS in the list.
+ url = "git://Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_wild_trusted_network(self):
+ # Ensure trusted_network returns true when the *.host IS in the list.
+ url = "git://Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_prefix_wild_trusted_network(self):
+ # Ensure trusted_network returns true when the prefix matches *.host.
+ url = "git://git.Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_two_prefix_wild_trusted_network(self):
+ # Ensure trusted_network returns true when the prefix matches *.host.
+ url = "git://something.git.Someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org *.someserver.org server2.org server3.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_port_trusted_network(self):
+ # Ensure trusted_network returns True, even if the url specifies a port.
+ url = "git://someserver.org:8080/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "someserver.org")
+ self.assertTrue(bb.fetch.trusted_network(self.d, url))
+
+ def test_untrusted_network(self):
+ # Ensure trusted_network returns False when the host is NOT in the list.
+ url = "git://someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
+ self.assertFalse(bb.fetch.trusted_network(self.d, url))
+
+ def test_wild_untrusted_network(self):
+ # Ensure trusted_network returns False when the host is NOT in the list.
+ url = "git://*.someserver.org/foo;rev=1"
+ self.d.setVar("BB_ALLOWED_NETWORKS", "server1.org server2.org server3.org")
+ self.assertFalse(bb.fetch.trusted_network(self.d, url))
class URLHandle(unittest.TestCase):
@@ -627,11 +661,18 @@ class URLHandle(unittest.TestCase):
"http://www.google.com/index.html" : ('http', 'www.google.com', '/index.html', '', '', {}),
"cvs://anoncvs@cvs.handhelds.org/cvs;module=familiar/dist/ipkg" : ('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', '', {'module': 'familiar/dist/ipkg'}),
"cvs://anoncvs:anonymous@cvs.handhelds.org/cvs;tag=V0-99-81;module=familiar/dist/ipkg" : ('cvs', 'cvs.handhelds.org', '/cvs', 'anoncvs', 'anonymous', {'tag': 'V0-99-81', 'module': 'familiar/dist/ipkg'}),
- "git://git.openembedded.org/bitbake;branch=@foo" : ('git', 'git.openembedded.org', '/bitbake', '', '', {'branch': '@foo'})
+ "git://git.openembedded.org/bitbake;branch=@foo" : ('git', 'git.openembedded.org', '/bitbake', '', '', {'branch': '@foo'}),
+ "file://somelocation;someparam=1": ('file', '', 'somelocation', '', '', {'someparam': '1'}),
}
+ # we require a pathname to encodeurl but users can still pass such urls to
+ # decodeurl and we need to handle them
+ decodedata = datatable.copy()
+ decodedata.update({
+ "http://somesite.net;someparam=1": ('http', 'somesite.net', '', '', '', {'someparam': '1'}),
+ })
def test_decodeurl(self):
- for k, v in self.datatable.items():
+ for k, v in self.decodedata.items():
result = bb.fetch.decodeurl(k)
self.assertEqual(result, v)
@@ -663,7 +704,7 @@ class FetchLatestVersionTest(FetcherTest):
# version pattern "yyyymmdd"
("mobile-broadband-provider-info", "git://git.gnome.org/mobile-broadband-provider-info", "4ed19e11c2975105b71b956440acdb25d46a347d", "")
: "20120614",
- # packages with a valid GITTAGREGEX
+ # packages with a valid UPSTREAM_CHECK_GITTAGREGEX
("xf86-video-omap", "git://anongit.freedesktop.org/xorg/driver/xf86-video-omap", "ae0394e687f1a77e966cf72f895da91840dffb8f", "(?P<pver>(\d+\.(\d\.?)*))")
: "0.4.3",
("build-appliance-image", "git://git.yoctoproject.org/poky", "b37dd451a52622d5b570183a81583cc34c2ff555", "(?P<pver>(([0-9][\.|_]?)+[0-9]))")
@@ -692,8 +733,8 @@ class FetchLatestVersionTest(FetcherTest):
: "5.0",
("xserver-xorg", "http://xorg.freedesktop.org/releases/individual/xserver/xorg-server-1.15.1.tar.bz2", "", "")
: "1.15.1",
- # packages with valid REGEX_URI and REGEX
- ("cups", "http://www.cups.org/software/1.7.2/cups-1.7.2-source.tar.bz2", "http://www.cups.org/software.php", "(?P<name>cups\-)(?P<pver>((\d+[\.\-_]*)+))\-source\.tar\.gz")
+ # packages with valid UPSTREAM_CHECK_URI and UPSTREAM_CHECK_REGEX
+ ("cups", "http://www.cups.org/software/1.7.2/cups-1.7.2-source.tar.bz2", "https://github.com/apple/cups/releases", "(?P<name>cups\-)(?P<pver>((\d+[\.\-_]*)+))\-source\.tar\.gz")
: "2.0.0",
("db", "http://download.oracle.com/berkeley-db/db-5.3.21.tar.gz", "http://www.oracle.com/technetwork/products/berkeleydb/downloads/index-082944.html", "http://download.oracle.com/otn/berkeley-db/(?P<name>db-)(?P<pver>((\d+[\.\-_]*)+))\.tar\.gz")
: "6.1.19",
@@ -705,7 +746,7 @@ class FetchLatestVersionTest(FetcherTest):
for k, v in self.test_git_uris.items():
self.d.setVar("PN", k[0])
self.d.setVar("SRCREV", k[2])
- self.d.setVar("GITTAGREGEX", k[3])
+ self.d.setVar("UPSTREAM_CHECK_GITTAGREGEX", k[3])
ud = bb.fetch2.FetchData(k[1], self.d)
pupver= ud.method.latest_versionstring(ud, self.d)
verstring = pupver[0]
@@ -715,8 +756,8 @@ class FetchLatestVersionTest(FetcherTest):
def test_wget_latest_versionstring(self):
for k, v in self.test_wget_uris.items():
self.d.setVar("PN", k[0])
- self.d.setVar("REGEX_URI", k[2])
- self.d.setVar("REGEX", k[3])
+ self.d.setVar("UPSTREAM_CHECK_URI", k[2])
+ self.d.setVar("UPSTREAM_CHECK_REGEX", k[3])
ud = bb.fetch2.FetchData(k[1], self.d)
pupver = ud.method.latest_versionstring(ud, self.d)
verstring = pupver[0]
@@ -738,6 +779,8 @@ class FetchCheckStatusTest(FetcherTest):
"ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz",
"ftp://ftp.gnu.org/gnu/chess/gnuchess-5.08.tar.gz",
"ftp://ftp.gnu.org/gnu/gmp/gmp-4.0.tar.gz",
+ # GitHub releases are hosted on Amazon S3, which doesn't support HEAD
+ "https://github.com/kergoth/tslib/releases/download/1.1/tslib-1.1.tar.xz"
]
if os.environ.get("BB_SKIP_NETTESTS") == "yes":
diff --git a/yocto-poky/bitbake/lib/bb/tests/utils.py b/yocto-poky/bitbake/lib/bb/tests/utils.py
index a035ccf17..2f4ccf3c6 100644
--- a/yocto-poky/bitbake/lib/bb/tests/utils.py
+++ b/yocto-poky/bitbake/lib/bb/tests/utils.py
@@ -23,6 +23,7 @@ import unittest
import bb
import os
import tempfile
+import re
class VerCmpString(unittest.TestCase):
@@ -176,7 +177,7 @@ do_functionname() {
# Test file doesn't get modified with some the same values
self._testeditfile({'THIS': ('that', None, 0, True),
'OTHER': ('anothervalue', None, 0, True),
- 'MULTILINE3': (' c1 c2 c3', None, 4, False)}, self._origfile)
+ 'MULTILINE3': (' c1 c2 c3 ', None, 4, False)}, self._origfile)
def test_edit_metadata_file_1(self):
@@ -377,6 +378,27 @@ do_functionname() {
self.assertTrue(updated, 'List should be updated but isn\'t')
self.assertEqual(newlines, newfile5.splitlines(True))
+ # Make sure the orig value matches what we expect it to be
+ def test_edit_metadata_origvalue(self):
+ origfile = """
+MULTILINE = " stuff \\
+ morestuff"
+"""
+ expected_value = "stuff morestuff"
+ global value_in_callback
+ value_in_callback = ""
+
+ def handle_var(varname, origvalue, op, newlines):
+ global value_in_callback
+ value_in_callback = origvalue
+ return (origvalue, op, -1, False)
+
+ bb.utils.edit_metadata(origfile.splitlines(True),
+ ['MULTILINE'],
+ handle_var)
+
+ testvalue = re.sub('\s+', ' ', value_in_callback.strip())
+ self.assertEqual(expected_value, testvalue)
class EditBbLayersConf(unittest.TestCase):
diff --git a/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py b/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
index 78f1e9274..93979054d 100644
--- a/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/yocto-poky/bitbake/lib/bb/ui/buildinfohelper.py
@@ -24,6 +24,7 @@ import os
os.environ["DJANGO_SETTINGS_MODULE"] = "toaster.toastermain.settings"
+import django
from django.utils import timezone
@@ -33,20 +34,23 @@ def _configure_toaster():
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'toaster'))
_configure_toaster()
-from toaster.orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
-from toaster.orm.models import Target_Image_File, BuildArtifact
-from toaster.orm.models import Variable, VariableHistory
-from toaster.orm.models import Package, Package_File, Target_Installed_Package, Target_File
-from toaster.orm.models import Task_Dependency, Package_Dependency
-from toaster.orm.models import Recipe_Dependency
+django.setup()
+
+from orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage, HelpText
+from orm.models import Target_Image_File, BuildArtifact
+from orm.models import Variable, VariableHistory
+from orm.models import Package, Package_File, Target_Installed_Package, Target_File
+from orm.models import Task_Dependency, Package_Dependency
+from orm.models import Recipe_Dependency, Provides
+from orm.models import Project, CustomImagePackage, CustomImageRecipe
-from toaster.orm.models import Project
from bldcontrol.models import BuildEnvironment, BuildRequest
from bb.msg import BBLogFormatter as formatter
from django.db import models
from pprint import pformat
import logging
+from datetime import datetime, timedelta
from django.db import transaction, connection
@@ -117,6 +121,12 @@ class ORMWrapper(object):
return vars(self)[dictname][key]
+ def _timestamp_to_datetime(self, secs):
+ """
+ Convert timestamp in seconds to Python datetime
+ """
+ return datetime(1970, 1, 1) + timedelta(seconds=secs)
+
# pylint: disable=no-self-use
# we disable detection of no self use in functions because the methods actually work on the object
# even if they don't touch self anywhere
@@ -146,7 +156,7 @@ class ORMWrapper(object):
prj = Project.objects.get(pk = project_id)
else: # this build was triggered by a legacy system, or command line interactive mode
- prj = Project.objects.get_default_project()
+ prj = Project.objects.get_or_create_default_project()
logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj)
@@ -208,6 +218,15 @@ class ORMWrapper(object):
assert isinstance(errors, int)
assert isinstance(warnings, int)
+ if build.outcome == Build.CANCELLED:
+ return
+ try:
+ if build.buildrequest.state == BuildRequest.REQ_CANCELLING:
+ return
+ except AttributeError:
+ # We may not have a buildrequest if this is a command line build
+ pass
+
outcome = Build.SUCCEEDED
if errors or taskfailures:
outcome = Build.FAILED
@@ -220,6 +239,30 @@ class ORMWrapper(object):
target.license_manifest_path = license_manifest_path
target.save()
+ def update_task_object(self, build, task_name, recipe_name, task_stats):
+ """
+ Find the task for build which matches the recipe and task name
+ to be stored
+ """
+ task_to_update = Task.objects.get(
+ build = build,
+ task_name = task_name,
+ recipe__name = recipe_name
+ )
+
+ if 'started' in task_stats and 'ended' in task_stats:
+ task_to_update.started = self._timestamp_to_datetime(task_stats['started'])
+ task_to_update.ended = self._timestamp_to_datetime(task_stats['ended'])
+ task_to_update.elapsed_time = (task_stats['ended'] - task_stats['started'])
+ task_to_update.cpu_time_user = task_stats.get('cpu_time_user')
+ task_to_update.cpu_time_system = task_stats.get('cpu_time_system')
+ if 'disk_io_read' in task_stats and 'disk_io_write' in task_stats:
+ task_to_update.disk_io_read = task_stats['disk_io_read']
+ task_to_update.disk_io_write = task_stats['disk_io_write']
+ task_to_update.disk_io = task_stats['disk_io_read'] + task_stats['disk_io_write']
+
+ task_to_update.save()
+
def get_update_task_object(self, task_information, must_exist = False):
assert 'build' in task_information
assert 'recipe' in task_information
@@ -256,14 +299,6 @@ class ORMWrapper(object):
task_object.sstate_result = Task.SSTATE_FAILED
object_changed = True
- # mark down duration if we have a start time and a current time
- if 'start_time' in task_information.keys() and 'end_time' in task_information.keys():
- duration = task_information['end_time'] - task_information['start_time']
- task_object.elapsed_time = duration
- object_changed = True
- del task_information['start_time']
- del task_information['end_time']
-
if object_changed:
task_object.save()
return task_object
@@ -304,18 +339,27 @@ class ORMWrapper(object):
break
- # If we're in analysis mode then we are wholly responsible for the data
+ # If we're in analysis mode or if this is a custom recipe
+ # then we are wholly responsible for the data
# and therefore we return the 'real' recipe rather than the build
# history copy of the recipe.
if recipe_information['layer_version'].build is not None and \
recipe_information['layer_version'].build.project == \
- Project.objects.get_default_project():
+ Project.objects.get_or_create_default_project():
+ return recipe
+
+ if built_recipe is None:
return recipe
return built_recipe
def get_update_layer_version_object(self, build_obj, layer_obj, layer_version_information):
if isinstance(layer_obj, Layer_Version):
+ # Special case the toaster-custom-images layer which is created
+ # on the fly so don't update the values which may cause the layer
+ # to be duplicated on a future get_or_create
+ if layer_obj.layer.name == CustomImageRecipe.LAYER_NAME:
+ return layer_obj
# We already found our layer version for this build so just
# update it with the new build information
logger.debug("We found our layer from toaster")
@@ -325,12 +369,17 @@ class ORMWrapper(object):
# create a new copy of this layer version as a snapshot for
# historical purposes
- layer_copy, c = Layer_Version.objects.get_or_create(build=build_obj,
- layer=layer_obj.layer,
- commit=layer_version_information['commit'],
- local_path = layer_version_information['local_path'],
- )
- logger.info("created new historical layer version %d", layer_copy.pk)
+ layer_copy, c = Layer_Version.objects.get_or_create(
+ build=build_obj,
+ layer=layer_obj.layer,
+ up_branch=layer_obj.up_branch,
+ branch=layer_version_information['branch'],
+ commit=layer_version_information['commit'],
+ local_path=layer_version_information['local_path'],
+ )
+
+ logger.info("created new historical layer version %d",
+ layer_copy.pk)
self.layer_version_built.append(layer_copy)
@@ -346,7 +395,7 @@ class ORMWrapper(object):
# If we're doing a command line build then associate this new layer with the
# project to avoid it 'contaminating' toaster data
project = None
- if build_obj.project == Project.objects.get_default_project():
+ if build_obj.project == Project.objects.get_or_create_default_project():
project = build_obj.project
layer_version_object, _ = Layer_Version.objects.get_or_create(
@@ -445,7 +494,7 @@ class ORMWrapper(object):
parent_obj = self._cached_get(Target_File, target = target_obj, path = parent_path, inodetype = Target_File.ITYPE_DIRECTORY)
tf_obj = Target_File.objects.create(
target = target_obj,
- path = path,
+ path = unicode(path, 'utf-8'),
size = size,
inodetype = Target_File.ITYPE_DIRECTORY,
permission = permission,
@@ -470,7 +519,7 @@ class ORMWrapper(object):
tf_obj = Target_File.objects.create(
target = target_obj,
- path = path,
+ path = unicode(path, 'utf-8'),
size = size,
inodetype = inodetype,
permission = permission,
@@ -501,7 +550,9 @@ class ORMWrapper(object):
filetarget_path = "/".join(fcpl)
try:
- filetarget_obj = Target_File.objects.get(target = target_obj, path = filetarget_path)
+ filetarget_obj = Target_File.objects.get(
+ target = target_obj,
+ path = unicode(filetarget_path, 'utf-8'))
except Target_File.DoesNotExist:
# we might have an invalid link; no way to detect this. just set it to None
filetarget_obj = None
@@ -510,7 +561,7 @@ class ORMWrapper(object):
tf_obj = Target_File.objects.create(
target = target_obj,
- path = path,
+ path = unicode(path, 'utf-8'),
size = size,
inodetype = Target_File.ITYPE_SYMLINK,
permission = permission,
@@ -520,12 +571,14 @@ class ORMWrapper(object):
sym_target = filetarget_obj)
- def save_target_package_information(self, build_obj, target_obj, packagedict, pkgpnmap, recipes):
+ def save_target_package_information(self, build_obj, target_obj, packagedict, pkgpnmap, recipes, built_package=False):
assert isinstance(build_obj, Build)
assert isinstance(target_obj, Target)
errormsg = ""
for p in packagedict:
+ # Search name swtiches round the installed name vs package name
+ # by default installed name == package name
searchname = p
if p not in pkgpnmap:
logger.warning("Image packages list contains %p, but is"
@@ -536,11 +589,38 @@ class ORMWrapper(object):
if 'OPKGN' in pkgpnmap[p].keys():
searchname = pkgpnmap[p]['OPKGN']
- packagedict[p]['object'], created = Package.objects.get_or_create( build = build_obj, name = searchname )
+ built_recipe = recipes[pkgpnmap[p]['PN']]
+
+ if built_package:
+ packagedict[p]['object'], created = Package.objects.get_or_create( build = build_obj, name = searchname )
+ recipe = built_recipe
+ else:
+ packagedict[p]['object'], created = \
+ CustomImagePackage.objects.get_or_create(name=searchname)
+ # Clear the Package_Dependency objects as we're going to update
+ # the CustomImagePackage with the latest dependency information
+ packagedict[p]['object'].package_dependencies_target.all().delete()
+ packagedict[p]['object'].package_dependencies_source.all().delete()
+ try:
+ recipe = self._cached_get(
+ Recipe,
+ name=built_recipe.name,
+ layer_version__build=None,
+ layer_version__up_branch=
+ built_recipe.layer_version.up_branch,
+ file_path=built_recipe.file_path,
+ version=built_recipe.version
+ )
+ except (Recipe.DoesNotExist,
+ Recipe.MultipleObjectsReturned) as e:
+ logger.info("We did not find one recipe for the"
+ "configuration data package %s %s" % (p, e))
+ continue
+
if created or packagedict[p]['object'].size == -1: # save the data anyway we can, not just if it was not created here; bug [YOCTO #6887]
# fill in everything we can from the runtime-reverse package data
try:
- packagedict[p]['object'].recipe = recipes[pkgpnmap[p]['PN']]
+ packagedict[p]['object'].recipe = recipe
packagedict[p]['object'].version = pkgpnmap[p]['PV']
packagedict[p]['object'].installed_name = p
packagedict[p]['object'].revision = pkgpnmap[p]['PR']
@@ -566,7 +646,8 @@ class ORMWrapper(object):
packagedict[p]['object'].installed_size = packagedict[p]['size']
packagedict[p]['object'].save()
- Target_Installed_Package.objects.create(target = target_obj, package = packagedict[p]['object'])
+ if built_package:
+ Target_Installed_Package.objects.create(target = target_obj, package = packagedict[p]['object'])
packagedeps_objs = []
for p in packagedict:
@@ -627,19 +708,37 @@ class ORMWrapper(object):
return log_object.save()
- def save_build_package_information(self, build_obj, package_info, recipes):
- assert isinstance(build_obj, Build)
+ def save_build_package_information(self, build_obj, package_info, recipes,
+ built_package):
+ # assert isinstance(build_obj, Build)
# create and save the object
pname = package_info['PKG']
+ built_recipe = recipes[package_info['PN']]
if 'OPKGN' in package_info.keys():
pname = package_info['OPKGN']
- bp_object, _ = Package.objects.get_or_create( build = build_obj,
- name = pname )
+ if built_package:
+ bp_object, _ = Package.objects.get_or_create( build = build_obj,
+ name = pname )
+ recipe = built_recipe
+ else:
+ bp_object, created = \
+ CustomImagePackage.objects.get_or_create(name=pname)
+ try:
+ recipe = self._cached_get(Recipe,
+ name=built_recipe.name,
+ layer_version__build=None,
+ file_path=built_recipe.file_path,
+ version=built_recipe.version)
+
+ except (Recipe.DoesNotExist, Recipe.MultipleObjectsReturned):
+ logger.debug("We did not find one recipe for the configuration"
+ "data package %s" % pname)
+ return
bp_object.installed_name = package_info['PKG']
- bp_object.recipe = recipes[package_info['PN']]
+ bp_object.recipe = recipe
bp_object.version = package_info['PKGV']
bp_object.revision = package_info['PKGR']
bp_object.summary = package_info['SUMMARY']
@@ -659,7 +758,12 @@ class ORMWrapper(object):
Package_File.objects.bulk_create(packagefile_objects)
def _po_byname(p):
- pkg, created = Package.objects.get_or_create(build = build_obj, name = p)
+ if built_package:
+ pkg, created = Package.objects.get_or_create(build=build_obj,
+ name=p)
+ else:
+ pkg, created = CustomImagePackage.objects.get_or_create(name=p)
+
if created:
pkg.size = -1
pkg.save()
@@ -700,7 +804,6 @@ class ORMWrapper(object):
def save_build_variables(self, build_obj, vardump):
assert isinstance(build_obj, Build)
- helptext_objects = []
for k in vardump:
desc = vardump[k]['doc']
if desc is None:
@@ -711,10 +814,9 @@ class ORMWrapper(object):
if desc is None:
desc = ''
if len(desc):
- helptext_objects.append(HelpText(build=build_obj,
- area=HelpText.VARIABLE,
- key=k,
- text=desc))
+ HelpText.objects.get_or_create(build=build_obj,
+ area=HelpText.VARIABLE,
+ key=k, text=desc)
if not bool(vardump[k]['func']):
value = vardump[k]['v']
if value is None:
@@ -734,8 +836,6 @@ class ORMWrapper(object):
if len(varhist_objects):
VariableHistory.objects.bulk_create(varhist_objects)
- HelpText.objects.bulk_create(helptext_objects)
-
class MockEvent(object):
""" This object is used to create event, for which normal event-processing methods can
@@ -762,7 +862,7 @@ class BuildInfoHelper(object):
# pylint: disable=bad-continuation
# we do not follow the python conventions for continuation indentation due to long lines here
- def __init__(self, server, has_build_history = False):
+ def __init__(self, server, has_build_history = False, brbe = None):
self.internal_state = {}
self.internal_state['taskdata'] = {}
self.internal_state['targets'] = []
@@ -775,8 +875,13 @@ class BuildInfoHelper(object):
self.orm_wrapper = ORMWrapper()
self.has_build_history = has_build_history
self.tmp_dir = self.server.runCommand(["getVariable", "TMPDIR"])[0]
- self.brbe = self.server.runCommand(["getVariable", "TOASTER_BRBE"])[0]
- self.project = self.server.runCommand(["getVariable", "TOASTER_PROJECT"])[0]
+
+ # this is set for Toaster-triggered builds by localhostbecontroller
+ # via toasterui
+ self.brbe = brbe
+
+ self.project = None
+
logger.debug(1, "buildinfohelper: Build info helper inited %s" % vars(self))
@@ -786,8 +891,6 @@ class BuildInfoHelper(object):
def _get_build_information(self, build_log_path):
build_info = {}
- # Generate an identifier for each new build
-
build_info['machine'] = self.server.runCommand(["getVariable", "MACHINE"])[0]
build_info['distro'] = self.server.runCommand(["getVariable", "DISTRO"])[0]
build_info['distro_version'] = self.server.runCommand(["getVariable", "DISTRO_VERSION"])[0]
@@ -796,7 +899,7 @@ class BuildInfoHelper(object):
build_info['cooker_log_path'] = build_log_path
build_info['build_name'] = self.server.runCommand(["getVariable", "BUILDNAME"])[0]
build_info['bitbake_version'] = self.server.runCommand(["getVariable", "BB_VERSION"])[0]
-
+ build_info['project'] = self.project = self.server.runCommand(["getVariable", "TOASTER_PROJECT"])[0]
return build_info
def _get_task_information(self, event, recipe):
@@ -818,44 +921,15 @@ class BuildInfoHelper(object):
assert path.startswith("/")
assert 'build' in self.internal_state
- if self.brbe is None:
- def _slkey_interactive(layer_version):
- assert isinstance(layer_version, Layer_Version)
- return len(layer_version.local_path)
-
- # Heuristics: we always match recipe to the deepest layer path in the discovered layers
- for lvo in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_slkey_interactive):
- # we can match to the recipe file path
- if path.startswith(lvo.local_path):
- return lvo
-
- else:
- br_id, be_id = self.brbe.split(":")
- from bldcontrol.bbcontroller import getBuildEnvironmentController
- bc = getBuildEnvironmentController(pk = be_id)
-
- def _slkey_managed(layer_version):
- return len(bc.getGitCloneDirectory(layer_version.giturl, layer_version.commit) + layer_version.dirpath)
-
- # Heuristics: we match the path to where the layers have been checked out
- for brl in sorted(BuildRequest.objects.get(pk = br_id).brlayer_set.all(), reverse = True, key = _slkey_managed):
- localdirname = os.path.join(bc.getGitCloneDirectory(brl.giturl, brl.commit), brl.dirpath)
- # we get a relative path, unless running in HEAD mode where the path is absolute
- if not localdirname.startswith("/"):
- localdirname = os.path.join(bc.be.sourcedir, localdirname)
- if path.startswith(localdirname):
- # If the build request came from toaster this field
- # should contain the information from the layer_version
- # That created this build request.
- if brl.layer_version:
- return brl.layer_version
-
- #logger.warn("-- managed: matched path %s with layer %s " % (path, localdirname))
- # we matched the BRLayer, but we need the layer_version that generated this br
+ def _slkey_interactive(layer_version):
+ assert isinstance(layer_version, Layer_Version)
+ return len(layer_version.local_path)
- for lvo in self.orm_wrapper.layer_version_objects:
- if brl.name == lvo.layer.name:
- return lvo
+ # Heuristics: we always match recipe to the deepest layer path in the discovered layers
+ for lvo in sorted(self.orm_wrapper.layer_version_objects, reverse=True, key=_slkey_interactive):
+ # we can match to the recipe file path
+ if path.startswith(lvo.local_path):
+ return lvo
#if we get here, we didn't read layers correctly; dump whatever information we have on the error log
logger.warn("Could not match layer version for recipe path %s : %s", path, self.orm_wrapper.layer_version_objects)
@@ -890,12 +964,10 @@ class BuildInfoHelper(object):
def _get_path_information(self, task_object):
assert isinstance(task_object, Task)
- build_stats_format = "{tmpdir}/buildstats/{target}-{machine}/{buildname}/{package}/"
+ build_stats_format = "{tmpdir}/buildstats/{buildname}/{package}/"
build_stats_path = []
for t in self.internal_state['targets']:
- target = t.target
- machine = self.internal_state['build'].machine
buildname = self.internal_state['build'].build_name
pe, pv = task_object.recipe.version.split(":",1)
if len(pe) > 0:
@@ -903,8 +975,8 @@ class BuildInfoHelper(object):
else:
package = task_object.recipe.name + "-" + pv
- build_stats_path.append(build_stats_format.format(tmpdir=self.tmp_dir, target=target,
- machine=machine, buildname=buildname,
+ build_stats_path.append(build_stats_format.format(tmpdir=self.tmp_dir,
+ buildname=buildname,
package=package))
return build_stats_path
@@ -938,6 +1010,9 @@ class BuildInfoHelper(object):
assert '_pkgs' in vars(event)
build_information = self._get_build_information(build_log_path)
+ # Update brbe and project as they can be changed for every build
+ self.project = build_information['project']
+
build_obj = self.orm_wrapper.create_build_object(build_information, self.brbe, self.project)
self.internal_state['build'] = build_obj
@@ -1059,31 +1134,11 @@ class BuildInfoHelper(object):
def store_tasks_stats(self, event):
- for (taskfile, taskname, taskstats, recipename) in BuildInfoHelper._get_data_from_event(event):
- localfilepath = taskfile.split(":")[-1]
- assert localfilepath.startswith("/")
+ task_data = BuildInfoHelper._get_data_from_event(event)
- recipe_information = self._get_recipe_information_from_taskfile(taskfile)
- try:
- if recipe_information['file_path'].startswith(recipe_information['layer_version'].local_path):
- recipe_information['file_path'] = recipe_information['file_path'][len(recipe_information['layer_version'].local_path):].lstrip("/")
-
- recipe_object = Recipe.objects.get(layer_version = recipe_information['layer_version'],
- file_path__endswith = recipe_information['file_path'],
- name = recipename)
- except Recipe.DoesNotExist:
- logger.error("Could not find recipe for recipe_information %s name %s" , pformat(recipe_information), recipename)
- raise
-
- task_information = {}
- task_information['build'] = self.internal_state['build']
- task_information['recipe'] = recipe_object
- task_information['task_name'] = taskname
- task_information['cpu_usage'] = taskstats['cpu_usage']
- task_information['disk_io'] = taskstats['disk_io']
- if 'elapsed_time' in taskstats:
- task_information['elapsed_time'] = taskstats['elapsed_time']
- self.orm_wrapper.get_update_task_object(task_information)
+ for (task_file, task_name, task_stats, recipe_name) in task_data:
+ build = self.internal_state['build']
+ self.orm_wrapper.update_task_object(build, task_name, recipe_name, task_stats)
def update_and_store_task(self, event):
assert 'taskfile' in vars(event)
@@ -1105,13 +1160,6 @@ class BuildInfoHelper(object):
recipe = self.orm_wrapper.get_update_recipe_object(recipe_information, True)
task_information = self._get_task_information(event,recipe)
- if 'time' in vars(event):
- if not 'start_time' in self.internal_state['taskdata'][identifier]:
- self.internal_state['taskdata'][identifier]['start_time'] = event.time
- else:
- task_information['end_time'] = event.time
- task_information['start_time'] = self.internal_state['taskdata'][identifier]['start_time']
-
task_information['outcome'] = self.internal_state['taskdata'][identifier]['outcome']
if 'logfile' in vars(event):
@@ -1185,11 +1233,12 @@ class BuildInfoHelper(object):
for target in self.internal_state['targets']:
if target.is_image:
pkgdata = BuildInfoHelper._get_data_from_event(event)['pkgdata']
- imgdata = BuildInfoHelper._get_data_from_event(event)['imgdata'][target.target]
- filedata = BuildInfoHelper._get_data_from_event(event)['filedata'][target.target]
+ imgdata = BuildInfoHelper._get_data_from_event(event)['imgdata'].get(target.target, {})
+ filedata = BuildInfoHelper._get_data_from_event(event)['filedata'].get(target.target, {})
try:
- self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata, pkgdata, self.internal_state['recipes'])
+ self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata, pkgdata, self.internal_state['recipes'], built_package=True)
+ self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata.copy(), pkgdata, self.internal_state['recipes'], built_package=False)
except KeyError as e:
logger.warn("KeyError in save_target_package_information"
"%s ", e)
@@ -1269,6 +1318,9 @@ class BuildInfoHelper(object):
for cls in event._depgraph['pn'][pn]['inherits']:
if cls.endswith('/image.bbclass'):
recipe.is_image = True
+ recipe_info['is_image'] = True
+ # Save the is_image state to the relevant recipe objects
+ self.orm_wrapper.get_update_recipe_object(recipe_info)
break
if recipe.is_image:
for t in self.internal_state['targets']:
@@ -1285,15 +1337,27 @@ class BuildInfoHelper(object):
# buildtime
recipedeps_objects = []
for recipe in event._depgraph['depends']:
- try:
- target = self.internal_state['recipes'][recipe]
- for dep in event._depgraph['depends'][recipe]:
+ target = self.internal_state['recipes'][recipe]
+ for dep in event._depgraph['depends'][recipe]:
+ if dep in assume_provided:
+ continue
+ via = None
+ if 'providermap' in event._depgraph and dep in event._depgraph['providermap']:
+ deprecipe = event._depgraph['providermap'][dep][0]
+ dependency = self.internal_state['recipes'][deprecipe]
+ via = Provides.objects.get_or_create(name=dep,
+ recipe=dependency)[0]
+ elif dep in self.internal_state['recipes']:
dependency = self.internal_state['recipes'][dep]
- recipedeps_objects.append(Recipe_Dependency( recipe = target,
- depends_on = dependency, dep_type = Recipe_Dependency.TYPE_DEPENDS))
- except KeyError as e:
- if e not in assume_provided and not str(e).startswith("virtual/"):
- errormsg += " stpd: KeyError saving recipe dependency for %s, %s \n" % (recipe, e)
+ else:
+ errormsg += " stpd: KeyError saving recipe dependency for %s, %s \n" % (recipe, dep)
+ continue
+ recipe_dep = Recipe_Dependency(recipe=target,
+ depends_on=dependency,
+ via=via,
+ dep_type=Recipe_Dependency.TYPE_DEPENDS)
+ recipedeps_objects.append(recipe_dep)
+
Recipe_Dependency.objects.bulk_create(recipedeps_objects)
# save all task information
@@ -1333,10 +1397,17 @@ class BuildInfoHelper(object):
def store_build_package_information(self, event):
package_info = BuildInfoHelper._get_data_from_event(event)
- self.orm_wrapper.save_build_package_information(self.internal_state['build'],
- package_info,
- self.internal_state['recipes'],
- )
+ self.orm_wrapper.save_build_package_information(
+ self.internal_state['build'],
+ package_info,
+ self.internal_state['recipes'],
+ built_package=True)
+
+ self.orm_wrapper.save_build_package_information(
+ self.internal_state['build'],
+ package_info,
+ self.internal_state['recipes'],
+ built_package=False)
def _store_build_done(self, errorcode):
logger.info("Build exited with errorcode %d", errorcode)
@@ -1345,9 +1416,18 @@ class BuildInfoHelper(object):
be.lock = BuildEnvironment.LOCK_LOCK
be.save()
br = BuildRequest.objects.get(pk = br_id)
+
+ # if we're 'done' because we got cancelled update the build outcome
+ if br.state == BuildRequest.REQ_CANCELLING:
+ logger.info("Build cancelled")
+ br.build.outcome = Build.CANCELLED
+ br.build.save()
+ self.internal_state['build'] = br.build
+ errorcode = 0
+
if errorcode == 0:
# request archival of the project artifacts
- br.state = BuildRequest.REQ_ARCHIVE
+ br.state = BuildRequest.REQ_COMPLETED
else:
br.state = BuildRequest.REQ_FAILED
br.save()
@@ -1434,3 +1514,8 @@ class BuildInfoHelper(object):
if not connection.features.autocommits_when_autocommit_is_off:
transaction.set_autocommit(True)
+
+ # unset the brbe; this is to prevent subsequent command-line builds
+ # being incorrectly attached to the previous Toaster-triggered build;
+ # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=9021
+ self.brbe = None
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py
deleted file mode 100755
index 7fc690e2f..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/builddetailspage.py
+++ /dev/null
@@ -1,437 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import pango
-import gobject
-import bb.process
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hobwidget import hic, HobNotebook, HobAltButton, HobWarpCellRendererText, HobButton, HobInfoButton
-from bb.ui.crumbs.runningbuild import RunningBuildTreeView
-from bb.ui.crumbs.runningbuild import BuildFailureTreeView
-from bb.ui.crumbs.hobpages import HobPage
-from bb.ui.crumbs.hobcolor import HobColors
-
-class BuildConfigurationTreeView(gtk.TreeView):
- def __init__ (self):
- gtk.TreeView.__init__(self)
- self.set_rules_hint(False)
- self.set_headers_visible(False)
- self.set_property("hover-expand", True)
- self.get_selection().set_mode(gtk.SELECTION_SINGLE)
-
- # The icon that indicates whether we're building or failed.
- renderer0 = gtk.CellRendererText()
- renderer0.set_property('font-desc', pango.FontDescription('courier bold 12'))
- col0 = gtk.TreeViewColumn ("Name", renderer0, text=0)
- self.append_column (col0)
-
- # The message of configuration.
- renderer1 = HobWarpCellRendererText(col_number=1)
- col1 = gtk.TreeViewColumn ("Values", renderer1, text=1)
- self.append_column (col1)
-
- def set_vars(self, key="", var=[""]):
- d = {}
- if type(var) == str:
- d = {key: [var]}
- elif type(var) == list and len(var) > 1:
- #create the sub item line
- l = []
- text = ""
- for item in var:
- text = " - " + item
- l.append(text)
- d = {key: var}
-
- return d
-
- def set_config_model(self, show_vars):
- listmodel = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- parent = None
- for var in show_vars:
- for subitem in var.items():
- name = subitem[0]
- is_parent = True
- for value in subitem[1]:
- if is_parent:
- parent = listmodel.append(parent, (name, value))
- is_parent = False
- else:
- listmodel.append(parent, (None, value))
- name = " - "
- parent = None
- # renew the tree model after get the configuration messages
- self.set_model(listmodel)
-
- def show(self, src_config_info, src_params):
- vars = []
- vars.append(self.set_vars("BB version:", src_params.bb_version))
- vars.append(self.set_vars("Target arch:", src_params.target_arch))
- vars.append(self.set_vars("Target OS:", src_params.target_os))
- vars.append(self.set_vars("Machine:", src_config_info.curr_mach))
- vars.append(self.set_vars("Distro:", src_config_info.curr_distro))
- vars.append(self.set_vars("Distro version:", src_params.distro_version))
- vars.append(self.set_vars("SDK machine:", src_config_info.curr_sdk_machine))
- vars.append(self.set_vars("Tune features:", src_params.tune_pkgarch))
- vars.append(self.set_vars("Layers:", src_config_info.layers))
-
- for path in src_config_info.layers:
- import os, os.path
- if os.path.exists(path):
- branch = bb.process.run('cd %s; git branch | grep "^* " | tr -d "* "' % path)[0]
- if branch.startswith("fatal:"):
- branch = "(unknown)"
- if branch:
- branch = branch.strip('\n')
- vars.append(self.set_vars("Branch:", branch))
- break
-
- self.set_config_model(vars)
-
- def reset(self):
- self.set_model(None)
-
-#
-# BuildDetailsPage
-#
-
-class BuildDetailsPage (HobPage):
-
- def __init__(self, builder):
- super(BuildDetailsPage, self).__init__(builder, "Building ...")
-
- self.num_of_issues = 0
- self.endpath = (0,)
- # create visual elements
- self.create_visual_elements()
-
- def create_visual_elements(self):
- # create visual elements
- self.vbox = gtk.VBox(False, 12)
-
- self.progress_box = gtk.VBox(False, 12)
- self.task_status = gtk.Label("\n") # to ensure layout is correct
- self.task_status.set_alignment(0.0, 0.5)
- self.progress_box.pack_start(self.task_status, expand=False, fill=False)
- self.progress_hbox = gtk.HBox(False, 6)
- self.progress_box.pack_end(self.progress_hbox, expand=True, fill=True)
- self.progress_bar = HobProgressBar()
- self.progress_hbox.pack_start(self.progress_bar, expand=True, fill=True)
- self.stop_button = HobAltButton("Stop")
- self.stop_button.connect("clicked", self.stop_button_clicked_cb)
- self.stop_button.set_sensitive(False)
- self.progress_hbox.pack_end(self.stop_button, expand=False, fill=False)
-
- self.notebook = HobNotebook()
- self.config_tv = BuildConfigurationTreeView()
- self.scrolled_view_config = gtk.ScrolledWindow ()
- self.scrolled_view_config.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- self.scrolled_view_config.add(self.config_tv)
- self.notebook.append_page(self.scrolled_view_config, "Build configuration")
-
- self.failure_tv = BuildFailureTreeView()
- self.failure_model = self.builder.handler.build.model.failure_model()
- self.failure_tv.set_model(self.failure_model)
- self.scrolled_view_failure = gtk.ScrolledWindow ()
- self.scrolled_view_failure.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- self.scrolled_view_failure.add(self.failure_tv)
- self.notebook.append_page(self.scrolled_view_failure, "Issues")
-
- self.build_tv = RunningBuildTreeView(readonly=True, hob=True)
- self.build_tv.set_model(self.builder.handler.build.model)
- self.scrolled_view_build = gtk.ScrolledWindow ()
- self.scrolled_view_build.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
- self.scrolled_view_build.add(self.build_tv)
- self.notebook.append_page(self.scrolled_view_build, "Log")
-
- self.builder.handler.build.model.connect_after("row-changed", self.scroll_to_present_row, self.scrolled_view_build.get_vadjustment(), self.build_tv)
-
- self.button_box = gtk.HBox(False, 6)
- self.back_button = HobAltButton('&lt;&lt; Back')
- self.back_button.connect("clicked", self.back_button_clicked_cb)
- self.button_box.pack_start(self.back_button, expand=False, fill=False)
-
- def update_build_status(self, current, total, task):
- recipe_path, recipe_task = task.split(", ")
- recipe = os.path.basename(recipe_path).rstrip(".bb")
- tsk_msg = "<b>Running task %s of %s:</b> %s\n<b>Recipe:</b> %s" % (current, total, recipe_task, recipe)
- self.task_status.set_markup(tsk_msg)
- self.stop_button.set_sensitive(True)
-
- def reset_build_status(self):
- self.task_status.set_markup("\n") # to ensure layout is correct
- self.endpath = (0,)
-
- def show_issues(self):
- self.num_of_issues += 1
- self.notebook.show_indicator_icon("Issues", self.num_of_issues)
- self.notebook.queue_draw()
-
- def reset_issues(self):
- self.num_of_issues = 0
- self.notebook.hide_indicator_icon("Issues")
-
- def _remove_all_widget(self):
- children = self.vbox.get_children() or []
- for child in children:
- self.vbox.remove(child)
- children = self.box_group_area.get_children() or []
- for child in children:
- self.box_group_area.remove(child)
- children = self.get_children() or []
- for child in children:
- self.remove(child)
-
- def add_build_fail_top_bar(self, actions, log_file=None):
- primary_action = "Edit %s" % actions
-
- color = HobColors.ERROR
- build_fail_top = gtk.EventBox()
- #build_fail_top.set_size_request(-1, 200)
- build_fail_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
-
- build_fail_tab = gtk.Table(14, 46, True)
- build_fail_top.add(build_fail_tab)
-
- icon = gtk.Image()
- icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INDI_ERROR_FILE)
- icon.set_from_pixbuf(icon_pix_buffer)
- build_fail_tab.attach(icon, 1, 4, 0, 6)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup("<span size='x-large'><b>%s</b></span>" % self.title)
- build_fail_tab.attach(label, 4, 26, 0, 6)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- # Ensure variable disk_full is defined
- if not hasattr(self.builder, 'disk_full'):
- self.builder.disk_full = False
-
- if self.builder.disk_full:
- markup = "<span size='medium'>There is no disk space left, so Hob cannot finish building your image. Free up some disk space\n"
- markup += "and restart the build. Check the \"Issues\" tab for more details</span>"
- label.set_markup(markup)
- else:
- label.set_markup("<span size='medium'>Check the \"Issues\" information for more details</span>")
- build_fail_tab.attach(label, 4, 40, 4, 9)
-
- # create button 'Edit packages'
- action_button = HobButton(primary_action)
- #action_button.set_size_request(-1, 40)
- action_button.set_tooltip_text("Edit the %s parameters" % actions)
- action_button.connect('clicked', self.failure_primary_action_button_clicked_cb, primary_action)
-
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.set_relief(gtk.RELIEF_HALF)
- open_log_button.set_tooltip_text("Open the build's log file")
- open_log_button.connect('clicked', self.open_log_button_clicked_cb, log_file)
-
- attach_pos = (24 if log_file else 14)
- file_bug_button = HobAltButton('File a bug')
- file_bug_button.set_relief(gtk.RELIEF_HALF)
- file_bug_button.set_tooltip_text("Open the Yocto Project bug tracking website")
- file_bug_button.connect('clicked', self.failure_activate_file_bug_link_cb)
-
- if not self.builder.disk_full:
- build_fail_tab.attach(action_button, 4, 13, 9, 12)
- if log_file:
- build_fail_tab.attach(open_log_button, 14, 23, 9, 12)
- build_fail_tab.attach(file_bug_button, attach_pos, attach_pos + 9, 9, 12)
-
- else:
- restart_build = HobButton("Restart the build")
- restart_build.set_tooltip_text("Restart the build")
- restart_build.connect('clicked', self.restart_build_button_clicked_cb)
-
- build_fail_tab.attach(restart_build, 4, 13, 9, 12)
- build_fail_tab.attach(action_button, 14, 23, 9, 12)
- if log_file:
- build_fail_tab.attach(open_log_button, attach_pos, attach_pos + 9, 9, 12)
-
- self.builder.disk_full = False
- return build_fail_top
-
- def show_fail_page(self, title):
- self._remove_all_widget()
- self.title = "Hob cannot build your %s" % title
-
- self.build_fail_bar = self.add_build_fail_top_bar(title, self.builder.current_logfile)
-
- self.pack_start(self.group_align, expand=True, fill=True)
- self.box_group_area.pack_start(self.build_fail_bar, expand=False, fill=False)
- self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
-
- self.vbox.pack_start(self.notebook, expand=True, fill=True)
- self.show_all()
- self.notebook.set_page("Issues")
- self.back_button.hide()
-
- def add_build_stop_top_bar(self, action, log_file=None):
- color = HobColors.LIGHT_GRAY
- build_stop_top = gtk.EventBox()
- #build_stop_top.set_size_request(-1, 200)
- build_stop_top.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
- build_stop_top.set_flags(gtk.CAN_DEFAULT)
- build_stop_top.grab_default()
-
- build_stop_tab = gtk.Table(11, 46, True)
- build_stop_top.add(build_stop_tab)
-
- icon = gtk.Image()
- icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INFO_HOVER_FILE)
- icon.set_from_pixbuf(icon_pix_buffer)
- build_stop_tab.attach(icon, 1, 4, 0, 6)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup("<span size='x-large'><b>%s</b></span>" % self.title)
- build_stop_tab.attach(label, 4, 26, 0, 6)
-
- action_button = HobButton("Edit %s" % action)
- action_button.set_size_request(-1, 40)
- if action == "image":
- action_button.set_tooltip_text("Edit the image parameters")
- elif action == "recipes":
- action_button.set_tooltip_text("Edit the included recipes")
- elif action == "packages":
- action_button.set_tooltip_text("Edit the included packages")
- action_button.connect('clicked', self.stop_primary_action_button_clicked_cb, action)
- build_stop_tab.attach(action_button, 4, 13, 6, 9)
-
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.set_relief(gtk.RELIEF_HALF)
- open_log_button.set_tooltip_text("Open the build's log file")
- open_log_button.connect('clicked', self.open_log_button_clicked_cb, log_file)
- build_stop_tab.attach(open_log_button, 14, 23, 6, 9)
-
- attach_pos = (24 if log_file else 14)
- build_button = HobAltButton("Build new image")
- #build_button.set_size_request(-1, 40)
- build_button.set_tooltip_text("Create a new image from scratch")
- build_button.connect('clicked', self.new_image_button_clicked_cb)
- build_stop_tab.attach(build_button, attach_pos, attach_pos + 9, 6, 9)
-
- return build_stop_top, action_button
-
- def show_stop_page(self, action):
- self._remove_all_widget()
- self.title = "Build stopped"
- self.build_stop_bar, action_button = self.add_build_stop_top_bar(action, self.builder.current_logfile)
-
- self.pack_start(self.group_align, expand=True, fill=True)
- self.box_group_area.pack_start(self.build_stop_bar, expand=False, fill=False)
- self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
-
- self.vbox.pack_start(self.notebook, expand=True, fill=True)
- self.show_all()
- self.back_button.hide()
- return action_button
-
- def show_page(self, step):
- self._remove_all_widget()
- if step == self.builder.PACKAGE_GENERATING or step == self.builder.FAST_IMAGE_GENERATING:
- self.title = "Building packages ..."
- else:
- self.title = "Building image ..."
- self.build_details_top = self.add_onto_top_bar(None)
- self.pack_start(self.build_details_top, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- self.box_group_area.pack_start(self.vbox, expand=True, fill=True)
-
- self.progress_bar.reset()
- self.config_tv.reset()
- self.vbox.pack_start(self.progress_box, expand=False, fill=False)
-
- self.vbox.pack_start(self.notebook, expand=True, fill=True)
-
- self.box_group_area.pack_end(self.button_box, expand=False, fill=False)
- self.show_all()
- self.notebook.set_page("Log")
- self.back_button.hide()
-
- self.reset_build_status()
- self.reset_issues()
-
- def update_progress_bar(self, title, fraction, status=None):
- self.progress_bar.update(fraction)
- self.progress_bar.set_title(title)
- self.progress_bar.set_rcstyle(status)
-
- def back_button_clicked_cb(self, button):
- self.builder.show_configuration()
-
- def new_image_button_clicked_cb(self, button):
- self.builder.reset()
-
- def show_back_button(self):
- self.back_button.show()
-
- def stop_button_clicked_cb(self, button):
- self.builder.stop_build()
-
- def hide_stop_button(self):
- self.stop_button.set_sensitive(False)
- self.stop_button.hide()
-
- def scroll_to_present_row(self, model, path, iter, v_adj, treeview):
- if treeview and v_adj:
- if path[0] > self.endpath[0]: # check the event is a new row append or not
- self.endpath = path
- # check the gtk.adjustment position is at end boundary or not
- if (v_adj.upper <= v_adj.page_size) or (v_adj.value == v_adj.upper - v_adj.page_size):
- treeview.scroll_to_cell(path)
-
- def show_configurations(self, configurations, params):
- self.config_tv.show(configurations, params)
-
- def failure_primary_action_button_clicked_cb(self, button, action):
- if "Edit recipes" in action:
- self.builder.show_recipes()
- elif "Edit packages" in action:
- self.builder.show_packages()
- elif "Edit image" in action:
- self.builder.show_configuration()
-
- def restart_build_button_clicked_cb(self, button):
- self.builder.just_bake()
-
- def stop_primary_action_button_clicked_cb(self, button, action):
- if "recipes" in action:
- self.builder.show_recipes()
- elif "packages" in action:
- self.builder.show_packages()
- elif "image" in action:
- self.builder.show_configuration()
-
- def open_log_button_clicked_cb(self, button, log_file):
- if log_file:
- log_file = "file:///" + log_file
- gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)
-
- def failure_activate_file_bug_link_cb(self, button):
- button.child.emit('activate-link', "http://bugzilla.yoctoproject.org")
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/builder.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/builder.py
deleted file mode 100755
index dcc410426..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/builder.py
+++ /dev/null
@@ -1,1475 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import glib
-import gtk, gobject
-import copy
-import os
-import subprocess
-import shlex
-import re
-import logging
-import sys
-import signal
-import time
-from bb.ui.crumbs.imageconfigurationpage import ImageConfigurationPage
-from bb.ui.crumbs.recipeselectionpage import RecipeSelectionPage
-from bb.ui.crumbs.packageselectionpage import PackageSelectionPage
-from bb.ui.crumbs.builddetailspage import BuildDetailsPage
-from bb.ui.crumbs.imagedetailspage import ImageDetailsPage
-from bb.ui.crumbs.sanitycheckpage import SanityCheckPage
-from bb.ui.crumbs.hobwidget import hwc, HobButton, HobAltButton
-from bb.ui.crumbs.persistenttooltip import PersistentTooltip
-import bb.ui.crumbs.utils
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.simplesettingsdialog import SimpleSettingsDialog
-from bb.ui.crumbs.hig.advancedsettingsdialog import AdvancedSettingsDialog
-from bb.ui.crumbs.hig.deployimagedialog import DeployImageDialog
-from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog
-from bb.ui.crumbs.hig.imageselectiondialog import ImageSelectionDialog
-from bb.ui.crumbs.hig.parsingwarningsdialog import ParsingWarningsDialog
-from bb.ui.crumbs.hig.propertydialog import PropertyDialog
-
-hobVer = 20120808
-
-class Configuration:
- '''Represents the data structure of configuration.'''
-
- @classmethod
- def parse_proxy_string(cls, proxy):
- pattern = "^\s*((http|https|ftp|socks|cvs)://)?((\S+):(\S+)@)?([^\s:]+)(:(\d+))?/?"
- match = re.search(pattern, proxy)
- if match:
- return match.group(2), match.group(4), match.group(5), match.group(6), match.group(8)
- else:
- return None, None, None, "", ""
-
- @classmethod
- def make_host_string(cls, prot, user, passwd, host, default_prot=""):
- if host == None or host == "":
- return ""
-
- passwd = passwd or ""
-
- if user != None and user != "":
- if prot == None or prot == "":
- prot = default_prot
- return prot + "://" + user + ":" + passwd + "@" + host
- else:
- if prot == None or prot == "":
- return host
- else:
- return prot + "://" + host
-
- @classmethod
- def make_port_string(cls, port):
- port = port or ""
- return port
-
- @classmethod
- def make_proxy_string(cls, prot, user, passwd, host, port, default_prot=""):
- if host == None or host == "":# or port == None or port == "":
- return ""
-
- return Configuration.make_host_string(prot, user, passwd, host, default_prot) + (":" + Configuration.make_port_string(port) if port else "")
-
- def __init__(self):
- self.curr_mach = ""
- self.selected_image = None
- # settings
- self.curr_distro = ""
- self.dldir = self.sstatedir = self.sstatemirror = ""
- self.pmake = self.bbthread = 0
- self.curr_package_format = ""
- self.image_rootfs_size = self.image_extra_size = 0
- self.image_overhead_factor = 1
- self.incompat_license = ""
- self.curr_sdk_machine = ""
- self.conf_version = self.lconf_version = ""
- self.extra_setting = {}
- self.toolchain_build = False
- self.image_fstypes = ""
- self.image_size = None
- self.image_packages = []
- # bblayers.conf
- self.layers = []
- # image/recipes/packages
- self.clear_selection()
-
- self.user_selected_packages = []
-
- self.default_task = "build"
-
- # proxy settings
- self.enable_proxy = None
- self.same_proxy = False
- self.proxies = {
- "http" : [None, None, None, "", ""], # protocol : [prot, user, passwd, host, port]
- "https" : [None, None, None, "", ""],
- "ftp" : [None, None, None, "", ""],
- "socks" : [None, None, None, "", ""],
- "cvs" : [None, None, None, "", ""],
- }
-
- def clear_selection(self):
- self.selected_recipes = []
- self.selected_packages = []
- self.initial_selected_image = None
- self.initial_selected_packages = []
- self.initial_user_selected_packages = []
-
- def split_proxy(self, protocol, proxy):
- entry = []
- prot, user, passwd, host, port = Configuration.parse_proxy_string(proxy)
- entry.append(prot)
- entry.append(user)
- entry.append(passwd)
- entry.append(host)
- entry.append(port)
- self.proxies[protocol] = entry
-
- def combine_proxy(self, protocol):
- entry = self.proxies[protocol]
- return Configuration.make_proxy_string(entry[0], entry[1], entry[2], entry[3], entry[4], protocol)
-
- def combine_host_only(self, protocol):
- entry = self.proxies[protocol]
- return Configuration.make_host_string(entry[0], entry[1], entry[2], entry[3], protocol)
-
- def combine_port_only(self, protocol):
- entry = self.proxies[protocol]
- return Configuration.make_port_string(entry[4])
-
- def update(self, params):
- # settings
- self.curr_distro = params["distro"]
- self.dldir = params["dldir"]
- self.sstatedir = params["sstatedir"]
- self.sstatemirror = params["sstatemirror"]
- self.pmake = int(params["pmake"].split()[1])
- self.bbthread = params["bbthread"]
- self.curr_package_format = " ".join(params["pclass"].split("package_")).strip()
- self.image_rootfs_size = params["image_rootfs_size"]
- self.image_extra_size = params["image_extra_size"]
- self.image_overhead_factor = params['image_overhead_factor']
- self.incompat_license = params["incompat_license"]
- self.curr_sdk_machine = params["sdk_machine"]
- self.conf_version = params["conf_version"]
- self.lconf_version = params["lconf_version"]
- self.image_fstypes = params["image_fstypes"]
- # self.extra_setting/self.toolchain_build
- # bblayers.conf
- self.layers = params["layer"].split()
- self.layers_non_removable = params["layers_non_removable"].split()
- self.default_task = params["default_task"]
-
- # proxy settings
- self.enable_proxy = params["http_proxy"] != "" or params["https_proxy"] != "" \
- or params["ftp_proxy"] != "" or params["socks_proxy"] != "" \
- or params["cvs_proxy_host"] != "" or params["cvs_proxy_port"] != ""
- self.split_proxy("http", params["http_proxy"])
- self.split_proxy("https", params["https_proxy"])
- self.split_proxy("ftp", params["ftp_proxy"])
- self.split_proxy("socks", params["socks_proxy"])
- self.split_proxy("cvs", params["cvs_proxy_host"] + ":" + params["cvs_proxy_port"])
-
- def save(self, handler, defaults=False):
- # bblayers.conf
- handler.set_var_in_file("BBLAYERS", self.layers, "bblayers.conf")
- # local.conf
- if not defaults:
- handler.early_assign_var_in_file("MACHINE", self.curr_mach, "local.conf")
- handler.set_var_in_file("DISTRO", self.curr_distro, "local.conf")
- handler.set_var_in_file("DL_DIR", self.dldir, "local.conf")
- handler.set_var_in_file("SSTATE_DIR", self.sstatedir, "local.conf")
- sstate_mirror_list = self.sstatemirror.split("\\n ")
- sstate_mirror_list_modified = []
- for mirror in sstate_mirror_list:
- if mirror != "":
- mirror = mirror + "\\n"
- sstate_mirror_list_modified.append(mirror)
- handler.set_var_in_file("SSTATE_MIRRORS", sstate_mirror_list_modified, "local.conf")
- handler.set_var_in_file("PARALLEL_MAKE", "-j %s" % self.pmake, "local.conf")
- handler.set_var_in_file("BB_NUMBER_THREADS", self.bbthread, "local.conf")
- handler.set_var_in_file("PACKAGE_CLASSES", " ".join(["package_" + i for i in self.curr_package_format.split()]), "local.conf")
- handler.set_var_in_file("IMAGE_ROOTFS_SIZE", self.image_rootfs_size, "local.conf")
- handler.set_var_in_file("IMAGE_EXTRA_SPACE", self.image_extra_size, "local.conf")
- handler.set_var_in_file("INCOMPATIBLE_LICENSE", self.incompat_license, "local.conf")
- handler.set_var_in_file("SDKMACHINE", self.curr_sdk_machine, "local.conf")
- handler.set_var_in_file("CONF_VERSION", self.conf_version, "local.conf")
- handler.set_var_in_file("LCONF_VERSION", self.lconf_version, "bblayers.conf")
- handler.set_extra_config(self.extra_setting)
- handler.set_var_in_file("TOOLCHAIN_BUILD", self.toolchain_build, "local.conf")
- handler.set_var_in_file("IMAGE_FSTYPES", self.image_fstypes, "local.conf")
- if not defaults:
- # image/recipes/packages
- handler.set_var_in_file("__SELECTED_IMAGE__", self.selected_image, "local.conf")
- handler.set_var_in_file("DEPENDS", self.selected_recipes, "local.conf")
- handler.set_var_in_file("IMAGE_INSTALL", self.user_selected_packages, "local.conf")
- # proxy
- if self.enable_proxy == True:
- handler.set_var_in_file("http_proxy", self.combine_proxy("http"), "local.conf")
- handler.set_var_in_file("https_proxy", self.combine_proxy("https"), "local.conf")
- handler.set_var_in_file("ftp_proxy", self.combine_proxy("ftp"), "local.conf")
- handler.set_var_in_file("all_proxy", self.combine_proxy("socks"), "local.conf")
- handler.set_var_in_file("CVS_PROXY_HOST", self.combine_host_only("cvs"), "local.conf")
- handler.set_var_in_file("CVS_PROXY_PORT", self.combine_port_only("cvs"), "local.conf")
- else:
- handler.set_var_in_file("http_proxy", "", "local.conf")
- handler.set_var_in_file("https_proxy", "", "local.conf")
- handler.set_var_in_file("ftp_proxy", "", "local.conf")
- handler.set_var_in_file("all_proxy", "", "local.conf")
- handler.set_var_in_file("CVS_PROXY_HOST", "", "local.conf")
- handler.set_var_in_file("CVS_PROXY_PORT", "", "local.conf")
-
- def __str__(self):
- s = "VERSION: '%s', BBLAYERS: '%s', MACHINE: '%s', DISTRO: '%s', DL_DIR: '%s'," % \
- (hobVer, " ".join(self.layers), self.curr_mach, self.curr_distro, self.dldir )
- s += "SSTATE_DIR: '%s', SSTATE_MIRROR: '%s', PARALLEL_MAKE: '-j %s', BB_NUMBER_THREADS: '%s', PACKAGE_CLASSES: '%s', " % \
- (self.sstatedir, self.sstatemirror, self.pmake, self.bbthread, " ".join(["package_" + i for i in self.curr_package_format.split()]))
- s += "IMAGE_ROOTFS_SIZE: '%s', IMAGE_EXTRA_SPACE: '%s', INCOMPATIBLE_LICENSE: '%s', SDKMACHINE: '%s', CONF_VERSION: '%s', " % \
- (self.image_rootfs_size, self.image_extra_size, self.incompat_license, self.curr_sdk_machine, self.conf_version)
- s += "LCONF_VERSION: '%s', EXTRA_SETTING: '%s', TOOLCHAIN_BUILD: '%s', IMAGE_FSTYPES: '%s', __SELECTED_IMAGE__: '%s', " % \
- (self.lconf_version, self.extra_setting, self.toolchain_build, self.image_fstypes, self.selected_image)
- s += "DEPENDS: '%s', IMAGE_INSTALL: '%s', enable_proxy: '%s', use_same_proxy: '%s', http_proxy: '%s', " % \
- (self.selected_recipes, self.user_selected_packages, self.enable_proxy, self.same_proxy, self.combine_proxy("http"))
- s += "https_proxy: '%s', ftp_proxy: '%s', all_proxy: '%s', CVS_PROXY_HOST: '%s', CVS_PROXY_PORT: '%s'" % \
- (self.combine_proxy("https"), self.combine_proxy("ftp"), self.combine_proxy("socks"),
- self.combine_host_only("cvs"), self.combine_port_only("cvs"))
- return s
-
-class Parameters:
- '''Represents other variables like available machines, etc.'''
-
- def __init__(self):
- # Variables
- self.max_threads = 65535
- self.core_base = ""
- self.image_addr = ""
- self.image_types = []
- self.runnable_image_types = []
- self.runnable_machine_patterns = []
- self.deployable_image_types = []
- self.tmpdir = ""
-
- self.all_machines = []
- self.all_package_formats = []
- self.all_distros = []
- self.all_sdk_machines = []
- self.all_layers = []
- self.image_names = []
- self.image_white_pattern = ""
- self.image_black_pattern = ""
-
- # for build log to show
- self.bb_version = ""
- self.target_arch = ""
- self.target_os = ""
- self.distro_version = ""
- self.tune_pkgarch = ""
-
- def update(self, params):
- self.max_threads = params["max_threads"]
- self.core_base = params["core_base"]
- self.image_addr = params["image_addr"]
- self.image_types = params["image_types"].split()
- self.runnable_image_types = params["runnable_image_types"].split()
- self.runnable_machine_patterns = params["runnable_machine_patterns"].split()
- self.deployable_image_types = params["deployable_image_types"].split()
- self.tmpdir = params["tmpdir"]
- self.image_white_pattern = params["image_white_pattern"]
- self.image_black_pattern = params["image_black_pattern"]
- self.kernel_image_type = params["kernel_image_type"]
- # for build log to show
- self.bb_version = params["bb_version"]
- self.target_arch = params["target_arch"]
- self.target_os = params["target_os"]
- self.distro_version = params["distro_version"]
- self.tune_pkgarch = params["tune_pkgarch"]
-
-def hob_conf_filter(fn, data):
- if fn.endswith("/local.conf"):
- distro = data.getVar("DISTRO_HOB", False)
- if distro:
- if distro != "defaultsetup":
- data.setVar("DISTRO", distro)
- else:
- data.delVar("DISTRO")
-
- keys = ["MACHINE_HOB", "SDKMACHINE_HOB", "PACKAGE_CLASSES_HOB", \
- "BB_NUMBER_THREADS_HOB", "PARALLEL_MAKE_HOB", "DL_DIR_HOB", \
- "SSTATE_DIR_HOB", "SSTATE_MIRRORS_HOB", "INCOMPATIBLE_LICENSE_HOB"]
- for key in keys:
- var_hob = data.getVar(key, False)
- if var_hob:
- data.setVar(key.split("_HOB")[0], var_hob)
- return
-
- if fn.endswith("/bblayers.conf"):
- layers = data.getVar("BBLAYERS_HOB", False)
- if layers:
- data.setVar("BBLAYERS", layers)
- return
-
-class Builder(gtk.Window):
-
- (INITIAL_CHECKS,
- MACHINE_SELECTION,
- RCPPKGINFO_POPULATING,
- RCPPKGINFO_POPULATED,
- BASEIMG_SELECTED,
- RECIPE_SELECTION,
- PACKAGE_GENERATING,
- PACKAGE_GENERATED,
- PACKAGE_SELECTION,
- FAST_IMAGE_GENERATING,
- IMAGE_GENERATING,
- IMAGE_GENERATED,
- MY_IMAGE_OPENED,
- BACK,
- END_NOOP) = range(15)
-
- (SANITY_CHECK,
- IMAGE_CONFIGURATION,
- RECIPE_DETAILS,
- BUILD_DETAILS,
- PACKAGE_DETAILS,
- IMAGE_DETAILS,
- END_TAB) = range(7)
-
- __step2page__ = {
- INITIAL_CHECKS : SANITY_CHECK,
- MACHINE_SELECTION : IMAGE_CONFIGURATION,
- RCPPKGINFO_POPULATING : IMAGE_CONFIGURATION,
- RCPPKGINFO_POPULATED : IMAGE_CONFIGURATION,
- BASEIMG_SELECTED : IMAGE_CONFIGURATION,
- RECIPE_SELECTION : RECIPE_DETAILS,
- PACKAGE_GENERATING : BUILD_DETAILS,
- PACKAGE_GENERATED : PACKAGE_DETAILS,
- PACKAGE_SELECTION : PACKAGE_DETAILS,
- FAST_IMAGE_GENERATING : BUILD_DETAILS,
- IMAGE_GENERATING : BUILD_DETAILS,
- IMAGE_GENERATED : IMAGE_DETAILS,
- MY_IMAGE_OPENED : IMAGE_DETAILS,
- END_NOOP : None,
- }
-
- SANITY_CHECK_MIN_DISPLAY_TIME = 5
-
- def __init__(self, hobHandler, recipe_model, package_model):
- super(Builder, self).__init__()
-
- self.hob_image = "hob-image"
-
- # handler
- self.handler = hobHandler
-
- # logger
- self.logger = logging.getLogger("BitBake")
- self.consolelog = None
- self.current_logfile = None
-
- # configuration and parameters
- self.configuration = Configuration()
- self.parameters = Parameters()
-
- # build step
- self.current_step = None
- self.previous_step = None
-
- self.stopping = False
-
- # recipe model and package model
- self.recipe_model = recipe_model
- self.package_model = package_model
-
- # Indicate whether user has customized the image
- self.customized = False
-
- # Indicate whether the UI is working
- self.sensitive = True
-
- # Indicate whether the sanity check ran
- self.sanity_checked = False
-
- # save parsing warnings
- self.parsing_warnings = []
-
- # create visual elements
- self.create_visual_elements()
-
- # connect the signals to functions
- self.connect("delete-event", self.destroy_window_cb)
- self.recipe_model.connect ("recipe-selection-changed", self.recipelist_changed_cb)
- self.package_model.connect("package-selection-changed", self.packagelist_changed_cb)
- self.handler.connect("config-updated", self.handler_config_updated_cb)
- self.handler.connect("package-formats-updated", self.handler_package_formats_updated_cb)
- self.handler.connect("parsing-started", self.handler_parsing_started_cb)
- self.handler.connect("parsing", self.handler_parsing_cb)
- self.handler.connect("parsing-completed", self.handler_parsing_completed_cb)
- self.handler.build.connect("build-started", self.handler_build_started_cb)
- self.handler.build.connect("build-succeeded", self.handler_build_succeeded_cb)
- self.handler.build.connect("build-failed", self.handler_build_failed_cb)
- self.handler.build.connect("build-aborted", self.handler_build_aborted_cb)
- self.handler.build.connect("task-started", self.handler_task_started_cb)
- self.handler.build.connect("disk-full", self.handler_disk_full_cb)
- self.handler.build.connect("log-error", self.handler_build_failure_cb)
- self.handler.build.connect("log-warning", self.handler_build_failure_cb)
- self.handler.build.connect("log", self.handler_build_log_cb)
- self.handler.build.connect("no-provider", self.handler_no_provider_cb)
- self.handler.connect("generating-data", self.handler_generating_data_cb)
- self.handler.connect("data-generated", self.handler_data_generated_cb)
- self.handler.connect("command-succeeded", self.handler_command_succeeded_cb)
- self.handler.connect("command-failed", self.handler_command_failed_cb)
- self.handler.connect("parsing-warning", self.handler_parsing_warning_cb)
- self.handler.connect("sanity-failed", self.handler_sanity_failed_cb)
- self.handler.connect("recipe-populated", self.handler_recipe_populated_cb)
- self.handler.connect("package-populated", self.handler_package_populated_cb)
-
- self.handler.append_to_bbfiles("${TOPDIR}/recipes/images/custom/*.bb")
- self.handler.append_to_bbfiles("${TOPDIR}/recipes/images/*.bb")
- self.initiate_new_build_async()
-
- signal.signal(signal.SIGINT, self.event_handle_SIGINT)
-
- def create_visual_elements(self):
- self.set_title("Hob")
- self.set_icon_name("applications-development")
- self.set_resizable(True)
-
- try:
- window_width = self.get_screen().get_width()
- window_height = self.get_screen().get_height()
- except AttributeError:
- print "Please set DISPLAY variable before running Hob."
- sys.exit(1)
-
- if window_width >= hwc.MAIN_WIN_WIDTH:
- window_width = hwc.MAIN_WIN_WIDTH
- window_height = hwc.MAIN_WIN_HEIGHT
- self.set_size_request(window_width, window_height)
-
- self.vbox = gtk.VBox(False, 0)
- self.vbox.set_border_width(0)
- self.add(self.vbox)
-
- # create pages
- self.image_configuration_page = ImageConfigurationPage(self)
- self.recipe_details_page = RecipeSelectionPage(self)
- self.build_details_page = BuildDetailsPage(self)
- self.package_details_page = PackageSelectionPage(self)
- self.image_details_page = ImageDetailsPage(self)
- self.sanity_check_page = SanityCheckPage(self)
- self.display_sanity_check = False
- self.sanity_check_post_func = False
- self.had_network_error = False
-
- self.nb = gtk.Notebook()
- self.nb.set_show_tabs(False)
- self.nb.insert_page(self.sanity_check_page, None, self.SANITY_CHECK)
- self.nb.insert_page(self.image_configuration_page, None, self.IMAGE_CONFIGURATION)
- self.nb.insert_page(self.recipe_details_page, None, self.RECIPE_DETAILS)
- self.nb.insert_page(self.build_details_page, None, self.BUILD_DETAILS)
- self.nb.insert_page(self.package_details_page, None, self.PACKAGE_DETAILS)
- self.nb.insert_page(self.image_details_page, None, self.IMAGE_DETAILS)
- self.vbox.pack_start(self.nb, expand=True, fill=True)
-
- self.show_all()
- self.nb.set_current_page(0)
-
- def sanity_check_timeout(self):
- # The minimum time for showing the 'sanity check' page has passe
- # If someone set the 'sanity_check_post_step' meanwhile, execute it now
- self.display_sanity_check = False
- if self.sanity_check_post_func:
- temp = self.sanity_check_post_func
- self.sanity_check_post_func = None
- temp()
- return False
-
- def show_sanity_check_page(self):
- # This window must stay on screen for at least 5 seconds, according to the design document
- self.nb.set_current_page(self.SANITY_CHECK)
- self.sanity_check_post_step = None
- self.display_sanity_check = True
- self.sanity_check_page.start()
- gobject.timeout_add(self.SANITY_CHECK_MIN_DISPLAY_TIME * 1000, self.sanity_check_timeout)
-
- def execute_after_sanity_check(self, func):
- if not self.display_sanity_check:
- func()
- else:
- self.sanity_check_post_func = func
-
- def generate_configuration(self):
- if not self.sanity_checked:
- self.show_sanity_check_page()
- self.handler.generate_configuration()
-
- def initiate_new_build_async(self):
- self.configuration.selected_image = None
- self.switch_page(self.MACHINE_SELECTION)
- self.handler.init_cooker()
- self.handler.set_extra_inherit("image_types")
- self.generate_configuration()
-
- def update_config_async(self):
- self.set_user_config()
- self.generate_configuration()
- self.switch_page(self.MACHINE_SELECTION)
-
- def sanity_check(self):
- self.handler.trigger_sanity_check()
-
- def populate_recipe_package_info_async(self):
- self.switch_page(self.RCPPKGINFO_POPULATING)
- # Parse recipes
- self.set_user_config()
- self.handler.generate_recipes()
-
- def generate_packages_async(self, log = False):
- self.switch_page(self.PACKAGE_GENERATING)
- if log:
- self.current_logfile = self.handler.get_logfile()
- self.do_log(self.current_logfile)
- # Build packages
- _, all_recipes = self.recipe_model.get_selected_recipes()
- self.set_user_config()
- self.handler.reset_build()
- self.handler.generate_packages(all_recipes, self.configuration.default_task)
-
- def restore_initial_selected_packages(self):
- self.package_model.set_selected_packages(self.configuration.initial_user_selected_packages, True)
- self.package_model.set_selected_packages(self.configuration.initial_selected_packages)
- for package in self.configuration.selected_packages:
- if package not in self.configuration.initial_selected_packages:
- self.package_model.exclude_item(self.package_model.find_path_for_item(package))
-
- def fast_generate_image_async(self, log = False):
- self.switch_page(self.FAST_IMAGE_GENERATING)
- if log:
- self.current_logfile = self.handler.get_logfile()
- self.do_log(self.current_logfile)
- # Build packages
- _, all_recipes = self.recipe_model.get_selected_recipes()
- self.set_user_config()
- self.handler.reset_build()
- self.handler.generate_packages(all_recipes, self.configuration.default_task)
-
- def generate_image_async(self, cont = False):
- self.switch_page(self.IMAGE_GENERATING)
- self.handler.reset_build()
- if not cont:
- self.current_logfile = self.handler.get_logfile()
- self.do_log(self.current_logfile)
- # Build image
- self.set_user_config()
- toolchain_packages = []
- base_image = None
- if self.configuration.toolchain_build:
- toolchain_packages = self.package_model.get_selected_packages_toolchain()
- if self.configuration.selected_image == self.recipe_model.__custom_image__:
- packages = self.package_model.get_selected_packages()
- image = self.hob_image
- base_image = self.configuration.initial_selected_image
- else:
- packages = []
- image = self.configuration.selected_image
- self.handler.generate_image(image,
- base_image,
- packages,
- toolchain_packages,
- self.configuration.default_task)
-
- def generate_new_image(self, image, description):
- base_image = self.configuration.initial_selected_image
- if base_image == self.recipe_model.__custom_image__:
- base_image = None
- packages = self.package_model.get_selected_packages()
- self.handler.generate_new_image(image, base_image, packages, description)
-
- def ensure_dir(self, directory):
- self.handler.ensure_dir(directory)
-
- def get_parameters_sync(self):
- return self.handler.get_parameters()
-
- def request_package_info_async(self):
- self.handler.request_package_info()
-
- def cancel_build_sync(self, force=False):
- self.handler.cancel_build(force)
-
- def cancel_parse_sync(self):
- self.handler.cancel_parse()
-
- def switch_page(self, next_step):
- # Main Workflow (Business Logic)
- self.nb.set_current_page(self.__step2page__[next_step])
-
- if next_step == self.MACHINE_SELECTION: # init step
- self.image_configuration_page.show_machine()
-
- elif next_step == self.RCPPKGINFO_POPULATING:
- # MACHINE CHANGED action or SETTINGS CHANGED
- # show the progress bar
- self.image_configuration_page.show_info_populating()
-
- elif next_step == self.RCPPKGINFO_POPULATED:
- self.image_configuration_page.show_info_populated()
-
- elif next_step == self.BASEIMG_SELECTED:
- self.image_configuration_page.show_baseimg_selected()
-
- elif next_step == self.RECIPE_SELECTION:
- if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
- self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.ALL)
- else:
- self.recipe_details_page.set_recipe_curr_tab(self.recipe_details_page.INCLUDED)
-
- elif next_step == self.PACKAGE_SELECTION:
- self.configuration.initial_selected_packages = self.configuration.selected_packages
- self.configuration.initial_user_selected_packages = self.configuration.user_selected_packages
- self.package_details_page.set_title("Edit packages")
- if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
- else:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
- self.package_details_page.show_page(self.current_logfile)
-
-
- elif next_step == self.PACKAGE_GENERATING or next_step == self.FAST_IMAGE_GENERATING:
- # both PACKAGE_GENERATING and FAST_IMAGE_GENERATING share the same page
- self.build_details_page.show_page(next_step)
-
- elif next_step == self.PACKAGE_GENERATED:
- self.package_details_page.set_title("Step 2 of 2: Edit packages")
- if self.recipe_model.get_selected_image() == self.recipe_model.__custom_image__:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.ALL)
- else:
- self.package_details_page.set_packages_curr_tab(self.package_details_page.INCLUDED)
- self.package_details_page.show_page(self.current_logfile)
-
- elif next_step == self.IMAGE_GENERATING:
- # after packages are generated, selected_packages need to
- # be updated in package_model per selected_image in recipe_model
- self.build_details_page.show_page(next_step)
-
- elif next_step == self.IMAGE_GENERATED:
- self.image_details_page.show_page(next_step)
-
- elif next_step == self.MY_IMAGE_OPENED:
- self.image_details_page.show_page(next_step)
-
- self.previous_step = self.current_step
- self.current_step = next_step
-
- def set_user_config_proxies(self):
- if self.configuration.enable_proxy == True:
- self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
- self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
- self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
- self.handler.set_socks_proxy(self.configuration.combine_proxy("socks"))
- self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
- elif self.configuration.enable_proxy == False:
- self.handler.set_http_proxy("")
- self.handler.set_https_proxy("")
- self.handler.set_ftp_proxy("")
- self.handler.set_socks_proxy("")
- self.handler.set_cvs_proxy("", "")
-
- def set_user_config_extra(self):
- self.handler.set_rootfs_size(self.configuration.image_rootfs_size)
- self.handler.set_extra_size(self.configuration.image_extra_size)
- self.handler.set_incompatible_license(self.configuration.incompat_license)
- self.handler.set_sdk_machine(self.configuration.curr_sdk_machine)
- self.handler.set_image_fstypes(self.configuration.image_fstypes)
- self.handler.set_extra_config(self.configuration.extra_setting)
- self.handler.set_extra_inherit("packageinfo image_types")
- self.set_user_config_proxies()
-
- def set_user_config(self):
- # set bb layers
- self.handler.set_bblayers(self.configuration.layers)
- # set local configuration
- self.handler.set_machine(self.configuration.curr_mach)
- self.handler.set_package_format(self.configuration.curr_package_format)
- self.handler.set_distro(self.configuration.curr_distro)
- self.handler.set_dl_dir(self.configuration.dldir)
- self.handler.set_sstate_dir(self.configuration.sstatedir)
- self.handler.set_sstate_mirrors(self.configuration.sstatemirror)
- self.handler.set_pmake(self.configuration.pmake)
- self.handler.set_bbthreads(self.configuration.bbthread)
- self.set_user_config_extra()
-
- def update_recipe_model(self, selected_image, selected_recipes):
- self.recipe_model.set_selected_image(selected_image)
- self.recipe_model.set_selected_recipes(selected_recipes)
-
- def update_package_model(self, selected_packages, user_selected_packages=None):
- if user_selected_packages:
- left = self.package_model.set_selected_packages(user_selected_packages, True)
- self.configuration.user_selected_packages += left
- left = self.package_model.set_selected_packages(selected_packages)
- self.configuration.selected_packages += left
-
- def update_configuration_parameters(self, params):
- if params:
- self.configuration.update(params)
- self.parameters.update(params)
-
- def set_base_image(self):
- self.configuration.initial_selected_image = self.configuration.selected_image
- if self.configuration.selected_image != self.recipe_model.__custom_image__:
- self.hob_image = self.configuration.selected_image + "-edited"
-
- def reset(self):
- self.configuration.curr_mach = ""
- self.configuration.clear_selection()
- self.image_configuration_page.switch_machine_combo()
- self.switch_page(self.MACHINE_SELECTION)
-
- # Callback Functions
- def handler_config_updated_cb(self, handler, which, values):
- if which == "distro":
- self.parameters.all_distros = values
- elif which == "machine":
- self.parameters.all_machines = values
- self.image_configuration_page.update_machine_combo()
- elif which == "machine-sdk":
- self.parameters.all_sdk_machines = values
-
- def handler_package_formats_updated_cb(self, handler, formats):
- self.parameters.all_package_formats = formats
-
- def switch_to_image_configuration_helper(self):
- self.sanity_check_page.stop()
- self.switch_page(self.IMAGE_CONFIGURATION)
- self.image_configuration_page.switch_machine_combo()
-
- def show_network_error_dialog_helper(self):
- self.sanity_check_page.stop()
- self.show_network_error_dialog()
-
- def handler_command_succeeded_cb(self, handler, initcmd):
- if initcmd == self.handler.GENERATE_CONFIGURATION:
- if not self.configuration.curr_mach:
- self.configuration.curr_mach = self.handler.runCommand(["getVariable", "HOB_MACHINE"]) or ""
- self.update_configuration_parameters(self.get_parameters_sync())
- if not self.sanity_checked:
- self.sanity_check()
- self.sanity_checked = True
- elif initcmd == self.handler.SANITY_CHECK:
- if self.had_network_error:
- self.had_network_error = False
- self.execute_after_sanity_check(self.show_network_error_dialog_helper)
- else:
- # Switch to the 'image configuration' page now, but we might need
- # to wait for the minimum display time of the sanity check page
- self.execute_after_sanity_check(self.switch_to_image_configuration_helper)
- elif initcmd in [self.handler.GENERATE_RECIPES,
- self.handler.GENERATE_PACKAGES,
- self.handler.GENERATE_IMAGE]:
- self.update_configuration_parameters(self.get_parameters_sync())
- self.request_package_info_async()
- elif initcmd == self.handler.POPULATE_PACKAGEINFO:
- if self.current_step == self.RCPPKGINFO_POPULATING:
- self.switch_page(self.RCPPKGINFO_POPULATED)
- self.rcppkglist_populated()
- return
-
- self.rcppkglist_populated()
- if self.current_step == self.FAST_IMAGE_GENERATING:
- self.generate_image_async(True)
-
- def show_error_dialog(self, msg):
- lbl = "<b>Hob found an error</b>"
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
-
- def show_warning_dialog(self):
- dialog = ParsingWarningsDialog(title = "View warnings",
- warnings = self.parsing_warnings,
- parent = None,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- response = dialog.run()
- dialog.destroy()
-
- def show_network_error_dialog(self):
- lbl = "<b>Hob cannot connect to the network</b>"
- msg = msg + "Please check your network connection. If you are using a proxy server, please make sure it is configured correctly."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- button = dialog.add_button("Proxy settings", gtk.RESPONSE_CANCEL)
- HobButton.style_button(button)
- res = dialog.run()
- dialog.destroy()
- if res == gtk.RESPONSE_CANCEL:
- res, settings_changed = self.show_simple_settings_dialog(SimpleSettingsDialog.PROXIES_PAGE_ID)
- if not res:
- return
- if settings_changed:
- self.reparse_post_adv_settings()
-
- def handler_command_failed_cb(self, handler, msg):
- if msg:
- self.show_error_dialog(msg)
- self.reset()
-
- def handler_parsing_warning_cb(self, handler, warn_msg):
- self.parsing_warnings.append(warn_msg)
-
- def handler_sanity_failed_cb(self, handler, msg, network_error):
- self.reset()
- if network_error:
- # Mark this in an internal field. The "network error" dialog will be
- # shown later, when a SanityCheckPassed event will be handled
- # (as sent by sanity.bbclass)
- self.had_network_error = True
- else:
- msg = msg.replace("your local.conf", "Settings")
- self.show_error_dialog(msg)
- self.reset()
-
- def window_sensitive(self, sensitive):
- self.image_configuration_page.machine_combo.set_sensitive(sensitive)
- self.image_configuration_page.machine_combo.child.set_sensitive(sensitive)
- self.image_configuration_page.image_combo.set_sensitive(sensitive)
- self.image_configuration_page.image_combo.child.set_sensitive(sensitive)
- self.image_configuration_page.layer_button.set_sensitive(sensitive)
- self.image_configuration_page.layer_info_icon.set_sensitive(sensitive)
- self.image_configuration_page.toolbar.set_sensitive(sensitive)
- self.image_configuration_page.view_adv_configuration_button.set_sensitive(sensitive)
- self.image_configuration_page.config_build_button.set_sensitive(sensitive)
-
- self.recipe_details_page.set_sensitive(sensitive)
- self.package_details_page.set_sensitive(sensitive)
- self.build_details_page.set_sensitive(sensitive)
- self.image_details_page.set_sensitive(sensitive)
-
- if sensitive:
- self.window.set_cursor(None)
- else:
- self.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
- self.sensitive = sensitive
-
-
- def handler_generating_data_cb(self, handler):
- self.window_sensitive(False)
-
- def handler_data_generated_cb(self, handler):
- self.window_sensitive(True)
-
- def rcppkglist_populated(self):
- selected_image = self.configuration.selected_image
- selected_recipes = self.configuration.selected_recipes[:]
- selected_packages = self.configuration.selected_packages[:]
- user_selected_packages = self.configuration.user_selected_packages[:]
-
- self.image_configuration_page.update_image_combo(self.recipe_model, selected_image)
- self.image_configuration_page.update_image_desc()
- self.update_recipe_model(selected_image, selected_recipes)
- self.update_package_model(selected_packages, user_selected_packages)
-
- def recipelist_changed_cb(self, recipe_model):
- self.recipe_details_page.refresh_selection()
-
- def packagelist_changed_cb(self, package_model):
- self.package_details_page.refresh_selection()
-
- def handler_recipe_populated_cb(self, handler):
- self.image_configuration_page.update_progress_bar("Populating recipes", 0.99)
-
- def handler_package_populated_cb(self, handler):
- self.image_configuration_page.update_progress_bar("Populating packages", 1.0)
-
- def handler_parsing_started_cb(self, handler, message):
- if self.current_step != self.RCPPKGINFO_POPULATING:
- return
-
- fraction = 0
- if message["eventname"] == "TreeDataPreparationStarted":
- fraction = 0.6 + fraction
- self.image_configuration_page.stop_button.set_sensitive(False)
- self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
- else:
- self.image_configuration_page.stop_button.set_sensitive(True)
- self.image_configuration_page.update_progress_bar(message["title"], fraction)
-
- def handler_parsing_cb(self, handler, message):
- if self.current_step != self.RCPPKGINFO_POPULATING:
- return
-
- fraction = message["current"] * 1.0/message["total"]
- if message["eventname"] == "TreeDataPreparationProgress":
- fraction = 0.6 + 0.38 * fraction
- self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
- else:
- fraction = 0.6 * fraction
- self.image_configuration_page.update_progress_bar(message["title"], fraction)
-
- def handler_parsing_completed_cb(self, handler, message):
- if self.current_step != self.RCPPKGINFO_POPULATING:
- return
-
- if message["eventname"] == "TreeDataPreparationCompleted":
- fraction = 0.98
- else:
- fraction = 0.6
- self.image_configuration_page.update_progress_bar("Generating dependency tree", fraction)
-
- def handler_build_started_cb(self, running_build):
- if self.current_step == self.FAST_IMAGE_GENERATING:
- fraction = 0
- elif self.current_step == self.IMAGE_GENERATING:
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- fraction = 0.9
- else:
- fraction = 0
- elif self.current_step == self.PACKAGE_GENERATING:
- fraction = 0
- self.build_details_page.update_progress_bar("Build Started: ", fraction)
- self.build_details_page.show_configurations(self.configuration, self.parameters)
-
- def build_succeeded(self):
- if self.current_step == self.FAST_IMAGE_GENERATING:
- fraction = 0.9
- elif self.current_step == self.IMAGE_GENERATING:
- fraction = 1.0
- version = ""
- self.parameters.image_names = []
- selected_image = self.recipe_model.get_selected_image()
- if selected_image == self.recipe_model.__custom_image__:
- if self.configuration.initial_selected_image != selected_image:
- version = self.recipe_model.get_custom_image_version()
- linkname = self.hob_image + version + "-" + self.configuration.curr_mach
- else:
- linkname = selected_image + '-' + self.configuration.curr_mach
- image_extension = self.get_image_extension()
- for image_type in self.parameters.image_types:
- if image_type in image_extension:
- real_types = image_extension[image_type]
- else:
- real_types = [image_type]
- for real_image_type in real_types:
- linkpath = self.parameters.image_addr + '/' + linkname + '.' + real_image_type
- if os.path.exists(linkpath):
- self.parameters.image_names.append(os.readlink(linkpath))
- elif self.current_step == self.PACKAGE_GENERATING:
- fraction = 1.0
- self.build_details_page.update_progress_bar("Build Completed: ", fraction)
- self.handler.build_succeeded_async()
- self.stopping = False
-
- if self.current_step == self.PACKAGE_GENERATING:
- self.switch_page(self.PACKAGE_GENERATED)
- elif self.current_step == self.IMAGE_GENERATING:
- self.switch_page(self.IMAGE_GENERATED)
-
- def build_failed(self):
- if self.stopping:
- status = "stop"
- message = "Build stopped: "
- fraction = self.build_details_page.progress_bar.get_fraction()
- stop_to_next_edit = ""
- if self.current_step == self.FAST_IMAGE_GENERATING:
- stop_to_next_edit = "image configuration"
- elif self.current_step == self.IMAGE_GENERATING:
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- stop_to_next_edit = "image configuration"
- else:
- stop_to_next_edit = "packages"
- elif self.current_step == self.PACKAGE_GENERATING:
- stop_to_next_edit = "recipes"
- button = self.build_details_page.show_stop_page(stop_to_next_edit.split(' ')[0])
- self.set_default(button)
- else:
- fail_to_next_edit = ""
- if self.current_step == self.FAST_IMAGE_GENERATING:
- fail_to_next_edit = "image configuration"
- fraction = 0.9
- elif self.current_step == self.IMAGE_GENERATING:
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- fail_to_next_edit = "image configuration"
- else:
- fail_to_next_edit = "packages"
- fraction = 1.0
- elif self.current_step == self.PACKAGE_GENERATING:
- fail_to_next_edit = "recipes"
- fraction = 1.0
- self.build_details_page.show_fail_page(fail_to_next_edit.split(' ')[0])
- status = "fail"
- message = "Build failed: "
- self.build_details_page.update_progress_bar(message, fraction, status)
- self.build_details_page.show_back_button()
- self.build_details_page.hide_stop_button()
- self.handler.build_failed_async()
- self.stopping = False
-
- def handler_build_succeeded_cb(self, running_build):
- if not self.stopping:
- self.build_succeeded()
- else:
- self.build_failed()
-
-
- def handler_build_failed_cb(self, running_build):
- self.build_failed()
-
- def handler_build_aborted_cb(self, running_build):
- self.build_failed()
-
- def handler_no_provider_cb(self, running_build, msg):
- dialog = CrumbsMessageDialog(self, glib.markup_escape_text(msg), gtk.MESSAGE_INFO)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- self.build_failed()
-
- def handler_task_started_cb(self, running_build, message):
- fraction = message["current"] * 1.0/message["total"]
- title = "Build packages"
- if self.current_step == self.FAST_IMAGE_GENERATING:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.27 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.27 + 0.63 * fraction
- elif self.current_step == self.IMAGE_GENERATING:
- title = "Build image"
- if self.previous_step == self.FAST_IMAGE_GENERATING:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.27 + 0.63 + 0.03 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.27 + 0.63 + 0.03 + 0.07 * fraction
- else:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.2 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.2 + 0.8 * fraction
- elif self.current_step == self.PACKAGE_GENERATING:
- if message["eventname"] == "sceneQueueTaskStarted":
- fraction = 0.2 * fraction
- elif message["eventname"] == "runQueueTaskStarted":
- fraction = 0.2 + 0.8 * fraction
- self.build_details_page.update_progress_bar(title + ": ", fraction)
- self.build_details_page.update_build_status(message["current"], message["total"], message["task"])
-
- def handler_disk_full_cb(self, running_build):
- self.disk_full = True
-
- def handler_build_failure_cb(self, running_build):
- self.build_details_page.show_issues()
-
- def handler_build_log_cb(self, running_build, func, obj):
- if hasattr(self.logger, func):
- getattr(self.logger, func)(obj)
-
- def destroy_window_cb(self, widget, event):
- if not self.sensitive:
- return True
- elif self.handler.building:
- self.stop_build()
- return True
- else:
- gtk.main_quit()
-
- def event_handle_SIGINT(self, signal, frame):
- for w in gtk.window_list_toplevels():
- if w.get_modal():
- w.response(gtk.RESPONSE_DELETE_EVENT)
- sys.exit(0)
-
- def build_packages(self):
- _, all_recipes = self.recipe_model.get_selected_recipes()
- if not all_recipes:
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- msg = msg + " so there isn't anything to bake at this time."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
- self.generate_packages_async(True)
-
- def build_image(self):
- selected_packages = self.package_model.get_selected_packages()
- if not selected_packages:
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- msg = msg + " so there isn't anything to bake at this time."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
- self.generate_image_async(True)
-
- def just_bake(self):
- selected_image = self.recipe_model.get_selected_image()
- selected_packages = self.package_model.get_selected_packages() or []
-
- # If no base image and no selected packages don't build anything
- if not (selected_packages or selected_image != self.recipe_model.__custom_image__):
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- msg = msg + " so there isn't anything to bake at this time."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
-
- self.fast_generate_image_async(True)
-
- def show_recipe_property_dialog(self, properties):
- information = {}
- dialog = PropertyDialog(title = properties["name"] +' '+ "properties",
- parent = self,
- information = properties,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
-
- dialog.set_modal(False)
-
- button = dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button.connect("clicked", lambda w: dialog.destroy())
-
- dialog.run()
-
- def show_packages_property_dialog(self, properties):
- information = {}
- dialog = PropertyDialog(title = properties["name"] +' '+ "properties",
- parent = self,
- information = properties,
- flags = gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
-
- dialog.set_modal(False)
-
- button = dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button.connect("clicked", lambda w: dialog.destroy())
-
- dialog.run()
-
- def show_layer_selection_dialog(self):
- dialog = LayerSelectionDialog(title = "Layers",
- layers = copy.deepcopy(self.configuration.layers),
- layers_non_removable = copy.deepcopy(self.configuration.layers_non_removable),
- all_layers = self.parameters.all_layers,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("OK", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- response = dialog.run()
- if response == gtk.RESPONSE_YES:
- self.configuration.layers = dialog.layers
- # DO refresh layers
- if dialog.layers_changed:
- self.update_config_async()
- dialog.destroy()
-
- def get_image_extension(self):
- image_extension = {}
- for type in self.parameters.image_types:
- ext = self.handler.runCommand(["getVariable", "IMAGE_EXTENSION_%s" % type])
- if ext:
- image_extension[type] = ext.split(' ')
-
- return image_extension
-
- def show_load_my_images_dialog(self):
- image_extension = self.get_image_extension()
- dialog = ImageSelectionDialog(self.parameters.image_addr, self.parameters.image_types,
- "Open My Images", self,
- gtk.FILE_CHOOSER_ACTION_SAVE, None,
- image_extension)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Open", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- response = dialog.run()
- if response == gtk.RESPONSE_YES:
- if not dialog.image_names:
- lbl = "<b>No selections made</b>"
- msg = "You have not made any selections"
- crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg)
- button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- crumbs_dialog.run()
- crumbs_dialog.destroy()
- dialog.destroy()
- return
-
- self.parameters.image_addr = dialog.image_folder
- self.parameters.image_names = dialog.image_names[:]
- self.switch_page(self.MY_IMAGE_OPENED)
-
- dialog.destroy()
-
- def show_adv_settings_dialog(self, tab=None):
- dialog = AdvancedSettingsDialog(title = "Advanced configuration",
- configuration = copy.deepcopy(self.configuration),
- all_image_types = self.parameters.image_types,
- all_package_formats = self.parameters.all_package_formats,
- all_distros = self.parameters.all_distros,
- all_sdk_machines = self.parameters.all_sdk_machines,
- max_threads = self.parameters.max_threads,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Save", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- dialog.set_save_button(button)
- response = dialog.run()
- settings_changed = False
- if response == gtk.RESPONSE_YES:
- self.configuration = dialog.configuration
- self.configuration.save(self.handler, True) # remember settings
- settings_changed = dialog.settings_changed
- dialog.destroy()
- return response == gtk.RESPONSE_YES, settings_changed
-
- def show_simple_settings_dialog(self, tab=None):
- dialog = SimpleSettingsDialog(title = "Settings",
- configuration = copy.deepcopy(self.configuration),
- all_image_types = self.parameters.image_types,
- all_package_formats = self.parameters.all_package_formats,
- all_distros = self.parameters.all_distros,
- all_sdk_machines = self.parameters.all_sdk_machines,
- max_threads = self.parameters.max_threads,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR,
- handler = self.handler)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Save", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- if tab:
- dialog.switch_to_page(tab)
- response = dialog.run()
- settings_changed = False
- if response == gtk.RESPONSE_YES:
- self.configuration = dialog.configuration
- self.configuration.save(self.handler, True) # remember settings
- settings_changed = dialog.settings_changed
- if dialog.proxy_settings_changed:
- self.set_user_config_proxies()
- elif dialog.proxy_test_ran:
- # The user might have modified the proxies in the "Proxy"
- # tab, which in turn made the proxy settings modify in bb.
- # If "Cancel" was pressed, restore the previous proxy
- # settings inside bb.
- self.set_user_config_proxies()
- dialog.destroy()
- return response == gtk.RESPONSE_YES, settings_changed
-
- def reparse_post_adv_settings(self):
- if not self.configuration.curr_mach:
- self.update_config_async()
- else:
- self.configuration.clear_selection()
- # DO reparse recipes
- self.populate_recipe_package_info_async()
-
- def deploy_image(self, image_name):
- if not image_name:
- lbl = "<b>Please select an image to deploy.</b>"
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
-
- image_path = os.path.join(self.parameters.image_addr, image_name)
- dialog = DeployImageDialog(title = "Usb Image Maker",
- image_path = image_path,
- parent = self,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- button = dialog.add_button("Close", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Make usb image", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
-
- def show_load_kernel_dialog(self):
- dialog = gtk.FileChooserDialog("Load Kernel Files", self,
- gtk.FILE_CHOOSER_ACTION_SAVE)
- button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
- HobAltButton.style_button(button)
- button = dialog.add_button("Open", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- filter = gtk.FileFilter()
- filter.set_name("Kernel Files")
- filter.add_pattern("*.bin")
- dialog.add_filter(filter)
-
- dialog.set_current_folder(self.parameters.image_addr)
-
- response = dialog.run()
- kernel_path = ""
- if response == gtk.RESPONSE_YES:
- kernel_path = dialog.get_filename()
-
- dialog.destroy()
-
- return kernel_path
-
- def runqemu_image(self, image_name, kernel_name):
- if not image_name or not kernel_name:
- lbl = "<b>Please select %s to launch in QEMU.</b>" % ("a kernel" if image_name else "an image")
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
- return
-
- kernel_path = os.path.join(self.parameters.image_addr, kernel_name)
- image_path = os.path.join(self.parameters.image_addr, image_name)
-
- source_env_path = os.path.join(self.parameters.core_base, "oe-init-build-env")
- tmp_path = self.parameters.tmpdir
- cmdline = bb.ui.crumbs.utils.which_terminal()
- if os.path.exists(image_path) and os.path.exists(kernel_path) \
- and os.path.exists(source_env_path) and os.path.exists(tmp_path) \
- and cmdline:
- cmdline += "\' bash -c \"export OE_TMPDIR=" + tmp_path + "; "
- cmdline += "source " + source_env_path + " " + os.getcwd() + "; "
- cmdline += "runqemu " + kernel_path + " " + image_path + "\"\'"
- subprocess.Popen(shlex.split(cmdline))
- else:
- lbl = "<b>Path error</b>"
- msg = "One of your paths is wrong,"
- msg = msg + " please make sure the following paths exist:\n"
- msg = msg + "image path:" + image_path + "\n"
- msg = msg + "kernel path:" + kernel_path + "\n"
- msg = msg + "source environment path:" + source_env_path + "\n"
- msg = msg + "tmp path: " + tmp_path + "."
- msg = msg + "You may be missing either xterm or vte for terminal services."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- dialog.run()
- dialog.destroy()
-
- def show_packages(self):
- self.package_details_page.refresh_tables()
- self.switch_page(self.PACKAGE_SELECTION)
-
- def show_recipes(self):
- self.switch_page(self.RECIPE_SELECTION)
-
- def show_image_details(self):
- self.switch_page(self.IMAGE_GENERATED)
-
- def show_configuration(self):
- self.switch_page(self.BASEIMG_SELECTED)
-
- def stop_build(self):
- if self.stopping:
- lbl = "<b>Force Stop build?</b>"
- msg = "You've already selected Stop once,"
- msg = msg + " would you like to 'Force Stop' the build?\n\n"
- msg = msg + "This will stop the build as quickly as possible but may"
- msg = msg + " well leave your build directory in an unusable state"
- msg = msg + " that requires manual steps to fix."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(button)
- button = dialog.add_button("Force Stop", gtk.RESPONSE_YES)
- HobButton.style_button(button)
- else:
- lbl = "<b>Stop build?</b>"
- msg = "Are you sure you want to stop this"
- msg = msg + " build?\n\n'Stop' will stop the build as soon as all in"
- msg = msg + " progress build tasks are finished. However if a"
- msg = msg + " lengthy compilation phase is in progress this may take"
- msg = msg + " some time.\n\n"
- msg = msg + "'Force Stop' will stop the build as quickly as"
- msg = msg + " possible but may well leave your build directory in an"
- msg = msg + " unusable state that requires manual steps to fix."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(button)
- button = dialog.add_button("Force stop", gtk.RESPONSE_YES)
- HobAltButton.style_button(button)
- button = dialog.add_button("Stop", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
- if response != gtk.RESPONSE_CANCEL:
- self.stopping = True
- if response == gtk.RESPONSE_OK:
- self.build_details_page.progress_bar.set_stop_title("Stopping the build....")
- self.build_details_page.progress_bar.set_rcstyle("stop")
- self.cancel_build_sync()
- elif response == gtk.RESPONSE_YES:
- self.cancel_build_sync(True)
-
- def do_log(self, consolelogfile = None):
- if consolelogfile:
- bb.utils.mkdirhier(os.path.dirname(consolelogfile))
- if self.consolelog:
- self.logger.removeHandler(self.consolelog)
- self.consolelog = None
- self.consolelog = logging.FileHandler(consolelogfile)
- bb.msg.addDefaultlogFilter(self.consolelog)
- format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
- self.consolelog.setFormatter(format)
-
- self.logger.addHandler(self.consolelog)
-
- def get_topdir(self):
- return self.handler.get_topdir()
-
- def wait(self, delay):
- time_start = time.time()
- time_end = time_start + delay
- while time_end > time.time():
- while gtk.events_pending():
- gtk.main_iteration()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py
deleted file mode 100644
index e858d75e4..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/buildmanager.py
+++ /dev/null
@@ -1,455 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2008 Intel Corporation
-#
-# Authored by Rob Bradford <rob@linux.intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import gobject
-import threading
-import os
-import datetime
-import time
-
-class BuildConfiguration:
- """ Represents a potential *or* historic *or* concrete build. It
- encompasses all the things that we need to tell bitbake to do to make it
- build what we want it to build.
-
- It also stored the metadata URL and the set of possible machines (and the
- distros / images / uris for these. Apart from the metdata URL these are
- not serialised to file (since they may be transient). In some ways this
- functionality might be shifted to the loader class."""
-
- def __init__ (self):
- self.metadata_url = None
-
- # Tuple of (distros, image, urls)
- self.machine_options = {}
-
- self.machine = None
- self.distro = None
- self.image = None
- self.urls = []
- self.extra_urls = []
- self.extra_pkgs = []
-
- def get_machines_model (self):
- model = gtk.ListStore (gobject.TYPE_STRING)
- for machine in self.machine_options.keys():
- model.append ([machine])
-
- return model
-
- def get_distro_and_images_models (self, machine):
- distro_model = gtk.ListStore (gobject.TYPE_STRING)
-
- for distro in self.machine_options[machine][0]:
- distro_model.append ([distro])
-
- image_model = gtk.ListStore (gobject.TYPE_STRING)
-
- for image in self.machine_options[machine][1]:
- image_model.append ([image])
-
- return (distro_model, image_model)
-
- def get_repos (self):
- self.urls = self.machine_options[self.machine][2]
- return self.urls
-
- # It might be a lot lot better if we stored these in like, bitbake conf
- # file format.
- @staticmethod
- def load_from_file (filename):
-
- conf = BuildConfiguration()
- with open(filename, "r") as f:
- for line in f:
- data = line.split (";")[1]
- if (line.startswith ("metadata-url;")):
- conf.metadata_url = data.strip()
- continue
- if (line.startswith ("url;")):
- conf.urls += [data.strip()]
- continue
- if (line.startswith ("extra-url;")):
- conf.extra_urls += [data.strip()]
- continue
- if (line.startswith ("machine;")):
- conf.machine = data.strip()
- continue
- if (line.startswith ("distribution;")):
- conf.distro = data.strip()
- continue
- if (line.startswith ("image;")):
- conf.image = data.strip()
- continue
-
- return conf
-
- # Serialise to a file. This is part of the build process and we use this
- # to be able to repeat a given build (using the same set of parameters)
- # but also so that we can include the details of the image / machine /
- # distro in the build manager tree view.
- def write_to_file (self, filename):
- f = open (filename, "w")
-
- lines = []
-
- if (self.metadata_url):
- lines += ["metadata-url;%s\n" % (self.metadata_url)]
-
- for url in self.urls:
- lines += ["url;%s\n" % (url)]
-
- for url in self.extra_urls:
- lines += ["extra-url;%s\n" % (url)]
-
- if (self.machine):
- lines += ["machine;%s\n" % (self.machine)]
-
- if (self.distro):
- lines += ["distribution;%s\n" % (self.distro)]
-
- if (self.image):
- lines += ["image;%s\n" % (self.image)]
-
- f.writelines (lines)
- f.close ()
-
-class BuildResult(gobject.GObject):
- """ Represents an historic build. Perhaps not successful. But it includes
- things such as the files that are in the directory (the output from the
- build) as well as a deserialised BuildConfiguration file that is stored in
- ".conf" in the directory for the build.
-
- This is GObject so that it can be included in the TreeStore."""
-
- (STATE_COMPLETE, STATE_FAILED, STATE_ONGOING) = \
- (0, 1, 2)
-
- def __init__ (self, parent, identifier):
- gobject.GObject.__init__ (self)
- self.date = None
-
- self.files = []
- self.status = None
- self.identifier = identifier
- self.path = os.path.join (parent, identifier)
-
- # Extract the date, since the directory name is of the
- # format build-<year><month><day>-<ordinal> we can easily
- # pull it out.
- # TODO: Better to stat a file?
- (_, date, revision) = identifier.split ("-")
- print(date)
-
- year = int (date[0:4])
- month = int (date[4:6])
- day = int (date[6:8])
-
- self.date = datetime.date (year, month, day)
-
- self.conf = None
-
- # By default builds are STATE_FAILED unless we find a "complete" file
- # in which case they are STATE_COMPLETE
- self.state = BuildResult.STATE_FAILED
- for file in os.listdir (self.path):
- if (file.startswith (".conf")):
- conffile = os.path.join (self.path, file)
- self.conf = BuildConfiguration.load_from_file (conffile)
- elif (file.startswith ("complete")):
- self.state = BuildResult.STATE_COMPLETE
- else:
- self.add_file (file)
-
- def add_file (self, file):
- # Just add the file for now. Don't care about the type.
- self.files += [(file, None)]
-
-class BuildManagerModel (gtk.TreeStore):
- """ Model for the BuildManagerTreeView. This derives from gtk.TreeStore
- but it abstracts nicely what the columns mean and the setup of the columns
- in the model. """
-
- (COL_IDENT, COL_DESC, COL_MACHINE, COL_DISTRO, COL_BUILD_RESULT, COL_DATE, COL_STATE) = \
- (0, 1, 2, 3, 4, 5, 6)
-
- def __init__ (self):
- gtk.TreeStore.__init__ (self,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_OBJECT,
- gobject.TYPE_INT64,
- gobject.TYPE_INT)
-
-class BuildManager (gobject.GObject):
- """ This class manages the historic builds that have been found in the
- "results" directory but is also used for starting a new build."""
-
- __gsignals__ = {
- 'population-finished' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- 'populate-error' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ())
- }
-
- def update_build_result (self, result, iter):
- # Convert the date into something we can sort by.
- date = long (time.mktime (result.date.timetuple()))
-
- # Add a top level entry for the build
-
- self.model.set (iter,
- BuildManagerModel.COL_IDENT, result.identifier,
- BuildManagerModel.COL_DESC, result.conf.image,
- BuildManagerModel.COL_MACHINE, result.conf.machine,
- BuildManagerModel.COL_DISTRO, result.conf.distro,
- BuildManagerModel.COL_BUILD_RESULT, result,
- BuildManagerModel.COL_DATE, date,
- BuildManagerModel.COL_STATE, result.state)
-
- # And then we use the files in the directory as the children for the
- # top level iter.
- for file in result.files:
- self.model.append (iter, (None, file[0], None, None, None, date, -1))
-
- # This function is called as an idle by the BuildManagerPopulaterThread
- def add_build_result (self, result):
- gtk.gdk.threads_enter()
- self.known_builds += [result]
-
- self.update_build_result (result, self.model.append (None))
-
- gtk.gdk.threads_leave()
-
- def notify_build_finished (self):
- # This is a bit of a hack. If we have a running build running then we
- # will have a row in the model in STATE_ONGOING. Find it and make it
- # as if it was a proper historic build (well, it is completed now....)
-
- # We need to use the iters here rather than the Python iterator
- # interface to the model since we need to pass it into
- # update_build_result
-
- iter = self.model.get_iter_first()
-
- while (iter):
- (ident, state) = self.model.get(iter,
- BuildManagerModel.COL_IDENT,
- BuildManagerModel.COL_STATE)
-
- if state == BuildResult.STATE_ONGOING:
- result = BuildResult (self.results_directory, ident)
- self.update_build_result (result, iter)
- iter = self.model.iter_next(iter)
-
- def notify_build_succeeded (self):
- # Write the "complete" file so that when we create the BuildResult
- # object we put into the model
-
- complete_file_path = os.path.join (self.cur_build_directory, "complete")
- f = file (complete_file_path, "w")
- f.close()
- self.notify_build_finished()
-
- def notify_build_failed (self):
- # Without a "complete" file then this will mark the build as failed:
- self.notify_build_finished()
-
- # This function is called as an idle
- def emit_population_finished_signal (self):
- gtk.gdk.threads_enter()
- self.emit ("population-finished")
- gtk.gdk.threads_leave()
-
- class BuildManagerPopulaterThread (threading.Thread):
- def __init__ (self, manager, directory):
- threading.Thread.__init__ (self)
- self.manager = manager
- self.directory = directory
-
- def run (self):
- # For each of the "build-<...>" directories ..
-
- if os.path.exists (self.directory):
- for directory in os.listdir (self.directory):
-
- if not directory.startswith ("build-"):
- continue
-
- build_result = BuildResult (self.directory, directory)
- self.manager.add_build_result (build_result)
-
- gobject.idle_add (BuildManager.emit_population_finished_signal,
- self.manager)
-
- def __init__ (self, server, results_directory):
- gobject.GObject.__init__ (self)
-
- # The builds that we've found from walking the result directory
- self.known_builds = []
-
- # Save out the bitbake server, we need this for issuing commands to
- # the cooker:
- self.server = server
-
- # The TreeStore that we use
- self.model = BuildManagerModel ()
-
- # The results directory is where we create (and look for) the
- # build-<xyz>-<n> directories. We need to populate ourselves from
- # directory
- self.results_directory = results_directory
- self.populate_from_directory (self.results_directory)
-
- def populate_from_directory (self, directory):
- thread = BuildManager.BuildManagerPopulaterThread (self, directory)
- thread.start()
-
- # Come up with the name for the next build ident by combining "build-"
- # with the date formatted as yyyymmdd and then an ordinal. We do this by
- # an optimistic algorithm incrementing the ordinal if we find that it
- # already exists.
- def get_next_build_ident (self):
- today = datetime.date.today ()
- datestr = str (today.year) + str (today.month) + str (today.day)
-
- revision = 0
- test_name = "build-%s-%d" % (datestr, revision)
- test_path = os.path.join (self.results_directory, test_name)
-
- while (os.path.exists (test_path)):
- revision += 1
- test_name = "build-%s-%d" % (datestr, revision)
- test_path = os.path.join (self.results_directory, test_name)
-
- return test_name
-
- # Take a BuildConfiguration and then try and build it based on the
- # parameters of that configuration. S
- def do_build (self, conf):
- server = self.server
-
- # Work out the build directory. Note we actually create the
- # directories here since we need to write the ".conf" file. Otherwise
- # we could have relied on bitbake's builder thread to actually make
- # the directories as it proceeds with the build.
- ident = self.get_next_build_ident ()
- build_directory = os.path.join (self.results_directory,
- ident)
- self.cur_build_directory = build_directory
- os.makedirs (build_directory)
-
- conffile = os.path.join (build_directory, ".conf")
- conf.write_to_file (conffile)
-
- # Add a row to the model representing this ongoing build. It's kinda a
- # fake entry. If this build completes or fails then this gets updated
- # with the real stuff like the historic builds
- date = long (time.time())
- self.model.append (None, (ident, conf.image, conf.machine, conf.distro,
- None, date, BuildResult.STATE_ONGOING))
- try:
- server.runCommand(["setVariable", "BUILD_IMAGES_FROM_FEEDS", 1])
- server.runCommand(["setVariable", "MACHINE", conf.machine])
- server.runCommand(["setVariable", "DISTRO", conf.distro])
- server.runCommand(["setVariable", "PACKAGE_CLASSES", "package_ipk"])
- server.runCommand(["setVariable", "BBFILES", \
- """${OEROOT}/meta/packages/*/*.bb ${OEROOT}/meta-moblin/packages/*/*.bb"""])
- server.runCommand(["setVariable", "TMPDIR", "${OEROOT}/build/tmp"])
- server.runCommand(["setVariable", "IPK_FEED_URIS", \
- " ".join(conf.get_repos())])
- server.runCommand(["setVariable", "DEPLOY_DIR_IMAGE",
- build_directory])
- server.runCommand(["buildTargets", [conf.image], "rootfs"])
-
- except Exception as e:
- print(e)
-
-class BuildManagerTreeView (gtk.TreeView):
- """ The tree view for the build manager. This shows the historic builds
- and so forth. """
-
- # We use this function to control what goes in the cell since we store
- # the date in the model as seconds since the epoch (for sorting) and so we
- # need to make it human readable.
- def date_format_custom_cell_data_func (self, col, cell, model, iter):
- date = model.get (iter, BuildManagerModel.COL_DATE)[0]
- datestr = time.strftime("%A %d %B %Y", time.localtime(date))
- cell.set_property ("text", datestr)
-
- # This format function controls what goes in the cell. We use this to map
- # the integer state to a string and also to colourise the text
- def state_format_custom_cell_data_fun (self, col, cell, model, iter):
- state = model.get (iter, BuildManagerModel.COL_STATE)[0]
-
- if (state == BuildResult.STATE_ONGOING):
- cell.set_property ("text", "Active")
- cell.set_property ("foreground", "#000000")
- elif (state == BuildResult.STATE_FAILED):
- cell.set_property ("text", "Failed")
- cell.set_property ("foreground", "#ff0000")
- elif (state == BuildResult.STATE_COMPLETE):
- cell.set_property ("text", "Complete")
- cell.set_property ("foreground", "#00ff00")
- else:
- cell.set_property ("text", "")
-
- def __init__ (self):
- gtk.TreeView.__init__(self)
-
- # Misc descriptiony thing
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn (None, renderer,
- text=BuildManagerModel.COL_DESC)
- self.append_column (col)
-
- # Machine
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Machine", renderer,
- text=BuildManagerModel.COL_MACHINE)
- self.append_column (col)
-
- # distro
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Distribution", renderer,
- text=BuildManagerModel.COL_DISTRO)
- self.append_column (col)
-
- # date (using a custom function for formatting the cell contents it
- # takes epoch -> human readable string)
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Date", renderer,
- text=BuildManagerModel.COL_DATE)
- self.append_column (col)
- col.set_cell_data_func (renderer,
- self.date_format_custom_cell_data_func)
-
- # For status.
- renderer = gtk.CellRendererText ()
- col = gtk.TreeViewColumn ("Status", renderer,
- text = BuildManagerModel.COL_STATE)
- self.append_column (col)
- col.set_cell_data_func (renderer,
- self.state_format_custom_cell_data_fun)
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py
deleted file mode 100644
index e0b3553c2..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py
+++ /dev/null
@@ -1,341 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import hashlib
-from bb.ui.crumbs.hobwidget import HobInfoButton, HobButton
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-class AdvancedSettingsDialog (CrumbsDialog, SettingsUIHelper):
-
- def details_cb(self, button, parent, protocol):
- dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
- user = self.configuration.proxies[protocol][1],
- passwd = self.configuration.proxies[protocol][2],
- parent = parent,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- self.configuration.proxies[protocol][1] = dialog.user
- self.configuration.proxies[protocol][2] = dialog.passwd
- self.refresh_proxy_components()
- dialog.destroy()
-
- def set_save_button(self, button):
- self.save_button = button
-
- def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
- combo_item = self.rootfs_combo.get_active_text()
- modified = False
- for child in check_hbox.get_children():
- if isinstance(child, gtk.CheckButton):
- check_hbox.remove(child)
- modified = True
- for format in all_package_format:
- if format != combo_item:
- check_button = gtk.CheckButton(format)
- check_hbox.pack_start(check_button, expand=False, fill=False)
- modified = True
- if modified:
- check_hbox.remove(self.pkgfmt_info)
- check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
- check_hbox.show_all()
-
- def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
- pkgfmt_vbox = gtk.VBox(False, 6)
-
- label = self.gen_label_widget("Root file system package format")
- pkgfmt_vbox.pack_start(label, expand=False, fill=False)
-
- rootfs_format = ""
- if curr_package_format:
- rootfs_format = curr_package_format.split()[0]
-
- rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
- pkgfmt_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
-
- label = self.gen_label_widget("Additional package formats")
- pkgfmt_vbox.pack_start(label, expand=False, fill=False)
-
- check_hbox = gtk.HBox(False, 12)
- pkgfmt_vbox.pack_start(check_hbox, expand=False, fill=False)
- for format in all_package_format:
- if format != rootfs_format:
- check_button = gtk.CheckButton(format)
- is_active = (format in curr_package_format.split())
- check_button.set_active(is_active)
- check_hbox.pack_start(check_button, expand=False, fill=False)
-
- self.pkgfmt_info = HobInfoButton(tooltip_extra, self)
- check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
-
- rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
-
- pkgfmt_vbox.show_all()
-
- return pkgfmt_vbox, rootfs_combo, check_hbox
-
- def __init__(self, title, configuration, all_image_types,
- all_package_formats, all_distros, all_sdk_machines,
- max_threads, parent, flags, buttons=None):
- super(AdvancedSettingsDialog, self).__init__(title, parent, flags, buttons)
-
- # class members from other objects
- # bitbake settings from Builder.Configuration
- self.configuration = configuration
- self.image_types = all_image_types
- self.all_package_formats = all_package_formats
- self.all_distros = all_distros[:]
- self.all_sdk_machines = all_sdk_machines
- self.max_threads = max_threads
-
- # class members for internal use
- self.distro_combo = None
- self.dldir_text = None
- self.sstatedir_text = None
- self.sstatemirror_text = None
- self.bb_spinner = None
- self.pmake_spinner = None
- self.rootfs_size_spinner = None
- self.extra_size_spinner = None
- self.gplv3_checkbox = None
- self.sdk_checkbox = None
- self.image_types_checkbuttons = {}
-
- self.md5 = self.config_md5()
- self.settings_changed = False
-
- # create visual elements on the dialog
- self.save_button = None
- self.create_visual_elements()
- self.connect("response", self.response_cb)
-
- def _get_sorted_value(self, var):
- return " ".join(sorted(str(var).split())) + "\n"
-
- def config_md5(self):
- data = ""
- data += ("PACKAGE_CLASSES: " + self.configuration.curr_package_format + '\n')
- data += ("DISTRO: " + self._get_sorted_value(self.configuration.curr_distro))
- data += ("IMAGE_ROOTFS_SIZE: " + self._get_sorted_value(self.configuration.image_rootfs_size))
- data += ("IMAGE_EXTRA_SIZE: " + self._get_sorted_value(self.configuration.image_extra_size))
- data += ("INCOMPATIBLE_LICENSE: " + self._get_sorted_value(self.configuration.incompat_license))
- data += ("SDK_MACHINE: " + self._get_sorted_value(self.configuration.curr_sdk_machine))
- data += ("TOOLCHAIN_BUILD: " + self._get_sorted_value(self.configuration.toolchain_build))
- data += ("IMAGE_FSTYPES: " + self._get_sorted_value(self.configuration.image_fstypes))
- return hashlib.md5(data).hexdigest()
-
- def create_visual_elements(self):
- self.nb = gtk.Notebook()
- self.nb.set_show_tabs(True)
- self.nb.append_page(self.create_image_types_page(), gtk.Label("Image types"))
- self.nb.append_page(self.create_output_page(), gtk.Label("Output"))
- self.nb.set_current_page(0)
- self.vbox.pack_start(self.nb, expand=True, fill=True)
- self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
-
- self.show_all()
-
- def get_num_checked_image_types(self):
- total = 0
- for b in self.image_types_checkbuttons.values():
- if b.get_active():
- total = total + 1
- return total
-
- def set_save_button_state(self):
- if self.save_button:
- self.save_button.set_sensitive(self.get_num_checked_image_types() > 0)
-
- def image_type_checkbutton_clicked_cb(self, button):
- self.set_save_button_state()
- if self.get_num_checked_image_types() == 0:
- # Show an error dialog
- lbl = "<b>Select an image type</b>"
- msg = "You need to select at least one image type."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("OK", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
-
- def create_image_types_page(self):
- main_vbox = gtk.VBox(False, 16)
- main_vbox.set_border_width(6)
-
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- distro_vbox = gtk.VBox(False, 6)
- label = self.gen_label_widget("Distro:")
- tooltip = "Selects the Yocto Project distribution you want"
- try:
- i = self.all_distros.index( "defaultsetup" )
- except ValueError:
- i = -1
- if i != -1:
- self.all_distros[ i ] = "Default"
- if self.configuration.curr_distro == "defaultsetup":
- self.configuration.curr_distro = "Default"
- distro_widget, self.distro_combo = self.gen_combo_widget(self.configuration.curr_distro, self.all_distros,"<b>Distro</b>" + "*" + tooltip)
- distro_vbox.pack_start(label, expand=False, fill=False)
- distro_vbox.pack_start(distro_widget, expand=False, fill=False)
- main_vbox.pack_start(distro_vbox, expand=False, fill=False)
-
-
- rows = (len(self.image_types)+1)/3
- table = gtk.Table(rows + 1, 10, True)
- advanced_vbox.pack_start(table, expand=False, fill=False)
-
- tooltip = "Image file system types you want."
- info = HobInfoButton("<b>Image types</b>" + "*" + tooltip, self)
- label = self.gen_label_widget("Image types:")
- align = gtk.Alignment(0, 0.5, 0, 0)
- table.attach(align, 0, 4, 0, 1)
- align.add(label)
- table.attach(info, 4, 5, 0, 1)
-
- i = 1
- j = 1
- for image_type in sorted(self.image_types):
- self.image_types_checkbuttons[image_type] = gtk.CheckButton(image_type)
- self.image_types_checkbuttons[image_type].connect("toggled", self.image_type_checkbutton_clicked_cb)
- article = ""
- if image_type.startswith(("a", "e", "i", "o", "u")):
- article = "n"
- if image_type == "live":
- self.image_types_checkbuttons[image_type].set_tooltip_text("Build iso and hddimg images")
- else:
- self.image_types_checkbuttons[image_type].set_tooltip_text("Build a%s %s image" % (article, image_type))
- table.attach(self.image_types_checkbuttons[image_type], j - 1, j + 3, i, i + 1)
- if image_type in self.configuration.image_fstypes.split():
- self.image_types_checkbuttons[image_type].set_active(True)
- i += 1
- if i > rows:
- i = 1
- j = j + 4
-
- main_vbox.pack_start(advanced_vbox, expand=False, fill=False)
- self.set_save_button_state()
-
- return main_vbox
-
- def create_output_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Package format</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- tooltip_combo = "Selects the package format used to generate rootfs."
- tooltip_extra = "Selects extra package formats to build"
- pkgfmt_widget, self.rootfs_combo, self.check_hbox = self.gen_pkgfmt_widget(self.configuration.curr_package_format, self.all_package_formats,"<b>Root file system package format</b>" + "*" + tooltip_combo,"<b>Additional package formats</b>" + "*" + tooltip_extra)
- sub_vbox.pack_start(pkgfmt_widget, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Image size</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Image basic size (in MB)")
- tooltip = "Defines the size for the generated image. The OpenEmbedded build system determines the final size for the generated image using an algorithm that takes into account the initial disk space used for the generated image, the Image basic size value, and the Additional free space value.\n\nFor more information, check the <a href=\"http://www.yoctoproject.org/docs/current/poky-ref-manual/poky-ref-manual.html#var-IMAGE_ROOTFS_SIZE\">Yocto Project Reference Manual</a>."
- rootfs_size_widget, self.rootfs_size_spinner = self.gen_spinner_widget(int(self.configuration.image_rootfs_size*1.0/1024), 0, 65536,"<b>Image basic size</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(rootfs_size_widget, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Additional free space (in MB)")
- tooltip = "Sets extra free disk space to be added to the generated image. Use this variable when you want to ensure that a specific amount of free disk space is available on a device after an image is installed and running."
- extra_size_widget, self.extra_size_spinner = self.gen_spinner_widget(int(self.configuration.image_extra_size*1.0/1024), 0, 65536,"<b>Additional free space</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(extra_size_widget, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Licensing</span>'), expand=False, fill=False)
- self.gplv3_checkbox = gtk.CheckButton("Exclude GPLv3 packages")
- self.gplv3_checkbox.set_tooltip_text("Check this box to prevent GPLv3 packages from being included in your image")
- if "GPLv3" in self.configuration.incompat_license.split():
- self.gplv3_checkbox.set_active(True)
- else:
- self.gplv3_checkbox.set_active(False)
- advanced_vbox.pack_start(self.gplv3_checkbox, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">SDK</span>'), expand=False, fill=False)
- sub_hbox = gtk.HBox(False, 6)
- advanced_vbox.pack_start(sub_hbox, expand=False, fill=False)
- self.sdk_checkbox = gtk.CheckButton("Populate SDK")
- tooltip = "Check this box to generate an SDK tarball that consists of the cross-toolchain and a sysroot that contains development packages for your image."
- self.sdk_checkbox.set_tooltip_text(tooltip)
- self.sdk_checkbox.set_active(self.configuration.toolchain_build)
- sub_hbox.pack_start(self.sdk_checkbox, expand=False, fill=False)
-
- tooltip = "Select the host platform for which you want to run the toolchain contained in the SDK tarball."
- sdk_machine_widget, self.sdk_machine_combo = self.gen_combo_widget(self.configuration.curr_sdk_machine, self.all_sdk_machines,"<b>Populate SDK</b>" + "*" + tooltip)
- sub_hbox.pack_start(sdk_machine_widget, expand=False, fill=False)
-
- return advanced_vbox
-
- def response_cb(self, dialog, response_id):
- package_format = []
- package_format.append(self.rootfs_combo.get_active_text())
- for child in self.check_hbox:
- if isinstance(child, gtk.CheckButton) and child.get_active():
- package_format.append(child.get_label())
- self.configuration.curr_package_format = " ".join(package_format)
-
- distro = self.distro_combo.get_active_text()
- if distro == "Default":
- distro = "defaultsetup"
- self.configuration.curr_distro = distro
- self.configuration.image_rootfs_size = self.rootfs_size_spinner.get_value_as_int() * 1024
- self.configuration.image_extra_size = self.extra_size_spinner.get_value_as_int() * 1024
-
- self.configuration.image_fstypes = ""
- for image_type in self.image_types:
- if self.image_types_checkbuttons[image_type].get_active():
- self.configuration.image_fstypes += (" " + image_type)
- self.configuration.image_fstypes.strip()
-
- if self.gplv3_checkbox.get_active():
- if "GPLv3" not in self.configuration.incompat_license.split():
- self.configuration.incompat_license += " GPLv3"
- else:
- if "GPLv3" in self.configuration.incompat_license.split():
- self.configuration.incompat_license = self.configuration.incompat_license.split().remove("GPLv3")
- self.configuration.incompat_license = " ".join(self.configuration.incompat_license or [])
- self.configuration.incompat_license = self.configuration.incompat_license.strip()
-
- self.configuration.toolchain_build = self.sdk_checkbox.get_active()
- self.configuration.curr_sdk_machine = self.sdk_machine_combo.get_active_text()
- md5 = self.config_md5()
- self.settings_changed = (self.md5 != md5)
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py
deleted file mode 100644
index 33bac39db..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/parsingwarningsdialog.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Cristiana Voicu <cristiana.voicu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import gobject
-from bb.ui.crumbs.hobwidget import HobAltButton
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-#
-# ParsingWarningsDialog
-#
-class ParsingWarningsDialog (CrumbsDialog):
-
- def __init__(self, title, warnings, parent, flags, buttons=None):
- super(ParsingWarningsDialog, self).__init__(title, parent, flags, buttons)
-
- self.warnings = warnings
- self.warning_on = 0
- self.warn_nb = len(warnings)
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def cancel_button_cb(self, button):
- self.destroy()
-
- def previous_button_cb(self, button):
- self.warning_on = self.warning_on - 1
- self.refresh_components()
-
- def next_button_cb(self, button):
- self.warning_on = self.warning_on + 1
- self.refresh_components()
-
- def refresh_components(self):
- lbl = self.warnings[self.warning_on]
- #when the warning text has more than 400 chars, it uses a scroll bar
- if 0<= len(lbl) < 400:
- self.warning_label.set_size_request(320, 230)
- self.warning_label.set_use_markup(True)
- self.warning_label.set_line_wrap(True)
- self.warning_label.set_markup(lbl)
- self.warning_label.set_property("yalign", 0.00)
- else:
- self.textWindow.set_shadow_type(gtk.SHADOW_IN)
- self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- self.msgView = gtk.TextView()
- self.msgView.set_editable(False)
- self.msgView.set_wrap_mode(gtk.WRAP_WORD)
- self.msgView.set_cursor_visible(False)
- self.msgView.set_size_request(320, 230)
- self.buf = gtk.TextBuffer()
- self.buf.set_text(lbl)
- self.msgView.set_buffer(self.buf)
- self.textWindow.add(self.msgView)
- self.msgView.show()
-
- if self.warning_on==0:
- self.previous_button.set_sensitive(False)
- else:
- self.previous_button.set_sensitive(True)
-
- if self.warning_on==self.warn_nb-1:
- self.next_button.set_sensitive(False)
- else:
- self.next_button.set_sensitive(True)
-
- if self.warn_nb>1:
- self.heading = "Warning " + str(self.warning_on + 1) + " of " + str(self.warn_nb)
- self.heading_label.set_markup('<span weight="bold">%s</span>' % self.heading)
- else:
- self.heading = "Warning"
- self.heading_label.set_markup('<span weight="bold">%s</span>' % self.heading)
-
- self.show_all()
-
- if 0<= len(lbl) < 400:
- self.textWindow.hide()
- else:
- self.warning_label.hide()
-
- def create_visual_elements(self):
- self.set_size_request(350, 350)
- self.heading_label = gtk.Label()
- self.heading_label.set_alignment(0, 0)
- self.warning_label = gtk.Label()
- self.warning_label.set_selectable(True)
- self.warning_label.set_alignment(0, 0)
- self.textWindow = gtk.ScrolledWindow()
-
- table = gtk.Table(1, 10, False)
-
- cancel_button = gtk.Button()
- cancel_button.set_label("Close")
- cancel_button.connect("clicked", self.cancel_button_cb)
- cancel_button.set_size_request(110, 30)
-
- self.previous_button = gtk.Button()
- image1 = gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON)
- image1.show()
- box = gtk.HBox(False, 6)
- box.show()
- self.previous_button.add(box)
- lbl = gtk.Label("Previous")
- lbl.show()
- box.pack_start(image1, expand=False, fill=False, padding=3)
- box.pack_start(lbl, expand=True, fill=True, padding=3)
- self.previous_button.connect("clicked", self.previous_button_cb)
- self.previous_button.set_size_request(110, 30)
-
- self.next_button = gtk.Button()
- image2 = gtk.image_new_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON)
- image2.show()
- box = gtk.HBox(False, 6)
- box.show()
- self.next_button.add(box)
- lbl = gtk.Label("Next")
- lbl.show()
- box.pack_start(lbl, expand=True, fill=True, padding=3)
- box.pack_start(image2, expand=False, fill=False, padding=3)
- self.next_button.connect("clicked", self.next_button_cb)
- self.next_button.set_size_request(110, 30)
-
- #when there more than one warning, we need "previous" and "next" button
- if self.warn_nb>1:
- self.vbox.pack_start(self.heading_label, expand=False, fill=False)
- self.vbox.pack_start(self.warning_label, expand=False, fill=False)
- self.vbox.pack_start(self.textWindow, expand=False, fill=False)
- table.attach(cancel_button, 6, 7, 0, 1, xoptions=gtk.SHRINK)
- table.attach(self.previous_button, 7, 8, 0, 1, xoptions=gtk.SHRINK)
- table.attach(self.next_button, 8, 9, 0, 1, xoptions=gtk.SHRINK)
- self.vbox.pack_end(table, expand=False, fill=False)
- else:
- self.vbox.pack_start(self.heading_label, expand=False, fill=False)
- self.vbox.pack_start(self.warning_label, expand=False, fill=False)
- self.vbox.pack_start(self.textWindow, expand=False, fill=False)
- cancel_button = self.add_button("Close", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(cancel_button)
-
- self.refresh_components()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py
deleted file mode 100644
index 69e7dffb6..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py
+++ /dev/null
@@ -1,90 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-class ProxyDetailsDialog (CrumbsDialog):
-
- def __init__(self, title, user, passwd, parent, flags, buttons=None):
- super(ProxyDetailsDialog, self).__init__(title, parent, flags, buttons)
- self.connect("response", self.response_cb)
-
- self.auth = not (user == None or passwd == None or user == "")
- self.user = user or ""
- self.passwd = passwd or ""
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def create_visual_elements(self):
- self.auth_checkbox = gtk.CheckButton("Use authentication")
- self.auth_checkbox.set_tooltip_text("Check this box to set the username and the password")
- self.auth_checkbox.set_active(self.auth)
- self.auth_checkbox.connect("toggled", self.auth_checkbox_toggled_cb)
- self.vbox.pack_start(self.auth_checkbox, expand=False, fill=False)
-
- hbox = gtk.HBox(False, 6)
- self.user_label = gtk.Label("Username:")
- self.user_text = gtk.Entry()
- self.user_text.set_text(self.user)
- hbox.pack_start(self.user_label, expand=False, fill=False)
- hbox.pack_end(self.user_text, expand=False, fill=False)
- self.vbox.pack_start(hbox, expand=False, fill=False)
-
- hbox = gtk.HBox(False, 6)
- self.passwd_label = gtk.Label("Password:")
- self.passwd_text = gtk.Entry()
- self.passwd_text.set_text(self.passwd)
- hbox.pack_start(self.passwd_label, expand=False, fill=False)
- hbox.pack_end(self.passwd_text, expand=False, fill=False)
- self.vbox.pack_start(hbox, expand=False, fill=False)
-
- self.refresh_auth_components()
- self.show_all()
-
- def refresh_auth_components(self):
- self.user_label.set_sensitive(self.auth)
- self.user_text.set_editable(self.auth)
- self.user_text.set_sensitive(self.auth)
- self.passwd_label.set_sensitive(self.auth)
- self.passwd_text.set_editable(self.auth)
- self.passwd_text.set_sensitive(self.auth)
-
- def auth_checkbox_toggled_cb(self, button):
- self.auth = self.auth_checkbox.get_active()
- self.refresh_auth_components()
-
- def response_cb(self, dialog, response_id):
- if response_id == gtk.RESPONSE_OK:
- if self.auth:
- self.user = self.user_text.get_text()
- self.passwd = self.passwd_text.get_text()
- else:
- self.user = None
- self.passwd = None
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py
deleted file mode 100644
index 901713985..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/retrieveimagedialog.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2013 Intel Corporation
-#
-# Authored by Cristiana Voicu <cristiana.voicu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-
-class RetrieveImageDialog (gtk.FileChooserDialog):
- """
- This class is used to create a dialog that permits to retrieve
- a custom image saved previously from Hob.
- """
- def __init__(self, directory,title, parent, flags, buttons=None):
- super(RetrieveImageDialog, self).__init__(title, None, gtk.FILE_CHOOSER_ACTION_OPEN,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN, gtk.RESPONSE_OK))
- self.directory = directory
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def create_visual_elements(self):
- self.set_show_hidden(True)
- self.set_default_response(gtk.RESPONSE_OK)
- self.set_current_folder(self.directory)
-
- vbox = self.get_children()[0].get_children()[0].get_children()[0]
- for child in vbox.get_children()[0].get_children()[0].get_children()[0].get_children():
- vbox.get_children()[0].get_children()[0].get_children()[0].remove(child)
-
- label1 = gtk.Label()
- label1.set_text("File system" + self.directory)
- label1.show()
- vbox.get_children()[0].get_children()[0].get_children()[0].pack_start(label1, expand=False, fill=False, padding=0)
- vbox.get_children()[0].get_children()[1].get_children()[0].hide()
-
- self.get_children()[0].get_children()[1].get_children()[0].set_label("Select")
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py
deleted file mode 100644
index 4195f70e1..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/saveimagedialog.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2013 Intel Corporation
-#
-# Authored by Cristiana Voicu <cristiana.voicu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import glib
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hobwidget import HobButton
-
-class SaveImageDialog (CrumbsDialog):
- """
- This class is used to create a dialog that permits to save
- a custom image in a predefined directory.
- """
- def __init__(self, directory, name, description, title, parent, flags, buttons=None):
- super(SaveImageDialog, self).__init__(title, parent, flags, buttons)
- self.directory = directory
- self.builder = parent
- self.name_field = name
- self.description_field = description
-
- # create visual elements on the dialog
- self.create_visual_elements()
-
- def create_visual_elements(self):
- self.set_default_response(gtk.RESPONSE_OK)
- self.vbox.set_border_width(6)
-
- sub_vbox = gtk.VBox(False, 12)
- self.vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup("<b>Name</b>")
- sub_label = gtk.Label()
- sub_label.set_alignment(0, 0)
- content = "Image recipe names should be all lowercase and include only alphanumeric\n"
- content += "characters. The only special character you can use is the ASCII hyphen (-)."
- sub_label.set_markup(content)
- self.name_entry = gtk.Entry()
- self.name_entry.set_text(self.name_field)
- self.name_entry.set_size_request(350,30)
- self.name_entry.connect("changed", self.name_entry_changed)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sub_label, expand=False, fill=False)
- sub_vbox.pack_start(self.name_entry, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 12)
- self.vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup("<b>Description</b> (optional)")
- sub_label = gtk.Label()
- sub_label.set_alignment(0, 0)
- sub_label.set_markup("The description should be less than 150 characters long.")
- self.description_entry = gtk.TextView()
- description_buffer = self.description_entry.get_buffer()
- description_buffer.set_text(self.description_field)
- description_buffer.connect("insert-text", self.limit_description_length)
- self.description_entry.set_wrap_mode(gtk.WRAP_WORD)
- self.description_entry.set_size_request(350,50)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sub_label, expand=False, fill=False)
- sub_vbox.pack_start(self.description_entry, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 12)
- self.vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = gtk.Label()
- label.set_alignment(0, 0)
- label.set_markup("Your image recipe will be saved to:")
- sub_label = gtk.Label()
- sub_label.set_alignment(0, 0)
- sub_label.set_markup(self.directory)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sub_label, expand=False, fill=False)
-
- table = gtk.Table(1, 4, True)
-
- cancel_button = gtk.Button()
- cancel_button.set_label("Cancel")
- cancel_button.connect("clicked", self.cancel_button_cb)
- cancel_button.set_size_request(110, 30)
-
- self.save_button = gtk.Button()
- self.save_button.set_label("Save")
- self.save_button.connect("clicked", self.save_button_cb)
- self.save_button.set_size_request(110, 30)
- if self.name_entry.get_text() == '':
- self.save_button.set_sensitive(False)
-
- table.attach(cancel_button, 2, 3, 0, 1)
- table.attach(self.save_button, 3, 4, 0, 1)
- self.vbox.pack_end(table, expand=False, fill=False)
-
- self.show_all()
-
- def limit_description_length(self, textbuffer, iter, text, length):
- buffer_bounds = textbuffer.get_bounds()
- entire_text = textbuffer.get_text(*buffer_bounds)
- entire_text += text
- if len(entire_text)>150 or text=="\n":
- textbuffer.emit_stop_by_name("insert-text")
-
- def name_entry_changed(self, entry):
- text = entry.get_text()
- if text == '':
- self.save_button.set_sensitive(False)
- else:
- self.save_button.set_sensitive(True)
-
- def cancel_button_cb(self, button):
- self.destroy()
-
- def save_button_cb(self, button):
- text = self.name_entry.get_text()
- new_text = text.replace("-","")
- description_buffer = self.description_entry.get_buffer()
- description = description_buffer.get_text(description_buffer.get_start_iter(),description_buffer.get_end_iter())
- if new_text.islower() and new_text.isalnum():
- self.builder.image_details_page.image_saved = True
- self.builder.customized = False
- self.builder.generate_new_image(self.directory+text, description)
- self.builder.recipe_model.set_in_list(text, description)
- self.builder.recipe_model.set_selected_image(text)
- self.builder.image_details_page.show_page(self.builder.IMAGE_GENERATED)
- self.builder.image_details_page.name_field_template = text
- self.builder.image_details_page.description_field_template = description
- self.destroy()
- else:
- self.show_invalid_input_error_dialog()
-
- def show_invalid_input_error_dialog(self):
- lbl = "<b>Invalid characters in image recipe name</b>"
- msg = "Image recipe names should be all lowercase and\n"
- msg += "include only alphanumeric characters. The only\n"
- msg += "special character you can use is the ASCII hyphen (-)."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_ERROR, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
-
- res = dialog.run()
- self.name_entry.grab_focus()
- dialog.destroy()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py
deleted file mode 100644
index b5eb3d873..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py
+++ /dev/null
@@ -1,891 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011-2012 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import gobject
-import hashlib
-from bb.ui.crumbs.hobwidget import hic, HobInfoButton, HobButton, HobAltButton
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
-from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog
-
-"""
-The following are convenience classes for implementing GNOME HIG compliant
-BitBake GUI's
-In summary: spacing = 12px, border-width = 6px
-"""
-
-class SimpleSettingsDialog (CrumbsDialog, SettingsUIHelper):
-
- (BUILD_ENV_PAGE_ID,
- SHARED_STATE_PAGE_ID,
- PROXIES_PAGE_ID,
- OTHERS_PAGE_ID) = range(4)
-
- (TEST_NETWORK_NONE,
- TEST_NETWORK_INITIAL,
- TEST_NETWORK_RUNNING,
- TEST_NETWORK_PASSED,
- TEST_NETWORK_FAILED,
- TEST_NETWORK_CANCELED) = range(6)
-
- TARGETS = [
- ("MY_TREE_MODEL_ROW", gtk.TARGET_SAME_WIDGET, 0),
- ("text/plain", 0, 1),
- ("TEXT", 0, 2),
- ("STRING", 0, 3),
- ]
-
- def __init__(self, title, configuration, all_image_types,
- all_package_formats, all_distros, all_sdk_machines,
- max_threads, parent, flags, handler, buttons=None):
- super(SimpleSettingsDialog, self).__init__(title, parent, flags, buttons)
-
- # class members from other objects
- # bitbake settings from Builder.Configuration
- self.configuration = configuration
- self.image_types = all_image_types
- self.all_package_formats = all_package_formats
- self.all_distros = all_distros
- self.all_sdk_machines = all_sdk_machines
- self.max_threads = max_threads
-
- # class members for internal use
- self.dldir_text = None
- self.sstatedir_text = None
- self.sstatemirrors_list = []
- self.sstatemirrors_changed = 0
- self.bb_spinner = None
- self.pmake_spinner = None
- self.rootfs_size_spinner = None
- self.extra_size_spinner = None
- self.gplv3_checkbox = None
- self.toolchain_checkbox = None
- self.setting_store = None
- self.image_types_checkbuttons = {}
-
- self.md5 = self.config_md5()
- self.proxy_md5 = self.config_proxy_md5()
- self.settings_changed = False
- self.proxy_settings_changed = False
- self.handler = handler
- self.proxy_test_ran = False
- self.selected_mirror_row = 0
- self.new_mirror = False
-
- # create visual elements on the dialog
- self.create_visual_elements()
- self.connect("response", self.response_cb)
-
- def _get_sorted_value(self, var):
- return " ".join(sorted(str(var).split())) + "\n"
-
- def config_proxy_md5(self):
- data = ("ENABLE_PROXY: " + self._get_sorted_value(self.configuration.enable_proxy))
- if self.configuration.enable_proxy:
- for protocol in self.configuration.proxies.keys():
- data += (protocol + ": " + self._get_sorted_value(self.configuration.combine_proxy(protocol)))
- return hashlib.md5(data).hexdigest()
-
- def config_md5(self):
- data = ""
- for key in self.configuration.extra_setting.keys():
- data += (key + ": " + self._get_sorted_value(self.configuration.extra_setting[key]))
- return hashlib.md5(data).hexdigest()
-
- def gen_proxy_entry_widget(self, protocol, parent, need_button=True, line=0):
- label = gtk.Label(protocol.upper() + " proxy")
- self.proxy_table.attach(label, 0, 1, line, line+1, xpadding=24)
-
- proxy_entry = gtk.Entry()
- proxy_entry.set_size_request(300, -1)
- self.proxy_table.attach(proxy_entry, 1, 2, line, line+1, ypadding=4)
-
- self.proxy_table.attach(gtk.Label(":"), 2, 3, line, line+1, xpadding=12, ypadding=4)
-
- port_entry = gtk.Entry()
- port_entry.set_size_request(60, -1)
- self.proxy_table.attach(port_entry, 3, 4, line, line+1, ypadding=4)
-
- details_button = HobAltButton("Details")
- details_button.connect("clicked", self.details_cb, parent, protocol)
- self.proxy_table.attach(details_button, 4, 5, line, line+1, xpadding=4, yoptions=gtk.EXPAND)
-
- return proxy_entry, port_entry, details_button
-
- def refresh_proxy_components(self):
- self.same_checkbox.set_sensitive(self.configuration.enable_proxy)
-
- self.http_proxy.set_text(self.configuration.combine_host_only("http"))
- self.http_proxy.set_editable(self.configuration.enable_proxy)
- self.http_proxy.set_sensitive(self.configuration.enable_proxy)
- self.http_proxy_port.set_text(self.configuration.combine_port_only("http"))
- self.http_proxy_port.set_editable(self.configuration.enable_proxy)
- self.http_proxy_port.set_sensitive(self.configuration.enable_proxy)
- self.http_proxy_details.set_sensitive(self.configuration.enable_proxy)
-
- self.https_proxy.set_text(self.configuration.combine_host_only("https"))
- self.https_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy_port.set_text(self.configuration.combine_port_only("https"))
- self.https_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.https_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- self.ftp_proxy.set_text(self.configuration.combine_host_only("ftp"))
- self.ftp_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy_port.set_text(self.configuration.combine_port_only("ftp"))
- self.ftp_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.ftp_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- self.socks_proxy.set_text(self.configuration.combine_host_only("socks"))
- self.socks_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy_port.set_text(self.configuration.combine_port_only("socks"))
- self.socks_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.socks_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- self.cvs_proxy.set_text(self.configuration.combine_host_only("cvs"))
- self.cvs_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy_port.set_text(self.configuration.combine_port_only("cvs"))
- self.cvs_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
- self.cvs_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
-
- if self.configuration.same_proxy:
- if self.http_proxy.get_text():
- [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
- if self.http_proxy_port.get_text():
- [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
-
- def proxy_checkbox_toggled_cb(self, button):
- self.configuration.enable_proxy = self.proxy_checkbox.get_active()
- if not self.configuration.enable_proxy:
- self.configuration.same_proxy = False
- self.same_checkbox.set_active(self.configuration.same_proxy)
- self.save_proxy_data()
- self.refresh_proxy_components()
-
- def same_checkbox_toggled_cb(self, button):
- self.configuration.same_proxy = self.same_checkbox.get_active()
- self.save_proxy_data()
- self.refresh_proxy_components()
-
- def save_proxy_data(self):
- self.configuration.split_proxy("http", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- if self.configuration.same_proxy:
- self.configuration.split_proxy("https", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- self.configuration.split_proxy("ftp", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- self.configuration.split_proxy("socks", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- self.configuration.split_proxy("cvs", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
- else:
- self.configuration.split_proxy("https", self.https_proxy.get_text() + ":" + self.https_proxy_port.get_text())
- self.configuration.split_proxy("ftp", self.ftp_proxy.get_text() + ":" + self.ftp_proxy_port.get_text())
- self.configuration.split_proxy("socks", self.socks_proxy.get_text() + ":" + self.socks_proxy_port.get_text())
- self.configuration.split_proxy("cvs", self.cvs_proxy.get_text() + ":" + self.cvs_proxy_port.get_text())
-
- def response_cb(self, dialog, response_id):
- if response_id == gtk.RESPONSE_YES:
- if self.proxy_checkbox.get_active():
- # Check that all proxy entries have a corresponding port
- for proxy, port in zip(self.all_proxy_addresses, self.all_proxy_ports):
- if proxy.get_text() and not port.get_text():
- lbl = "<b>Enter all port numbers</b>"
- msg = "Proxy servers require a port number. Please make sure you have entered a port number for each proxy server."
- dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg)
- button = dialog.add_button("Close", gtk.RESPONSE_OK)
- HobButton.style_button(button)
- response = dialog.run()
- dialog.destroy()
- self.emit_stop_by_name("response")
- return
-
- self.configuration.dldir = self.dldir_text.get_text()
- self.configuration.sstatedir = self.sstatedir_text.get_text()
- self.configuration.sstatemirror = ""
- for mirror in self.sstatemirrors_list:
- if mirror[1] != "" and mirror[2].startswith("file://"):
- smirror = mirror[2] + " " + mirror[1] + " \\n "
- self.configuration.sstatemirror += smirror
- self.configuration.bbthread = self.bb_spinner.get_value_as_int()
- self.configuration.pmake = self.pmake_spinner.get_value_as_int()
- self.save_proxy_data()
- self.configuration.extra_setting = {}
- it = self.setting_store.get_iter_first()
- while it:
- key = self.setting_store.get_value(it, 0)
- value = self.setting_store.get_value(it, 1)
- self.configuration.extra_setting[key] = value
- it = self.setting_store.iter_next(it)
-
- md5 = self.config_md5()
- self.settings_changed = (self.md5 != md5)
- self.proxy_settings_changed = (self.proxy_md5 != self.config_proxy_md5())
-
- def create_build_environment_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Parallel threads</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("BitBake parallel threads")
- tooltip = "Sets the number of threads that BitBake tasks can simultaneously run. See the <a href=\""
- tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
- tooltip += "poky-ref-manual.html#var-BB_NUMBER_THREADS\">Poky reference manual</a> for information"
- bbthread_widget, self.bb_spinner = self.gen_spinner_widget(self.configuration.bbthread, 1, self.max_threads,"<b>BitBake prallalel threads</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(bbthread_widget, expand=False, fill=False)
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Make parallel threads")
- tooltip = "Sets the maximum number of threads the host can use during the build. See the <a href=\""
- tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
- tooltip += "poky-ref-manual.html#var-PARALLEL_MAKE\">Poky reference manual</a> for information"
- pmake_widget, self.pmake_spinner = self.gen_spinner_widget(self.configuration.pmake, 1, self.max_threads,"<b>Make parallel threads</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(pmake_widget, expand=False, fill=False)
-
- advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Downloaded source code</span>'), expand=False, fill=False)
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("Downloads directory")
- tooltip = "Select a folder that caches the upstream project source code"
- dldir_widget, self.dldir_text = self.gen_entry_widget(self.configuration.dldir, self,"<b>Downloaded source code</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(dldir_widget, expand=False, fill=False)
-
- return advanced_vbox
-
- def create_shared_state_page(self):
- advanced_vbox = gtk.VBox(False)
- advanced_vbox.set_border_width(12)
-
- sub_vbox = gtk.VBox(False)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False, padding=24)
- content = "<span>Shared state directory</span>"
- tooltip = "Select a folder that caches your prebuilt results"
- label = self.gen_label_info_widget(content,"<b>Shared state directory</b>" + "*" + tooltip)
- sstatedir_widget, self.sstatedir_text = self.gen_entry_widget(self.configuration.sstatedir, self)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(sstatedir_widget, expand=False, fill=False, padding=6)
-
- content = "<span weight=\"bold\">Shared state mirrors</span>"
- tooltip = "URLs pointing to pre-built mirrors that will speed your build. "
- tooltip += "Select the \'Standard\' configuration if the structure of your "
- tooltip += "mirror replicates the structure of your local shared state directory. "
- tooltip += "For more information on shared state mirrors, check the <a href=\""
- tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
- tooltip += "poky-ref-manual.html#shared-state\">Yocto Project Reference Manual</a>."
- table = self.gen_label_info_widget(content,"<b>Shared state mirrors</b>" + "*" + tooltip)
- advanced_vbox.pack_start(table, expand=False, fill=False, padding=6)
-
- sub_vbox = gtk.VBox(False)
- advanced_vbox.pack_start(sub_vbox, gtk.TRUE, gtk.TRUE, 0)
-
- if self.sstatemirrors_changed == 0:
- self.sstatemirrors_changed = 1
- sstatemirrors = self.configuration.sstatemirror
- if sstatemirrors == "":
- sm_list = ["Standard", "", "file://(.*)"]
- self.sstatemirrors_list.append(sm_list)
- else:
- sstatemirrors = [x for x in sstatemirrors.split('\\n')]
- for sstatemirror in sstatemirrors:
- sstatemirror_fields = [x for x in sstatemirror.split(' ') if x.strip()]
- if len(sstatemirror_fields) == 2:
- if sstatemirror_fields[0] == "file://(.*)" or sstatemirror_fields[0] == "file://.*":
- sm_list = ["Standard", sstatemirror_fields[1], sstatemirror_fields[0]]
- else:
- sm_list = ["Custom", sstatemirror_fields[1], sstatemirror_fields[0]]
- self.sstatemirrors_list.append(sm_list)
-
- sstatemirrors_widget, sstatemirrors_store = self.gen_shared_sstate_widget(self.sstatemirrors_list, self)
- sub_vbox.pack_start(sstatemirrors_widget, expand=True, fill=True)
-
- table = gtk.Table(1, 10, False)
- table.set_col_spacings(6)
- add_mirror_button = HobAltButton("Add mirror")
- add_mirror_button.connect("clicked", self.add_mirror)
- add_mirror_button.set_size_request(120,30)
- table.attach(add_mirror_button, 1, 2, 0, 1, xoptions=gtk.SHRINK)
-
- self.delete_button = HobAltButton("Delete mirror")
- self.delete_button.connect("clicked", self.delete_cb)
- self.delete_button.set_size_request(120, 30)
- table.attach(self.delete_button, 3, 4, 0, 1, xoptions=gtk.SHRINK)
-
- advanced_vbox.pack_start(table, expand=False, fill=False, padding=6)
-
- return advanced_vbox
-
- def gen_shared_sstate_widget(self, sstatemirrors_list, window):
- hbox = gtk.HBox(False)
-
- sstatemirrors_store = gtk.ListStore(str, str, str)
- for sstatemirror in sstatemirrors_list:
- sstatemirrors_store.append(sstatemirror)
-
- self.sstatemirrors_tv = gtk.TreeView()
- self.sstatemirrors_tv.set_rules_hint(True)
- self.sstatemirrors_tv.set_headers_visible(True)
- tree_selection = self.sstatemirrors_tv.get_selection()
- tree_selection.set_mode(gtk.SELECTION_SINGLE)
-
- # Allow enable drag and drop of rows including row move
- self.sstatemirrors_tv.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
- self.TARGETS,
- gtk.gdk.ACTION_DEFAULT|
- gtk.gdk.ACTION_MOVE)
- self.sstatemirrors_tv.enable_model_drag_dest(self.TARGETS,
- gtk.gdk.ACTION_DEFAULT)
- self.sstatemirrors_tv.connect("drag_data_get", self.drag_data_get_cb)
- self.sstatemirrors_tv.connect("drag_data_received", self.drag_data_received_cb)
-
-
- self.scroll = gtk.ScrolledWindow()
- self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
- self.scroll.set_shadow_type(gtk.SHADOW_IN)
- self.scroll.connect('size-allocate', self.scroll_changed)
- self.scroll.add(self.sstatemirrors_tv)
-
- #list store for cell renderer
- m = gtk.ListStore(gobject.TYPE_STRING)
- m.append(["Standard"])
- m.append(["Custom"])
-
- cell0 = gtk.CellRendererCombo()
- cell0.set_property("model",m)
- cell0.set_property("text-column", 0)
- cell0.set_property("editable", True)
- cell0.set_property("has-entry", False)
- col0 = gtk.TreeViewColumn("Configuration")
- col0.pack_start(cell0, False)
- col0.add_attribute(cell0, "text", 0)
- col0.set_cell_data_func(cell0, self.configuration_field)
- self.sstatemirrors_tv.append_column(col0)
-
- cell0.connect("edited", self.combo_changed, sstatemirrors_store)
-
- self.cell1 = gtk.CellRendererText()
- self.cell1.set_padding(5,2)
- col1 = gtk.TreeViewColumn('Regex', self.cell1)
- col1.set_cell_data_func(self.cell1, self.regex_field)
- self.sstatemirrors_tv.append_column(col1)
-
- self.cell1.connect("edited", self.regex_changed, sstatemirrors_store)
-
- cell2 = gtk.CellRendererText()
- cell2.set_padding(5,2)
- cell2.set_property("editable", True)
- col2 = gtk.TreeViewColumn('URL', cell2)
- col2.set_cell_data_func(cell2, self.url_field)
- self.sstatemirrors_tv.append_column(col2)
-
- cell2.connect("edited", self.url_changed, sstatemirrors_store)
-
- self.sstatemirrors_tv.set_model(sstatemirrors_store)
- self.sstatemirrors_tv.set_cursor(self.selected_mirror_row)
- hbox.pack_start(self.scroll, expand=True, fill=True)
- hbox.show_all()
-
- return hbox, sstatemirrors_store
-
- def drag_data_get_cb(self, treeview, context, selection, target_id, etime):
- treeselection = treeview.get_selection()
- model, iter = treeselection.get_selected()
- data = model.get_string_from_iter(iter)
- selection.set(selection.target, 8, data)
-
- def drag_data_received_cb(self, treeview, context, x, y, selection, info, etime):
- model = treeview.get_model()
- data = []
- tree_iter = model.get_iter_from_string(selection.data)
- data.append(model.get_value(tree_iter, 0))
- data.append(model.get_value(tree_iter, 1))
- data.append(model.get_value(tree_iter, 2))
-
- drop_info = treeview.get_dest_row_at_pos(x, y)
- if drop_info:
- path, position = drop_info
- iter = model.get_iter(path)
- if (position == gtk.TREE_VIEW_DROP_BEFORE or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
- model.insert_before(iter, data)
- else:
- model.insert_after(iter, data)
- else:
- model.append(data)
- if context.action == gtk.gdk.ACTION_MOVE:
- context.finish(True, True, etime)
- return
-
- def delete_cb(self, button):
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- if index == 0:
- self.selected_mirror_row = index
- else:
- self.selected_mirror_row = index - 1
- self.sstatemirrors_list.pop(index)
- self.refresh_shared_state_page()
- if not self.sstatemirrors_list:
- self.delete_button.set_sensitive(False)
-
- def add_mirror(self, button):
- self.new_mirror = True
- tooltip = "Select the pre-built mirror that will speed your build"
- index = len(self.sstatemirrors_list)
- self.selected_mirror_row = index
- sm_list = ["Standard", "", "file://(.*)"]
- self.sstatemirrors_list.append(sm_list)
- self.refresh_shared_state_page()
-
- def scroll_changed(self, widget, event, data=None):
- if self.new_mirror == True:
- adj = widget.get_vadjustment()
- adj.set_value(adj.upper - adj.page_size)
- self.new_mirror = False
-
- def combo_changed(self, widget, path, text, model):
- model[path][0] = text
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- self.sstatemirrors_list[index][0] = text
-
- def regex_changed(self, cell, path, new_text, user_data):
- user_data[path][2] = new_text
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- self.sstatemirrors_list[index][2] = new_text
- return
-
- def url_changed(self, cell, path, new_text, user_data):
- if new_text!="Enter the mirror URL" and new_text!="Match regex and replace it with this URL":
- user_data[path][1] = new_text
- selection = self.sstatemirrors_tv.get_selection()
- tree_model, tree_iter = selection.get_selected()
- index = int(tree_model.get_string_from_iter(tree_iter))
- self.sstatemirrors_list[index][1] = new_text
- return
-
- def configuration_field(self, column, cell, model, iter):
- cell.set_property('text', model.get_value(iter, 0))
- if model.get_value(iter, 0) == "Standard":
- self.cell1.set_property("sensitive", False)
- self.cell1.set_property("editable", False)
- else:
- self.cell1.set_property("sensitive", True)
- self.cell1.set_property("editable", True)
- return
-
- def regex_field(self, column, cell, model, iter):
- cell.set_property('text', model.get_value(iter, 2))
- return
-
- def url_field(self, column, cell, model, iter):
- text = model.get_value(iter, 1)
- if text == "":
- if model.get_value(iter, 0) == "Standard":
- text = "Enter the mirror URL"
- else:
- text = "Match regex and replace it with this URL"
- cell.set_property('text', text)
- return
-
- def refresh_shared_state_page(self):
- page_num = self.nb.get_current_page()
- self.nb.remove_page(page_num);
- self.nb.insert_page(self.create_shared_state_page(), gtk.Label("Shared state"),page_num)
- self.show_all()
- self.nb.set_current_page(page_num)
-
- def test_proxy_ended(self, passed):
- self.proxy_test_running = False
- self.set_test_proxy_state(self.TEST_NETWORK_PASSED if passed else self.TEST_NETWORK_FAILED)
- self.set_sensitive(True)
- self.refresh_proxy_components()
-
- def timer_func(self):
- self.test_proxy_progress.pulse()
- return self.proxy_test_running
-
- def test_network_button_cb(self, b):
- self.set_test_proxy_state(self.TEST_NETWORK_RUNNING)
- self.set_sensitive(False)
- self.save_proxy_data()
- if self.configuration.enable_proxy == True:
- self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
- self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
- self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
- self.handler.set_socks_proxy(self.configuration.combine_proxy("socks"))
- self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
- elif self.configuration.enable_proxy == False:
- self.handler.set_http_proxy("")
- self.handler.set_https_proxy("")
- self.handler.set_ftp_proxy("")
- self.handler.set_socks_proxy("")
- self.handler.set_cvs_proxy("", "")
- self.proxy_test_ran = True
- self.proxy_test_running = True
- gobject.timeout_add(100, self.timer_func)
- self.handler.trigger_network_test()
-
- def test_proxy_focus_event(self, w, direction):
- if self.test_proxy_state in [self.TEST_NETWORK_PASSED, self.TEST_NETWORK_FAILED]:
- self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
- return False
-
- def http_proxy_changed(self, e):
- if not self.configuration.same_proxy:
- return
- if e == self.http_proxy:
- [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
- else:
- [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
-
- def proxy_address_focus_out_event(self, w, direction):
- text = w.get_text()
- if not text:
- return False
- if text.find("//") == -1:
- w.set_text("http://" + text)
- return False
-
- def set_test_proxy_state(self, state):
- if self.test_proxy_state == state:
- return
- [self.proxy_table.remove(w) for w in self.test_gui_elements]
- if state == self.TEST_NETWORK_INITIAL:
- self.proxy_table.attach(self.test_network_button, 1, 2, 5, 6)
- self.test_network_button.show()
- elif state == self.TEST_NETWORK_RUNNING:
- self.test_proxy_progress.set_rcstyle("running")
- self.test_proxy_progress.set_text("Testing network configuration")
- self.proxy_table.attach(self.test_proxy_progress, 0, 5, 5, 6, xpadding=4)
- self.test_proxy_progress.show()
- else: # passed or failed
- self.dummy_progress.update(1.0)
- if state == self.TEST_NETWORK_PASSED:
- self.dummy_progress.set_text("Your network is properly configured")
- self.dummy_progress.set_rcstyle("running")
- else:
- self.dummy_progress.set_text("Network test failed")
- self.dummy_progress.set_rcstyle("fail")
- self.proxy_table.attach(self.dummy_progress, 0, 4, 5, 6)
- self.proxy_table.attach(self.retest_network_button, 4, 5, 5, 6, xpadding=4)
- self.dummy_progress.show()
- self.retest_network_button.show()
- self.test_proxy_state = state
-
- def create_network_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
- self.same_proxy_addresses = []
- self.same_proxy_ports = []
- self.all_proxy_ports = []
- self.all_proxy_addresses = []
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
- label = self.gen_label_widget("<span weight=\"bold\">Set the proxies used when fetching source code</span>")
- tooltip = "Set the proxies used when fetching source code. A blank field uses a direct internet connection."
- info = HobInfoButton("<span weight=\"bold\">Set the proxies used when fetching source code</span>" + "*" + tooltip, self)
- hbox = gtk.HBox(False, 12)
- hbox.pack_start(label, expand=True, fill=True)
- hbox.pack_start(info, expand=False, fill=False)
- sub_vbox.pack_start(hbox, expand=False, fill=False)
-
- proxy_test_focus = []
- self.direct_checkbox = gtk.RadioButton(None, "Direct network connection")
- proxy_test_focus.append(self.direct_checkbox)
- self.direct_checkbox.set_tooltip_text("Check this box to use a direct internet connection with no proxy")
- self.direct_checkbox.set_active(not self.configuration.enable_proxy)
- sub_vbox.pack_start(self.direct_checkbox, expand=False, fill=False)
-
- self.proxy_checkbox = gtk.RadioButton(self.direct_checkbox, "Manual proxy configuration")
- proxy_test_focus.append(self.proxy_checkbox)
- self.proxy_checkbox.set_tooltip_text("Check this box to manually set up a specific proxy")
- self.proxy_checkbox.set_active(self.configuration.enable_proxy)
- sub_vbox.pack_start(self.proxy_checkbox, expand=False, fill=False)
-
- self.same_checkbox = gtk.CheckButton("Use the HTTP proxy for all protocols")
- proxy_test_focus.append(self.same_checkbox)
- self.same_checkbox.set_tooltip_text("Check this box to use the HTTP proxy for all five proxies")
- self.same_checkbox.set_active(self.configuration.same_proxy)
- hbox = gtk.HBox(False, 12)
- hbox.pack_start(self.same_checkbox, expand=False, fill=False, padding=24)
- sub_vbox.pack_start(hbox, expand=False, fill=False)
-
- self.proxy_table = gtk.Table(6, 5, False)
- self.http_proxy, self.http_proxy_port, self.http_proxy_details = self.gen_proxy_entry_widget(
- "http", self, True, 0)
- proxy_test_focus +=[self.http_proxy, self.http_proxy_port]
- self.http_proxy.connect("changed", self.http_proxy_changed)
- self.http_proxy_port.connect("changed", self.http_proxy_changed)
-
- self.https_proxy, self.https_proxy_port, self.https_proxy_details = self.gen_proxy_entry_widget(
- "https", self, True, 1)
- proxy_test_focus += [self.https_proxy, self.https_proxy_port]
- self.same_proxy_addresses.append(self.https_proxy)
- self.same_proxy_ports.append(self.https_proxy_port)
-
- self.ftp_proxy, self.ftp_proxy_port, self.ftp_proxy_details = self.gen_proxy_entry_widget(
- "ftp", self, True, 2)
- proxy_test_focus += [self.ftp_proxy, self.ftp_proxy_port]
- self.same_proxy_addresses.append(self.ftp_proxy)
- self.same_proxy_ports.append(self.ftp_proxy_port)
-
- self.socks_proxy, self.socks_proxy_port, self.socks_proxy_details = self.gen_proxy_entry_widget(
- "socks", self, True, 3)
- proxy_test_focus += [self.socks_proxy, self.socks_proxy_port]
- self.same_proxy_addresses.append(self.socks_proxy)
- self.same_proxy_ports.append(self.socks_proxy_port)
-
- self.cvs_proxy, self.cvs_proxy_port, self.cvs_proxy_details = self.gen_proxy_entry_widget(
- "cvs", self, True, 4)
- proxy_test_focus += [self.cvs_proxy, self.cvs_proxy_port]
- self.same_proxy_addresses.append(self.cvs_proxy)
- self.same_proxy_ports.append(self.cvs_proxy_port)
- self.all_proxy_ports = self.same_proxy_ports + [self.http_proxy_port]
- self.all_proxy_addresses = self.same_proxy_addresses + [self.http_proxy]
- sub_vbox.pack_start(self.proxy_table, expand=False, fill=False)
- self.proxy_table.show_all()
-
- # Create the graphical elements for the network test feature, but don't display them yet
- self.test_network_button = HobAltButton("Test network configuration")
- self.test_network_button.connect("clicked", self.test_network_button_cb)
- self.test_proxy_progress = HobProgressBar()
- self.dummy_progress = HobProgressBar()
- self.retest_network_button = HobAltButton("Retest")
- self.retest_network_button.connect("clicked", self.test_network_button_cb)
- self.test_gui_elements = [self.test_network_button, self.test_proxy_progress, self.dummy_progress, self.retest_network_button]
- # Initialize the network tester
- self.test_proxy_state = self.TEST_NETWORK_NONE
- self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
- self.proxy_test_passed_id = self.handler.connect("network-passed", lambda h:self.test_proxy_ended(True))
- self.proxy_test_failed_id = self.handler.connect("network-failed", lambda h:self.test_proxy_ended(False))
- [w.connect("focus-in-event", self.test_proxy_focus_event) for w in proxy_test_focus]
- [w.connect("focus-out-event", self.proxy_address_focus_out_event) for w in self.all_proxy_addresses]
-
- self.direct_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
- self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
- self.same_checkbox.connect("toggled", self.same_checkbox_toggled_cb)
-
- self.refresh_proxy_components()
- return advanced_vbox
-
- def switch_to_page(self, page_id):
- self.nb.set_current_page(page_id)
-
- def details_cb(self, button, parent, protocol):
- self.save_proxy_data()
- dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
- user = self.configuration.proxies[protocol][1],
- passwd = self.configuration.proxies[protocol][2],
- parent = parent,
- flags = gtk.DIALOG_MODAL
- | gtk.DIALOG_DESTROY_WITH_PARENT
- | gtk.DIALOG_NO_SEPARATOR)
- dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- self.configuration.proxies[protocol][1] = dialog.user
- self.configuration.proxies[protocol][2] = dialog.passwd
- self.refresh_proxy_components()
- dialog.destroy()
-
- def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
- combo_item = self.rootfs_combo.get_active_text()
- for child in check_hbox.get_children():
- if isinstance(child, gtk.CheckButton):
- check_hbox.remove(child)
- for format in all_package_format:
- if format != combo_item:
- check_button = gtk.CheckButton(format)
- check_hbox.pack_start(check_button, expand=False, fill=False)
- check_hbox.show_all()
-
- def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
- pkgfmt_hbox = gtk.HBox(False, 24)
-
- rootfs_vbox = gtk.VBox(False, 6)
- pkgfmt_hbox.pack_start(rootfs_vbox, expand=False, fill=False)
-
- label = self.gen_label_widget("Root file system package format")
- rootfs_vbox.pack_start(label, expand=False, fill=False)
-
- rootfs_format = ""
- if curr_package_format:
- rootfs_format = curr_package_format.split()[0]
-
- rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
- rootfs_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
-
- extra_vbox = gtk.VBox(False, 6)
- pkgfmt_hbox.pack_start(extra_vbox, expand=False, fill=False)
-
- label = self.gen_label_widget("Additional package formats")
- extra_vbox.pack_start(label, expand=False, fill=False)
-
- check_hbox = gtk.HBox(False, 12)
- extra_vbox.pack_start(check_hbox, expand=False, fill=False)
- for format in all_package_format:
- if format != rootfs_format:
- check_button = gtk.CheckButton(format)
- is_active = (format in curr_package_format.split())
- check_button.set_active(is_active)
- check_hbox.pack_start(check_button, expand=False, fill=False)
-
- info = HobInfoButton(tooltip_extra, self)
- check_hbox.pack_end(info, expand=False, fill=False)
-
- rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
-
- pkgfmt_hbox.show_all()
-
- return pkgfmt_hbox, rootfs_combo, check_hbox
-
- def editable_settings_cell_edited(self, cell, path_string, new_text, model):
- it = model.get_iter_from_string(path_string)
- column = cell.get_data("column")
- model.set(it, column, new_text)
-
- def editable_settings_add_item_clicked(self, button, model):
- new_item = ["##KEY##", "##VALUE##"]
-
- iter = model.append()
- model.set (iter,
- 0, new_item[0],
- 1, new_item[1],
- )
-
- def editable_settings_remove_item_clicked(self, button, treeview):
- selection = treeview.get_selection()
- model, iter = selection.get_selected()
-
- if iter:
- path = model.get_path(iter)[0]
- model.remove(iter)
-
- def gen_editable_settings(self, setting, tooltip=""):
- setting_hbox = gtk.HBox(False, 12)
-
- vbox = gtk.VBox(False, 12)
- setting_hbox.pack_start(vbox, expand=True, fill=True)
-
- setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- for key in setting.keys():
- setting_store.set(setting_store.append(), 0, key, 1, setting[key])
-
- setting_tree = gtk.TreeView(setting_store)
- setting_tree.set_headers_visible(True)
- setting_tree.set_size_request(300, 100)
-
- col = gtk.TreeViewColumn('Key')
- col.set_min_width(100)
- col.set_max_width(150)
- col.set_resizable(True)
- col1 = gtk.TreeViewColumn('Value')
- col1.set_min_width(100)
- col1.set_max_width(150)
- col1.set_resizable(True)
- setting_tree.append_column(col)
- setting_tree.append_column(col1)
- cell = gtk.CellRendererText()
- cell.set_property('width-chars', 10)
- cell.set_property('editable', True)
- cell.set_data("column", 0)
- cell.connect("edited", self.editable_settings_cell_edited, setting_store)
- cell1 = gtk.CellRendererText()
- cell1.set_property('width-chars', 10)
- cell1.set_property('editable', True)
- cell1.set_data("column", 1)
- cell1.connect("edited", self.editable_settings_cell_edited, setting_store)
- col.pack_start(cell, True)
- col1.pack_end(cell1, True)
- col.set_attributes(cell, text=0)
- col1.set_attributes(cell1, text=1)
-
- scroll = gtk.ScrolledWindow()
- scroll.set_shadow_type(gtk.SHADOW_IN)
- scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scroll.add(setting_tree)
- vbox.pack_start(scroll, expand=True, fill=True)
-
- # some buttons
- hbox = gtk.HBox(True, 6)
- vbox.pack_start(hbox, False, False)
-
- button = gtk.Button(stock=gtk.STOCK_ADD)
- button.connect("clicked", self.editable_settings_add_item_clicked, setting_store)
- hbox.pack_start(button)
-
- button = gtk.Button(stock=gtk.STOCK_REMOVE)
- button.connect("clicked", self.editable_settings_remove_item_clicked, setting_tree)
- hbox.pack_start(button)
-
- info = HobInfoButton(tooltip, self)
- setting_hbox.pack_start(info, expand=False, fill=False)
-
- return setting_hbox, setting_store
-
- def create_others_page(self):
- advanced_vbox = gtk.VBox(False, 6)
- advanced_vbox.set_border_width(6)
-
- sub_vbox = gtk.VBox(False, 6)
- advanced_vbox.pack_start(sub_vbox, expand=True, fill=True)
- label = self.gen_label_widget("<span weight=\"bold\">Add your own variables:</span>")
- tooltip = "These are key/value pairs for your extra settings. Click \'Add\' and then directly edit the key and the value"
- setting_widget, self.setting_store = self.gen_editable_settings(self.configuration.extra_setting,"<b>Add your own variables</b>" + "*" + tooltip)
- sub_vbox.pack_start(label, expand=False, fill=False)
- sub_vbox.pack_start(setting_widget, expand=True, fill=True)
-
- return advanced_vbox
-
- def create_visual_elements(self):
- self.nb = gtk.Notebook()
- self.nb.set_show_tabs(True)
- self.nb.append_page(self.create_build_environment_page(), gtk.Label("Build environment"))
- self.nb.append_page(self.create_shared_state_page(), gtk.Label("Shared state"))
- self.nb.append_page(self.create_network_page(), gtk.Label("Network"))
- self.nb.append_page(self.create_others_page(), gtk.Label("Others"))
- self.nb.set_current_page(0)
- self.vbox.pack_start(self.nb, expand=True, fill=True)
- self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
-
- self.show_all()
-
- def destroy(self):
- self.handler.disconnect(self.proxy_test_passed_id)
- self.handler.disconnect(self.proxy_test_failed_id)
- super(SimpleSettingsDialog, self).destroy()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
deleted file mode 100644
index b71fb33d3..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobeventhandler.py
+++ /dev/null
@@ -1,645 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gobject
-import logging
-import ast
-from bb.ui.crumbs.runningbuild import RunningBuild
-
-class HobHandler(gobject.GObject):
-
- """
- This object does BitBake event handling for the hob gui.
- """
- __gsignals__ = {
- "package-formats-updated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "config-updated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_PYOBJECT,)),
- "command-succeeded" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_INT,)),
- "command-failed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,)),
- "parsing-warning" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,)),
- "sanity-failed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING, gobject.TYPE_INT)),
- "generating-data" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "data-generated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "parsing-started" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "parsing" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "parsing-completed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_PYOBJECT,)),
- "recipe-populated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "package-populated" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "network-passed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- "network-failed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- }
-
- (GENERATE_CONFIGURATION, GENERATE_RECIPES, GENERATE_PACKAGES, GENERATE_IMAGE, POPULATE_PACKAGEINFO, SANITY_CHECK, NETWORK_TEST) = range(7)
- (SUB_PATH_LAYERS, SUB_FILES_DISTRO, SUB_FILES_MACH, SUB_FILES_SDKMACH, SUB_MATCH_CLASS, SUB_PARSE_CONFIG, SUB_SANITY_CHECK,
- SUB_GNERATE_TGTS, SUB_GENERATE_PKGINFO, SUB_BUILD_RECIPES, SUB_BUILD_IMAGE, SUB_NETWORK_TEST) = range(12)
-
- def __init__(self, server, recipe_model, package_model):
- super(HobHandler, self).__init__()
-
- self.build = RunningBuild(sequential=True)
-
- self.recipe_model = recipe_model
- self.package_model = package_model
-
- self.commands_async = []
- self.generating = False
- self.current_phase = None
- self.building = False
- self.recipe_queue = []
- self.package_queue = []
-
- self.server = server
- self.error_msg = ""
- self.initcmd = None
- self.parsing = False
-
- def set_busy(self):
- if not self.generating:
- self.emit("generating-data")
- self.generating = True
-
- def clear_busy(self):
- if self.generating:
- self.emit("data-generated")
- self.generating = False
-
- def runCommand(self, commandline):
- try:
- result, error = self.server.runCommand(commandline)
- if error:
- raise Exception("Error running command '%s': %s" % (commandline, error))
- return result
- except Exception as e:
- self.commands_async = []
- self.clear_busy()
- self.emit("command-failed", "Hob Exception - %s" % (str(e)))
- return None
-
- def run_next_command(self, initcmd=None):
- if initcmd != None:
- self.initcmd = initcmd
-
- if self.commands_async:
- self.set_busy()
- next_command = self.commands_async.pop(0)
- else:
- self.clear_busy()
- if self.initcmd != None:
- self.emit("command-succeeded", self.initcmd)
- return
-
- if next_command == self.SUB_PATH_LAYERS:
- self.runCommand(["findConfigFilePath", "bblayers.conf"])
- elif next_command == self.SUB_FILES_DISTRO:
- self.runCommand(["findConfigFiles", "DISTRO"])
- elif next_command == self.SUB_FILES_MACH:
- self.runCommand(["findConfigFiles", "MACHINE"])
- elif next_command == self.SUB_FILES_SDKMACH:
- self.runCommand(["findConfigFiles", "MACHINE-SDK"])
- elif next_command == self.SUB_MATCH_CLASS:
- self.runCommand(["findFilesMatchingInDir", "rootfs_", "classes"])
- elif next_command == self.SUB_PARSE_CONFIG:
- self.runCommand(["resetCooker"])
- elif next_command == self.SUB_GNERATE_TGTS:
- self.runCommand(["generateTargetsTree", "classes/image.bbclass", []])
- elif next_command == self.SUB_GENERATE_PKGINFO:
- self.runCommand(["triggerEvent", "bb.event.RequestPackageInfo()"])
- elif next_command == self.SUB_SANITY_CHECK:
- self.runCommand(["triggerEvent", "bb.event.SanityCheck()"])
- elif next_command == self.SUB_NETWORK_TEST:
- self.runCommand(["triggerEvent", "bb.event.NetworkTest()"])
- elif next_command == self.SUB_BUILD_RECIPES:
- self.clear_busy()
- self.building = True
- self.runCommand(["buildTargets", self.recipe_queue, self.default_task])
- self.recipe_queue = []
- elif next_command == self.SUB_BUILD_IMAGE:
- self.clear_busy()
- self.building = True
- target = self.image
-
- if self.base_image:
- # Request the build of a custom image
- self.generate_hob_base_image(target)
- self.set_var_in_file("LINGUAS_INSTALL", "", "local.conf")
- hobImage = self.runCommand(["matchFile", target + ".bb"])
- if self.base_image != self.recipe_model.__custom_image__:
- baseImage = self.runCommand(["matchFile", self.base_image + ".bb"])
- version = self.runCommand(["generateNewImage", hobImage, baseImage, self.package_queue, True, ""])
- target += version
- self.recipe_model.set_custom_image_version(version)
-
- targets = [target]
- if self.toolchain_packages:
- self.set_var_in_file("TOOLCHAIN_TARGET_TASK", " ".join(self.toolchain_packages), "local.conf")
- targets.append(target + ":do_populate_sdk")
-
- self.runCommand(["buildTargets", targets, self.default_task])
-
- def display_error(self):
- self.clear_busy()
- self.emit("command-failed", self.error_msg)
- self.error_msg = ""
- if self.building:
- self.building = False
-
- def handle_event(self, event):
- if not event:
- return
- if self.building:
- self.current_phase = "building"
- self.build.handle_event(event)
-
- if isinstance(event, bb.event.PackageInfo):
- self.package_model.populate(event._pkginfolist)
- self.emit("package-populated")
- self.run_next_command()
-
- elif isinstance(event, bb.event.SanityCheckPassed):
- reparse = self.runCommand(["getVariable", "BB_INVALIDCONF"]) or None
- if reparse is True:
- self.set_var_in_file("BB_INVALIDCONF", False, "local.conf")
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.prepend(self.SUB_PARSE_CONFIG)
- self.run_next_command()
-
- elif isinstance(event, bb.event.SanityCheckFailed):
- self.emit("sanity-failed", event._msg, event._network_error)
-
- elif isinstance(event, logging.LogRecord):
- if not self.building:
- if event.levelno >= logging.ERROR:
- formatter = bb.msg.BBLogFormatter()
- msg = formatter.format(event)
- self.error_msg += msg + '\n'
- elif event.levelno >= logging.WARNING and self.parsing == True:
- formatter = bb.msg.BBLogFormatter()
- msg = formatter.format(event)
- warn_msg = msg + '\n'
- self.emit("parsing-warning", warn_msg)
-
- elif isinstance(event, bb.event.TargetsTreeGenerated):
- self.current_phase = "data generation"
- if event._model:
- self.recipe_model.populate(event._model)
- self.emit("recipe-populated")
- elif isinstance(event, bb.event.ConfigFilesFound):
- self.current_phase = "configuration lookup"
- var = event._variable
- values = event._values
- values.sort()
- self.emit("config-updated", var, values)
- elif isinstance(event, bb.event.ConfigFilePathFound):
- self.current_phase = "configuration lookup"
- elif isinstance(event, bb.event.FilesMatchingFound):
- self.current_phase = "configuration lookup"
- # FIXME: hard coding, should at least be a variable shared between
- # here and the caller
- if event._pattern == "rootfs_":
- formats = []
- for match in event._matches:
- classname, sep, cls = match.rpartition(".")
- fs, sep, format = classname.rpartition("_")
- formats.append(format)
- formats.sort()
- self.emit("package-formats-updated", formats)
- elif isinstance(event, bb.command.CommandCompleted):
- self.current_phase = None
- self.run_next_command()
- elif isinstance(event, bb.command.CommandFailed):
- if event.error not in ("Forced shutdown", "Stopped build"):
- self.error_msg += event.error
- self.commands_async = []
- self.display_error()
- elif isinstance(event, (bb.event.ParseStarted,
- bb.event.CacheLoadStarted,
- bb.event.TreeDataPreparationStarted,
- )):
- message = {}
- message["eventname"] = bb.event.getName(event)
- message["current"] = 0
- message["total"] = None
- message["title"] = "Parsing recipes"
- self.emit("parsing-started", message)
- if isinstance(event, bb.event.ParseStarted):
- self.parsing = True
- elif isinstance(event, (bb.event.ParseProgress,
- bb.event.CacheLoadProgress,
- bb.event.TreeDataPreparationProgress)):
- message = {}
- message["eventname"] = bb.event.getName(event)
- message["current"] = event.current
- message["total"] = event.total
- message["title"] = "Parsing recipes"
- self.emit("parsing", message)
- elif isinstance(event, (bb.event.ParseCompleted,
- bb.event.CacheLoadCompleted,
- bb.event.TreeDataPreparationCompleted)):
- message = {}
- message["eventname"] = bb.event.getName(event)
- message["current"] = event.total
- message["total"] = event.total
- message["title"] = "Parsing recipes"
- self.emit("parsing-completed", message)
- if isinstance(event, bb.event.ParseCompleted):
- self.parsing = False
- elif isinstance(event, bb.event.NetworkTestFailed):
- self.emit("network-failed")
- self.run_next_command()
- elif isinstance(event, bb.event.NetworkTestPassed):
- self.emit("network-passed")
- self.run_next_command()
-
- if self.error_msg and not self.commands_async:
- self.display_error()
-
- return
-
- def init_cooker(self):
- self.runCommand(["createConfigFile", ".hob.conf"])
-
- def set_extra_inherit(self, bbclass):
- self.append_var_in_file("INHERIT", bbclass, ".hob.conf")
-
- def set_bblayers(self, bblayers):
- self.set_var_in_file("BBLAYERS", " ".join(bblayers), "bblayers.conf")
-
- def set_machine(self, machine):
- if machine:
- self.early_assign_var_in_file("MACHINE", machine, "local.conf")
-
- def set_sdk_machine(self, sdk_machine):
- self.set_var_in_file("SDKMACHINE", sdk_machine, "local.conf")
-
- def set_image_fstypes(self, image_fstypes):
- self.set_var_in_file("IMAGE_FSTYPES", image_fstypes, "local.conf")
-
- def set_distro(self, distro):
- self.set_var_in_file("DISTRO", distro, "local.conf")
-
- def set_package_format(self, format):
- package_classes = ""
- for pkgfmt in format.split():
- package_classes += ("package_%s" % pkgfmt + " ")
- self.set_var_in_file("PACKAGE_CLASSES", package_classes, "local.conf")
-
- def set_bbthreads(self, threads):
- self.set_var_in_file("BB_NUMBER_THREADS", threads, "local.conf")
-
- def set_pmake(self, threads):
- pmake = "-j %s" % threads
- self.set_var_in_file("PARALLEL_MAKE", pmake, "local.conf")
-
- def set_dl_dir(self, directory):
- self.set_var_in_file("DL_DIR", directory, "local.conf")
-
- def set_sstate_dir(self, directory):
- self.set_var_in_file("SSTATE_DIR", directory, "local.conf")
-
- def set_sstate_mirrors(self, url):
- self.set_var_in_file("SSTATE_MIRRORS", url, "local.conf")
-
- def set_extra_size(self, image_extra_size):
- self.set_var_in_file("IMAGE_ROOTFS_EXTRA_SPACE", str(image_extra_size), "local.conf")
-
- def set_rootfs_size(self, image_rootfs_size):
- self.set_var_in_file("IMAGE_ROOTFS_SIZE", str(image_rootfs_size), "local.conf")
-
- def set_incompatible_license(self, incompat_license):
- self.set_var_in_file("INCOMPATIBLE_LICENSE", incompat_license, "local.conf")
-
- def set_extra_setting(self, extra_setting):
- self.set_var_in_file("EXTRA_SETTING", extra_setting, "local.conf")
-
- def set_extra_config(self, extra_setting):
- old_extra_setting = self.runCommand(["getVariable", "EXTRA_SETTING"]) or {}
- old_extra_setting = str(old_extra_setting)
-
- old_extra_setting = ast.literal_eval(old_extra_setting)
- if not type(old_extra_setting) == dict:
- old_extra_setting = {}
-
- # settings not changed
- if old_extra_setting == extra_setting:
- return
-
- # remove the old EXTRA SETTING variable
- self.remove_var_from_file("EXTRA_SETTING")
-
- # remove old settings from conf
- for key in old_extra_setting.keys():
- if key not in extra_setting:
- self.remove_var_from_file(key)
-
- # add new settings
- for key, value in extra_setting.iteritems():
- self.set_var_in_file(key, value, "local.conf")
-
- if extra_setting:
- self.set_var_in_file("EXTRA_SETTING", extra_setting, "local.conf")
-
- def set_http_proxy(self, http_proxy):
- self.set_var_in_file("http_proxy", http_proxy, "local.conf")
-
- def set_https_proxy(self, https_proxy):
- self.set_var_in_file("https_proxy", https_proxy, "local.conf")
-
- def set_ftp_proxy(self, ftp_proxy):
- self.set_var_in_file("ftp_proxy", ftp_proxy, "local.conf")
-
- def set_socks_proxy(self, socks_proxy):
- self.set_var_in_file("all_proxy", socks_proxy, "local.conf")
-
- def set_cvs_proxy(self, host, port):
- self.set_var_in_file("CVS_PROXY_HOST", host, "local.conf")
- self.set_var_in_file("CVS_PROXY_PORT", port, "local.conf")
-
- def request_package_info(self):
- self.commands_async.append(self.SUB_GENERATE_PKGINFO)
- self.run_next_command(self.POPULATE_PACKAGEINFO)
-
- def trigger_sanity_check(self):
- self.commands_async.append(self.SUB_SANITY_CHECK)
- self.run_next_command(self.SANITY_CHECK)
-
- def trigger_network_test(self):
- self.commands_async.append(self.SUB_NETWORK_TEST)
- self.run_next_command(self.NETWORK_TEST)
-
- def generate_configuration(self):
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_PATH_LAYERS)
- self.commands_async.append(self.SUB_FILES_DISTRO)
- self.commands_async.append(self.SUB_FILES_MACH)
- self.commands_async.append(self.SUB_FILES_SDKMACH)
- self.commands_async.append(self.SUB_MATCH_CLASS)
- self.run_next_command(self.GENERATE_CONFIGURATION)
-
- def generate_recipes(self):
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_GNERATE_TGTS)
- self.run_next_command(self.GENERATE_RECIPES)
-
- def generate_packages(self, tgts, default_task="build"):
- targets = []
- targets.extend(tgts)
- self.recipe_queue = targets
- self.default_task = default_task
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_BUILD_RECIPES)
- self.run_next_command(self.GENERATE_PACKAGES)
-
- def generate_image(self, image, base_image, image_packages=None, toolchain_packages=None, default_task="build"):
- self.image = image
- self.base_image = base_image
- if image_packages:
- self.package_queue = image_packages
- else:
- self.package_queue = []
- if toolchain_packages:
- self.toolchain_packages = toolchain_packages
- else:
- self.toolchain_packages = []
- self.default_task = default_task
- self.runCommand(["setPrePostConfFiles", "conf/.hob.conf", ""])
- self.commands_async.append(self.SUB_PARSE_CONFIG)
- self.commands_async.append(self.SUB_BUILD_IMAGE)
- self.run_next_command(self.GENERATE_IMAGE)
-
- def generate_new_image(self, image, base_image, package_queue, description):
- if base_image:
- base_image = self.runCommand(["matchFile", self.base_image + ".bb"])
- self.runCommand(["generateNewImage", image, base_image, package_queue, False, description])
-
- def generate_hob_base_image(self, hob_image):
- image_dir = self.get_topdir() + "/recipes/images/"
- recipe_name = hob_image + ".bb"
- self.ensure_dir(image_dir)
- self.generate_new_image(image_dir + recipe_name, None, [], "")
-
- def ensure_dir(self, directory):
- self.runCommand(["ensureDir", directory])
-
- def build_succeeded_async(self):
- self.building = False
-
- def build_failed_async(self):
- self.initcmd = None
- self.commands_async = []
- self.building = False
-
- def cancel_parse(self):
- self.runCommand(["stateForceShutdown"])
-
- def cancel_build(self, force=False):
- if force:
- # Force the cooker to stop as quickly as possible
- self.runCommand(["stateForceShutdown"])
- else:
- # Wait for tasks to complete before shutting down, this helps
- # leave the workdir in a usable state
- self.runCommand(["stateShutdown"])
-
- def reset_build(self):
- self.build.reset()
-
- def get_logfile(self):
- return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])[0]
-
- def get_topdir(self):
- return self.runCommand(["getVariable", "TOPDIR"]) or ""
-
- def _remove_redundant(self, string):
- ret = []
- for i in string.split():
- if i not in ret:
- ret.append(i)
- return " ".join(ret)
-
- def set_var_in_file(self, var, val, default_file=None):
- self.runCommand(["enableDataTracking"])
- self.server.runCommand(["setVarFile", var, val, default_file, "set"])
- self.runCommand(["disableDataTracking"])
-
- def early_assign_var_in_file(self, var, val, default_file=None):
- self.runCommand(["enableDataTracking"])
- self.server.runCommand(["setVarFile", var, val, default_file, "earlyAssign"])
- self.runCommand(["disableDataTracking"])
-
- def remove_var_from_file(self, var):
- self.server.runCommand(["removeVarFile", var])
-
- def append_var_in_file(self, var, val, default_file=None):
- self.server.runCommand(["setVarFile", var, val, default_file, "append"])
-
- def append_to_bbfiles(self, val):
- bbfiles = self.runCommand(["getVariable", "BBFILES", "False"]) or ""
- bbfiles = bbfiles.split()
- if val not in bbfiles:
- self.append_var_in_file("BBFILES", val, "bblayers.conf")
-
- def get_parameters(self):
- # retrieve the parameters from bitbake
- params = {}
- params["core_base"] = self.runCommand(["getVariable", "COREBASE"]) or ""
- params["layer"] = self.runCommand(["getVariable", "BBLAYERS"]) or ""
- params["layers_non_removable"] = self.runCommand(["getVariable", "BBLAYERS_NON_REMOVABLE"]) or ""
- params["dldir"] = self.runCommand(["getVariable", "DL_DIR"]) or ""
- params["machine"] = self.runCommand(["getVariable", "MACHINE"]) or ""
- params["distro"] = self.runCommand(["getVariable", "DISTRO"]) or "defaultsetup"
- params["pclass"] = self.runCommand(["getVariable", "PACKAGE_CLASSES"]) or ""
- params["sstatedir"] = self.runCommand(["getVariable", "SSTATE_DIR"]) or ""
- params["sstatemirror"] = self.runCommand(["getVariable", "SSTATE_MIRRORS"]) or ""
-
- num_threads = self.runCommand(["getCpuCount"])
- if not num_threads:
- num_threads = 1
- max_threads = 65536
- else:
- try:
- num_threads = int(num_threads)
- max_threads = 16 * num_threads
- except:
- num_threads = 1
- max_threads = 65536
- params["max_threads"] = max_threads
-
- bbthread = self.runCommand(["getVariable", "BB_NUMBER_THREADS"])
- if not bbthread:
- bbthread = num_threads
- else:
- try:
- bbthread = int(bbthread)
- except:
- bbthread = num_threads
- params["bbthread"] = bbthread
-
- pmake = self.runCommand(["getVariable", "PARALLEL_MAKE"])
- if not pmake:
- pmake = num_threads
- elif isinstance(pmake, int):
- pass
- else:
- try:
- pmake = int(pmake.lstrip("-j "))
- except:
- pmake = num_threads
- params["pmake"] = "-j %s" % pmake
-
- params["image_addr"] = self.runCommand(["getVariable", "DEPLOY_DIR_IMAGE"]) or ""
-
- image_extra_size = self.runCommand(["getVariable", "IMAGE_ROOTFS_EXTRA_SPACE"])
- if not image_extra_size:
- image_extra_size = 0
- else:
- try:
- image_extra_size = int(image_extra_size)
- except:
- image_extra_size = 0
- params["image_extra_size"] = image_extra_size
-
- image_rootfs_size = self.runCommand(["getVariable", "IMAGE_ROOTFS_SIZE"])
- if not image_rootfs_size:
- image_rootfs_size = 0
- else:
- try:
- image_rootfs_size = int(image_rootfs_size)
- except:
- image_rootfs_size = 0
- params["image_rootfs_size"] = image_rootfs_size
-
- image_overhead_factor = self.runCommand(["getVariable", "IMAGE_OVERHEAD_FACTOR"])
- if not image_overhead_factor:
- image_overhead_factor = 1
- else:
- try:
- image_overhead_factor = float(image_overhead_factor)
- except:
- image_overhead_factor = 1
- params['image_overhead_factor'] = image_overhead_factor
-
- params["incompat_license"] = self._remove_redundant(self.runCommand(["getVariable", "INCOMPATIBLE_LICENSE"]) or "")
- params["sdk_machine"] = self.runCommand(["getVariable", "SDKMACHINE"]) or self.runCommand(["getVariable", "SDK_ARCH"]) or ""
-
- params["image_fstypes"] = self._remove_redundant(self.runCommand(["getVariable", "IMAGE_FSTYPES"]) or "")
-
- params["image_types"] = self._remove_redundant(self.runCommand(["getVariable", "IMAGE_TYPES"]) or "")
-
- params["conf_version"] = self.runCommand(["getVariable", "CONF_VERSION"]) or ""
- params["lconf_version"] = self.runCommand(["getVariable", "LCONF_VERSION"]) or ""
-
- params["runnable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_IMAGE_TYPES"]) or "")
- params["runnable_machine_patterns"] = self._remove_redundant(self.runCommand(["getVariable", "RUNNABLE_MACHINE_PATTERNS"]) or "")
- params["deployable_image_types"] = self._remove_redundant(self.runCommand(["getVariable", "DEPLOYABLE_IMAGE_TYPES"]) or "")
- params["kernel_image_type"] = self.runCommand(["getVariable", "KERNEL_IMAGETYPE"]) or ""
- params["tmpdir"] = self.runCommand(["getVariable", "TMPDIR"]) or ""
- params["distro_version"] = self.runCommand(["getVariable", "DISTRO_VERSION"]) or ""
- params["target_os"] = self.runCommand(["getVariable", "TARGET_OS"]) or ""
- params["target_arch"] = self.runCommand(["getVariable", "TARGET_ARCH"]) or ""
- params["tune_pkgarch"] = self.runCommand(["getVariable", "TUNE_PKGARCH"]) or ""
- params["bb_version"] = self.runCommand(["getVariable", "BB_MIN_VERSION"]) or ""
-
- params["default_task"] = self.runCommand(["getVariable", "BB_DEFAULT_TASK"]) or "build"
-
- params["socks_proxy"] = self.runCommand(["getVariable", "all_proxy"]) or ""
- params["http_proxy"] = self.runCommand(["getVariable", "http_proxy"]) or ""
- params["ftp_proxy"] = self.runCommand(["getVariable", "ftp_proxy"]) or ""
- params["https_proxy"] = self.runCommand(["getVariable", "https_proxy"]) or ""
-
- params["cvs_proxy_host"] = self.runCommand(["getVariable", "CVS_PROXY_HOST"]) or ""
- params["cvs_proxy_port"] = self.runCommand(["getVariable", "CVS_PROXY_PORT"]) or ""
-
- params["image_white_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_WHITE_PATTERN"]) or ""
- params["image_black_pattern"] = self.runCommand(["getVariable", "BBUI_IMAGE_BLACK_PATTERN"]) or ""
- return params
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
deleted file mode 100644
index 50df156f4..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hoblistmodel.py
+++ /dev/null
@@ -1,903 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import gobject
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# PackageListModel
-#
-class PackageListModel(gtk.ListStore):
- """
- This class defines an gtk.ListStore subclass which will convert the output
- of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
- providing convenience functions to access gtk.TreeModel subclasses which
- provide filtered views of the data.
- """
-
- (COL_NAME, COL_VER, COL_REV, COL_RNM, COL_SEC, COL_SUM, COL_RDEP, COL_RPROV, COL_SIZE, COL_RCP, COL_BINB, COL_INC, COL_FADE_INC, COL_FONT, COL_FLIST) = range(15)
-
- __gsignals__ = {
- "package-selection-changed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- }
-
- __toolchain_required_packages__ = ["packagegroup-core-standalone-sdk-target", "packagegroup-core-standalone-sdk-target-dbg"]
-
- def __init__(self):
- self.rprov_pkg = {}
- gtk.ListStore.__init__ (self,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING)
- self.sort_column_id, self.sort_order = PackageListModel.COL_NAME, gtk.SORT_ASCENDING
-
- """
- Find the model path for the item_name
- Returns the path in the model or None
- """
- def find_path_for_item(self, item_name):
- pkg = item_name
- if item_name not in self.pn_path.keys():
- if item_name not in self.rprov_pkg.keys():
- return None
- pkg = self.rprov_pkg[item_name]
- if pkg not in self.pn_path.keys():
- return None
-
- return self.pn_path[pkg]
-
- def find_item_for_path(self, item_path):
- return self[item_path][self.COL_NAME]
-
- """
- Helper function to determine whether an item is an item specified by filter
- """
- def tree_model_filter(self, model, it, filter):
- name = model.get_value(it, self.COL_NAME)
-
- for key in filter.keys():
- if key == self.COL_NAME:
- if filter[key] != 'Search packages by name':
- if name and filter[key] not in name:
- return False
- else:
- if model.get_value(it, key) not in filter[key]:
- return False
- self.filtered_nb += 1
- return True
-
- """
- Create, if required, and return a filtered gtk.TreeModelSort
- containing only the items specified by filter
- """
- def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=False, search_data=None, initial=False):
- model = self.filter_new()
- self.filtered_nb = 0
- model.set_visible_func(self.tree_model_filter, filter)
-
- sort = gtk.TreeModelSort(model)
- sort.connect ('sort-column-changed', self.sort_column_changed_cb)
- if initial:
- sort.set_sort_column_id(PackageListModel.COL_NAME, gtk.SORT_ASCENDING)
- sort.set_default_sort_func(None)
- elif excluded_items_ahead:
- sort.set_default_sort_func(self.exclude_item_sort_func, search_data)
- elif included_items_ahead:
- sort.set_default_sort_func(self.include_item_sort_func, search_data)
- else:
- if search_data and search_data!='Search recipes by name' and search_data!='Search package groups by name':
- sort.set_default_sort_func(self.sort_func, search_data)
- else:
- sort.set_sort_column_id(self.sort_column_id, self.sort_order)
- sort.set_default_sort_func(None)
-
- sort.set_sort_func(PackageListModel.COL_INC, self.sort_column, PackageListModel.COL_INC)
- sort.set_sort_func(PackageListModel.COL_SIZE, self.sort_column, PackageListModel.COL_SIZE)
- sort.set_sort_func(PackageListModel.COL_BINB, self.sort_binb_column)
- sort.set_sort_func(PackageListModel.COL_RCP, self.sort_column, PackageListModel.COL_RCP)
- return sort
-
- def sort_column_changed_cb (self, data):
- self.sort_column_id, self.sort_order = data.get_sort_column_id ()
-
- def sort_column(self, model, row1, row2, col):
- value1 = model.get_value(row1, col)
- value2 = model.get_value(row2, col)
- if col==PackageListModel.COL_SIZE:
- value1 = HobPage._string_to_size(value1)
- value2 = HobPage._string_to_size(value2)
-
- cmp_res = cmp(value1, value2)
- if cmp_res!=0:
- if col==PackageListModel.COL_INC:
- return -cmp_res
- else:
- return cmp_res
- else:
- name1 = model.get_value(row1, PackageListModel.COL_NAME)
- name2 = model.get_value(row2, PackageListModel.COL_NAME)
- return cmp(name1,name2)
-
- def sort_binb_column(self, model, row1, row2):
- value1 = model.get_value(row1, PackageListModel.COL_BINB)
- value2 = model.get_value(row2, PackageListModel.COL_BINB)
- value1_list = value1.split(', ')
- value2_list = value2.split(', ')
-
- value1 = value1_list[0]
- value2 = value2_list[0]
-
- cmp_res = cmp(value1, value2)
- if cmp_res==0:
- cmp_size = cmp(len(value1_list), len(value2_list))
- if cmp_size==0:
- name1 = model.get_value(row1, PackageListModel.COL_NAME)
- name2 = model.get_value(row2, PackageListModel.COL_NAME)
- return cmp(name1,name2)
- else:
- return cmp_size
- else:
- return cmp_res
-
- def exclude_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, PackageListModel.COL_NAME)
- val2 = model.get_value(iter2, PackageListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, PackageListModel.COL_FADE_INC)
- val2 = model.get_value(iter2, PackageListModel.COL_INC)
- return ((val1 == True) and (val2 == False))
-
- def include_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, PackageListModel.COL_NAME)
- val2 = model.get_value(iter2, PackageListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, PackageListModel.COL_INC)
- val2 = model.get_value(iter2, PackageListModel.COL_INC)
- return ((val1 == False) and (val2 == True))
-
- def sort_func(self, model, iter1, iter2, user_data):
- val1 = model.get_value(iter1, PackageListModel.COL_NAME)
- val2 = model.get_value(iter2, PackageListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
-
- def cmp_vals(self, val1, val2, user_data):
- if val1 is None or val2 is None:
- return 0
- elif val1.startswith(user_data) and not val2.startswith(user_data):
- return -1
- elif not val1.startswith(user_data) and val2.startswith(user_data):
- return 1
- else:
- return cmp(val1, val2)
-
- def convert_vpath_to_path(self, view_model, view_path):
- # view_model is the model sorted
- # get the path of the model filtered
- filtered_model_path = view_model.convert_path_to_child_path(view_path)
- # get the model filtered
- filtered_model = view_model.get_model()
- # get the path of the original model
- path = filtered_model.convert_path_to_child_path(filtered_model_path)
- return path
-
- def convert_path_to_vpath(self, view_model, path):
- it = view_model.get_iter_first()
- while it:
- name = self.find_item_for_path(path)
- view_name = view_model.get_value(it, PackageListModel.COL_NAME)
- if view_name == name:
- view_path = view_model.get_path(it)
- return view_path
- it = view_model.iter_next(it)
- return None
-
- """
- The populate() function takes as input the data from a
- bb.event.PackageInfo event and populates the package list.
- """
- def populate(self, pkginfolist):
- # First clear the model, in case repopulating
- self.clear()
-
- def getpkgvalue(pkgdict, key, pkgname, defaultval = None):
- value = pkgdict.get('%s_%s' % (key, pkgname), None)
- if not value:
- value = pkgdict.get(key, defaultval)
- return value
-
- for pkginfo in pkginfolist:
- pn = pkginfo['PN']
- pv = pkginfo['PV']
- pr = pkginfo['PR']
- pkg = pkginfo['PKG']
- pkgv = getpkgvalue(pkginfo, 'PKGV', pkg)
- pkgr = getpkgvalue(pkginfo, 'PKGR', pkg)
- # PKGSIZE is artificial, will always be overridden with the package name if present
- pkgsize = int(pkginfo.get('PKGSIZE_%s' % pkg, "0"))
- # PKG_%s is the renamed version
- pkg_rename = pkginfo.get('PKG_%s' % pkg, "")
- # The rest may be overridden or not
- section = getpkgvalue(pkginfo, 'SECTION', pkg, "")
- summary = getpkgvalue(pkginfo, 'SUMMARY', pkg, "")
- rdep = getpkgvalue(pkginfo, 'RDEPENDS', pkg, "")
- rrec = getpkgvalue(pkginfo, 'RRECOMMENDS', pkg, "")
- rprov = getpkgvalue(pkginfo, 'RPROVIDES', pkg, "")
- files_list = getpkgvalue(pkginfo, 'FILES_INFO', pkg, "")
- for i in rprov.split():
- self.rprov_pkg[i] = pkg
-
- recipe = pn + '-' + pv + '-' + pr
-
- allow_empty = getpkgvalue(pkginfo, 'ALLOW_EMPTY', pkg, "")
-
- if pkgsize == 0 and not allow_empty:
- continue
-
- size = HobPage._size_to_string(pkgsize)
- self.set(self.append(), self.COL_NAME, pkg, self.COL_VER, pkgv,
- self.COL_REV, pkgr, self.COL_RNM, pkg_rename,
- self.COL_SEC, section, self.COL_SUM, summary,
- self.COL_RDEP, rdep + ' ' + rrec,
- self.COL_RPROV, rprov, self.COL_SIZE, size,
- self.COL_RCP, recipe, self.COL_BINB, "",
- self.COL_INC, False, self.COL_FONT, '10', self.COL_FLIST, files_list)
-
- self.pn_path = {}
- it = self.get_iter_first()
- while it:
- pn = self.get_value(it, self.COL_NAME)
- path = self.get_path(it)
- self.pn_path[pn] = path
- it = self.iter_next(it)
-
- """
- Update the model, send out the notification.
- """
- def selection_change_notification(self):
- self.emit("package-selection-changed")
-
- """
- Check whether the item at item_path is included or not
- """
- def path_included(self, item_path):
- return self[item_path][self.COL_INC]
-
- """
- Add this item, and any of its dependencies, to the image contents
- """
- def include_item(self, item_path, binb=""):
- if self.path_included(item_path):
- return
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_RDEP]
-
- self[item_path][self.COL_INC] = True
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if binb and not binb in item_bin:
- item_bin.append(binb)
- self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
-
- if item_deps:
- # Ensure all of the items deps are included and, where appropriate,
- # add this item to their COL_BINB
- for dep in item_deps.split(" "):
- if dep.startswith('('):
- continue
- # If the contents model doesn't already contain dep, add it
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_included = self.path_included(dep_path)
-
- if dep_included and not dep in item_bin:
- # don't set the COL_BINB to this item if the target is an
- # item in our own COL_BINB
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if not item_name in dep_bin:
- dep_bin.append(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
- elif not dep_included:
- self.include_item(dep_path, binb=item_name)
-
- def exclude_item(self, item_path):
- if not self.path_included(item_path):
- return
-
- self[item_path][self.COL_INC] = False
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_RDEP]
- if item_deps:
- for dep in item_deps.split(" "):
- if dep.startswith('('):
- continue
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if item_name in dep_bin:
- dep_bin.remove(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if item_bin:
- for binb in item_bin:
- binb_path = self.find_path_for_item(binb)
- if not binb_path:
- continue
- self.exclude_item(binb_path)
-
- """
- Empty self.contents by setting the include of each entry to None
- """
- def reset(self):
- it = self.get_iter_first()
- while it:
- self.set(it,
- self.COL_INC, False,
- self.COL_BINB, "")
- it = self.iter_next(it)
-
- self.selection_change_notification()
-
- def get_selected_packages(self):
- packagelist = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_NAME)
- packagelist.append(name)
- it = self.iter_next(it)
-
- return packagelist
-
- def get_user_selected_packages(self):
- packagelist = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- binb = self.get_value(it, self.COL_BINB)
- if binb == "User Selected":
- name = self.get_value(it, self.COL_NAME)
- packagelist.append(name)
- it = self.iter_next(it)
-
- return packagelist
-
- def get_selected_packages_toolchain(self):
- packagelist = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_NAME)
- if name.endswith("-dev") or name.endswith("-dbg"):
- packagelist.append(name)
- it = self.iter_next(it)
-
- return list(set(packagelist + self.__toolchain_required_packages__));
-
- """
- Package model may be incomplete, therefore when calling the
- set_selected_packages(), some packages will not be set included.
- Return the un-set packages list.
- """
- def set_selected_packages(self, packagelist, user_selected=False):
- left = []
- binb = 'User Selected' if user_selected else ''
- for pn in packagelist:
- if pn in self.pn_path.keys():
- path = self.pn_path[pn]
- self.include_item(item_path=path, binb=binb)
- else:
- left.append(pn)
-
- self.selection_change_notification()
- return left
-
- """
- Return the selected package size, unit is B.
- """
- def get_packages_size(self):
- packages_size = 0
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- str_size = self.get_value(it, self.COL_SIZE)
- if not str_size:
- continue
-
- packages_size += HobPage._string_to_size(str_size)
-
- it = self.iter_next(it)
- return packages_size
-
- """
- Resync the state of included items to a backup column before performing the fadeout visible effect
- """
- def resync_fadeout_column(self, model_first_iter=None):
- it = model_first_iter
- while it:
- active = self.get_value(it, self.COL_INC)
- self.set(it, self.COL_FADE_INC, active)
- it = self.iter_next(it)
-
-#
-# RecipeListModel
-#
-class RecipeListModel(gtk.ListStore):
- """
- This class defines an gtk.ListStore subclass which will convert the output
- of the bb.event.TargetsTreeGenerated event into a gtk.ListStore whilst also
- providing convenience functions to access gtk.TreeModel subclasses which
- provide filtered views of the data.
- """
- (COL_NAME, COL_DESC, COL_LIC, COL_GROUP, COL_DEPS, COL_BINB, COL_TYPE, COL_INC, COL_IMG, COL_INSTALL, COL_PN, COL_FADE_INC, COL_SUMMARY, COL_VERSION,
- COL_REVISION, COL_HOMEPAGE, COL_BUGTRACKER, COL_FILE) = range(18)
-
- __custom_image__ = "Start with an empty image recipe"
-
- __gsignals__ = {
- "recipe-selection-changed" : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- }
-
- """
- """
- def __init__(self):
- gtk.ListStore.__init__ (self,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_BOOLEAN,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING,
- gobject.TYPE_STRING)
- self.sort_column_id, self.sort_order = RecipeListModel.COL_NAME, gtk.SORT_ASCENDING
-
- """
- Find the model path for the item_name
- Returns the path in the model or None
- """
- def find_path_for_item(self, item_name):
- if self.non_target_name(item_name) or item_name not in self.pn_path.keys():
- return None
- else:
- return self.pn_path[item_name]
-
- def find_item_for_path(self, item_path):
- return self[item_path][self.COL_NAME]
-
- """
- Helper method to determine whether name is a target pn
- """
- def non_target_name(self, name):
- if name and ('-native' in name):
- return True
- return False
-
- """
- Helper function to determine whether an item is an item specified by filter
- """
- def tree_model_filter(self, model, it, filter):
- name = model.get_value(it, self.COL_NAME)
- if self.non_target_name(name):
- return False
-
- for key in filter.keys():
- if key == self.COL_NAME:
- if filter[key] != 'Search recipes by name' and filter[key] != 'Search package groups by name':
- if filter[key] not in name:
- return False
- else:
- if model.get_value(it, key) not in filter[key]:
- return False
- self.filtered_nb += 1
-
- return True
-
- def exclude_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
- val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, RecipeListModel.COL_FADE_INC)
- val2 = model.get_value(iter2, RecipeListModel.COL_INC)
- return ((val1 == True) and (val2 == False))
-
- def include_item_sort_func(self, model, iter1, iter2, user_data=None):
- if user_data:
- val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
- val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
- else:
- val1 = model.get_value(iter1, RecipeListModel.COL_INC)
- val2 = model.get_value(iter2, RecipeListModel.COL_INC)
- return ((val1 == False) and (val2 == True))
-
- def sort_func(self, model, iter1, iter2, user_data):
- val1 = model.get_value(iter1, RecipeListModel.COL_NAME)
- val2 = model.get_value(iter2, RecipeListModel.COL_NAME)
- return self.cmp_vals(val1, val2, user_data)
-
- def cmp_vals(self, val1, val2, user_data):
- if val1 is None or val2 is None:
- return 0
- elif val1.startswith(user_data) and not val2.startswith(user_data):
- return -1
- elif not val1.startswith(user_data) and val2.startswith(user_data):
- return 1
- else:
- return cmp(val1, val2)
-
- """
- Create, if required, and return a filtered gtk.TreeModelSort
- containing only the items specified by filter
- """
- def tree_model(self, filter, excluded_items_ahead=False, included_items_ahead=False, search_data=None, initial=False):
- model = self.filter_new()
- self.filtered_nb = 0
- model.set_visible_func(self.tree_model_filter, filter)
-
- sort = gtk.TreeModelSort(model)
- sort.connect ('sort-column-changed', self.sort_column_changed_cb)
- if initial:
- sort.set_sort_column_id(RecipeListModel.COL_NAME, gtk.SORT_ASCENDING)
- sort.set_default_sort_func(None)
- elif excluded_items_ahead:
- sort.set_default_sort_func(self.exclude_item_sort_func, search_data)
- elif included_items_ahead:
- sort.set_default_sort_func(self.include_item_sort_func, search_data)
- else:
- if search_data and search_data!='Search recipes by name' and search_data!='Search package groups by name':
- sort.set_default_sort_func(self.sort_func, search_data)
- else:
- sort.set_sort_column_id(self.sort_column_id, self.sort_order)
- sort.set_default_sort_func(None)
-
- sort.set_sort_func(RecipeListModel.COL_INC, self.sort_column, RecipeListModel.COL_INC)
- sort.set_sort_func(RecipeListModel.COL_GROUP, self.sort_column, RecipeListModel.COL_GROUP)
- sort.set_sort_func(RecipeListModel.COL_BINB, self.sort_binb_column)
- sort.set_sort_func(RecipeListModel.COL_LIC, self.sort_column, RecipeListModel.COL_LIC)
- return sort
-
- def sort_column_changed_cb (self, data):
- self.sort_column_id, self.sort_order = data.get_sort_column_id ()
-
- def sort_column(self, model, row1, row2, col):
- value1 = model.get_value(row1, col)
- value2 = model.get_value(row2, col)
- cmp_res = cmp(value1, value2)
- if cmp_res!=0:
- if col==RecipeListModel.COL_INC:
- return -cmp_res
- else:
- return cmp_res
- else:
- name1 = model.get_value(row1, RecipeListModel.COL_NAME)
- name2 = model.get_value(row2, RecipeListModel.COL_NAME)
- return cmp(name1,name2)
-
- def sort_binb_column(self, model, row1, row2):
- value1 = model.get_value(row1, RecipeListModel.COL_BINB)
- value2 = model.get_value(row2, RecipeListModel.COL_BINB)
- value1_list = value1.split(', ')
- value2_list = value2.split(', ')
-
- value1 = value1_list[0]
- value2 = value2_list[0]
-
- cmp_res = cmp(value1, value2)
- if cmp_res==0:
- cmp_size = cmp(len(value1_list), len(value2_list))
- if cmp_size==0:
- name1 = model.get_value(row1, RecipeListModel.COL_NAME)
- name2 = model.get_value(row2, RecipeListModel.COL_NAME)
- return cmp(name1,name2)
- else:
- return cmp_size
- else:
- return cmp_res
-
- def convert_vpath_to_path(self, view_model, view_path):
- filtered_model_path = view_model.convert_path_to_child_path(view_path)
- filtered_model = view_model.get_model()
-
- # get the path of the original model
- path = filtered_model.convert_path_to_child_path(filtered_model_path)
- return path
-
- def convert_path_to_vpath(self, view_model, path):
- it = view_model.get_iter_first()
- while it:
- name = self.find_item_for_path(path)
- view_name = view_model.get_value(it, RecipeListModel.COL_NAME)
- if view_name == name:
- view_path = view_model.get_path(it)
- return view_path
- it = view_model.iter_next(it)
- return None
-
- """
- The populate() function takes as input the data from a
- bb.event.TargetsTreeGenerated event and populates the RecipeList.
- """
- def populate(self, event_model):
- # First clear the model, in case repopulating
- self.clear()
-
- # dummy image for prompt
- self.set_in_list(self.__custom_image__, "Use 'Edit image recipe' to customize recipes and packages " \
- "to be included in your image ")
-
- for item in event_model["pn"]:
- name = item
- desc = event_model["pn"][item]["description"]
- lic = event_model["pn"][item]["license"]
- group = event_model["pn"][item]["section"]
- inherits = event_model["pn"][item]["inherits"]
- summary = event_model["pn"][item]["summary"]
- version = event_model["pn"][item]["version"]
- revision = event_model["pn"][item]["prevision"]
- homepage = event_model["pn"][item]["homepage"]
- bugtracker = event_model["pn"][item]["bugtracker"]
- filename = event_model["pn"][item]["filename"]
- install = []
-
- depends = event_model["depends"].get(item, []) + event_model["rdepends-pn"].get(item, [])
-
- if ('packagegroup.bbclass' in " ".join(inherits)):
- atype = 'packagegroup'
- elif ('/image.bbclass' in " ".join(inherits)):
- if "edited" not in name:
- atype = 'image'
- install = event_model["rdepends-pkg"].get(item, []) + event_model["rrecs-pkg"].get(item, [])
- elif ('meta-' in name):
- atype = 'toolchain'
- elif (name == 'dummy-image' or name == 'dummy-toolchain'):
- atype = 'dummy'
- else:
- atype = 'recipe'
-
- self.set(self.append(), self.COL_NAME, item, self.COL_DESC, desc,
- self.COL_LIC, lic, self.COL_GROUP, group,
- self.COL_DEPS, " ".join(depends), self.COL_BINB, "",
- self.COL_TYPE, atype, self.COL_INC, False,
- self.COL_IMG, False, self.COL_INSTALL, " ".join(install), self.COL_PN, item,
- self.COL_SUMMARY, summary, self.COL_VERSION, version, self.COL_REVISION, revision,
- self.COL_HOMEPAGE, homepage, self.COL_BUGTRACKER, bugtracker,
- self.COL_FILE, filename)
-
- self.pn_path = {}
- it = self.get_iter_first()
- while it:
- pn = self.get_value(it, self.COL_NAME)
- path = self.get_path(it)
- self.pn_path[pn] = path
- it = self.iter_next(it)
-
- def set_in_list(self, item, desc):
- self.set(self.append(), self.COL_NAME, item,
- self.COL_DESC, desc,
- self.COL_LIC, "", self.COL_GROUP, "",
- self.COL_DEPS, "", self.COL_BINB, "",
- self.COL_TYPE, "image", self.COL_INC, False,
- self.COL_IMG, False, self.COL_INSTALL, "", self.COL_PN, item,
- self.COL_SUMMARY, "", self.COL_VERSION, "", self.COL_REVISION, "",
- self.COL_HOMEPAGE, "", self.COL_BUGTRACKER, "")
- self.pn_path = {}
- it = self.get_iter_first()
- while it:
- pn = self.get_value(it, self.COL_NAME)
- path = self.get_path(it)
- self.pn_path[pn] = path
- it = self.iter_next(it)
-
- """
- Update the model, send out the notification.
- """
- def selection_change_notification(self):
- self.emit("recipe-selection-changed")
-
- def path_included(self, item_path):
- return self[item_path][self.COL_INC]
-
- """
- Add this item, and any of its dependencies, to the image contents
- """
- def include_item(self, item_path, binb="", image_contents=False):
- if self.path_included(item_path):
- return
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_DEPS]
-
- self[item_path][self.COL_INC] = True
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if binb and not binb in item_bin:
- item_bin.append(binb)
- self[item_path][self.COL_BINB] = ', '.join(item_bin).lstrip(', ')
-
- # We want to do some magic with things which are brought in by the
- # base image so tag them as so
- if image_contents:
- self[item_path][self.COL_IMG] = True
-
- if item_deps:
- # Ensure all of the items deps are included and, where appropriate,
- # add this item to their COL_BINB
- for dep in item_deps.split(" "):
- # If the contents model doesn't already contain dep, add it
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_included = self.path_included(dep_path)
-
- if dep_included and not dep in item_bin:
- # don't set the COL_BINB to this item if the target is an
- # item in our own COL_BINB
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if not item_name in dep_bin:
- dep_bin.append(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
- elif not dep_included:
- self.include_item(dep_path, binb=item_name, image_contents=image_contents)
- dep_bin = self[item_path][self.COL_BINB].split(', ')
- if self[item_path][self.COL_NAME] in dep_bin:
- dep_bin.remove(self[item_path][self.COL_NAME])
- self[item_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
-
- def exclude_item(self, item_path):
- if not self.path_included(item_path):
- return
-
- self[item_path][self.COL_INC] = False
-
- item_name = self[item_path][self.COL_NAME]
- item_deps = self[item_path][self.COL_DEPS]
- if item_deps:
- for dep in item_deps.split(" "):
- dep_path = self.find_path_for_item(dep)
- if not dep_path:
- continue
- dep_bin = self[dep_path][self.COL_BINB].split(', ')
- if item_name in dep_bin:
- dep_bin.remove(item_name)
- self[dep_path][self.COL_BINB] = ', '.join(dep_bin).lstrip(', ')
-
- item_bin = self[item_path][self.COL_BINB].split(', ')
- if item_bin:
- for binb in item_bin:
- binb_path = self.find_path_for_item(binb)
- if not binb_path:
- continue
- self.exclude_item(binb_path)
-
- def reset(self):
- it = self.get_iter_first()
- while it:
- self.set(it,
- self.COL_INC, False,
- self.COL_BINB, "",
- self.COL_IMG, False)
- it = self.iter_next(it)
-
- self.selection_change_notification()
-
- """
- Returns two lists. One of user selected recipes and the other containing
- all selected recipes
- """
- def get_selected_recipes(self):
- allrecipes = []
- userrecipes = []
-
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_PN)
- type = self.get_value(it, self.COL_TYPE)
- if type != "image":
- allrecipes.append(name)
- sel = "User Selected" in self.get_value(it, self.COL_BINB)
- if sel:
- userrecipes.append(name)
- it = self.iter_next(it)
-
- return list(set(userrecipes)), list(set(allrecipes))
-
- def set_selected_recipes(self, recipelist):
- for pn in recipelist:
- if pn in self.pn_path.keys():
- path = self.pn_path[pn]
- self.include_item(item_path=path,
- binb="User Selected")
- self.selection_change_notification()
-
- def get_selected_image(self):
- it = self.get_iter_first()
- while it:
- if self.get_value(it, self.COL_INC):
- name = self.get_value(it, self.COL_PN)
- type = self.get_value(it, self.COL_TYPE)
- if type == "image":
- sel = "User Selected" in self.get_value(it, self.COL_BINB)
- if sel:
- return name
- it = self.iter_next(it)
- return None
-
- def set_selected_image(self, img):
- if not img:
- return
- self.reset()
- path = self.find_path_for_item(img)
- self.include_item(item_path=path,
- binb="User Selected",
- image_contents=True)
- self.selection_change_notification()
-
- def set_custom_image_version(self, version):
- self.custom_image_version = version
-
- def get_custom_image_version(self):
- return self.custom_image_version
-
- def is_custom_image(self):
- return self.get_selected_image() == self.__custom_image__
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py
deleted file mode 100755
index 0fd3598c3..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/hobpages.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import hwc
-
-#
-# HobPage: the super class for all Hob-related pages
-#
-class HobPage (gtk.VBox):
-
- def __init__(self, builder, title = None):
- super(HobPage, self).__init__(False, 0)
- self.builder = builder
- self.builder_width, self.builder_height = self.builder.size_request()
-
- if not title:
- self.title = "Hob -- Image Creator"
- else:
- self.title = title
- self.title_label = gtk.Label()
-
- self.box_group_area = gtk.VBox(False, 12)
- self.box_group_area.set_size_request(self.builder_width - 73 - 73, self.builder_height - 88 - 15 - 15)
- self.group_align = gtk.Alignment(xalign = 0, yalign=0.5, xscale=1, yscale=1)
- self.group_align.set_padding(15, 15, 73, 73)
- self.group_align.add(self.box_group_area)
- self.box_group_area.set_homogeneous(False)
-
- def set_title(self, title):
- self.title = title
- self.title_label.set_markup("<span size='x-large'>%s</span>" % self.title)
-
- def add_onto_top_bar(self, widget = None, padding = 0):
- # the top button occupies 1/7 of the page height
- # setup an event box
- eventbox = gtk.EventBox()
- style = eventbox.get_style().copy()
- style.bg[gtk.STATE_NORMAL] = eventbox.get_colormap().alloc_color(HobColors.LIGHT_GRAY, False, False)
- eventbox.set_style(style)
- eventbox.set_size_request(-1, 88)
-
- hbox = gtk.HBox()
-
- self.title_label = gtk.Label()
- self.title_label.set_markup("<span size='x-large'>%s</span>" % self.title)
- hbox.pack_start(self.title_label, expand=False, fill=False, padding=20)
-
- if widget:
- # add the widget in the event box
- hbox.pack_end(widget, expand=False, fill=False, padding=padding)
- eventbox.add(hbox)
-
- return eventbox
-
- def span_tag(self, size="medium", weight="normal", forground="#1c1c1c"):
- span_tag = "weight='%s' foreground='%s' size='%s'" % (weight, forground, size)
- return span_tag
-
- def append_toolbar_button(self, toolbar, buttonname, icon_disp, icon_hovor, tip, cb):
- # Create a button and append it on the toolbar according to button name
- icon = gtk.Image()
- icon_display = icon_disp
- icon_hover = icon_hovor
- pix_buffer = gtk.gdk.pixbuf_new_from_file(icon_display)
- icon.set_from_pixbuf(pix_buffer)
- tip_text = tip
- button = toolbar.append_item(buttonname, tip, None, icon, cb)
- return button
-
- @staticmethod
- def _size_to_string(size):
- try:
- if not size:
- size_str = "0 B"
- else:
- if len(str(int(size))) > 6:
- size_str = '%.1f' % (size*1.0/(1024*1024)) + ' MB'
- elif len(str(int(size))) > 3:
- size_str = '%.1f' % (size*1.0/1024) + ' KB'
- else:
- size_str = str(size) + ' B'
- except:
- size_str = "0 B"
- return size_str
-
- @staticmethod
- def _string_to_size(str_size):
- try:
- if not str_size:
- size = 0
- else:
- unit = str_size.split()
- if len(unit) > 1:
- if unit[1] == 'MB':
- size = float(unit[0])*1024*1024
- elif unit[1] == 'KB':
- size = float(unit[0])*1024
- elif unit[1] == 'B':
- size = float(unit[0])
- else:
- size = 0
- else:
- size = float(unit[0])
- except:
- size = 0
- return size
-
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py
deleted file mode 100644
index 2766bea8c..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/imageconfigurationpage.py
+++ /dev/null
@@ -1,561 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import glib
-import re
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import hic, HobImageButton, HobInfoButton, HobAltButton, HobButton
-from bb.ui.crumbs.hoblistmodel import RecipeListModel
-from bb.ui.crumbs.hobpages import HobPage
-from bb.ui.crumbs.hig.retrieveimagedialog import RetrieveImageDialog
-
-#
-# ImageConfigurationPage
-#
-class ImageConfigurationPage (HobPage):
-
- __dummy_machine__ = "--select a machine--"
- __dummy_image__ = "--select an image recipe--"
- __custom_image__ = "Select from my image recipes"
-
- def __init__(self, builder):
- super(ImageConfigurationPage, self).__init__(builder, "Image configuration")
-
- self.image_combo_id = None
- # we use machine_combo_changed_by_manual to identify the machine is changed by code
- # or by manual. If by manual, all user's recipe selection and package selection are
- # cleared.
- self.machine_combo_changed_by_manual = True
- self.stopping = False
- self.warning_shift = 0
- self.custom_image_selected = None
- self.create_visual_elements()
-
- def create_visual_elements(self):
- # create visual elements
- self.toolbar = gtk.Toolbar()
- self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
- self.toolbar.set_style(gtk.TOOLBAR_BOTH)
-
- my_images_button = self.append_toolbar_button(self.toolbar,
- "Images",
- hic.ICON_IMAGES_DISPLAY_FILE,
- hic.ICON_IMAGES_HOVER_FILE,
- "Open previously built images",
- self.my_images_button_clicked_cb)
- settings_button = self.append_toolbar_button(self.toolbar,
- "Settings",
- hic.ICON_SETTINGS_DISPLAY_FILE,
- hic.ICON_SETTINGS_HOVER_FILE,
- "View additional build settings",
- self.settings_button_clicked_cb)
-
- self.config_top_button = self.add_onto_top_bar(self.toolbar)
-
- self.gtable = gtk.Table(40, 40, True)
- self.create_config_machine()
- self.create_config_baseimg()
- self.config_build_button = self.create_config_build_button()
-
- def _remove_all_widget(self):
- children = self.gtable.get_children() or []
- for child in children:
- self.gtable.remove(child)
- children = self.box_group_area.get_children() or []
- for child in children:
- self.box_group_area.remove(child)
- children = self.get_children() or []
- for child in children:
- self.remove(child)
-
- def _pack_components(self, pack_config_build_button = False):
- self._remove_all_widget()
- self.pack_start(self.config_top_button, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- self.box_group_area.pack_start(self.gtable, expand=True, fill=True)
- if pack_config_build_button:
- self.box_group_area.pack_end(self.config_build_button, expand=False, fill=False)
- else:
- box = gtk.HBox(False, 6)
- box.show()
- subbox = gtk.HBox(False, 0)
- subbox.set_size_request(205, 49)
- subbox.show()
- box.add(subbox)
- self.box_group_area.pack_end(box, False, False)
-
- def show_machine(self):
- self.progress_bar.reset()
- self._pack_components(pack_config_build_button = False)
- self.set_config_machine_layout(show_progress_bar = False)
- self.show_all()
-
- def update_progress_bar(self, title, fraction, status=None):
- if self.stopping == False:
- self.progress_bar.update(fraction)
- self.progress_bar.set_text(title)
- self.progress_bar.set_rcstyle(status)
-
- def show_info_populating(self):
- self._pack_components(pack_config_build_button = False)
- self.set_config_machine_layout(show_progress_bar = True)
- self.show_all()
-
- def show_info_populated(self):
- self.progress_bar.reset()
- self._pack_components(pack_config_build_button = False)
- self.set_config_machine_layout(show_progress_bar = False)
- self.set_config_baseimg_layout()
- self.show_all()
-
- def show_baseimg_selected(self):
- self.progress_bar.reset()
- self._pack_components(pack_config_build_button = True)
- self.set_config_machine_layout(show_progress_bar = False)
- self.set_config_baseimg_layout()
- self.show_all()
- if self.builder.recipe_model.get_selected_image() == self.builder.recipe_model.__custom_image__:
- self.just_bake_button.hide()
-
- def add_warnings_bar(self):
- #create the warnings bar shown when recipes parsing generates warnings
- color = HobColors.KHAKI
- warnings_bar = gtk.EventBox()
- warnings_bar.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
- warnings_bar.set_flags(gtk.CAN_DEFAULT)
- warnings_bar.grab_default()
-
- build_stop_tab = gtk.Table(10, 20, True)
- warnings_bar.add(build_stop_tab)
-
- icon = gtk.Image()
- icon_pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_INDI_ALERT_FILE)
- icon.set_from_pixbuf(icon_pix_buffer)
- build_stop_tab.attach(icon, 0, 2, 0, 10)
-
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- warnings_nb = len(self.builder.parsing_warnings)
- if warnings_nb == 1:
- label.set_markup("<span size='x-large'><b>1 recipe parsing warning</b></span>")
- else:
- label.set_markup("<span size='x-large'><b>%s recipe parsing warnings</b></span>" % warnings_nb)
- build_stop_tab.attach(label, 2, 12, 0, 10)
-
- view_warnings_button = HobButton("View warnings")
- view_warnings_button.connect('clicked', self.view_warnings_button_clicked_cb)
- build_stop_tab.attach(view_warnings_button, 15, 19, 1, 9)
-
- return warnings_bar
-
- def disable_warnings_bar(self):
- if self.builder.parsing_warnings:
- if hasattr(self, 'warnings_bar'):
- self.warnings_bar.hide_all()
- self.builder.parsing_warnings = []
-
- def create_config_machine(self):
- self.machine_title = gtk.Label()
- self.machine_title.set_alignment(0.0, 0.5)
- mark = "<span %s>Select a machine</span>" % self.span_tag('x-large', 'bold')
- self.machine_title.set_markup(mark)
-
- self.machine_title_desc = gtk.Label()
- self.machine_title_desc.set_alignment(0.0, 0.5)
- mark = ("<span %s>Your selection is the profile of the target machine for which you"
- " are building the image.\n</span>") % (self.span_tag('medium'))
- self.machine_title_desc.set_markup(mark)
-
- self.machine_combo = gtk.combo_box_new_text()
- self.machine_combo.connect("changed", self.machine_combo_changed_cb)
-
- icon_file = hic.ICON_LAYERS_DISPLAY_FILE
- hover_file = hic.ICON_LAYERS_HOVER_FILE
- self.layer_button = HobImageButton("Layers", "Add support for machines, software, etc.",
- icon_file, hover_file)
- self.layer_button.connect("clicked", self.layer_button_clicked_cb)
-
- markup = "Layers are a powerful mechanism to extend the Yocto Project "
- markup += "with your own functionality.\n"
- markup += "For more on layers, check the <a href=\""
- markup += "http://www.yoctoproject.org/docs/current/dev-manual/"
- markup += "dev-manual.html#understanding-and-using-layers\">reference manual</a>."
- self.layer_info_icon = HobInfoButton("<b>Layers</b>" + "*" + markup, self.get_parent())
- self.progress_bar = HobProgressBar()
- self.stop_button = HobAltButton("Stop")
- self.stop_button.connect("clicked", self.stop_button_clicked_cb)
- self.machine_separator = gtk.HSeparator()
-
- def set_config_machine_layout(self, show_progress_bar = False):
- self.gtable.attach(self.machine_title, 0, 40, 0, 4)
- self.gtable.attach(self.machine_title_desc, 0, 40, 4, 6)
- self.gtable.attach(self.machine_combo, 0, 12, 7, 10)
- self.gtable.attach(self.layer_button, 14, 36, 7, 12)
- self.gtable.attach(self.layer_info_icon, 36, 40, 7, 11)
- if show_progress_bar:
- #self.gtable.attach(self.progress_box, 0, 40, 15, 18)
- self.gtable.attach(self.progress_bar, 0, 37, 15, 18)
- self.gtable.attach(self.stop_button, 37, 40, 15, 18, 0, 0)
- if self.builder.parsing_warnings:
- self.warnings_bar = self.add_warnings_bar()
- self.gtable.attach(self.warnings_bar, 0, 40, 14, 18)
- self.warning_shift = 4
- else:
- self.warning_shift = 0
- self.gtable.attach(self.machine_separator, 0, 40, 13, 14)
-
- def create_config_baseimg(self):
- self.image_title = gtk.Label()
- self.image_title.set_alignment(0, 1.0)
- mark = "<span %s>Select an image recipe</span>" % self.span_tag('x-large', 'bold')
- self.image_title.set_markup(mark)
-
- self.image_title_desc = gtk.Label()
- self.image_title_desc.set_alignment(0, 0.5)
-
- mark = ("<span %s>Image recipes are a starting point for the type of image you want. "
- "You can build them as \n"
- "they are or edit them to suit your needs.\n</span>") % self.span_tag('medium')
- self.image_title_desc.set_markup(mark)
-
- self.image_combo = gtk.combo_box_new_text()
- self.image_combo.set_row_separator_func(self.combo_separator_func, None)
- self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
-
- self.image_desc = gtk.Label()
- self.image_desc.set_alignment(0.0, 0.5)
- self.image_desc.set_size_request(256, -1)
- self.image_desc.set_justify(gtk.JUSTIFY_LEFT)
- self.image_desc.set_line_wrap(True)
-
- # button to view recipes
- icon_file = hic.ICON_RCIPE_DISPLAY_FILE
- hover_file = hic.ICON_RCIPE_HOVER_FILE
- self.view_adv_configuration_button = HobImageButton("Advanced configuration",
- "Select image types, package formats, etc",
- icon_file, hover_file)
- self.view_adv_configuration_button.connect("clicked", self.view_adv_configuration_button_clicked_cb)
-
- self.image_separator = gtk.HSeparator()
-
- def combo_separator_func(self, model, iter, user_data):
- name = model.get_value(iter, 0)
- if name == "--Separator--":
- return True
-
- def set_config_baseimg_layout(self):
- self.gtable.attach(self.image_title, 0, 40, 15+self.warning_shift, 17+self.warning_shift)
- self.gtable.attach(self.image_title_desc, 0, 40, 18+self.warning_shift, 22+self.warning_shift)
- self.gtable.attach(self.image_combo, 0, 12, 23+self.warning_shift, 26+self.warning_shift)
- self.gtable.attach(self.image_desc, 0, 12, 27+self.warning_shift, 33+self.warning_shift)
- self.gtable.attach(self.view_adv_configuration_button, 14, 36, 23+self.warning_shift, 28+self.warning_shift)
- self.gtable.attach(self.image_separator, 0, 40, 35+self.warning_shift, 36+self.warning_shift)
-
- def create_config_build_button(self):
- # Create the "Build packages" and "Build image" buttons at the bottom
- button_box = gtk.HBox(False, 6)
-
- # create button "Build image"
- self.just_bake_button = HobButton("Build image")
- self.just_bake_button.set_tooltip_text("Build the image recipe as it is")
- self.just_bake_button.connect("clicked", self.just_bake_button_clicked_cb)
- button_box.pack_end(self.just_bake_button, expand=False, fill=False)
-
- # create button "Edit image recipe"
- self.edit_image_button = HobAltButton("Edit image recipe")
- self.edit_image_button.set_tooltip_text("Customize the recipes and packages to be included in your image")
- self.edit_image_button.connect("clicked", self.edit_image_button_clicked_cb)
- button_box.pack_end(self.edit_image_button, expand=False, fill=False)
-
- return button_box
-
- def stop_button_clicked_cb(self, button):
- self.stopping = True
- self.progress_bar.set_text("Stopping recipe parsing")
- self.progress_bar.set_rcstyle("stop")
- self.builder.cancel_parse_sync()
-
- def view_warnings_button_clicked_cb(self, button):
- self.builder.show_warning_dialog()
-
- def machine_combo_changed_idle_cb(self):
- self.builder.window.set_cursor(None)
-
- def machine_combo_changed_cb(self, machine_combo):
- self.stopping = False
- self.builder.parsing_warnings = []
- combo_item = machine_combo.get_active_text()
- if not combo_item or combo_item == self.__dummy_machine__:
- return
-
- self.builder.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
- self.builder.wait(0.1) #wait for combo and cursor to update
-
- # remove __dummy_machine__ item from the store list after first user selection
- # because it is no longer valid
- combo_store = machine_combo.get_model()
- if len(combo_store) and (combo_store[0][0] == self.__dummy_machine__):
- machine_combo.remove_text(0)
-
- self.builder.configuration.curr_mach = combo_item
- if self.machine_combo_changed_by_manual:
- self.builder.configuration.clear_selection()
- # reset machine_combo_changed_by_manual
- self.machine_combo_changed_by_manual = True
-
- self.builder.configuration.selected_image = None
-
- # Do reparse recipes
- self.builder.populate_recipe_package_info_async()
-
- glib.idle_add(self.machine_combo_changed_idle_cb)
-
- def update_machine_combo(self):
- self.disable_warnings_bar()
- all_machines = [self.__dummy_machine__] + self.builder.parameters.all_machines
-
- model = self.machine_combo.get_model()
- model.clear()
- for machine in all_machines:
- self.machine_combo.append_text(machine)
- self.machine_combo.set_active(0)
-
- def switch_machine_combo(self):
- self.disable_warnings_bar()
- self.machine_combo_changed_by_manual = False
- model = self.machine_combo.get_model()
- active = 0
- while active < len(model):
- if model[active][0] == self.builder.configuration.curr_mach:
- self.machine_combo.set_active(active)
- return
- active += 1
-
- if model[0][0] != self.__dummy_machine__:
- self.machine_combo.insert_text(0, self.__dummy_machine__)
-
- self.machine_combo.set_active(0)
-
- def update_image_desc(self):
- desc = ""
- selected_image = self.image_combo.get_active_text()
- if selected_image and selected_image in self.builder.recipe_model.pn_path.keys():
- image_path = self.builder.recipe_model.pn_path[selected_image]
- image_iter = self.builder.recipe_model.get_iter(image_path)
- desc = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC)
-
- mark = ("<span %s>%s</span>\n") % (self.span_tag('small'), desc)
- self.image_desc.set_markup(mark)
-
- def image_combo_changed_idle_cb(self, selected_image, selected_recipes, selected_packages):
- self.builder.update_recipe_model(selected_image, selected_recipes)
- self.builder.update_package_model(selected_packages)
- self.builder.window_sensitive(True)
-
- def image_combo_changed_cb(self, combo):
- self.builder.window_sensitive(False)
- selected_image = self.image_combo.get_active_text()
- if selected_image == self.__custom_image__:
- topdir = self.builder.get_topdir()
- images_dir = topdir + "/recipes/images/custom/"
- self.builder.ensure_dir(images_dir)
-
- dialog = RetrieveImageDialog(images_dir, "Select from my image recipes",
- self.builder, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- response = dialog.run()
- if response == gtk.RESPONSE_OK:
- image_name = dialog.get_filename()
- head, tail = os.path.split(image_name)
- selected_image = os.path.splitext(tail)[0]
- self.custom_image_selected = selected_image
- self.update_image_combo(self.builder.recipe_model, selected_image)
- else:
- selected_image = self.__dummy_image__
- self.update_image_combo(self.builder.recipe_model, None)
- dialog.destroy()
- else:
- if self.custom_image_selected:
- self.custom_image_selected = None
- self.update_image_combo(self.builder.recipe_model, selected_image)
-
- if not selected_image or (selected_image == self.__dummy_image__):
- self.builder.window_sensitive(True)
- self.just_bake_button.hide()
- self.edit_image_button.hide()
- return
-
- # remove __dummy_image__ item from the store list after first user selection
- # because it is no longer valid
- combo_store = combo.get_model()
- if len(combo_store) and (combo_store[0][0] == self.__dummy_image__):
- combo.remove_text(0)
-
- self.builder.customized = False
-
- selected_recipes = []
-
- image_path = self.builder.recipe_model.pn_path[selected_image]
- image_iter = self.builder.recipe_model.get_iter(image_path)
- selected_packages = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_INSTALL).split()
- self.update_image_desc()
-
- self.builder.recipe_model.reset()
- self.builder.package_model.reset()
-
- self.show_baseimg_selected()
-
- if selected_image == self.builder.recipe_model.__custom_image__:
- self.just_bake_button.hide()
-
- glib.idle_add(self.image_combo_changed_idle_cb, selected_image, selected_recipes, selected_packages)
-
- def _image_combo_connect_signal(self):
- if not self.image_combo_id:
- self.image_combo_id = self.image_combo.connect("changed", self.image_combo_changed_cb)
-
- def _image_combo_disconnect_signal(self):
- if self.image_combo_id:
- self.image_combo.disconnect(self.image_combo_id)
- self.image_combo_id = None
-
- def update_image_combo(self, recipe_model, selected_image):
- # Update the image combo according to the images in the recipe_model
- # populate image combo
- filter = {RecipeListModel.COL_TYPE : ['image']}
- image_model = recipe_model.tree_model(filter)
- image_model.set_sort_column_id(recipe_model.COL_NAME, gtk.SORT_ASCENDING)
- active = 0
- cnt = 0
-
- white_pattern = []
- if self.builder.parameters.image_white_pattern:
- for i in self.builder.parameters.image_white_pattern.split():
- white_pattern.append(re.compile(i))
-
- black_pattern = []
- if self.builder.parameters.image_black_pattern:
- for i in self.builder.parameters.image_black_pattern.split():
- black_pattern.append(re.compile(i))
- black_pattern.append(re.compile("hob-image"))
- black_pattern.append(re.compile("edited(-[0-9]*)*.bb$"))
-
- it = image_model.get_iter_first()
- self._image_combo_disconnect_signal()
- model = self.image_combo.get_model()
- model.clear()
- # Set a indicator text to combo store when first open
- if not selected_image:
- self.image_combo.append_text(self.__dummy_image__)
- cnt = cnt + 1
-
- self.image_combo.append_text(self.__custom_image__)
- self.image_combo.append_text("--Separator--")
- cnt = cnt + 2
-
- topdir = self.builder.get_topdir()
- # append and set active
- while it:
- path = image_model.get_path(it)
- it = image_model.iter_next(it)
- image_name = image_model[path][recipe_model.COL_NAME]
- if image_name == self.builder.recipe_model.__custom_image__:
- continue
-
- if black_pattern:
- allow = True
- for pattern in black_pattern:
- if pattern.search(image_name):
- allow = False
- break
- elif white_pattern:
- allow = False
- for pattern in white_pattern:
- if pattern.search(image_name):
- allow = True
- break
- else:
- allow = True
-
- file_name = image_model[path][recipe_model.COL_FILE]
- if file_name and topdir in file_name:
- allow = False
-
- if allow:
- self.image_combo.append_text(image_name)
- if image_name == selected_image:
- active = cnt
- cnt = cnt + 1
- self.image_combo.append_text(self.builder.recipe_model.__custom_image__)
-
- if selected_image == self.builder.recipe_model.__custom_image__:
- active = cnt
-
- if self.custom_image_selected:
- self.image_combo.append_text("--Separator--")
- self.image_combo.append_text(self.custom_image_selected)
- cnt = cnt + 2
- if self.custom_image_selected == selected_image:
- active = cnt
-
- self.image_combo.set_active(active)
-
- if active != 0:
- self.show_baseimg_selected()
-
- self._image_combo_connect_signal()
-
- def layer_button_clicked_cb(self, button):
- # Create a layer selection dialog
- self.builder.show_layer_selection_dialog()
-
- def view_adv_configuration_button_clicked_cb(self, button):
- # Create an advanced settings dialog
- response, settings_changed = self.builder.show_adv_settings_dialog()
- if not response:
- return
- if settings_changed:
- self.builder.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
- self.builder.wait(0.1) #wait for adv_settings_dialog to terminate
- self.builder.reparse_post_adv_settings()
- self.builder.window.set_cursor(None)
-
- def just_bake_button_clicked_cb(self, button):
- self.builder.parsing_warnings = []
- self.builder.just_bake()
-
- def edit_image_button_clicked_cb(self, button):
- self.builder.set_base_image()
- self.builder.show_recipes()
-
- def my_images_button_clicked_cb(self, button):
- self.builder.show_load_my_images_dialog()
-
- def settings_button_clicked_cb(self, button):
- # Create an advanced settings dialog
- response, settings_changed = self.builder.show_simple_settings_dialog()
- if not response:
- return
- if settings_changed:
- self.builder.reparse_post_adv_settings()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py
deleted file mode 100755
index 352e9489f..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/imagedetailspage.py
+++ /dev/null
@@ -1,669 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gobject
-import gtk
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobAltButton, HobButton
-from bb.ui.crumbs.hobpages import HobPage
-import subprocess
-from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
-from bb.ui.crumbs.hig.saveimagedialog import SaveImageDialog
-
-#
-# ImageDetailsPage
-#
-class ImageDetailsPage (HobPage):
-
- class DetailBox (gtk.EventBox):
- def __init__(self, widget = None, varlist = None, vallist = None, icon = None, button = None, button2=None, color = HobColors.LIGHT_GRAY):
- gtk.EventBox.__init__(self)
-
- # set color
- style = self.get_style().copy()
- style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
- self.set_style(style)
-
- self.row = gtk.Table(1, 2, False)
- self.row.set_border_width(10)
- self.add(self.row)
-
- total_rows = 0
- if widget:
- total_rows = 10
- if varlist and vallist:
- # pack the icon and the text on the left
- total_rows += len(varlist)
- self.table = gtk.Table(total_rows, 20, True)
- self.table.set_row_spacings(6)
- self.table.set_size_request(100, -1)
- self.row.attach(self.table, 0, 1, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL)
-
- colid = 0
- rowid = 0
- self.line_widgets = {}
- if icon:
- self.table.attach(icon, colid, colid + 2, 0, 1)
- colid = colid + 2
- if widget:
- self.table.attach(widget, colid, 20, 0, 10)
- rowid = 10
- if varlist and vallist:
- for row in range(rowid, total_rows):
- index = row - rowid
- self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
- self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
- # pack the button on the right
- if button:
- self.bbox = gtk.VBox()
- self.bbox.pack_start(button, expand=True, fill=False)
- if button2:
- self.bbox.pack_start(button2, expand=True, fill=False)
- self.bbox.set_size_request(150,-1)
- self.row.attach(self.bbox, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.EXPAND)
-
- def update_line_widgets(self, variable, value):
- if len(self.line_widgets) == 0:
- return
- if not isinstance(self.line_widgets[variable], gtk.Label):
- return
- self.line_widgets[variable].set_markup(self.format_line(variable, value))
-
- def wrap_line(self, inputs):
- # wrap the long text of inputs
- wrap_width_chars = 75
- outputs = ""
- tmps = inputs
- less_chars = len(inputs)
- while (less_chars - wrap_width_chars) > 0:
- less_chars -= wrap_width_chars
- outputs += tmps[:wrap_width_chars] + "\n "
- tmps = inputs[less_chars:]
- outputs += tmps
- return outputs
-
- def format_line(self, variable, value):
- wraped_value = self.wrap_line(value)
- markup = "<span weight=\'bold\'>%s</span>" % variable
- markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
- return markup
-
- def text2label(self, variable, value):
- # append the name:value to the left box
- # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup(self.format_line(variable, value))
- return label
-
- class BuildDetailBox (gtk.EventBox):
- def __init__(self, varlist = None, vallist = None, icon = None, color = HobColors.LIGHT_GRAY):
- gtk.EventBox.__init__(self)
-
- # set color
- style = self.get_style().copy()
- style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
- self.set_style(style)
-
- self.hbox = gtk.HBox()
- self.hbox.set_border_width(10)
- self.add(self.hbox)
-
- total_rows = 0
- if varlist and vallist:
- # pack the icon and the text on the left
- total_rows += len(varlist)
- self.table = gtk.Table(total_rows, 20, True)
- self.table.set_row_spacings(6)
- self.table.set_size_request(100, -1)
- self.hbox.pack_start(self.table, expand=True, fill=True, padding=15)
-
- colid = 0
- rowid = 0
- self.line_widgets = {}
- if icon:
- self.table.attach(icon, colid, colid + 2, 0, 1)
- colid = colid + 2
- if varlist and vallist:
- for row in range(rowid, total_rows):
- index = row - rowid
- self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
- self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
-
- def update_line_widgets(self, variable, value):
- if len(self.line_widgets) == 0:
- return
- if not isinstance(self.line_widgets[variable], gtk.Label):
- return
- self.line_widgets[variable].set_markup(self.format_line(variable, value))
-
- def wrap_line(self, inputs):
- # wrap the long text of inputs
- wrap_width_chars = 75
- outputs = ""
- tmps = inputs
- less_chars = len(inputs)
- while (less_chars - wrap_width_chars) > 0:
- less_chars -= wrap_width_chars
- outputs += tmps[:wrap_width_chars] + "\n "
- tmps = inputs[less_chars:]
- outputs += tmps
- return outputs
-
- def format_line(self, variable, value):
- wraped_value = self.wrap_line(value)
- markup = "<span weight=\'bold\'>%s</span>" % variable
- markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
- return markup
-
- def text2label(self, variable, value):
- # append the name:value to the left box
- # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- label.set_markup(self.format_line(variable, value))
- return label
-
- def __init__(self, builder):
- super(ImageDetailsPage, self).__init__(builder, "Image details")
-
- self.image_store = []
- self.button_ids = {}
- self.details_bottom_buttons = gtk.HBox(False, 6)
- self.image_saved = False
- self.create_visual_elements()
- self.name_field_template = ""
- self.description_field_template = ""
-
- def create_visual_elements(self):
- # create visual elements
- # create the toolbar
- self.toolbar = gtk.Toolbar()
- self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
- self.toolbar.set_style(gtk.TOOLBAR_BOTH)
-
- my_images_button = self.append_toolbar_button(self.toolbar,
- "Images",
- hic.ICON_IMAGES_DISPLAY_FILE,
- hic.ICON_IMAGES_HOVER_FILE,
- "Open previously built images",
- self.my_images_button_clicked_cb)
- settings_button = self.append_toolbar_button(self.toolbar,
- "Settings",
- hic.ICON_SETTINGS_DISPLAY_FILE,
- hic.ICON_SETTINGS_HOVER_FILE,
- "View additional build settings",
- self.settings_button_clicked_cb)
-
- self.details_top_buttons = self.add_onto_top_bar(self.toolbar)
-
- def _remove_all_widget(self):
- children = self.get_children() or []
- for child in children:
- self.remove(child)
- children = self.box_group_area.get_children() or []
- for child in children:
- self.box_group_area.remove(child)
- children = self.details_bottom_buttons.get_children() or []
- for child in children:
- self.details_bottom_buttons.remove(child)
-
- def show_page(self, step):
- self.build_succeeded = (step == self.builder.IMAGE_GENERATED)
- image_addr = self.builder.parameters.image_addr
- image_names = self.builder.parameters.image_names
- if self.build_succeeded:
- machine = self.builder.configuration.curr_mach
- base_image = self.builder.recipe_model.get_selected_image()
- layers = self.builder.configuration.layers
- pkg_num = "%s" % len(self.builder.package_model.get_selected_packages())
- log_file = self.builder.current_logfile
- else:
- pkg_num = "N/A"
- log_file = None
-
- # remove
- for button_id, button in self.button_ids.items():
- button.disconnect(button_id)
- self._remove_all_widget()
-
- # repack
- self.pack_start(self.details_top_buttons, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- self.build_result = None
- if self.image_saved or (self.build_succeeded and self.builder.current_step == self.builder.IMAGE_GENERATING):
- # building is the previous step
- icon = gtk.Image()
- pixmap_path = hic.ICON_INDI_CONFIRM_FILE
- color = HobColors.RUNNING
- pix_buffer = gtk.gdk.pixbuf_new_from_file(pixmap_path)
- icon.set_from_pixbuf(pix_buffer)
- varlist = [""]
- if self.image_saved:
- vallist = ["Your image recipe has been saved"]
- else:
- vallist = ["Your image is ready"]
- self.build_result = self.BuildDetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color)
- self.box_group_area.pack_start(self.build_result, expand=False, fill=False)
-
- self.buttonlist = ["Build new image", "Save image recipe", "Run image", "Deploy image"]
-
- # Name
- self.image_store = []
- self.toggled_image = ""
- default_image_size = 0
- self.num_toggled = 0
- i = 0
- for image_name in image_names:
- image_size = HobPage._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size)
-
- image_attr = ("run" if (self.test_type_runnable(image_name) and self.test_mach_runnable(image_name)) else \
- ("deploy" if self.test_deployable(image_name) else ""))
- is_toggled = (image_attr != "")
-
- if not self.toggled_image:
- if i == (len(image_names) - 1):
- is_toggled = True
- if is_toggled:
- default_image_size = image_size
- self.toggled_image = image_name
-
- split_stuff = image_name.split('.')
- if "rootfs" in split_stuff:
- image_type = image_name[(len(split_stuff[0]) + len(".rootfs") + 1):]
- else:
- image_type = image_name[(len(split_stuff[0]) + 1):]
-
- self.image_store.append({'name': image_name,
- 'type': image_type,
- 'size': image_size,
- 'is_toggled': is_toggled,
- 'action_attr': image_attr,})
-
- i = i + 1
- self.num_toggled += is_toggled
-
- is_runnable = self.create_bottom_buttons(self.buttonlist, self.toggled_image)
-
- # Generated image files info
- varlist = ["Name: ", "Files created: ", "Directory: "]
- vallist = []
-
- vallist.append(image_name.split('.')[0])
- vallist.append(', '.join(fileitem['type'] for fileitem in self.image_store))
- vallist.append(image_addr)
-
- view_files_button = HobAltButton("View files")
- view_files_button.connect("clicked", self.view_files_clicked_cb, image_addr)
- view_files_button.set_tooltip_text("Open the directory containing the image files")
- open_log_button = None
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
- open_log_button.set_tooltip_text("Open the build's log file")
- self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_button, button2=open_log_button)
- self.box_group_area.pack_start(self.image_detail, expand=False, fill=True)
-
- # The default kernel box for the qemu images
- self.sel_kernel = ""
- self.kernel_detail = None
- if 'qemu' in image_name:
- self.sel_kernel = self.get_kernel_file_name()
-
- # varlist = ["Kernel: "]
- # vallist = []
- # vallist.append(self.sel_kernel)
-
- # change_kernel_button = HobAltButton("Change")
- # change_kernel_button.connect("clicked", self.change_kernel_cb)
- # change_kernel_button.set_tooltip_text("Change qemu kernel file")
- # self.kernel_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=change_kernel_button)
- # self.box_group_area.pack_start(self.kernel_detail, expand=True, fill=True)
-
- # Machine, Image recipe and Layers
- layer_num_limit = 15
- varlist = ["Machine: ", "Image recipe: ", "Layers: "]
- vallist = []
- self.setting_detail = None
- if self.build_succeeded:
- vallist.append(machine)
- if self.builder.recipe_model.is_custom_image():
- if self.builder.configuration.initial_selected_image == self.builder.recipe_model.__custom_image__:
- base_image ="New image recipe"
- else:
- base_image = self.builder.configuration.initial_selected_image + " (edited)"
- vallist.append(base_image)
- i = 0
- for layer in layers:
- if i > layer_num_limit:
- break
- varlist.append(" - ")
- i += 1
- vallist.append("")
- i = 0
- for layer in layers:
- if i > layer_num_limit:
- break
- elif i == layer_num_limit:
- vallist.append("and more...")
- else:
- vallist.append(layer)
- i += 1
-
- edit_config_button = HobAltButton("Edit configuration")
- edit_config_button.set_tooltip_text("Edit machine and image recipe")
- edit_config_button.connect("clicked", self.edit_config_button_clicked_cb)
- self.setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_config_button)
- self.box_group_area.pack_start(self.setting_detail, expand=True, fill=True)
-
- # Packages included, and Total image size
- varlist = ["Packages included: ", "Total image size: "]
- vallist = []
- vallist.append(pkg_num)
- vallist.append(default_image_size)
- self.builder.configuration.image_size = default_image_size
- self.builder.configuration.image_packages = self.builder.configuration.selected_packages
- if self.build_succeeded:
- edit_packages_button = HobAltButton("Edit packages")
- edit_packages_button.set_tooltip_text("Edit the packages included in your image")
- edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb)
- else: # get to this page from "My images"
- edit_packages_button = None
- self.package_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_packages_button)
- self.box_group_area.pack_start(self.package_detail, expand=True, fill=True)
-
- # pack the buttons at the bottom, at this time they are already created.
- if self.build_succeeded:
- self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False)
- else: # for "My images" page
- self.details_separator = gtk.HSeparator()
- self.box_group_area.pack_start(self.details_separator, expand=False, fill=False)
- self.box_group_area.pack_start(self.details_bottom_buttons, expand=False, fill=False)
-
- self.show_all()
- if self.kernel_detail and (not is_runnable):
- self.kernel_detail.hide()
- self.image_saved = False
-
- def view_files_clicked_cb(self, button, image_addr):
- subprocess.call("xdg-open /%s" % image_addr, shell=True)
-
- def open_log_clicked_cb(self, button, log_file):
- if log_file:
- log_file = "file:///" + log_file
- gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)
-
- def refresh_package_detail_box(self, image_size):
- self.package_detail.update_line_widgets("Total image size: ", image_size)
-
- def test_type_runnable(self, image_name):
- type_runnable = False
- for t in self.builder.parameters.runnable_image_types:
- if image_name.endswith(t):
- type_runnable = True
- break
- return type_runnable
-
- def test_mach_runnable(self, image_name):
- mach_runnable = False
- for t in self.builder.parameters.runnable_machine_patterns:
- if t in image_name:
- mach_runnable = True
- break
- return mach_runnable
-
- def test_deployable(self, image_name):
- if self.builder.configuration.curr_mach.startswith("qemu"):
- return False
- deployable = False
- for t in self.builder.parameters.deployable_image_types:
- if image_name.endswith(t):
- deployable = True
- break
- return deployable
-
- def get_kernel_file_name(self, kernel_addr=""):
- kernel_name = ""
-
- if not kernel_addr:
- kernel_addr = self.builder.parameters.image_addr
-
- files = [f for f in os.listdir(kernel_addr) if f[0] <> '.']
- for check_file in files:
- if check_file.endswith(".bin"):
- name_splits = check_file.split(".")[0]
- if self.builder.parameters.kernel_image_type in name_splits.split("-"):
- kernel_name = check_file
- break
-
- return kernel_name
-
- def show_builded_images_dialog(self, widget, primary_action=""):
- title = primary_action if primary_action else "Your builded images"
- dialog = CrumbsDialog(title, self.builder,
- gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- dialog.set_border_width(12)
-
- label = gtk.Label()
- label.set_use_markup(True)
- label.set_alignment(0.0, 0.5)
- label.set_padding(12,0)
- if primary_action == "Run image":
- label.set_markup("<span font_desc='12'>Select the image file you want to run:</span>")
- elif primary_action == "Deploy image":
- label.set_markup("<span font_desc='12'>Select the image file you want to deploy:</span>")
- else:
- label.set_markup("<span font_desc='12'>Select the image file you want to %s</span>" % primary_action)
- dialog.vbox.pack_start(label, expand=False, fill=False)
-
- # filter created images as action attribution (deploy or run)
- action_attr = ""
- action_images = []
- for fileitem in self.image_store:
- action_attr = fileitem['action_attr']
- if (action_attr == 'run' and primary_action == "Run image") \
- or (action_attr == 'deploy' and primary_action == "Deploy image"):
- action_images.append(fileitem)
-
- # pack the corresponding 'runnable' or 'deploy' radio_buttons, if there has no more than one file.
- # assume that there does not both have 'deploy' and 'runnable' files in the same building result
- # in possible as design.
- curr_row = 0
- rows = (len(action_images)) if len(action_images) < 10 else 10
- table = gtk.Table(rows, 10, True)
- table.set_row_spacings(6)
- table.set_col_spacing(0, 12)
- table.set_col_spacing(5, 12)
-
- sel_parent_btn = None
- for fileitem in action_images:
- sel_btn = gtk.RadioButton(sel_parent_btn, fileitem['type'])
- sel_parent_btn = sel_btn if not sel_parent_btn else sel_parent_btn
- sel_btn.set_active(fileitem['is_toggled'])
- sel_btn.connect('toggled', self.table_selected_cb, fileitem)
- if curr_row < 10:
- table.attach(sel_btn, 0, 4, curr_row, curr_row + 1, xpadding=24)
- else:
- table.attach(sel_btn, 5, 9, curr_row - 10, curr_row - 9, xpadding=24)
- curr_row += 1
-
- dialog.vbox.pack_start(table, expand=False, fill=False, padding=6)
-
- button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
- HobAltButton.style_button(button)
-
- if primary_action:
- button = dialog.add_button(primary_action, gtk.RESPONSE_YES)
- HobButton.style_button(button)
-
- dialog.show_all()
-
- response = dialog.run()
- dialog.destroy()
-
- if response != gtk.RESPONSE_YES:
- return
-
- for fileitem in self.image_store:
- if fileitem['is_toggled']:
- if fileitem['action_attr'] == 'run':
- self.builder.runqemu_image(fileitem['name'], self.sel_kernel)
- elif fileitem['action_attr'] == 'deploy':
- self.builder.deploy_image(fileitem['name'])
-
- def table_selected_cb(self, tbutton, image):
- image['is_toggled'] = tbutton.get_active()
- if image['is_toggled']:
- self.toggled_image = image['name']
-
- def change_kernel_cb(self, widget):
- kernel_path = self.builder.show_load_kernel_dialog()
- if kernel_path and self.kernel_detail:
- import os.path
- self.sel_kernel = os.path.basename(kernel_path)
- markup = self.kernel_detail.format_line("Kernel: ", self.sel_kernel)
- label = ((self.kernel_detail.get_children()[0]).get_children()[0]).get_children()[0]
- label.set_markup(markup)
-
- def create_bottom_buttons(self, buttonlist, image_name):
- # Create the buttons at the bottom
- created = False
- packed = False
- self.button_ids = {}
- is_runnable = False
-
- # create button "Deploy image"
- name = "Deploy image"
- if name in buttonlist and self.test_deployable(image_name):
- deploy_button = HobButton('Deploy image')
- #deploy_button.set_size_request(205, 49)
- deploy_button.set_tooltip_text("Burn a live image to a USB drive or flash memory")
- deploy_button.set_flags(gtk.CAN_DEFAULT)
- button_id = deploy_button.connect("clicked", self.deploy_button_clicked_cb)
- self.button_ids[button_id] = deploy_button
- self.details_bottom_buttons.pack_end(deploy_button, expand=False, fill=False)
- created = True
- packed = True
-
- name = "Run image"
- if name in buttonlist and self.test_type_runnable(image_name) and self.test_mach_runnable(image_name):
- if created == True:
- # separator
- #label = gtk.Label(" or ")
- #self.details_bottom_buttons.pack_end(label, expand=False, fill=False)
-
- # create button "Run image"
- run_button = HobAltButton("Run image")
- else:
- # create button "Run image" as the primary button
- run_button = HobButton("Run image")
- #run_button.set_size_request(205, 49)
- run_button.set_flags(gtk.CAN_DEFAULT)
- packed = True
- run_button.set_tooltip_text("Start up an image with qemu emulator")
- button_id = run_button.connect("clicked", self.run_button_clicked_cb)
- self.button_ids[button_id] = run_button
- self.details_bottom_buttons.pack_end(run_button, expand=False, fill=False)
- created = True
- is_runnable = True
-
- name = "Save image recipe"
- if name in buttonlist and self.builder.recipe_model.is_custom_image():
- save_button = HobAltButton("Save image recipe")
- save_button.set_tooltip_text("Keep your changes saving them as an image recipe")
- save_button.set_sensitive(not self.image_saved)
- button_id = save_button.connect("clicked", self.save_button_clicked_cb)
- self.button_ids[button_id] = save_button
- self.details_bottom_buttons.pack_end(save_button, expand=False, fill=False)
-
- name = "Build new image"
- if name in buttonlist:
- # create button "Build new image"
- if packed:
- build_new_button = HobAltButton("Build new image")
- else:
- build_new_button = HobButton("Build new image")
- build_new_button.set_flags(gtk.CAN_DEFAULT)
- #build_new_button.set_size_request(205, 49)
- self.details_bottom_buttons.pack_end(build_new_button, expand=False, fill=False)
- build_new_button.set_tooltip_text("Create a new image from scratch")
- button_id = build_new_button.connect("clicked", self.build_new_button_clicked_cb)
- self.button_ids[button_id] = build_new_button
-
- return is_runnable
-
- def deploy_button_clicked_cb(self, button):
- if self.toggled_image:
- if self.num_toggled > 1:
- self.set_sensitive(False)
- self.show_builded_images_dialog(None, "Deploy image")
- self.set_sensitive(True)
- else:
- self.builder.deploy_image(self.toggled_image)
-
- def run_button_clicked_cb(self, button):
- if self.toggled_image:
- if self.num_toggled > 1:
- self.set_sensitive(False)
- self.show_builded_images_dialog(None, "Run image")
- self.set_sensitive(True)
- else:
- self.builder.runqemu_image(self.toggled_image, self.sel_kernel)
-
- def save_button_clicked_cb(self, button):
- topdir = self.builder.get_topdir()
- images_dir = topdir + "/recipes/images/custom/"
- self.builder.ensure_dir(images_dir)
-
- self.name_field_template = self.builder.image_configuration_page.custom_image_selected
- if self.name_field_template:
- image_path = self.builder.recipe_model.pn_path[self.name_field_template]
- image_iter = self.builder.recipe_model.get_iter(image_path)
- self.description_field_template = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC)
- else:
- self.name_field_template = ""
-
- dialog = SaveImageDialog(images_dir, self.name_field_template, self.description_field_template,
- "Save image recipe", self.builder, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
- response = dialog.run()
- dialog.destroy()
-
- def build_new_button_clicked_cb(self, button):
- self.builder.initiate_new_build_async()
-
- def edit_config_button_clicked_cb(self, button):
- self.builder.show_configuration()
-
- def edit_packages_button_clicked_cb(self, button):
- self.builder.show_packages()
-
- def my_images_button_clicked_cb(self, button):
- self.builder.show_load_my_images_dialog()
-
- def settings_button_clicked_cb(self, button):
- # Create an advanced settings dialog
- response, settings_changed = self.builder.show_simple_settings_dialog()
- if not response:
- return
- if settings_changed:
- self.builder.reparse_post_adv_settings()
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py
deleted file mode 100755
index 7c62b36e6..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/packageselectionpage.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import glib
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import HobViewTable, HobNotebook, HobAltButton, HobButton
-from bb.ui.crumbs.hoblistmodel import PackageListModel
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# PackageSelectionPage
-#
-class PackageSelectionPage (HobPage):
-
- pages = [
- {
- 'name' : 'Included packages',
- 'tooltip' : 'The packages currently included for your image',
- 'filter' : { PackageListModel.COL_INC : [True] },
- 'search' : 'Search packages by name',
- 'searchtip' : 'Enter a package name to find it',
- 'columns' : [{
- 'col_name' : 'Package name',
- 'col_id' : PackageListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 300,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Size',
- 'col_id' : PackageListModel.COL_SIZE,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 300,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Recipe',
- 'col_id' : PackageListModel.COL_RCP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 250,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Brought in by (+others)',
- 'col_id' : PackageListModel.COL_BINB,
- 'col_style': 'binb',
- 'col_min' : 100,
- 'col_max' : 350,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : PackageListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }, {
- 'name' : 'All packages',
- 'tooltip' : 'All packages that have been built',
- 'filter' : {},
- 'search' : 'Search packages by name',
- 'searchtip' : 'Enter a package name to find it',
- 'columns' : [{
- 'col_name' : 'Package name',
- 'col_id' : PackageListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Size',
- 'col_id' : PackageListModel.COL_SIZE,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 500,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Recipe',
- 'col_id' : PackageListModel.COL_RCP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 250,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : PackageListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }
- ]
-
- (INCLUDED,
- ALL) = range(2)
-
- def __init__(self, builder):
- super(PackageSelectionPage, self).__init__(builder, "Edit packages")
-
- # set invisible members
- self.recipe_model = self.builder.recipe_model
- self.package_model = self.builder.package_model
-
- # create visual elements
- self.create_visual_elements()
-
- def included_clicked_cb(self, button):
- self.ins.set_current_page(self.INCLUDED)
-
- def create_visual_elements(self):
- self.label = gtk.Label("Packages included: 0\nSelected packages size: 0 MB")
- self.eventbox = self.add_onto_top_bar(self.label, 73)
- self.pack_start(self.eventbox, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- # set visible members
- self.ins = HobNotebook()
- self.tables = [] # we need to modify table when the dialog is shown
-
- search_names = []
- search_tips = []
- # append the tab
- for page in self.pages:
- columns = page['columns']
- name = page['name']
- tab = HobViewTable(columns, name)
- search_names.append(page['search'])
- search_tips.append(page['searchtip'])
- filter = page['filter']
- sort_model = self.package_model.tree_model(filter, initial=True)
- tab.set_model(sort_model)
- tab.connect("toggled", self.table_toggled_cb, name)
- tab.connect("button-release-event", self.button_click_cb)
- tab.connect("cell-fadeinout-stopped", self.after_fadeout_checkin_include, filter)
- self.ins.append_page(tab, page['name'], page['tooltip'])
- self.tables.append(tab)
-
- self.ins.set_entry(search_names, search_tips)
- self.ins.search.connect("changed", self.search_entry_changed)
-
- # add all into the dialog
- self.box_group_area.pack_start(self.ins, expand=True, fill=True)
-
- self.button_box = gtk.HBox(False, 6)
- self.box_group_area.pack_start(self.button_box, expand=False, fill=False)
-
- self.build_image_button = HobButton('Build image')
- #self.build_image_button.set_size_request(205, 49)
- self.build_image_button.set_tooltip_text("Build target image")
- self.build_image_button.set_flags(gtk.CAN_DEFAULT)
- self.build_image_button.grab_default()
- self.build_image_button.connect("clicked", self.build_image_clicked_cb)
- self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
-
- self.back_button = HobAltButton('Cancel')
- self.back_button.connect("clicked", self.back_button_clicked_cb)
- self.button_box.pack_end(self.back_button, expand=False, fill=False)
-
- def search_entry_changed(self, entry):
- text = entry.get_text()
- if self.ins.search_focus:
- self.ins.search_focus = False
- elif self.ins.page_changed:
- self.ins.page_change = False
- self.filter_search(entry)
- elif text not in self.ins.search_names:
- self.filter_search(entry)
-
- def filter_search(self, entry):
- text = entry.get_text()
- current_tab = self.ins.get_current_page()
- filter = self.pages[current_tab]['filter']
- filter[PackageListModel.COL_NAME] = text
- self.tables[current_tab].set_model(self.package_model.tree_model(filter, search_data=text))
- if self.package_model.filtered_nb == 0:
- if not self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).add_no_result_bar(entry)
- self.ins.get_nth_page(current_tab).top_bar.set_no_show_all(True)
- self.ins.get_nth_page(current_tab).top_bar.show()
- self.ins.get_nth_page(current_tab).scroll.hide()
- else:
- if self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).top_bar.hide()
- self.ins.get_nth_page(current_tab).scroll.show()
- if entry.get_text() == '':
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False)
- else:
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, True)
-
- def button_click_cb(self, widget, event):
- path, col = widget.table_tree.get_cursor()
- tree_model = widget.table_tree.get_model()
- if path and col.get_title() != 'Included': # else activation is likely a removal
- properties = {'binb': '' , 'name': '', 'size':'', 'recipe':'', 'files_list':''}
- properties['binb'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_BINB)
- properties['name'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_NAME)
- properties['size'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_SIZE)
- properties['recipe'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_RCP)
- properties['files_list'] = tree_model.get_value(tree_model.get_iter(path), PackageListModel.COL_FLIST)
-
- self.builder.show_recipe_property_dialog(properties)
-
- def open_log_clicked_cb(self, button, log_file):
- if log_file:
- log_file = "file:///" + log_file
- gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)
-
- def show_page(self, log_file):
- children = self.button_box.get_children() or []
- for child in children:
- self.button_box.remove(child)
- # re-packed the buttons as request, add the 'open log' button if build success
- self.button_box.pack_end(self.build_image_button, expand=False, fill=False)
- if log_file:
- open_log_button = HobAltButton("Open log")
- open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
- open_log_button.set_tooltip_text("Open the build's log file")
- self.button_box.pack_end(open_log_button, expand=False, fill=False)
- self.button_box.pack_end(self.back_button, expand=False, fill=False)
- self.show_all()
-
- def build_image_clicked_cb(self, button):
- self.builder.parsing_warnings = []
- self.builder.build_image()
-
- def refresh_tables(self):
- self.ins.reset_entry(self.ins.search, 0)
- for tab in self.tables:
- index = self.tables.index(tab)
- filter = self.pages[index]['filter']
- tab.set_model(self.package_model.tree_model(filter, initial=True))
-
- def back_button_clicked_cb(self, button):
- if self.builder.previous_step == self.builder.IMAGE_GENERATED:
- self.builder.restore_initial_selected_packages()
- self.refresh_selection()
- self.builder.show_image_details()
- else:
- self.builder.show_configuration()
- self.refresh_tables()
-
- def refresh_selection(self):
- self.builder.configuration.selected_packages = self.package_model.get_selected_packages()
- self.builder.configuration.user_selected_packages = self.package_model.get_user_selected_packages()
- selected_packages_num = len(self.builder.configuration.selected_packages)
- selected_packages_size = self.package_model.get_packages_size()
- selected_packages_size_str = HobPage._size_to_string(selected_packages_size)
-
- if self.builder.configuration.image_packages == self.builder.configuration.selected_packages:
- image_total_size_str = self.builder.configuration.image_size
- else:
- image_overhead_factor = self.builder.configuration.image_overhead_factor
- image_rootfs_size = self.builder.configuration.image_rootfs_size / 1024 # image_rootfs_size is KB
- image_extra_size = self.builder.configuration.image_extra_size / 1024 # image_extra_size is KB
- base_size = image_overhead_factor * selected_packages_size
- image_total_size = max(base_size, image_rootfs_size) + image_extra_size
- if "zypper" in self.builder.configuration.selected_packages:
- image_total_size += (51200 * 1024)
- image_total_size_str = HobPage._size_to_string(image_total_size)
-
- self.label.set_label("Packages included: %s\nSelected packages size: %s\nEstimated image size: %s" %
- (selected_packages_num, selected_packages_size_str, image_total_size_str))
- self.ins.show_indicator_icon("Included packages", selected_packages_num)
-
- def toggle_item_idle_cb(self, path, view_tree, cell, pagename):
- if not self.package_model.path_included(path):
- self.package_model.include_item(item_path=path, binb="User Selected")
- else:
- self.pre_fadeout_checkout_include(view_tree)
- self.package_model.exclude_item(item_path=path)
- self.render_fadeout(view_tree, cell)
-
- self.refresh_selection()
- if not self.builder.customized:
- self.builder.customized = True
- self.builder.set_base_image()
- self.builder.configuration.selected_image = self.recipe_model.__custom_image__
- self.builder.rcppkglist_populated()
-
- self.builder.window_sensitive(True)
- view_model = view_tree.get_model()
- vpath = self.package_model.convert_path_to_vpath(view_model, path)
- view_tree.set_cursor(vpath)
-
- def table_toggled_cb(self, table, cell, view_path, toggled_columnid, view_tree, pagename):
- # Click to include a package
- self.builder.window_sensitive(False)
- view_model = view_tree.get_model()
- path = self.package_model.convert_vpath_to_path(view_model, view_path)
- glib.idle_add(self.toggle_item_idle_cb, path, view_tree, cell, pagename)
-
- def pre_fadeout_checkout_include(self, tree):
- #after the fadeout the table will be sorted as before
- self.sort_column_id = self.package_model.sort_column_id
- self.sort_order = self.package_model.sort_order
-
- self.package_model.resync_fadeout_column(self.package_model.get_iter_first())
- # Check out a model which base on the column COL_FADE_INC,
- # it's save the prev state of column COL_INC before do exclude_item
- filter = { PackageListModel.COL_FADE_INC : [True]}
- new_model = self.package_model.tree_model(filter, excluded_items_ahead=True)
- tree.set_model(new_model)
- tree.expand_all()
-
- def get_excluded_rows(self, to_render_cells, model, it):
- while it:
- path = model.get_path(it)
- prev_cell_is_active = model.get_value(it, PackageListModel.COL_FADE_INC)
- curr_cell_is_active = model.get_value(it, PackageListModel.COL_INC)
- if (prev_cell_is_active == True) and (curr_cell_is_active == False):
- to_render_cells.append(path)
- if model.iter_has_child(it):
- self.get_excluded_rows(to_render_cells, model, model.iter_children(it))
- it = model.iter_next(it)
-
- return to_render_cells
-
- def render_fadeout(self, tree, cell):
- if (not cell) or (not tree):
- return
- to_render_cells = []
- view_model = tree.get_model()
- self.get_excluded_rows(to_render_cells, view_model, view_model.get_iter_first())
-
- cell.fadeout(tree, 1000, to_render_cells)
-
- def after_fadeout_checkin_include(self, table, ctrl, cell, tree, filter):
- self.package_model.sort_column_id = self.sort_column_id
- self.package_model.sort_order = self.sort_order
- tree.set_model(self.package_model.tree_model(filter))
- tree.expand_all()
-
- def set_packages_curr_tab(self, curr_page):
- self.ins.set_current_page(curr_page)
-
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py
deleted file mode 100755
index 58db43f70..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/recipeselectionpage.py
+++ /dev/null
@@ -1,335 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-# Authored by Shane Wang <shane.wang@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import glib
-from bb.ui.crumbs.hobcolor import HobColors
-from bb.ui.crumbs.hobwidget import HobViewTable, HobNotebook, HobAltButton, HobButton
-from bb.ui.crumbs.hoblistmodel import RecipeListModel
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# RecipeSelectionPage
-#
-class RecipeSelectionPage (HobPage):
- pages = [
- {
- 'name' : 'Included recipes',
- 'tooltip' : 'The recipes currently included for your image',
- 'filter' : { RecipeListModel.COL_INC : [True],
- RecipeListModel.COL_TYPE : ['recipe', 'packagegroup'] },
- 'search' : 'Search recipes by name',
- 'searchtip' : 'Enter a recipe name to find it',
- 'columns' : [{
- 'col_name' : 'Recipe name',
- 'col_id' : RecipeListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Group',
- 'col_id' : RecipeListModel.COL_GROUP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 300,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Brought in by (+others)',
- 'col_id' : RecipeListModel.COL_BINB,
- 'col_style': 'binb',
- 'col_min' : 100,
- 'col_max' : 500,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : RecipeListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }, {
- 'name' : 'All recipes',
- 'tooltip' : 'All recipes in your configured layers',
- 'filter' : { RecipeListModel.COL_TYPE : ['recipe'] },
- 'search' : 'Search recipes by name',
- 'searchtip' : 'Enter a recipe name to find it',
- 'columns' : [{
- 'col_name' : 'Recipe name',
- 'col_id' : RecipeListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Group',
- 'col_id' : RecipeListModel.COL_GROUP,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'License',
- 'col_id' : RecipeListModel.COL_LIC,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : RecipeListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }, {
- 'name' : 'Package Groups',
- 'tooltip' : 'All package groups in your configured layers',
- 'filter' : { RecipeListModel.COL_TYPE : ['packagegroup'] },
- 'search' : 'Search package groups by name',
- 'searchtip' : 'Enter a package group name to find it',
- 'columns' : [{
- 'col_name' : 'Package group name',
- 'col_id' : RecipeListModel.COL_NAME,
- 'col_style': 'text',
- 'col_min' : 100,
- 'col_max' : 400,
- 'expand' : 'True'
- }, {
- 'col_name' : 'Included',
- 'col_id' : RecipeListModel.COL_INC,
- 'col_style': 'check toggle',
- 'col_min' : 100,
- 'col_max' : 100
- }]
- }
- ]
-
- (INCLUDED,
- ALL,
- TASKS) = range(3)
-
- def __init__(self, builder = None):
- super(RecipeSelectionPage, self).__init__(builder, "Step 1 of 2: Edit recipes")
-
- # set invisible members
- self.recipe_model = self.builder.recipe_model
-
- # create visual elements
- self.create_visual_elements()
-
- def included_clicked_cb(self, button):
- self.ins.set_current_page(self.INCLUDED)
-
- def create_visual_elements(self):
- self.eventbox = self.add_onto_top_bar(None, 73)
- self.pack_start(self.eventbox, expand=False, fill=False)
- self.pack_start(self.group_align, expand=True, fill=True)
-
- # set visible members
- self.ins = HobNotebook()
- self.tables = [] # we need modify table when the dialog is shown
-
- search_names = []
- search_tips = []
- # append the tabs in order
- for page in self.pages:
- columns = page['columns']
- name = page['name']
- tab = HobViewTable(columns, name)
- search_names.append(page['search'])
- search_tips.append(page['searchtip'])
- filter = page['filter']
- sort_model = self.recipe_model.tree_model(filter, initial=True)
- tab.set_model(sort_model)
- tab.connect("toggled", self.table_toggled_cb, name)
- tab.connect("button-release-event", self.button_click_cb)
- tab.connect("cell-fadeinout-stopped", self.after_fadeout_checkin_include, filter)
- self.ins.append_page(tab, page['name'], page['tooltip'])
- self.tables.append(tab)
-
- self.ins.set_entry(search_names, search_tips)
- self.ins.search.connect("changed", self.search_entry_changed)
-
- # add all into the window
- self.box_group_area.pack_start(self.ins, expand=True, fill=True)
-
- button_box = gtk.HBox(False, 6)
- self.box_group_area.pack_end(button_box, expand=False, fill=False)
-
- self.build_packages_button = HobButton('Build packages')
- #self.build_packages_button.set_size_request(205, 49)
- self.build_packages_button.set_tooltip_text("Build selected recipes into packages")
- self.build_packages_button.set_flags(gtk.CAN_DEFAULT)
- self.build_packages_button.grab_default()
- self.build_packages_button.connect("clicked", self.build_packages_clicked_cb)
- button_box.pack_end(self.build_packages_button, expand=False, fill=False)
-
- self.back_button = HobAltButton('Cancel')
- self.back_button.connect("clicked", self.back_button_clicked_cb)
- button_box.pack_end(self.back_button, expand=False, fill=False)
-
- def search_entry_changed(self, entry):
- text = entry.get_text()
- if self.ins.search_focus:
- self.ins.search_focus = False
- elif self.ins.page_changed:
- self.ins.page_change = False
- self.filter_search(entry)
- elif text not in self.ins.search_names:
- self.filter_search(entry)
-
- def filter_search(self, entry):
- text = entry.get_text()
- current_tab = self.ins.get_current_page()
- filter = self.pages[current_tab]['filter']
- filter[RecipeListModel.COL_NAME] = text
- self.tables[current_tab].set_model(self.recipe_model.tree_model(filter, search_data=text))
- if self.recipe_model.filtered_nb == 0:
- if not self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).add_no_result_bar(entry)
- self.ins.get_nth_page(current_tab).top_bar.set_no_show_all(True)
- self.ins.get_nth_page(current_tab).top_bar.show()
- self.ins.get_nth_page(current_tab).scroll.hide()
- else:
- if self.ins.get_nth_page(current_tab).top_bar:
- self.ins.get_nth_page(current_tab).top_bar.hide()
- self.ins.get_nth_page(current_tab).scroll.show()
- if entry.get_text() == '':
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, False)
- else:
- entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, True)
-
- def button_click_cb(self, widget, event):
- path, col = widget.table_tree.get_cursor()
- tree_model = widget.table_tree.get_model()
- if path and col.get_title() != 'Included': # else activation is likely a removal
- properties = {'summary': '', 'name': '', 'version': '', 'revision': '', 'binb': '', 'group': '', 'license': '', 'homepage': '', 'bugtracker': '', 'description': ''}
- properties['summary'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_SUMMARY)
- properties['name'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_NAME)
- properties['version'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_VERSION)
- properties['revision'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_REVISION)
- properties['binb'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_BINB)
- properties['group'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_GROUP)
- properties['license'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_LIC)
- properties['homepage'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_HOMEPAGE)
- properties['bugtracker'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_BUGTRACKER)
- properties['description'] = tree_model.get_value(tree_model.get_iter(path), RecipeListModel.COL_DESC)
- self.builder.show_recipe_property_dialog(properties)
-
- def build_packages_clicked_cb(self, button):
- self.refresh_tables()
- self.builder.build_packages()
-
- def refresh_tables(self):
- self.ins.reset_entry(self.ins.search, 0)
- for tab in self.tables:
- index = self.tables.index(tab)
- filter = self.pages[index]['filter']
- tab.set_model(self.recipe_model.tree_model(filter, search_data="", initial=True))
-
- def back_button_clicked_cb(self, button):
- self.builder.recipe_model.set_selected_image(self.builder.configuration.initial_selected_image)
- self.builder.image_configuration_page.update_image_combo(self.builder.recipe_model, self.builder.configuration.initial_selected_image)
- self.builder.image_configuration_page.update_image_desc()
- self.builder.show_configuration()
- self.refresh_tables()
-
- def refresh_selection(self):
- self.builder.configuration.selected_image = self.recipe_model.get_selected_image()
- _, self.builder.configuration.selected_recipes = self.recipe_model.get_selected_recipes()
- self.ins.show_indicator_icon("Included recipes", len(self.builder.configuration.selected_recipes))
-
- def toggle_item_idle_cb(self, path, view_tree, cell, pagename):
- if not self.recipe_model.path_included(path):
- self.recipe_model.include_item(item_path=path, binb="User Selected", image_contents=False)
- else:
- self.pre_fadeout_checkout_include(view_tree, pagename)
- self.recipe_model.exclude_item(item_path=path)
- self.render_fadeout(view_tree, cell)
-
- self.refresh_selection()
- if not self.builder.customized:
- self.builder.customized = True
- self.builder.configuration.selected_image = self.recipe_model.__custom_image__
- self.builder.rcppkglist_populated()
-
- self.builder.window_sensitive(True)
-
- view_model = view_tree.get_model()
- vpath = self.recipe_model.convert_path_to_vpath(view_model, path)
- view_tree.set_cursor(vpath)
-
- def table_toggled_cb(self, table, cell, view_path, toggled_columnid, view_tree, pagename):
- # Click to include a recipe
- self.builder.window_sensitive(False)
- view_model = view_tree.get_model()
- path = self.recipe_model.convert_vpath_to_path(view_model, view_path)
- glib.idle_add(self.toggle_item_idle_cb, path, view_tree, cell, pagename)
-
- def pre_fadeout_checkout_include(self, tree, pagename):
- #after the fadeout the table will be sorted as before
- self.sort_column_id = self.recipe_model.sort_column_id
- self.sort_order = self.recipe_model.sort_order
-
- #resync the included items to a backup fade include column
- it = self.recipe_model.get_iter_first()
- while it:
- active = self.recipe_model.get_value(it, self.recipe_model.COL_INC)
- self.recipe_model.set(it, self.recipe_model.COL_FADE_INC, active)
- it = self.recipe_model.iter_next(it)
- # Check out a model which base on the column COL_FADE_INC,
- # it's save the prev state of column COL_INC before do exclude_item
- filter = { RecipeListModel.COL_FADE_INC:[True] }
- if pagename == "Included recipes":
- filter[RecipeListModel.COL_TYPE] = ['recipe', 'packagegroup']
- elif pagename == "All recipes":
- filter[RecipeListModel.COL_TYPE] = ['recipe']
- else:
- filter[RecipeListModel.COL_TYPE] = ['packagegroup']
-
- new_model = self.recipe_model.tree_model(filter, excluded_items_ahead=True)
- tree.set_model(new_model)
-
- def render_fadeout(self, tree, cell):
- if (not cell) or (not tree):
- return
- to_render_cells = []
- model = tree.get_model()
- it = model.get_iter_first()
- while it:
- path = model.get_path(it)
- prev_cell_is_active = model.get_value(it, RecipeListModel.COL_FADE_INC)
- curr_cell_is_active = model.get_value(it, RecipeListModel.COL_INC)
- if (prev_cell_is_active == True) and (curr_cell_is_active == False):
- to_render_cells.append(path)
- it = model.iter_next(it)
-
- cell.fadeout(tree, 1000, to_render_cells)
-
- def after_fadeout_checkin_include(self, table, ctrl, cell, tree, filter):
- self.recipe_model.sort_column_id = self.sort_column_id
- self.recipe_model.sort_order = self.sort_order
- tree.set_model(self.recipe_model.tree_model(filter))
-
- def set_recipe_curr_tab(self, curr_page):
- self.ins.set_current_page(curr_page)
diff --git a/yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py b/yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py
deleted file mode 100644
index 76ce2ecc2..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/crumbs/sanitycheckpage.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2012 Intel Corporation
-#
-# Authored by Bogdan Marinescu <bogdan.a.marinescu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk, gobject
-from bb.ui.crumbs.progressbar import HobProgressBar
-from bb.ui.crumbs.hobwidget import hic
-from bb.ui.crumbs.hobpages import HobPage
-
-#
-# SanityCheckPage
-#
-class SanityCheckPage (HobPage):
-
- def __init__(self, builder):
- super(SanityCheckPage, self).__init__(builder)
- self.running = False
- self.create_visual_elements()
- self.show_all()
-
- def make_label(self, text, bold=True):
- label = gtk.Label()
- label.set_alignment(0.0, 0.5)
- mark = "<span %s>%s</span>" % (self.span_tag('x-large', 'bold') if bold else self.span_tag('medium'), text)
- label.set_markup(mark)
- return label
-
- def start(self):
- if not self.running:
- self.running = True
- gobject.timeout_add(100, self.timer_func)
-
- def stop(self):
- self.running = False
-
- def is_running(self):
- return self.running
-
- def timer_func(self):
- self.progress_bar.pulse()
- return self.running
-
- def create_visual_elements(self):
- # Table'd layout. 'rows' and 'cols' give the table size
- rows, cols = 30, 50
- self.table = gtk.Table(rows, cols, True)
- self.pack_start(self.table, expand=False, fill=False)
- sx, sy = 2, 2
- # 'info' icon
- image = gtk.Image()
- image.set_from_file(hic.ICON_INFO_DISPLAY_FILE)
- self.table.attach(image, sx, sx + 2, sy, sy + 3 )
- image.show()
- # 'Checking' message
- label = self.make_label('Hob is checking for correct build system setup')
- self.table.attach(label, sx + 2, cols, sy, sy + 3, xpadding=5 )
- label.show()
- # 'Shouldn't take long' message.
- label = self.make_label("The check shouldn't take long.", False)
- self.table.attach(label, sx + 2, cols, sy + 3, sy + 4, xpadding=5)
- label.show()
- # Progress bar
- self.progress_bar = HobProgressBar()
- self.table.attach(self.progress_bar, sx + 2, cols - 3, sy + 5, sy + 7, xpadding=5)
- self.progress_bar.show()
- # All done
- self.table.show()
-
diff --git a/yocto-poky/bitbake/lib/bb/ui/hob.py b/yocto-poky/bitbake/lib/bb/ui/hob.py
deleted file mode 100755
index da5b41189..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/hob.py
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env python
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2011 Intel Corporation
-#
-# Authored by Joshua Lock <josh@linux.intel.com>
-# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import sys
-import os
-requirements = "FATAL: Hob requires Gtk+ 2.20.0 or higher, PyGtk 2.21.0 or higher"
-try:
- import gobject
- import gtk
- import pygtk
- pygtk.require('2.0') # to be certain we don't have gtk+ 1.x !?!
- gtkver = gtk.gtk_version
- pygtkver = gtk.pygtk_version
- if gtkver < (2, 20, 0) or pygtkver < (2, 21, 0):
- sys.exit("%s,\nYou have Gtk+ %s and PyGtk %s." % (requirements,
- ".".join(map(str, gtkver)),
- ".".join(map(str, pygtkver))))
-except ImportError as exc:
- sys.exit("%s (%s)." % (requirements, str(exc)))
-sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
-try:
- import bb
-except RuntimeError as exc:
- sys.exit(str(exc))
-from bb.ui import uihelper
-from bb.ui.crumbs.hoblistmodel import RecipeListModel, PackageListModel
-from bb.ui.crumbs.hobeventhandler import HobHandler
-from bb.ui.crumbs.builder import Builder
-
-featureSet = [bb.cooker.CookerFeatures.HOB_EXTRA_CACHES, bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING]
-
-def event_handle_idle_func(eventHandler, hobHandler):
- # Consume as many messages as we can in the time available to us
- if not eventHandler:
- return False
- event = eventHandler.getEvent()
- while event:
- hobHandler.handle_event(event)
- event = eventHandler.getEvent()
- return True
-
-_evt_list = [ "bb.runqueue.runQueueExitWait", "bb.event.LogExecTTY", "logging.LogRecord",
- "bb.build.TaskFailed", "bb.build.TaskBase", "bb.event.ParseStarted",
- "bb.event.ParseProgress", "bb.event.ParseCompleted", "bb.event.CacheLoadStarted",
- "bb.event.CacheLoadProgress", "bb.event.CacheLoadCompleted", "bb.command.CommandFailed",
- "bb.command.CommandExit", "bb.command.CommandCompleted", "bb.cooker.CookerExit",
- "bb.event.MultipleProviders", "bb.event.NoProvider", "bb.runqueue.sceneQueueTaskStarted",
- "bb.runqueue.runQueueTaskStarted", "bb.runqueue.runQueueTaskFailed", "bb.runqueue.sceneQueueTaskFailed",
- "bb.event.BuildBase", "bb.build.TaskStarted", "bb.build.TaskSucceeded", "bb.build.TaskFailedSilent",
- "bb.event.SanityCheckPassed", "bb.event.SanityCheckFailed", "bb.event.PackageInfo",
- "bb.event.TargetsTreeGenerated", "bb.event.ConfigFilesFound", "bb.event.ConfigFilePathFound",
- "bb.event.FilesMatchingFound", "bb.event.NetworkTestFailed", "bb.event.NetworkTestPassed",
- "bb.event.BuildStarted", "bb.event.BuildCompleted", "bb.event.DiskFull"]
-
-def main (server, eventHandler, params):
- params.updateFromServer(server)
- gobject.threads_init()
-
- # That indicates whether the Hob and the bitbake server are
- # running on different machines
- # recipe model and package model
- recipe_model = RecipeListModel()
- package_model = PackageListModel()
-
- llevel, debug_domains = bb.msg.constructLogOptions()
- server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
- hobHandler = HobHandler(server, recipe_model, package_model)
- builder = Builder(hobHandler, recipe_model, package_model)
-
- # This timeout function regularly probes the event queue to find out if we
- # have any messages waiting for us.
- gobject.timeout_add(10, event_handle_idle_func, eventHandler, hobHandler)
-
- try:
- gtk.main()
- except EnvironmentError as ioerror:
- # ignore interrupted io
- if ioerror.args[0] == 4:
- pass
- finally:
- hobHandler.cancel_build(force = True)
-
-if __name__ == "__main__":
- try:
- ret = main()
- except Exception:
- ret = 1
- import traceback
- traceback.print_exc(15)
- sys.exit(ret)
diff --git a/yocto-poky/bitbake/lib/bb/ui/knotty.py b/yocto-poky/bitbake/lib/bb/ui/knotty.py
index 90c318376..268562770 100644
--- a/yocto-poky/bitbake/lib/bb/ui/knotty.py
+++ b/yocto-poky/bitbake/lib/bb/ui/knotty.py
@@ -104,10 +104,11 @@ class InteractConsoleLogFilter(logging.Filter):
return True
class TerminalFilter(object):
+ rows = 25
columns = 80
def sigwinch_handle(self, signum, frame):
- self.columns = self.getTerminalColumns()
+ self.rows, self.columns = self.getTerminalColumns()
if self._sigwinch_default:
self._sigwinch_default(signum, frame)
@@ -131,7 +132,7 @@ class TerminalFilter(object):
cr = (env['LINES'], env['COLUMNS'])
except:
cr = (25, 80)
- return cr[1]
+ return cr
def __init__(self, main, helper, console, errconsole, format):
self.main = main
@@ -170,9 +171,13 @@ class TerminalFilter(object):
signal.signal(signal.SIGWINCH, self.sigwinch_handle)
except:
pass
- self.columns = self.getTerminalColumns()
+ self.rows, self.columns = self.getTerminalColumns()
except:
self.cuu = None
+ if not self.cuu:
+ self.interactive = False
+ bb.note("Unable to use interactive mode for this terminal, using fallback")
+ return
console.addFilter(InteractConsoleLogFilter(self, format))
errconsole.addFilter(InteractConsoleLogFilter(self, format))
@@ -207,7 +212,7 @@ class TerminalFilter(object):
content = "Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)
print(content)
lines = 1 + int(len(content) / (self.columns + 1))
- for tasknum, task in enumerate(tasks):
+ for tasknum, task in enumerate(tasks[:(self.rows - 2)]):
content = "%s: %s" % (tasknum, task)
print(content)
lines = lines + 1 + int(len(content) / (self.columns + 1))
@@ -267,6 +272,8 @@ def main(server, eventHandler, params, tf = TerminalFilter):
logger.addHandler(console)
logger.addHandler(errconsole)
+ bb.utils.set_process_name("KnottyUI")
+
if params.options.remote_server and params.options.kill_server:
server.terminateServer()
return
@@ -282,6 +289,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
llevel, debug_domains = bb.msg.constructLogOptions()
server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
+ universe = False
if not params.observe_only:
params.updateFromServer(server)
params.updateToServer(server, os.environ.copy())
@@ -292,6 +300,8 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if 'msg' in cmdline and cmdline['msg']:
logger.error(cmdline['msg'])
return 1
+ if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]:
+ universe = True
ret, error = server.runCommand(cmdline['action'])
if error:
@@ -349,11 +359,20 @@ def main(server, eventHandler, params, tf = TerminalFilter):
return_value = 1
elif event.levelno == format.WARNING:
warnings = warnings + 1
- # For "normal" logging conditions, don't show note logs from tasks
- # but do show them if the user has changed the default log level to
- # include verbose/debug messages
- if event.taskpid != 0 and event.levelno <= format.NOTE and (event.levelno < llevel or (event.levelno == format.NOTE and llevel != format.VERBOSE)):
- continue
+
+ if event.taskpid != 0:
+ # For "normal" logging conditions, don't show note logs from tasks
+ # but do show them if the user has changed the default log level to
+ # include verbose/debug messages
+ if event.levelno <= format.NOTE and (event.levelno < llevel or (event.levelno == format.NOTE and llevel != format.VERBOSE)):
+ continue
+
+ # Prefix task messages with recipe/task
+ if event.taskpid in helper.running_tasks:
+ taskinfo = helper.running_tasks[event.taskpid]
+ event.msg = taskinfo['title'] + ': ' + event.msg
+ if hasattr(event, 'fn'):
+ event.msg = event.fn + ': ' + event.msg
logger.handle(event)
continue
@@ -434,11 +453,12 @@ def main(server, eventHandler, params, tf = TerminalFilter):
logger.info("multiple providers are available for %s%s (%s)", event._is_runtime and "runtime " or "",
event._item,
", ".join(event._candidates))
- logger.info("consider defining a PREFERRED_PROVIDER entry to match %s", event._item)
+ rtime = ""
+ if event._is_runtime:
+ rtime = "R"
+ logger.info("consider defining a PREFERRED_%sPROVIDER entry to match %s" % (rtime, event._item))
continue
if isinstance(event, bb.event.NoProvider):
- return_value = 1
- errors = errors + 1
if event._runtime:
r = "R"
else:
@@ -449,13 +469,20 @@ def main(server, eventHandler, params, tf = TerminalFilter):
if event._close_matches:
extra = ". Close matches:\n %s" % '\n '.join(event._close_matches)
+ # For universe builds, only show these as warnings, not errors
+ h = logger.warning
+ if not universe:
+ return_value = 1
+ errors = errors + 1
+ h = logger.error
+
if event._dependees:
- logger.error("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s", r, event._item, ", ".join(event._dependees), r, extra)
+ h("Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s", r, event._item, ", ".join(event._dependees), r, extra)
else:
- logger.error("Nothing %sPROVIDES '%s'%s", r, event._item, extra)
+ h("Nothing %sPROVIDES '%s'%s", r, event._item, extra)
if event._reasons:
for reason in event._reasons:
- logger.error("%s", reason)
+ h("%s", reason)
continue
if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
@@ -475,6 +502,7 @@ def main(server, eventHandler, params, tf = TerminalFilter):
continue
if isinstance(event, bb.runqueue.runQueueTaskFailed):
+ return_value = 1
taskfailures.append(event.taskstring)
logger.error("Task %s (%s) failed with exit code '%s'",
event.taskid, event.taskstring, event.exitcode)
@@ -532,10 +560,12 @@ def main(server, eventHandler, params, tf = TerminalFilter):
main.shutdown = main.shutdown + 1
pass
except Exception as e:
- sys.stderr.write(str(e))
+ import traceback
+ sys.stderr.write(traceback.format_exc())
if not params.observe_only:
_, error = server.runCommand(["stateForceShutdown"])
main.shutdown = 2
+ return_value = 1
try:
summary = ""
if taskfailures:
diff --git a/yocto-poky/bitbake/lib/bb/ui/puccho.py b/yocto-poky/bitbake/lib/bb/ui/puccho.py
deleted file mode 100644
index 3ce4590c1..000000000
--- a/yocto-poky/bitbake/lib/bb/ui/puccho.py
+++ /dev/null
@@ -1,425 +0,0 @@
-#
-# BitBake Graphical GTK User Interface
-#
-# Copyright (C) 2008 Intel Corporation
-#
-# Authored by Rob Bradford <rob@linux.intel.com>
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-import gtk
-import gobject
-import gtk.glade
-import threading
-import urllib2
-import os
-import contextlib
-
-from bb.ui.crumbs.buildmanager import BuildManager, BuildConfiguration
-from bb.ui.crumbs.buildmanager import BuildManagerTreeView
-
-from bb.ui.crumbs.runningbuild import RunningBuild, RunningBuildTreeView
-
-# The metadata loader is used by the BuildSetupDialog to download the
-# available options to populate the dialog
-class MetaDataLoader(gobject.GObject):
- """ This class provides the mechanism for loading the metadata (the
- fetching and parsing) from a given URL. The metadata encompasses details
- on what machines are available. The distribution and images available for
- the machine and the the uris to use for building the given machine."""
- __gsignals__ = {
- 'success' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- ()),
- 'error' : (gobject.SIGNAL_RUN_LAST,
- gobject.TYPE_NONE,
- (gobject.TYPE_STRING,))
- }
-
- # We use these little helper functions to ensure that we take the gdk lock
- # when emitting the signal. These functions are called as idles (so that
- # they happen in the gtk / main thread's main loop.
- def emit_error_signal (self, remark):
- gtk.gdk.threads_enter()
- self.emit ("error", remark)
- gtk.gdk.threads_leave()
-
- def emit_success_signal (self):
- gtk.gdk.threads_enter()
- self.emit ("success")
- gtk.gdk.threads_leave()
-
- def __init__ (self):
- gobject.GObject.__init__ (self)
-
- class LoaderThread(threading.Thread):
- """ This class provides an asynchronous loader for the metadata (by
- using threads and signals). This is useful since the metadata may be
- at a remote URL."""
- class LoaderImportException (Exception):
- pass
-
- def __init__(self, loader, url):
- threading.Thread.__init__ (self)
- self.url = url
- self.loader = loader
-
- def run (self):
- result = {}
- try:
- with contextlib.closing (urllib2.urlopen (self.url)) as f:
- # Parse the metadata format. The format is....
- # <machine>;<default distro>|<distro>...;<default image>|<image>...;<type##url>|...
- for line in f:
- components = line.split(";")
- if (len (components) < 4):
- raise MetaDataLoader.LoaderThread.LoaderImportException
- machine = components[0]
- distros = components[1].split("|")
- images = components[2].split("|")
- urls = components[3].split("|")
-
- result[machine] = (distros, images, urls)
-
- # Create an object representing this *potential*
- # configuration. It can become concrete if the machine, distro
- # and image are all chosen in the UI
- configuration = BuildConfiguration()
- configuration.metadata_url = self.url
- configuration.machine_options = result
- self.loader.configuration = configuration
-
- # Emit that we've actually got a configuration
- gobject.idle_add (MetaDataLoader.emit_success_signal,
- self.loader)
-
- except MetaDataLoader.LoaderThread.LoaderImportException as e:
- gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader,
- "Repository metadata corrupt")
- except Exception as e:
- gobject.idle_add (MetaDataLoader.emit_error_signal, self.loader,
- "Unable to download repository metadata")
- print(e)
-
- def try_fetch_from_url (self, url):
- # Try and download the metadata. Firing a signal if successful
- thread = MetaDataLoader.LoaderThread(self, url)
- thread.start()
-
-class BuildSetupDialog (gtk.Dialog):
- RESPONSE_BUILD = 1
-
- # A little helper method that just sets the states on the widgets based on
- # whether we've got good metadata or not.
- def set_configurable (self, configurable):
- if (self.configurable == configurable):
- return
-
- self.configurable = configurable
- for widget in self.conf_widgets:
- widget.set_sensitive (configurable)
-
- if not configurable:
- self.machine_combo.set_active (-1)
- self.distribution_combo.set_active (-1)
- self.image_combo.set_active (-1)
-
- # GTK widget callbacks
- def refresh_button_clicked (self, button):
- # Refresh button clicked.
-
- url = self.location_entry.get_chars (0, -1)
- self.loader.try_fetch_from_url(url)
-
- def repository_entry_editable_changed (self, entry):
- if (len (entry.get_chars (0, -1)) > 0):
- self.refresh_button.set_sensitive (True)
- else:
- self.refresh_button.set_sensitive (False)
- self.clear_status_message()
-
- # If we were previously configurable we are no longer since the
- # location entry has been changed
- self.set_configurable (False)
-
- def machine_combo_changed (self, combobox):
- active_iter = combobox.get_active_iter()
-
- if not active_iter:
- return
-
- model = combobox.get_model()
-
- if model:
- chosen_machine = model.get (active_iter, 0)[0]
-
- (distros_model, images_model) = \
- self.loader.configuration.get_distro_and_images_models (chosen_machine)
-
- self.distribution_combo.set_model (distros_model)
- self.image_combo.set_model (images_model)
-
- # Callbacks from the loader
- def loader_success_cb (self, loader):
- self.status_image.set_from_icon_name ("info",
- gtk.ICON_SIZE_BUTTON)
- self.status_image.show()
- self.status_label.set_label ("Repository metadata successfully downloaded")
-
- # Set the models on the combo boxes based on the models generated from
- # the configuration that the loader has created
-
- # We just need to set the machine here, that then determines the
- # distro and image options. Cunning huh? :-)
-
- self.configuration = self.loader.configuration
- model = self.configuration.get_machines_model ()
- self.machine_combo.set_model (model)
-
- self.set_configurable (True)
-
- def loader_error_cb (self, loader, message):
- self.status_image.set_from_icon_name ("error",
- gtk.ICON_SIZE_BUTTON)
- self.status_image.show()
- self.status_label.set_text ("Error downloading repository metadata")
- for widget in self.conf_widgets:
- widget.set_sensitive (False)
-
- def clear_status_message (self):
- self.status_image.hide()
- self.status_label.set_label (
- """<i>Enter the repository location and press _Refresh</i>""")
-
- def __init__ (self):
- gtk.Dialog.__init__ (self)
-
- # Cancel
- self.add_button (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
-
- # Build
- button = gtk.Button ("_Build", None, True)
- image = gtk.Image ()
- image.set_from_stock (gtk.STOCK_EXECUTE, gtk.ICON_SIZE_BUTTON)
- button.set_image (image)
- self.add_action_widget (button, BuildSetupDialog.RESPONSE_BUILD)
- button.show_all ()
-
- # Pull in *just* the table from the Glade XML data.
- gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade",
- root = "build_table")
- table = gxml.get_widget ("build_table")
- self.vbox.pack_start (table, True, False, 0)
-
- # Grab all the widgets that we need to turn on/off when we refresh...
- self.conf_widgets = []
- self.conf_widgets += [gxml.get_widget ("machine_label")]
- self.conf_widgets += [gxml.get_widget ("distribution_label")]
- self.conf_widgets += [gxml.get_widget ("image_label")]
- self.conf_widgets += [gxml.get_widget ("machine_combo")]
- self.conf_widgets += [gxml.get_widget ("distribution_combo")]
- self.conf_widgets += [gxml.get_widget ("image_combo")]
-
- # Grab the status widgets
- self.status_image = gxml.get_widget ("status_image")
- self.status_label = gxml.get_widget ("status_label")
-
- # Grab the refresh button and connect to the clicked signal
- self.refresh_button = gxml.get_widget ("refresh_button")
- self.refresh_button.connect ("clicked", self.refresh_button_clicked)
-
- # Grab the location entry and connect to editable::changed
- self.location_entry = gxml.get_widget ("location_entry")
- self.location_entry.connect ("changed",
- self.repository_entry_editable_changed)
-
- # Grab the machine combo and hook onto the changed signal. This then
- # allows us to populate the distro and image combos
- self.machine_combo = gxml.get_widget ("machine_combo")
- self.machine_combo.connect ("changed", self.machine_combo_changed)
-
- # Setup the combo
- cell = gtk.CellRendererText()
- self.machine_combo.pack_start(cell, True)
- self.machine_combo.add_attribute(cell, 'text', 0)
-
- # Grab the distro and image combos. We need these to populate with
- # models once the machine is chosen
- self.distribution_combo = gxml.get_widget ("distribution_combo")
- cell = gtk.CellRendererText()
- self.distribution_combo.pack_start(cell, True)
- self.distribution_combo.add_attribute(cell, 'text', 0)
-
- self.image_combo = gxml.get_widget ("image_combo")
- cell = gtk.CellRendererText()
- self.image_combo.pack_start(cell, True)
- self.image_combo.add_attribute(cell, 'text', 0)
-
- # Put the default descriptive text in the status box
- self.clear_status_message()
-
- # Mark as non-configurable, this is just greys out the widgets the
- # user can't yet use
- self.configurable = False
- self.set_configurable(False)
-
- # Show the table
- table.show_all ()
-
- # The loader and some signals connected to it to update the status
- # area
- self.loader = MetaDataLoader()
- self.loader.connect ("success", self.loader_success_cb)
- self.loader.connect ("error", self.loader_error_cb)
-
- def update_configuration (self):
- """ A poorly named function but it updates the internal configuration
- from the widgets. This can make that configuration concrete and can
- thus be used for building """
- # Extract the chosen machine from the combo
- model = self.machine_combo.get_model()
- active_iter = self.machine_combo.get_active_iter()
- if (active_iter):
- self.configuration.machine = model.get(active_iter, 0)[0]
-
- # Extract the chosen distro from the combo
- model = self.distribution_combo.get_model()
- active_iter = self.distribution_combo.get_active_iter()
- if (active_iter):
- self.configuration.distro = model.get(active_iter, 0)[0]
-
- # Extract the chosen image from the combo
- model = self.image_combo.get_model()
- active_iter = self.image_combo.get_active_iter()
- if (active_iter):
- self.configuration.image = model.get(active_iter, 0)[0]
-
-# This function operates to pull events out from the event queue and then push
-# them into the RunningBuild (which then drives the RunningBuild which then
-# pushes through and updates the progress tree view.)
-#
-# TODO: Should be a method on the RunningBuild class
-def event_handle_timeout (eventHandler, build):
- # Consume as many messages as we can ...
- event = eventHandler.getEvent()
- while event:
- build.handle_event (event)
- event = eventHandler.getEvent()
- return True
-
-class MainWindow (gtk.Window):
-
- # Callback that gets fired when the user hits a button in the
- # BuildSetupDialog.
- def build_dialog_box_response_cb (self, dialog, response_id):
- conf = None
- if (response_id == BuildSetupDialog.RESPONSE_BUILD):
- dialog.update_configuration()
- print(dialog.configuration.machine, dialog.configuration.distro, \
- dialog.configuration.image)
- conf = dialog.configuration
-
- dialog.destroy()
-
- if conf:
- self.manager.do_build (conf)
-
- def build_button_clicked_cb (self, button):
- dialog = BuildSetupDialog ()
-
- # For some unknown reason Dialog.run causes nice little deadlocks ... :-(
- dialog.connect ("response", self.build_dialog_box_response_cb)
- dialog.show()
-
- def __init__ (self):
- gtk.Window.__init__ (self)
-
- # Pull in *just* the main vbox from the Glade XML data and then pack
- # that inside the window
- gxml = gtk.glade.XML (os.path.dirname(__file__) + "/crumbs/puccho.glade",
- root = "main_window_vbox")
- vbox = gxml.get_widget ("main_window_vbox")
- self.add (vbox)
-
- # Create the tree views for the build manager view and the progress view
- self.build_manager_view = BuildManagerTreeView()
- self.running_build_view = RunningBuildTreeView()
-
- # Grab the scrolled windows that we put the tree views into
- self.results_scrolledwindow = gxml.get_widget ("results_scrolledwindow")
- self.progress_scrolledwindow = gxml.get_widget ("progress_scrolledwindow")
-
- # Put the tree views inside ...
- self.results_scrolledwindow.add (self.build_manager_view)
- self.progress_scrolledwindow.add (self.running_build_view)
-
- # Hook up the build button...
- self.build_button = gxml.get_widget ("main_toolbutton_build")
- self.build_button.connect ("clicked", self.build_button_clicked_cb)
-
-# I'm not very happy about the current ownership of the RunningBuild. I have
-# my suspicions that this object should be held by the BuildManager since we
-# care about the signals in the manager
-
-def running_build_succeeded_cb (running_build, manager):
- # Notify the manager that a build has succeeded. This is necessary as part
- # of the 'hack' that we use for making the row in the model / view
- # representing the ongoing build change into a row representing the
- # completed build. Since we know only one build can be running a time then
- # we can handle this.
-
- # FIXME: Refactor all this so that the RunningBuild is owned by the
- # BuildManager. It can then hook onto the signals directly and drive
- # interesting things it cares about.
- manager.notify_build_succeeded ()
- print("build succeeded")
-
-def running_build_failed_cb (running_build, manager):
- # As above
- print("build failed")
- manager.notify_build_failed ()
-
-def main (server, eventHandler):
- # Initialise threading...
- gobject.threads_init()
- gtk.gdk.threads_init()
-
- main_window = MainWindow ()
- main_window.show_all ()
-
- # Set up the build manager stuff in general
- builds_dir = os.path.join (os.getcwd(), "results")
- manager = BuildManager (server, builds_dir)
- main_window.build_manager_view.set_model (manager.model)
-
- # Do the running build setup
- running_build = RunningBuild ()
- main_window.running_build_view.set_model (running_build.model)
- running_build.connect ("build-succeeded", running_build_succeeded_cb,
- manager)
- running_build.connect ("build-failed", running_build_failed_cb, manager)
-
- # We need to save the manager into the MainWindow so that the toolbar
- # button can use it.
- # FIXME: Refactor ?
- main_window.manager = manager
-
- # Use a timeout function for probing the event queue to find out if we
- # have a message waiting for us.
- gobject.timeout_add (200,
- event_handle_timeout,
- eventHandler,
- running_build)
-
- gtk.main()
diff --git a/yocto-poky/bitbake/lib/bb/ui/toasterui.py b/yocto-poky/bitbake/lib/bb/ui/toasterui.py
index 3d261503e..6bf4c1f03 100644
--- a/yocto-poky/bitbake/lib/bb/ui/toasterui.py
+++ b/yocto-poky/bitbake/lib/bb/ui/toasterui.py
@@ -92,6 +92,43 @@ def _close_build_log(build_log):
build_log.close()
logger.removeHandler(build_log)
+_evt_list = [
+ "bb.build.TaskBase",
+ "bb.build.TaskFailed",
+ "bb.build.TaskFailedSilent",
+ "bb.build.TaskStarted",
+ "bb.build.TaskSucceeded",
+ "bb.command.CommandCompleted",
+ "bb.command.CommandExit",
+ "bb.command.CommandFailed",
+ "bb.cooker.CookerExit",
+ "bb.event.BuildCompleted",
+ "bb.event.BuildStarted",
+ "bb.event.CacheLoadCompleted",
+ "bb.event.CacheLoadProgress",
+ "bb.event.CacheLoadStarted",
+ "bb.event.ConfigParsed",
+ "bb.event.DepTreeGenerated",
+ "bb.event.LogExecTTY",
+ "bb.event.MetadataEvent",
+ "bb.event.MultipleProviders",
+ "bb.event.NoProvider",
+ "bb.event.ParseCompleted",
+ "bb.event.ParseProgress",
+ "bb.event.RecipeParsed",
+ "bb.event.SanityCheck",
+ "bb.event.SanityCheckPassed",
+ "bb.event.TreeDataPreparationCompleted",
+ "bb.event.TreeDataPreparationStarted",
+ "bb.runqueue.runQueueTaskCompleted",
+ "bb.runqueue.runQueueTaskFailed",
+ "bb.runqueue.runQueueTaskSkipped",
+ "bb.runqueue.runQueueTaskStarted",
+ "bb.runqueue.sceneQueueTaskCompleted",
+ "bb.runqueue.sceneQueueTaskFailed",
+ "bb.runqueue.sceneQueueTaskStarted",
+ "logging.LogRecord"]
+
def main(server, eventHandler, params):
# set to a logging.FileHandler instance when a build starts;
# see _open_build_log()
@@ -115,6 +152,11 @@ def main(server, eventHandler, params):
console.setFormatter(formatter)
logger.addHandler(console)
logger.setLevel(logging.INFO)
+ llevel, debug_domains = bb.msg.constructLogOptions()
+ result, error = server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
+ if not result or error:
+ logger.error("can't set event mask: %s", error)
+ return 1
# verify and warn
build_history_enabled = True
@@ -125,8 +167,23 @@ def main(server, eventHandler, params):
build_history_enabled = False
if not params.observe_only:
- logger.error("ToasterUI can only work in observer mode")
- return 1
+ params.updateFromServer(server)
+ params.updateToServer(server, os.environ.copy())
+ cmdline = params.parseActions()
+ if not cmdline:
+ print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
+ return 1
+ if 'msg' in cmdline and cmdline['msg']:
+ logger.error(cmdline['msg'])
+ return 1
+
+ ret, error = server.runCommand(cmdline['action'])
+ if error:
+ logger.error("Command '%s' failed: %s" % (cmdline, error))
+ return 1
+ elif ret != True:
+ logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
+ return 1
# set to 1 when toasterui needs to shut down
main.shutdown = 0
@@ -138,7 +195,8 @@ def main(server, eventHandler, params):
taskfailures = []
first = True
- buildinfohelper = BuildInfoHelper(server, build_history_enabled)
+ buildinfohelper = BuildInfoHelper(server, build_history_enabled,
+ os.getenv('TOASTER_BRBE'))
# write our own log files into bitbake's log directory;
# we're only interested in the path to the parent directory of
@@ -182,12 +240,11 @@ def main(server, eventHandler, params):
continue
if isinstance(event, bb.event.BuildStarted):
- # command-line builds don't fire a ParseStarted event,
- # so we have to start the log file for those on BuildStarted instead
if not (build_log and build_log_file_path):
build_log, build_log_file_path = _open_build_log(log_dir)
buildinfohelper.store_started_build(event, build_log_file_path)
+ continue
if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded, bb.build.TaskFailedSilent)):
buildinfohelper.update_and_store_task(event)
@@ -315,28 +372,30 @@ def main(server, eventHandler, params):
# update the build info helper on BuildCompleted, not on CommandXXX
buildinfohelper.update_build_information(event, errors, warnings, taskfailures)
+
+ brbe = buildinfohelper.brbe
buildinfohelper.close(errorcode)
- # mark the log output; controllers may kill the toasterUI after seeing this log
- logger.info("ToasterUI build done 1, brbe: %s", buildinfohelper.brbe )
# we start a new build info
- if buildinfohelper.brbe is not None:
- logger.debug("ToasterUI under BuildEnvironment management - exiting after the build")
- server.terminateServer()
- else:
+ if params.observe_only:
logger.debug("ToasterUI prepared for new build")
errors = 0
warnings = 0
taskfailures = []
buildinfohelper = BuildInfoHelper(server, build_history_enabled)
+ else:
+ main.shutdown = 1
- logger.info("ToasterUI build done 2")
+ logger.info("ToasterUI build done, brbe: %s", brbe)
continue
if isinstance(event, (bb.command.CommandCompleted,
bb.command.CommandFailed,
bb.command.CommandExit)):
- errorcode = 0
+ if params.observe_only:
+ errorcode = 0
+ else:
+ main.shutdown = 1
continue
@@ -357,6 +416,10 @@ def main(server, eventHandler, params):
buildinfohelper.update_artifact_image_file(event)
elif event.type == "LicenseManifestPath":
buildinfohelper.store_license_manifest_path(event)
+ elif event.type == "SetBRBE":
+ buildinfohelper.brbe = buildinfohelper._get_data_from_event(event)
+ elif event.type == "OSErrorException":
+ logger.error(event)
else:
logger.error("Unprocessed MetadataEvent %s ", str(event))
continue
@@ -366,19 +429,6 @@ def main(server, eventHandler, params):
main.shutdown = 1
continue
- # ignore
- if isinstance(event, (bb.event.BuildBase,
- bb.event.StampUpdate,
- bb.event.RecipePreFinalise,
- bb.runqueue.runQueueEvent,
- bb.runqueue.runQueueExitWait,
- bb.event.OperationProgress,
- bb.command.CommandFailed,
- bb.command.CommandExit,
- bb.command.CommandCompleted,
- bb.event.ReachableStamps)):
- continue
-
if isinstance(event, bb.event.DepTreeGenerated):
buildinfohelper.store_dependency_information(event)
continue
@@ -399,13 +449,6 @@ def main(server, eventHandler, params):
exception_data = traceback.format_exc()
logger.error("%s\n%s" , e, exception_data)
- _, _, tb = sys.exc_info()
- if tb is not None:
- curr = tb
- while curr is not None:
- logger.error("Error data dump %s\n%s\n" , traceback.format_tb(curr,1), pformat(curr.tb_frame.f_locals))
- curr = curr.tb_next
-
# save them to database, if possible; if it fails, we already logged to console.
try:
buildinfohelper.store_log_exception("%s\n%s" % (str(e), exception_data))
diff --git a/yocto-poky/bitbake/lib/bb/ui/uievent.py b/yocto-poky/bitbake/lib/bb/ui/uievent.py
index 7fc50c759..df093c53c 100644
--- a/yocto-poky/bitbake/lib/bb/ui/uievent.py
+++ b/yocto-poky/bitbake/lib/bb/ui/uievent.py
@@ -24,7 +24,7 @@ server and queue them for the UI to process. This process must be used to avoid
client/server deadlocks.
"""
-import socket, threading, pickle
+import socket, threading, pickle, collections
from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
class BBUIEventQueue:
@@ -44,27 +44,32 @@ class BBUIEventQueue:
server.register_function( self.send_event, "event.sendpickle" )
server.socket.settimeout(1)
- self.EventHandler = None
- count_tries = 0
+ self.EventHandle = None
# the event handler registration may fail here due to cooker being in invalid state
# this is a transient situation, and we should retry a couple of times before
# giving up
- while self.EventHandler == None and count_tries < 5:
- self.EventHandle = self.BBServer.registerEventHandler(self.host, self.port)
+ for count_tries in range(5):
+ ret = self.BBServer.registerEventHandler(self.host, self.port)
- if (self.EventHandle != None):
+ if isinstance(ret, collections.Iterable):
+ self.EventHandle, error = ret
+ else:
+ self.EventHandle = ret
+ error = ""
+
+ if self.EventHandle != None:
break
- bb.warn("Could not register UI event handler %s:%d, retry" % (self.host, self.port))
- count_tries += 1
+ errmsg = "Could not register UI event handler. Error: %s, host %s, "\
+ "port %d" % (error, self.host, self.port)
+ bb.warn("%s, retry" % errmsg)
+
import time
time.sleep(1)
-
-
- if self.EventHandle == None:
- raise Exception("Could not register UI event handler")
+ else:
+ raise Exception(errmsg)
self.server = server
@@ -105,6 +110,7 @@ class BBUIEventQueue:
def startCallbackHandler(self):
self.server.timeout = 1
+ bb.utils.set_process_name("UIEventQueue")
while not self.server.quit:
try:
self.server.handle_request()
diff --git a/yocto-poky/bitbake/lib/bb/ui/uihelper.py b/yocto-poky/bitbake/lib/bb/ui/uihelper.py
index a703387fb..db70b763f 100644
--- a/yocto-poky/bitbake/lib/bb/ui/uihelper.py
+++ b/yocto-poky/bitbake/lib/bb/ui/uihelper.py
@@ -57,44 +57,3 @@ class BBUIHelper:
self.needUpdate = False
return (self.running_tasks, self.failed_tasks)
- def findServerDetails(self):
- import sys
- import optparse
- from bb.server.xmlrpc import BitbakeServerInfo, BitBakeServerConnection
- host = ""
- port = 0
- bind = ""
- parser = optparse.OptionParser(
- usage = """%prog -H host -P port -B bindaddr""")
-
- parser.add_option("-H", "--host", help = "Bitbake server's IP address",
- action = "store", dest = "host", default = None)
-
- parser.add_option("-P", "--port", help = "Bitbake server's Port number",
- action = "store", dest = "port", default = None)
-
- parser.add_option("-B", "--bind", help = "Hob2 local bind address",
- action = "store", dest = "bind", default = None)
-
- options, args = parser.parse_args(sys.argv)
- for key, val in options.__dict__.items():
- if key == 'host' and val:
- host = val
- elif key == 'port' and val:
- port = int(val)
- elif key == 'bind' and val:
- bind = val
-
- if not host or not port or not bind:
- parser.print_usage()
- sys.exit(1)
-
- serverinfo = BitbakeServerInfo(host, port)
- clientinfo = (bind, 0)
- connection = BitBakeServerConnection(serverinfo, clientinfo)
-
- server = connection.connection
- eventHandler = connection.events
-
- return server, eventHandler, host, bind
-
diff --git a/yocto-poky/bitbake/lib/bb/utils.py b/yocto-poky/bitbake/lib/bb/utils.py
index 31ec2b7c9..3544bbe17 100644
--- a/yocto-poky/bitbake/lib/bb/utils.py
+++ b/yocto-poky/bitbake/lib/bb/utils.py
@@ -33,6 +33,7 @@ import fnmatch
import traceback
import errno
import signal
+import ast
from commands import getstatusoutput
from contextlib import contextmanager
from ctypes import cdll
@@ -291,19 +292,26 @@ def _print_trace(body, line):
error.append(' %.4d:%s' % (i, body[i-1].rstrip()))
return error
-def better_compile(text, file, realfile, mode = "exec"):
+def better_compile(text, file, realfile, mode = "exec", lineno = 0):
"""
A better compile method. This method
will print the offending lines.
"""
try:
- return compile(text, file, mode)
+ cache = bb.methodpool.compile_cache(text)
+ if cache:
+ return cache
+ # We can't add to the linenumbers for compile, we can pad to the correct number of blank lines though
+ text2 = "\n" * int(lineno) + text
+ code = compile(text2, realfile, mode)
+ bb.methodpool.compile_cache_add(text, code)
+ return code
except Exception as e:
error = []
# split the text into lines again
body = text.split('\n')
- error.append("Error in compiling python function in %s:\n" % realfile)
- if e.lineno:
+ error.append("Error in compiling python function in %s, line %s:\n" % (realfile, lineno))
+ if hasattr(e, "lineno"):
error.append("The code lines resulting in this error were:")
error.extend(_print_trace(body, e.lineno))
else:
@@ -323,8 +331,10 @@ def _print_exception(t, value, tb, realfile, text, context):
exception = traceback.format_exception_only(t, value)
error.append('Error executing a python function in %s:\n' % realfile)
- # Strip 'us' from the stack (better_exec call)
- tb = tb.tb_next
+ # Strip 'us' from the stack (better_exec call) unless that was where the
+ # error came from
+ if tb.tb_next is not None:
+ tb = tb.tb_next
textarray = text.split('\n')
@@ -353,15 +363,6 @@ def _print_exception(t, value, tb, realfile, text, context):
error.extend(_print_trace(text, tbextract[level+1][1]))
except:
error.append(tbformat[level+1])
- elif "d" in context and tbextract[level+1][2]:
- # Try and find the code in the datastore based on the functionname
- d = context["d"]
- functionname = tbextract[level+1][2]
- text = d.getVar(functionname, True)
- if text:
- error.extend(_print_trace(text.split('\n'), tbextract[level+1][1]))
- else:
- error.append(tbformat[level+1])
else:
error.append(tbformat[level+1])
nexttb = tb.tb_next
@@ -371,7 +372,7 @@ def _print_exception(t, value, tb, realfile, text, context):
finally:
logger.error("\n".join(error))
-def better_exec(code, context, text = None, realfile = "<code>"):
+def better_exec(code, context, text = None, realfile = "<code>", pythonexception=False):
"""
Similiar to better_compile, better_exec will
print the lines that are responsible for the
@@ -388,6 +389,8 @@ def better_exec(code, context, text = None, realfile = "<code>"):
# Error already shown so passthrough, no need for traceback
raise
except Exception as e:
+ if pythonexception:
+ raise
(t, value, tb) = sys.exc_info()
try:
_print_exception(t, value, tb, realfile, text, context)
@@ -533,6 +536,21 @@ def sha256_file(filename):
s.update(line)
return s.hexdigest()
+def sha1_file(filename):
+ """
+ Return the hex string representation of the SHA1 checksum of the filename
+ """
+ try:
+ import hashlib
+ except ImportError:
+ return None
+
+ s = hashlib.sha1()
+ with open(filename, "rb") as f:
+ for line in f:
+ s.update(line)
+ return s.hexdigest()
+
def preserved_envvars_exported():
"""Variables which are taken from the environment and placed in and exported
from the metadata"""
@@ -621,7 +639,7 @@ def build_environment(d):
"""
import bb.data
for var in bb.data.keys(d):
- export = d.getVarFlag(var, "export")
+ export = d.getVarFlag(var, "export", False)
if export:
os.environ[var] = d.getVar(var, True) or ""
@@ -906,6 +924,24 @@ def to_boolean(string, default=None):
raise ValueError("Invalid value for to_boolean: %s" % string)
def contains(variable, checkvalues, truevalue, falsevalue, d):
+ """Check if a variable contains all the values specified.
+
+ Arguments:
+
+ variable -- the variable name. This will be fetched and expanded (using
+ d.getVar(variable, True)) and then split into a set().
+
+ checkvalues -- if this is a string it is split on whitespace into a set(),
+ otherwise coerced directly into a set().
+
+ truevalue -- the value to return if checkvalues is a subset of variable.
+
+ falsevalue -- the value to return if variable is empty or if checkvalues is
+ not a subset of variable.
+
+ d -- the data store.
+ """
+
val = d.getVar(variable, True)
if not val:
return falsevalue
@@ -914,7 +950,7 @@ def contains(variable, checkvalues, truevalue, falsevalue, d):
checkvalues = set(checkvalues.split())
else:
checkvalues = set(checkvalues)
- if checkvalues.issubset(val):
+ if checkvalues.issubset(val):
return truevalue
return falsevalue
@@ -1140,7 +1176,7 @@ def edit_metadata(meta_lines, variables, varfunc, match_overrides=False):
if in_var.endswith('()'):
if full_value.count('{') - full_value.count('}') >= 0:
continue
- full_value = full_value[:-1]
+ full_value = full_value[:-1]
if handle_var_end():
updated = True
checkspc = True
@@ -1385,3 +1421,33 @@ def ioprio_set(who, cls, value):
raise ValueError("Unable to set ioprio, syscall returned %s" % rc)
else:
bb.warn("Unable to set IO Prio for arch %s" % _unamearch)
+
+def set_process_name(name):
+ from ctypes import cdll, byref, create_string_buffer
+ # This is nice to have for debugging, not essential
+ try:
+ libc = cdll.LoadLibrary('libc.so.6')
+ buff = create_string_buffer(len(name)+1)
+ buff.value = name
+ libc.prctl(15, byref(buff), 0, 0, 0)
+ except:
+ pass
+
+# export common proxies variables from datastore to environment
+def export_proxies(d):
+ import os
+
+ variables = ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY',
+ 'ftp_proxy', 'FTP_PROXY', 'no_proxy', 'NO_PROXY']
+ exported = False
+
+ for v in variables:
+ if v in os.environ.keys():
+ exported = True
+ else:
+ v_proxy = d.getVar(v, True)
+ if v_proxy is not None:
+ os.environ[v] = v_proxy
+ exported = True
+
+ return exported
diff --git a/yocto-poky/bitbake/lib/prserv/db.py b/yocto-poky/bitbake/lib/prserv/db.py
index 36c9f7b63..2a8618417 100644
--- a/yocto-poky/bitbake/lib/prserv/db.py
+++ b/yocto-poky/bitbake/lib/prserv/db.py
@@ -231,6 +231,14 @@ class PRTable(object):
datainfo.append(col)
return (metainfo, datainfo)
+ def dump_db(self, fd):
+ writeCount = 0
+ for line in self.conn.iterdump():
+ writeCount = writeCount + len(line) + 1
+ fd.write(line)
+ fd.write('\n')
+ return writeCount
+
class PRData(object):
"""Object representing the PR database"""
def __init__(self, filename, nohist=True):
diff --git a/yocto-poky/bitbake/lib/prserv/serv.py b/yocto-poky/bitbake/lib/prserv/serv.py
index eafc3aab7..affccd9b3 100644
--- a/yocto-poky/bitbake/lib/prserv/serv.py
+++ b/yocto-poky/bitbake/lib/prserv/serv.py
@@ -4,6 +4,7 @@ from SimpleXMLRPCServer import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
import threading
import Queue
import socket
+import StringIO
try:
import sqlite3
@@ -59,12 +60,10 @@ class PRServer(SimpleXMLRPCServer):
self.register_function(self.quit, "quit")
self.register_function(self.ping, "ping")
self.register_function(self.export, "export")
+ self.register_function(self.dump_db, "dump_db")
self.register_function(self.importone, "importone")
self.register_introspection_functions()
- self.db = prserv.db.PRData(self.dbfile)
- self.table = self.db["PRMAIN"]
-
self.requestqueue = Queue.Queue()
self.handlerthread = threading.Thread(target = self.process_request_thread)
self.handlerthread.daemon = False
@@ -79,6 +78,8 @@ class PRServer(SimpleXMLRPCServer):
# 60 iterations between syncs or sync if dirty every ~30 seconds
iterations_between_sync = 60
+ bb.utils.set_process_name("PRServ Handler")
+
while not self.quit:
try:
(request, client_address) = self.requestqueue.get(True, 30)
@@ -98,11 +99,13 @@ class PRServer(SimpleXMLRPCServer):
self.table.sync_if_dirty()
def sigint_handler(self, signum, stack):
- self.table.sync()
+ if self.table:
+ self.table.sync()
def sigterm_handler(self, signum, stack):
- self.table.sync()
- raise SystemExit
+ if self.table:
+ self.table.sync()
+ self.quit=True
def process_request(self, request, client_address):
self.requestqueue.put((request, client_address))
@@ -114,6 +117,26 @@ class PRServer(SimpleXMLRPCServer):
logger.error(str(exc))
return None
+ def dump_db(self):
+ """
+ Returns a script (string) that reconstructs the state of the
+ entire database at the time this function is called. The script
+ language is defined by the backing database engine, which is a
+ function of server configuration.
+ Returns None if the database engine does not support dumping to
+ script or if some other error is encountered in processing.
+ """
+ buff = StringIO.StringIO()
+ try:
+ self.table.sync()
+ self.table.dump_db(buff)
+ return buff.getvalue()
+ except Exception as exc:
+ logger.error(str(exc))
+ return None
+ finally:
+ buff.close()
+
def importone(self, version, pkgarch, checksum, value):
return self.table.importone(version, pkgarch, checksum, value)
@@ -141,6 +164,12 @@ class PRServer(SimpleXMLRPCServer):
self.quit = False
self.timeout = 0.5
+ bb.utils.set_process_name("PRServ")
+
+ # DB connection must be created after all forks
+ self.db = prserv.db.PRData(self.dbfile)
+ self.table = self.db["PRMAIN"]
+
logger.info("Started PRServer with DBfile: %s, IP: %s, PORT: %s, PID: %s" %
(self.dbfile, self.host, self.port, str(os.getpid())))
@@ -209,7 +238,6 @@ class PRServer(SimpleXMLRPCServer):
def cleanup_handles(self):
signal.signal(signal.SIGINT, self.sigint_handler)
signal.signal(signal.SIGTERM, self.sigterm_handler)
- os.umask(0)
os.chdir("/")
sys.stdout.flush()
@@ -282,6 +310,9 @@ class PRServerConnection(object):
def export(self,version=None, pkgarch=None, checksum=None, colinfo=True):
return self.connection.export(version, pkgarch, checksum, colinfo)
+ def dump_db(self):
+ return self.connection.dump_db()
+
def importone(self, version, pkgarch, checksum, value):
return self.connection.importone(version, pkgarch, checksum, value)
diff --git a/yocto-poky/bitbake/lib/toaster/bldcollector/urls.py b/yocto-poky/bitbake/lib/toaster/bldcollector/urls.py
index 144387b56..64722f2cd 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcollector/urls.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcollector/urls.py
@@ -18,7 +18,6 @@
from django.conf.urls import patterns, include, url
-from django.views.generic import RedirectView
urlpatterns = patterns('bldcollector.views',
# landing point for pushing a bitbake_eventlog.json file to this toaster instace
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/bbcontroller.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/bbcontroller.py
index ad70ac8b5..d09ac1787 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/bbcontroller.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/bbcontroller.py
@@ -37,11 +37,12 @@ class BitbakeController(object):
It is outside the scope of this class on how the server is started and aquired
"""
- def __init__(self, connection):
- self.connection = connection
+ def __init__(self, be):
+ self.connection = bb.server.xmlrpc._create_server(be.bbaddress,
+ int(be.bbport))[0]
def _runCommand(self, command):
- result, error = self.connection.connection.runCommand(command)
+ result, error = self.connection.runCommand(command)
if error:
raise Exception(error)
return result
@@ -52,11 +53,20 @@ class BitbakeController(object):
def setVariable(self, name, value):
return self._runCommand(["setVariable", name, value])
+ def getVariable(self, name):
+ return self._runCommand(["getVariable", name])
+
+ def triggerEvent(self, event):
+ return self._runCommand(["triggerEvent", event])
+
def build(self, targets, task = None):
if task is None:
task = "build"
return self._runCommand(["buildTargets", targets, task])
+ def forceShutDown(self):
+ return self._runCommand(["stateForceShutdown"])
+
def getBuildEnvironmentController(**kwargs):
@@ -70,13 +80,10 @@ def getBuildEnvironmentController(**kwargs):
"""
from localhostbecontroller import LocalhostBEController
- from sshbecontroller import SSHBEController
be = BuildEnvironment.objects.filter(Q(**kwargs))[0]
if be.betype == BuildEnvironment.TYPE_LOCAL:
return LocalhostBEController(be)
- elif be.betype == BuildEnvironment.TYPE_SSH:
- return SSHBEController(be)
else:
raise Exception("FIXME: Implement BEC for type %s" % str(be.betype))
@@ -99,9 +106,6 @@ class BuildEnvironmentController(object):
on the local machine, with the "build/" directory under the "poky/" source checkout directory.
Bash is expected to be available.
- * SSH controller will run the Toaster BE on a remote machine, where the current user
- can connect without raise Exception("FIXME: implement")word (set up with either ssh-agent or raise Exception("FIXME: implement")phrase-less key authentication)
-
"""
def __init__(self, be):
""" Takes a BuildEnvironment object as parameter that points to the settings of the BE.
@@ -109,89 +113,25 @@ class BuildEnvironmentController(object):
self.be = be
self.connection = None
- @staticmethod
- def _updateBBLayers(bblayerconf, layerlist):
- conflines = open(bblayerconf, "r").readlines()
-
- bblayerconffile = open(bblayerconf, "w")
- skip = 0
- for i in xrange(len(conflines)):
- if skip > 0:
- skip =- 1
- continue
- if conflines[i].startswith("# line added by toaster"):
- skip = 1
- else:
- bblayerconffile.write(conflines[i])
-
- bblayerconffile.write("# line added by toaster build control\nBBLAYERS = \"" + " ".join(layerlist) + "\"")
- bblayerconffile.close()
-
-
- def writeConfFile(self, variable_list = None, raw = None):
- """ Writes a configuration file in the build directory. Override with buildenv-specific implementation. """
- raise Exception("FIXME: Must override to actually write a configuration file")
-
-
- def startBBServer(self):
- """ Starts a BB server with Toaster toasterui set up to record the builds, an no controlling UI.
- After this method executes, self.be bbaddress/bbport MUST point to a running and free server,
- and the bbstate MUST be updated to "started".
- """
- raise Exception("FIXME: Must override in order to actually start the BB server")
-
- def stopBBServer(self):
- """ Stops the currently running BB server.
- The bbstate MUST be updated to "stopped".
- self.connection must be none.
- """
- raise Exception("FIXME: Must override stoBBServer")
-
- def setLayers(self, bbs, ls):
+ def setLayers(self, bitbake, ls):
""" Checks-out bitbake executor and layers from git repositories.
Sets the layer variables in the config file, after validating local layer paths.
- The bitbakes must be a 1-length list of BRBitbake
+ bitbake must be a single BRBitbake instance
The layer paths must be in a list of BRLayer object
a word of attention: by convention, the first layer for any build will be poky!
"""
- raise Exception("FIXME: Must override setLayers")
-
-
- def getBBController(self):
- """ returns a BitbakeController to an already started server; this is the point where the server
- starts if needed; or reconnects to the server if we can
- """
- if not self.connection:
- self.startBBServer()
- self.be.lock = BuildEnvironment.LOCK_RUNNING
- self.be.save()
-
- server = bb.server.xmlrpc.BitBakeXMLRPCClient()
- server.initServer()
- server.saveConnectionDetails("%s:%s" % (self.be.bbaddress, self.be.bbport))
- self.connection = server.establishConnection([])
-
- self.be.bbtoken = self.connection.transport.connection_token
- self.be.save()
-
- return BitbakeController(self.connection)
+ raise NotImplementedError("FIXME: Must override setLayers")
def getArtifact(self, path):
""" This call returns an artifact identified by the 'path'. How 'path' is interpreted as
up to the implementing BEC. The return MUST be a REST URL where a GET will actually return
the content of the artifact, e.g. for use as a "download link" in a web UI.
"""
- raise Exception("Must return the REST URL of the artifact")
-
- def release(self):
- """ This stops the server and releases any resources. After this point, all resources
- are un-available for further reference
- """
- raise Exception("Must override BE release")
+ raise NotImplementedError("Must return the REST URL of the artifact")
def triggerBuild(self, bitbake, layers, variables, targets):
- raise Exception("Must override BE release")
+ raise NotImplementedError("Must override BE release")
class ShellCmdException(Exception):
pass
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
index b5cf5591f..7def1f3a1 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
@@ -32,7 +32,7 @@ import subprocess
from toastermain import settings
-from bbcontroller import BuildEnvironmentController, ShellCmdException, BuildSetupException
+from bbcontroller import BuildEnvironmentController, ShellCmdException, BuildSetupException, BitbakeController
import logging
logger = logging.getLogger("toaster")
@@ -48,16 +48,17 @@ class LocalhostBEController(BuildEnvironmentController):
def __init__(self, be):
super(LocalhostBEController, self).__init__(be)
- self.dburl = settings.getDATABASE_URL()
self.pokydirname = None
self.islayerset = False
- def _shellcmd(self, command, cwd = None):
+ def _shellcmd(self, command, cwd=None, nowait=False):
if cwd is None:
cwd = self.be.sourcedir
logger.debug("lbc_shellcmmd: (%s) %s" % (cwd, command))
p = subprocess.Popen(command, cwd = cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ if nowait:
+ return
(out,err) = p.communicate()
p.wait()
if p.returncode:
@@ -71,115 +72,6 @@ class LocalhostBEController(BuildEnvironmentController):
logger.debug("localhostbecontroller: shellcmd success")
return out
- def _setupBE(self):
- assert self.pokydirname and os.path.exists(self.pokydirname)
- path = self.be.builddir
- if not path:
- raise Exception("Invalid path creation specified.")
- if not os.path.exists(path):
- os.makedirs(path, 0755)
- self._shellcmd("bash -c \"source %s/oe-init-build-env %s\"" % (self.pokydirname, path))
- # delete the templateconf.cfg; it may come from an unsupported layer configuration
- os.remove(os.path.join(path, "conf/templateconf.cfg"))
-
-
- def writeConfFile(self, file_name, variable_list = None, raw = None):
- filepath = os.path.join(self.be.builddir, file_name)
- with open(filepath, "w") as conffile:
- if variable_list is not None:
- for i in variable_list:
- conffile.write("%s=\"%s\"\n" % (i.name, i.value))
- if raw is not None:
- conffile.write(raw)
-
-
- def startBBServer(self):
- assert self.pokydirname and os.path.exists(self.pokydirname)
- assert self.islayerset
-
- # find our own toasterui listener/bitbake
- from toaster.bldcontrol.management.commands.loadconf import _reduce_canon_path
-
- own_bitbake = _reduce_canon_path(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../bin/bitbake"))
-
- assert os.path.exists(own_bitbake) and os.path.isfile(own_bitbake)
-
- logger.debug("localhostbecontroller: running the listener at %s" % own_bitbake)
-
- toaster_ui_log_filepath = os.path.join(self.be.builddir, "toaster_ui.log")
- # get the file length; we need to detect the _last_ start of the toaster UI, not the first
- toaster_ui_log_filelength = 0
- if os.path.exists(toaster_ui_log_filepath):
- with open(toaster_ui_log_filepath, "w") as f:
- f.seek(0, 2) # jump to the end
- toaster_ui_log_filelength = f.tell()
-
- cmd = "bash -c \"source %s/oe-init-build-env %s 2>&1 >toaster_server.log && bitbake --read %s/conf/toaster-pre.conf --postread %s/conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0 2>&1 >>toaster_server.log \"" % (self.pokydirname, self.be.builddir, self.be.builddir, self.be.builddir)
-
- port = "-1"
- logger.debug("localhostbecontroller: starting builder \n%s\n" % cmd)
-
- cmdoutput = self._shellcmd(cmd)
- with open(self.be.builddir + "/toaster_server.log", "r") as f:
- for i in f.readlines():
- if i.startswith("Bitbake server address"):
- port = i.split(" ")[-1]
- logger.debug("localhostbecontroller: Found bitbake server port %s" % port)
-
- cmd = "bash -c \"source %s/oe-init-build-env-memres -1 %s && DATABASE_URL=%s %s --observe-only -u toasterui --remote-server=0.0.0.0:-1 -t xmlrpc\"" % (self.pokydirname, self.be.builddir, self.dburl, own_bitbake)
- with open(toaster_ui_log_filepath, "a+") as f:
- p = subprocess.Popen(cmd, cwd = self.be.builddir, shell=True, stdout=f, stderr=f)
-
- def _toaster_ui_started(filepath, filepos = 0):
- if not os.path.exists(filepath):
- return False
- with open(filepath, "r") as f:
- f.seek(filepos)
- for line in f:
- if line.startswith("NOTE: ToasterUI waiting for events"):
- return True
- return False
-
- retries = 0
- started = False
- while not started and retries < 50:
- started = _toaster_ui_started(toaster_ui_log_filepath, toaster_ui_log_filelength)
- import time
- logger.debug("localhostbecontroller: Waiting bitbake server to start")
- time.sleep(0.5)
- retries += 1
-
- if not started:
- toaster_ui_log = open(os.path.join(self.be.builddir, "toaster_ui.log"), "r").read()
- toaster_server_log = open(os.path.join(self.be.builddir, "toaster_server.log"), "r").read()
- raise BuildSetupException("localhostbecontroller: Bitbake server did not start in 25 seconds, aborting (Error: '%s' '%s')" % (toaster_ui_log, toaster_server_log))
-
- logger.debug("localhostbecontroller: Started bitbake server")
-
- while port == "-1":
- # the port specification is "autodetect"; read the bitbake.lock file
- with open("%s/bitbake.lock" % self.be.builddir, "r") as f:
- for line in f.readlines():
- if ":" in line:
- port = line.split(":")[1].strip()
- logger.debug("localhostbecontroller: Autodetected bitbake port %s", port)
- break
-
- assert self.be.sourcedir and os.path.exists(self.be.builddir)
- self.be.bbaddress = "localhost"
- self.be.bbport = port
- self.be.bbstate = BuildEnvironment.SERVER_STARTED
- self.be.save()
-
- def stopBBServer(self):
- assert self.pokydirname and os.path.exists(self.pokydirname)
- assert self.islayerset
- self._shellcmd("bash -c \"source %s/oe-init-build-env %s && %s source toaster stop\"" %
- (self.pokydirname, self.be.builddir, (lambda: "" if self.be.bbtoken is None else "BBTOKEN=%s" % self.be.bbtoken)()))
- self.be.bbstate = BuildEnvironment.SERVER_STOPPED
- self.be.save()
- logger.debug("localhostbecontroller: Stopped bitbake server")
-
def getGitCloneDirectory(self, url, branch):
"""Construct unique clone directory name out of url and branch."""
if branch != "HEAD":
@@ -193,22 +85,22 @@ class LocalhostBEController(BuildEnvironmentController):
return local_checkout_path
- def setLayers(self, bitbakes, layers, targets):
+ def setLayers(self, bitbake, layers, targets):
""" a word of attention: by convention, the first layer for any build will be poky! """
assert self.be.sourcedir is not None
- assert len(bitbakes) == 1
# set layers in the layersource
# 1. get a list of repos with branches, and map dirpaths for each layer
gitrepos = {}
- gitrepos[(bitbakes[0].giturl, bitbakes[0].commit)] = []
- gitrepos[(bitbakes[0].giturl, bitbakes[0].commit)].append( ("bitbake", bitbakes[0].dirpath) )
+ gitrepos[(bitbake.giturl, bitbake.commit)] = []
+ gitrepos[(bitbake.giturl, bitbake.commit)].append( ("bitbake", bitbake.dirpath) )
for layer in layers:
- # we don't process local URLs
- if layer.giturl.startswith("file://"):
+ # We don't need to git clone the layer for the CustomImageRecipe
+ # as it's generated by us layer on if needed
+ if CustomImageRecipe.LAYER_NAME in layer.name:
continue
if not (layer.giturl, layer.commit) in gitrepos:
gitrepos[(layer.giturl, layer.commit)] = []
@@ -276,7 +168,7 @@ class LocalhostBEController(BuildEnvironmentController):
# make sure we have a working bitbake
if not os.path.exists(os.path.join(self.pokydirname, 'bitbake')):
logger.debug("localhostbecontroller: checking bitbake into the poky dirname %s " % self.pokydirname)
- self._shellcmd("git clone -b \"%s\" \"%s\" \"%s\" " % (bitbakes[0].commit, bitbakes[0].giturl, os.path.join(self.pokydirname, 'bitbake')))
+ self._shellcmd("git clone -b \"%s\" \"%s\" \"%s\" " % (bitbake.commit, bitbake.giturl, os.path.join(self.pokydirname, 'bitbake')))
# verify our repositories
for name, dirpath in gitrepos[(giturl, commit)]:
@@ -290,23 +182,13 @@ class LocalhostBEController(BuildEnvironmentController):
logger.debug("localhostbecontroller: current layer list %s " % pformat(layerlist))
- # 4. configure the build environment, so we have a conf/bblayers.conf
- assert self.pokydirname is not None
- self._setupBE()
-
- # 5. update the bblayers.conf
- bblayerconf = os.path.join(self.be.builddir, "conf/bblayers.conf")
- if not os.path.exists(bblayerconf):
- raise BuildSetupException("BE is not consistent: bblayers.conf file missing at %s" % bblayerconf)
-
- # 6. create custom layer and add custom recipes to it
- layerpath = os.path.join(self.be.sourcedir, "_meta-toaster-custom")
- if os.path.isdir(layerpath):
- shutil.rmtree(layerpath) # remove leftovers from previous builds
+ # 5. create custom layer and add custom recipes to it
+ layerpath = os.path.join(self.be.builddir,
+ CustomImageRecipe.LAYER_NAME)
for target in targets:
try:
customrecipe = CustomImageRecipe.objects.get(name=target.target,
- project=bitbakes[0].req.project)
+ project=bitbake.req.project)
except CustomImageRecipe.DoesNotExist:
continue # not a custom recipe, skip
@@ -322,60 +204,129 @@ class LocalhostBEController(BuildEnvironmentController):
with open(config, "w") as conf:
conf.write('BBPATH .= ":${LAYERDIR}"\nBBFILES += "${LAYERDIR}/recipes/*.bb"\n')
+ # Update the Layer_Version dirpath that has our base_recipe in
+ # to be able to read the base recipe to then generate the
+ # custom recipe.
+ br_layer_base_recipe = layers.get(
+ layer_version=customrecipe.base_recipe.layer_version)
+
+ br_layer_base_dirpath = \
+ os.path.join(self.be.sourcedir,
+ self.getGitCloneDirectory(
+ br_layer_base_recipe.giturl,
+ br_layer_base_recipe.commit),
+ customrecipe.base_recipe.layer_version.dirpath
+ )
+
+ customrecipe.base_recipe.layer_version.dirpath = \
+ br_layer_base_dirpath
+
+ customrecipe.base_recipe.layer_version.save()
+
# create recipe
- recipe = os.path.join(layerpath, "recipes", "%s.bb" % target.target)
- with open(recipe, "w") as recipef:
- recipef.write("require %s\n" % customrecipe.base_recipe.recipe.file_path)
- packages = [pkg.name for pkg in customrecipe.packages.all()]
- if packages:
- recipef.write('IMAGE_INSTALL = "%s"\n' % ' '.join(packages))
+ recipe_path = \
+ os.path.join(layerpath, "recipes", "%s.bb" % target.target)
+ with open(recipe_path, "w") as recipef:
+ recipef.write(customrecipe.generate_recipe_file_contents())
+
+ # Update the layer and recipe objects
+ customrecipe.layer_version.dirpath = layerpath
+ customrecipe.layer_version.save()
+
+ customrecipe.file_path = recipe_path
+ customrecipe.save()
# create *Layer* objects needed for build machinery to work
- layer = Layer.objects.get_or_create(name="Toaster Custom layer",
- summary="Layer for custom recipes",
- vcs_url="file://%s" % layerpath)[0]
- breq = target.req
- lver = Layer_Version.objects.get_or_create(project=breq.project, layer=layer,
- dirpath=layerpath, build=breq.build)[0]
- ProjectLayer.objects.get_or_create(project=breq.project, layercommit=lver,
- optional=False)
- BRLayer.objects.get_or_create(req=breq, name=layer.name, dirpath=layerpath,
+ BRLayer.objects.get_or_create(req=target.req,
+ name=layer.name,
+ dirpath=layerpath,
giturl="file://%s" % layerpath)
if os.path.isdir(layerpath):
layerlist.append(layerpath)
- BuildEnvironmentController._updateBBLayers(bblayerconf, layerlist)
-
self.islayerset = True
- return True
+ return layerlist
def readServerLogFile(self):
return open(os.path.join(self.be.builddir, "toaster_server.log"), "r").read()
- def release(self):
- assert self.be.sourcedir and os.path.exists(self.be.builddir)
- import shutil
- shutil.rmtree(os.path.join(self.be.sourcedir, "build"))
- assert not os.path.exists(self.be.builddir)
-
-
- def triggerBuild(self, bitbake, layers, variables, targets):
- # set up the buid environment with the needed layers
- self.setLayers(bitbake, layers, targets)
- self.writeConfFile("conf/toaster-pre.conf", variables)
- self.writeConfFile("conf/toaster.conf", raw = "INHERIT+=\"toaster buildhistory\"")
-
- # get the bb server running with the build req id and build env id
- bbctrl = self.getBBController()
- # trigger the build command
- task = reduce(lambda x, y: x if len(y)== 0 else y, map(lambda y: y.task, targets))
- if len(task) == 0:
- task = None
-
- bbctrl.build(list(map(lambda x:x.target, targets)), task)
+ def triggerBuild(self, bitbake, layers, variables, targets, brbe):
+ layers = self.setLayers(bitbake, layers, targets)
+
+ # init build environment from the clone
+ builddir = '%s-toaster-%d' % (self.be.builddir, bitbake.req.project.id)
+ oe_init = os.path.join(self.pokydirname, 'oe-init-build-env')
+ # init build environment
+ self._shellcmd("bash -c 'source %s %s'" % (oe_init, builddir),
+ self.be.sourcedir)
+
+ # update bblayers.conf
+ bblconfpath = os.path.join(builddir, "conf/bblayers.conf")
+ conflines = open(bblconfpath, "r").readlines()
+ skip = False
+ with open(bblconfpath, 'w') as bblayers:
+ for line in conflines:
+ if line.startswith("# line added by toaster"):
+ skip = True
+ continue
+ if skip:
+ skip = False
+ else:
+ bblayers.write(line)
+
+ bblayers.write('# line added by toaster build control\n'
+ 'BBLAYERS = "%s"' % ' '.join(layers))
+
+ # write configuration file
+ confpath = os.path.join(builddir, 'conf/toaster.conf')
+ with open(confpath, 'w') as conf:
+ for var in variables:
+ conf.write('%s="%s"\n' % (var.name, var.value))
+ conf.write('INHERIT+="toaster buildhistory"')
+
+ # run bitbake server from the clone
+ bitbake = os.path.join(self.pokydirname, 'bitbake', 'bin', 'bitbake')
+ self._shellcmd('bash -c \"source %s %s; BITBAKE_UI="" %s --read %s '
+ '--server-only -t xmlrpc -B 0.0.0.0:0\"' % (oe_init,
+ builddir, bitbake, confpath), self.be.sourcedir)
+
+ # read port number from bitbake.lock
+ self.be.bbport = ""
+ bblock = os.path.join(builddir, 'bitbake.lock')
+ with open(bblock) as fplock:
+ for line in fplock:
+ if ":" in line:
+ self.be.bbport = line.split(":")[-1].strip()
+ logger.debug("localhostbecontroller: bitbake port %s", self.be.bbport)
+ break
+
+ if not self.be.bbport:
+ raise BuildSetupException("localhostbecontroller: can't read bitbake port from %s" % bblock)
- logger.debug("localhostbecontroller: Build launched, exiting. Follow build logs at %s/toaster_ui.log" % self.be.builddir)
+ self.be.bbaddress = "localhost"
+ self.be.bbstate = BuildEnvironment.SERVER_STARTED
+ self.be.lock = BuildEnvironment.LOCK_RUNNING
+ self.be.save()
- # disconnect from the server
- bbctrl.disconnect()
+ bbtargets = ''
+ for target in targets:
+ task = target.task
+ if task:
+ if not task.startswith('do_'):
+ task = 'do_' + task
+ task = ':%s' % task
+ bbtargets += '%s%s ' % (target.target, task)
+
+ # run build with local bitbake. stop the server after the build.
+ log = os.path.join(builddir, 'toaster_ui.log')
+ local_bitbake = os.path.join(os.path.dirname(os.getenv('BBBASEDIR')),
+ 'bitbake')
+ self._shellcmd(['bash -c \"(TOASTER_BRBE="%s" BBSERVER="0.0.0.0:-1" '
+ '%s %s -u toasterui --token="" >>%s 2>&1;'
+ 'BITBAKE_UI="" BBSERVER=0.0.0.0:-1 %s -m)&\"' \
+ % (brbe, local_bitbake, bbtargets, log, bitbake)],
+ builddir, nowait=True)
+
+ logger.debug('localhostbecontroller: Build launched, exiting. '
+ 'Follow build logs at %s' % log)
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py
index 48dc618bc..27289be5f 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py
@@ -1,43 +1,50 @@
from django.core.management.base import NoArgsCommand, CommandError
from django.db import transaction
+from django.db.models import Q
+
+from bldcontrol.bbcontroller import getBuildEnvironmentController
+from bldcontrol.bbcontroller import ShellCmdException, BuildSetupException
+from bldcontrol.models import BuildRequest, BuildEnvironment
+from bldcontrol.models import BRError, BRVariable
+
from orm.models import Build, ToasterSetting, LogMessage, Target
-from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException, BuildSetupException
-from bldcontrol.models import BuildRequest, BuildEnvironment, BRError, BRVariable
+
import os
import logging
import time
+import sys
+import traceback
-logger = logging.getLogger("ToasterScheduler")
+logger = logging.getLogger("toaster")
class Command(NoArgsCommand):
args = ""
- help = "Schedules and executes build requests as possible. Does not return (interrupt with Ctrl-C)"
+ help = "Schedules and executes build requests as possible."
+ "Does not return (interrupt with Ctrl-C)"
- @transaction.commit_on_success
+ @transaction.atomic
def _selectBuildEnvironment(self):
bec = getBuildEnvironmentController(lock = BuildEnvironment.LOCK_FREE)
bec.be.lock = BuildEnvironment.LOCK_LOCK
bec.be.save()
return bec
- @transaction.commit_on_success
+ @transaction.atomic
def _selectBuildRequest(self):
- br = BuildRequest.objects.filter(state = BuildRequest.REQ_QUEUED).order_by('pk')[0]
- br.state = BuildRequest.REQ_INPROGRESS
- br.save()
+ br = BuildRequest.objects.filter(state=BuildRequest.REQ_QUEUED).first()
return br
def schedule(self):
- import traceback
try:
- br = None
- try:
- # select the build environment and the request to build
- br = self._selectBuildRequest()
- except IndexError as e:
- #logger.debug("runbuilds: No build request")
+ # select the build environment and the request to build
+ br = self._selectBuildRequest()
+ if br:
+ br.state = BuildRequest.REQ_INPROGRESS
+ br.save()
+ else:
return
+
try:
bec = self._selectBuildEnvironment()
except IndexError as e:
@@ -47,17 +54,17 @@ class Command(NoArgsCommand):
logger.debug("runbuilds: No build env")
return
- logger.debug("runbuilds: starting build %s, environment %s" % (br, bec.be))
-
- # write the build identification variable
- BRVariable.objects.create(req = br, name="TOASTER_BRBE", value="%d:%d" % (br.pk, bec.be.pk))
+ logger.debug("runbuilds: starting build %s, environment %s" % \
+ (str(br).decode('utf-8'), bec.be))
# let the build request know where it is being executed
br.environment = bec.be
br.save()
# this triggers an async build
- bec.triggerBuild(br.brbitbake_set.all(), br.brlayer_set.all(), br.brvariable_set.all(), br.brtarget_set.all())
+ bec.triggerBuild(br.brbitbake, br.brlayer_set.all(),
+ br.brvariable_set.all(), br.brtarget_set.all(),
+ "%d:%d" % (br.pk, bec.be.pk))
except Exception as e:
logger.error("runbuilds: Error launching build %s" % e)
@@ -88,29 +95,41 @@ class Command(NoArgsCommand):
def cleanup(self):
from django.utils import timezone
from datetime import timedelta
- # environments locked for more than 30 seconds - they should be unlocked
- BuildEnvironment.objects.filter(buildrequest__state__in=[BuildRequest.REQ_FAILED, BuildRequest.REQ_COMPLETED]).filter(lock=BuildEnvironment.LOCK_LOCK).filter(updated__lt = timezone.now() - timedelta(seconds = 30)).update(lock = BuildEnvironment.LOCK_FREE)
-
-
- # update all Builds that failed to start
-
- for br in BuildRequest.objects.filter(state = BuildRequest.REQ_FAILED, build__outcome = Build.IN_PROGRESS):
+ # environments locked for more than 30 seconds
+ # they should be unlocked
+ BuildEnvironment.objects.filter(
+ Q(buildrequest__state__in=[BuildRequest.REQ_FAILED,
+ BuildRequest.REQ_COMPLETED,
+ BuildRequest.REQ_CANCELLING]) &
+ Q(lock=BuildEnvironment.LOCK_LOCK) &
+ Q(updated__lt=timezone.now() - timedelta(seconds = 30))
+ ).update(lock=BuildEnvironment.LOCK_FREE)
+
+
+ # update all Builds that were in progress and failed to start
+ for br in BuildRequest.objects.filter(
+ state=BuildRequest.REQ_FAILED,
+ build__outcome=Build.IN_PROGRESS):
# transpose the launch errors in ToasterExceptions
br.build.outcome = Build.FAILED
for brerror in br.brerror_set.all():
logger.debug("Saving error %s" % brerror)
- LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg)
+ LogMessage.objects.create(build=br.build,
+ level=LogMessage.EXCEPTION,
+ message=brerror.errmsg)
br.build.save()
- # we don't have a true build object here; hence, toasterui didn't have a change to release the BE lock
+ # we don't have a true build object here; hence, toasterui
+ # didn't have a change to release the BE lock
br.environment.lock = BuildEnvironment.LOCK_FREE
br.environment.save()
-
# update all BuildRequests without a build created
for br in BuildRequest.objects.filter(build = None):
- br.build = Build.objects.create(project = br.project, completed_on = br.updated, started_on = br.created)
+ br.build = Build.objects.create(project=br.project,
+ completed_on=br.updated,
+ started_on=br.created)
br.build.outcome = Build.FAILED
try:
br.build.machine = br.brvariable_set.get(name='MACHINE').value
@@ -119,22 +138,42 @@ class Command(NoArgsCommand):
br.save()
# transpose target information
for brtarget in br.brtarget_set.all():
- Target.objects.create(build=br.build, target=brtarget.target, task=brtarget.task)
+ Target.objects.create(build=br.build,
+ target=brtarget.target,
+ task=brtarget.task)
# transpose the launch errors in ToasterExceptions
for brerror in br.brerror_set.all():
- LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg)
+ LogMessage.objects.create(build=br.build,
+ level=LogMessage.EXCEPTION,
+ message=brerror.errmsg)
br.build.save()
- pass
+
+ # Make sure the LOCK is removed for builds which have been fully
+ # cancelled
+ for br in BuildRequest.objects.filter(
+ Q(build__outcome=Build.CANCELLED) &
+ Q(state=BuildRequest.REQ_CANCELLING) &
+ ~Q(environment=None)):
+ br.environment.lock = BuildEnvironment.LOCK_FREE
+ br.environment.save()
def handle_noargs(self, **options):
while True:
try:
self.cleanup()
+ except Exception as e:
+ logger.warn("runbuilds: cleanup exception %s" % str(e))
+
+ try:
self.archive()
+ except Exception as e:
+ logger.warn("runbuilds: archive exception %s" % str(e))
+
+ try:
self.schedule()
- except:
- pass
+ except Exception as e:
+ logger.warn("runbuilds: schedule exception %s" % str(e))
time.sleep(1)
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0001_initial.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0001_initial.py
index a7e6350a6..67db37856 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0001_initial.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0001_initial.py
@@ -1,154 +1,113 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'BuildEnvironment'
- db.create_table(u'bldcontrol_buildenvironment', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('address', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ('betype', self.gf('django.db.models.fields.IntegerField')()),
- ('bbaddress', self.gf('django.db.models.fields.CharField')(max_length=254, blank=True)),
- ('bbport', self.gf('django.db.models.fields.IntegerField')(default=-1)),
- ('bbtoken', self.gf('django.db.models.fields.CharField')(max_length=126, blank=True)),
- ('bbstate', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('lock', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
- ('updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
- ))
- db.send_create_signal(u'bldcontrol', ['BuildEnvironment'])
-
- # Adding model 'BuildRequest'
- db.create_table(u'bldcontrol_buildrequest', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'])),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'], null=True)),
- ('state', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
- ('updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
- ))
- db.send_create_signal(u'bldcontrol', ['BuildRequest'])
-
- # Adding model 'BRLayer'
- db.create_table(u'bldcontrol_brlayer', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('req', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['bldcontrol.BuildRequest'])),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('giturl', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ('commit', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ))
- db.send_create_signal(u'bldcontrol', ['BRLayer'])
-
- # Adding model 'BRVariable'
- db.create_table(u'bldcontrol_brvariable', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('req', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['bldcontrol.BuildRequest'])),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('value', self.gf('django.db.models.fields.TextField')(blank=True)),
- ))
- db.send_create_signal(u'bldcontrol', ['BRVariable'])
-
- # Adding model 'BRTarget'
- db.create_table(u'bldcontrol_brtarget', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('req', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['bldcontrol.BuildRequest'])),
- ('target', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('task', self.gf('django.db.models.fields.CharField')(max_length=100, null=True)),
- ))
- db.send_create_signal(u'bldcontrol', ['BRTarget'])
-
-
- def backwards(self, orm):
- # Deleting model 'BuildEnvironment'
- db.delete_table(u'bldcontrol_buildenvironment')
-
- # Deleting model 'BuildRequest'
- db.delete_table(u'bldcontrol_buildrequest')
-
- # Deleting model 'BRLayer'
- db.delete_table(u'bldcontrol_brlayer')
-
- # Deleting model 'BRVariable'
- db.delete_table(u'bldcontrol_brvariable')
-
- # Deleting model 'BRTarget'
- db.delete_table(u'bldcontrol_brtarget')
-
-
- models = {
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- }
- }
-
- complete_apps = ['bldcontrol']
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('orm', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='BRBitbake',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('giturl', models.CharField(max_length=254)),
+ ('commit', models.CharField(max_length=254)),
+ ('dirpath', models.CharField(max_length=254)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BRError',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('errtype', models.CharField(max_length=100)),
+ ('errmsg', models.TextField()),
+ ('traceback', models.TextField()),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BRLayer',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=100)),
+ ('giturl', models.CharField(max_length=254)),
+ ('commit', models.CharField(max_length=254)),
+ ('dirpath', models.CharField(max_length=254)),
+ ('layer_version', models.ForeignKey(to='orm.Layer_Version', null=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BRTarget',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('target', models.CharField(max_length=100)),
+ ('task', models.CharField(max_length=100, null=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BRVariable',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=100)),
+ ('value', models.TextField(blank=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BuildEnvironment',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('address', models.CharField(max_length=254)),
+ ('betype', models.IntegerField(choices=[(0, b'local'), (1, b'ssh')])),
+ ('bbaddress', models.CharField(max_length=254, blank=True)),
+ ('bbport', models.IntegerField(default=-1)),
+ ('bbtoken', models.CharField(max_length=126, blank=True)),
+ ('bbstate', models.IntegerField(default=0, choices=[(0, b'stopped'), (1, b'started')])),
+ ('sourcedir', models.CharField(max_length=512, blank=True)),
+ ('builddir', models.CharField(max_length=512, blank=True)),
+ ('lock', models.IntegerField(default=0, choices=[(0, b'free'), (1, b'lock'), (2, b'running')])),
+ ('created', models.DateTimeField(auto_now_add=True)),
+ ('updated', models.DateTimeField(auto_now=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BuildRequest',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('state', models.IntegerField(default=0, choices=[(0, b'created'), (1, b'queued'), (2, b'in progress'), (3, b'completed'), (4, b'failed'), (5, b'deleted'), (6, b'archive')])),
+ ('created', models.DateTimeField(auto_now_add=True)),
+ ('updated', models.DateTimeField(auto_now=True)),
+ ('build', models.OneToOneField(null=True, to='orm.Build')),
+ ('environment', models.ForeignKey(to='bldcontrol.BuildEnvironment', null=True)),
+ ('project', models.ForeignKey(to='orm.Project')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='brvariable',
+ name='req',
+ field=models.ForeignKey(to='bldcontrol.BuildRequest'),
+ ),
+ migrations.AddField(
+ model_name='brtarget',
+ name='req',
+ field=models.ForeignKey(to='bldcontrol.BuildRequest'),
+ ),
+ migrations.AddField(
+ model_name='brlayer',
+ name='req',
+ field=models.ForeignKey(to='bldcontrol.BuildRequest'),
+ ),
+ migrations.AddField(
+ model_name='brerror',
+ name='req',
+ field=models.ForeignKey(to='bldcontrol.BuildRequest'),
+ ),
+ migrations.AddField(
+ model_name='brbitbake',
+ name='req',
+ field=models.OneToOneField(to='bldcontrol.BuildRequest'),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto_20160120_1250.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto_20160120_1250.py
new file mode 100644
index 000000000..0c2475aba
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto_20160120_1250.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('bldcontrol', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='buildenvironment',
+ name='betype',
+ field=models.IntegerField(choices=[(0, b'local')]),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto__add_field_buildenvironment_sourcedir__add_field_buildenvironment.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto__add_field_buildenvironment_sourcedir__add_field_buildenvironment.py
deleted file mode 100644
index f522a500b..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0002_auto__add_field_buildenvironment_sourcedir__add_field_buildenvironment.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'BuildEnvironment.sourcedir'
- db.add_column(u'bldcontrol_buildenvironment', 'sourcedir',
- self.gf('django.db.models.fields.CharField')(default='', max_length=512, blank=True),
- keep_default=False)
-
- # Adding field 'BuildEnvironment.builddir'
- db.add_column(u'bldcontrol_buildenvironment', 'builddir',
- self.gf('django.db.models.fields.CharField')(default='', max_length=512, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'BuildEnvironment.sourcedir'
- db.delete_column(u'bldcontrol_buildenvironment', 'sourcedir')
-
- # Deleting field 'BuildEnvironment.builddir'
- db.delete_column(u'bldcontrol_buildenvironment', 'builddir')
-
-
- models = {
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- }
- }
-
- complete_apps = ['bldcontrol'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_add_cancelling_state.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_add_cancelling_state.py
new file mode 100644
index 000000000..eec9216ca
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_add_cancelling_state.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('bldcontrol', '0002_auto_20160120_1250'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='buildrequest',
+ name='state',
+ field=models.IntegerField(default=0, choices=[(0, b'created'), (1, b'queued'), (2, b'in progress'), (3, b'completed'), (4, b'failed'), (5, b'deleted'), (6, b'cancelling'), (7, b'archive')]),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_auto__add_field_brlayer_dirpath.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_auto__add_field_brlayer_dirpath.py
deleted file mode 100644
index b9ba838d9..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0003_auto__add_field_brlayer_dirpath.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'BRLayer.dirpath'
- db.add_column(u'bldcontrol_brlayer', 'dirpath',
- self.gf('django.db.models.fields.CharField')(default='', max_length=254),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'BRLayer.dirpath'
- db.delete_column(u'bldcontrol_brlayer', 'dirpath')
-
-
- models = {
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- }
- }
-
- complete_apps = ['bldcontrol'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0004_loadinitialdata.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0004_loadinitialdata.py
deleted file mode 100644
index d90857813..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0004_loadinitialdata.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import DataMigration
-from django.db import models
-
-class Migration(DataMigration):
-
- def forwards(self, orm):
- "Write your forwards methods here."
- # Note: Don't use "from appname.models import ModelName".
- # Use orm.ModelName to refer to models in this application,
- # and orm['appname.ModelName'] for models in other applications.
- try:
- orm.BuildEnvironment.objects.get(pk = 1)
- except:
- from django.utils import timezone
- orm.BuildEnvironment.objects.create(pk = 1,
- created = timezone.now(),
- updated = timezone.now(),
- betype = 0)
-
- def backwards(self, orm):
- "Write your backwards methods here."
-
- models = {
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- }
- }
-
- complete_apps = ['bldcontrol']
- symmetrical = True
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0005_auto__add_brerror.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0005_auto__add_brerror.py
deleted file mode 100644
index 98aeb41ce..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0005_auto__add_brerror.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'BRError'
- db.create_table(u'bldcontrol_brerror', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('req', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['bldcontrol.BuildRequest'])),
- ('errtype', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('errmsg', self.gf('django.db.models.fields.TextField')()),
- ('traceback', self.gf('django.db.models.fields.TextField')()),
- ))
- db.send_create_signal(u'bldcontrol', ['BRError'])
-
-
- def backwards(self, orm):
- # Deleting model 'BRError'
- db.delete_table(u'bldcontrol_brerror')
-
-
- models = {
- u'bldcontrol.brerror': {
- 'Meta': {'object_name': 'BRError'},
- 'errmsg': ('django.db.models.fields.TextField', [], {}),
- 'errtype': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'traceback': ('django.db.models.fields.TextField', [], {})
- },
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- }
- }
-
- complete_apps = ['bldcontrol'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0006_auto__add_brbitbake.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0006_auto__add_brbitbake.py
deleted file mode 100644
index 74388f843..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0006_auto__add_brbitbake.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'BRBitbake'
- db.create_table(u'bldcontrol_brbitbake', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('req', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['bldcontrol.BuildRequest'], unique=True)),
- ('giturl', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ('commit', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ('dirpath', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ))
- db.send_create_signal(u'bldcontrol', ['BRBitbake'])
-
-
- def backwards(self, orm):
- # Deleting model 'BRBitbake'
- db.delete_table(u'bldcontrol_brbitbake')
-
-
- models = {
- u'bldcontrol.brbitbake': {
- 'Meta': {'object_name': 'BRBitbake'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']", 'unique': 'True'})
- },
- u'bldcontrol.brerror': {
- 'Meta': {'object_name': 'BRError'},
- 'errmsg': ('django.db.models.fields.TextField', [], {}),
- 'errtype': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'traceback': ('django.db.models.fields.TextField', [], {})
- },
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- }
- }
-
- complete_apps = ['bldcontrol'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0007_auto__add_field_buildrequest_environment__chg_field_buildrequest_build.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0007_auto__add_field_buildrequest_environment__chg_field_buildrequest_build.py
deleted file mode 100644
index 70677a294..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0007_auto__add_field_buildrequest_environment__chg_field_buildrequest_build.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'BuildRequest.environment'
- db.add_column(u'bldcontrol_buildrequest', 'environment',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['bldcontrol.BuildEnvironment'], null=True),
- keep_default=False)
-
-
- # Changing field 'BuildRequest.build'
- db.alter_column(u'bldcontrol_buildrequest', 'build_id', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['orm.Build'], unique=True, null=True))
- # Adding unique constraint on 'BuildRequest', fields ['build']
- db.create_unique(u'bldcontrol_buildrequest', ['build_id'])
-
-
- def backwards(self, orm):
- # Removing unique constraint on 'BuildRequest', fields ['build']
- db.delete_unique(u'bldcontrol_buildrequest', ['build_id'])
-
- # Deleting field 'BuildRequest.environment'
- db.delete_column(u'bldcontrol_buildrequest', 'environment_id')
-
-
- # Changing field 'BuildRequest.build'
- db.alter_column(u'bldcontrol_buildrequest', 'build_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'], null=True))
-
- models = {
- u'bldcontrol.brbitbake': {
- 'Meta': {'object_name': 'BRBitbake'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']", 'unique': 'True'})
- },
- u'bldcontrol.brerror': {
- 'Meta': {'object_name': 'BRError'},
- 'errmsg': ('django.db.models.fields.TextField', [], {}),
- 'errtype': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'traceback': ('django.db.models.fields.TextField', [], {})
- },
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['orm.Build']", 'unique': 'True', 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'environment': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildEnvironment']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- }
- }
-
- complete_apps = ['bldcontrol'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0008_brarchive.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0008_brarchive.py
deleted file mode 100644
index f5469607f..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0008_brarchive.py
+++ /dev/null
@@ -1,138 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import DataMigration
-from django.db import models
-
-class Migration(DataMigration):
- # ids that cannot be imported from BuildRequest
-
- def forwards(self, orm):
- REQ_COMPLETED = 3
- REQ_ARCHIVE = 6
- "Write your forwards methods here."
- # Note: Don't use "from appname.models import ModelName".
- # Use orm.ModelName to refer to models in this application,
- # and orm['appname.ModelName'] for models in other applications.
- orm.BuildRequest.objects.filter(state=REQ_COMPLETED).update(state=REQ_ARCHIVE)
-
- def backwards(self, orm):
- REQ_COMPLETED = 3
- REQ_ARCHIVE = 6
- "Write your backwards methods here."
- orm.BuildRequest.objects.filter(state=REQ_ARCHIVE).update(state=REQ_COMPLETED)
-
- models = {
- u'bldcontrol.brbitbake': {
- 'Meta': {'object_name': 'BRBitbake'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']", 'unique': 'True'})
- },
- u'bldcontrol.brerror': {
- 'Meta': {'object_name': 'BRError'},
- 'errmsg': ('django.db.models.fields.TextField', [], {}),
- 'errtype': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'traceback': ('django.db.models.fields.TextField', [], {})
- },
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['orm.Build']", 'unique': 'True', 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'environment': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildEnvironment']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- }
- }
-
- complete_apps = ['bldcontrol']
- symmetrical = True
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0009_auto__add_field_brlayer_layer_version.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0009_auto__add_field_brlayer_layer_version.py
deleted file mode 100644
index 9b50bc1c0..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/migrations/0009_auto__add_field_brlayer_layer_version.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'BRLayer.layer_version'
- db.add_column(u'bldcontrol_brlayer', 'layer_version',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer_Version'], null=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'BRLayer.layer_version'
- db.delete_column(u'bldcontrol_brlayer', 'layer_version_id')
-
-
- models = {
- u'bldcontrol.brbitbake': {
- 'Meta': {'object_name': 'BRBitbake'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']", 'unique': 'True'})
- },
- u'bldcontrol.brerror': {
- 'Meta': {'object_name': 'BRError'},
- 'errmsg': ('django.db.models.fields.TextField', [], {}),
- 'errtype': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'traceback': ('django.db.models.fields.TextField', [], {})
- },
- u'bldcontrol.brlayer': {
- 'Meta': {'object_name': 'BRLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"})
- },
- u'bldcontrol.brtarget': {
- 'Meta': {'object_name': 'BRTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'bldcontrol.brvariable': {
- 'Meta': {'object_name': 'BRVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'req': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildRequest']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'bldcontrol.buildenvironment': {
- 'Meta': {'object_name': 'BuildEnvironment'},
- 'address': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'bbaddress': ('django.db.models.fields.CharField', [], {'max_length': '254', 'blank': 'True'}),
- 'bbport': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'bbstate': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'bbtoken': ('django.db.models.fields.CharField', [], {'max_length': '126', 'blank': 'True'}),
- 'betype': ('django.db.models.fields.IntegerField', [], {}),
- 'builddir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'lock': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'sourcedir': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'bldcontrol.buildrequest': {
- 'Meta': {'object_name': 'BuildRequest'},
- 'build': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['orm.Build']", 'unique': 'True', 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- 'environment': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['bldcontrol.BuildEnvironment']", 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'state': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- }
- }
-
- complete_apps = ['bldcontrol'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/models.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/models.py
index ab4110530..cb49a58c4 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/models.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/models.py
@@ -1,7 +1,11 @@
+from __future__ import unicode_literals
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
+from django.utils.encoding import force_bytes
from orm.models import Project, ProjectLayer, ProjectVariable, ProjectTarget, Build, Layer_Version
+import logging
+logger = logging.getLogger("toaster")
# a BuildEnvironment is the equivalent of the "build/" directory on the localhost
class BuildEnvironment(models.Model):
SERVER_STOPPED = 0
@@ -12,10 +16,8 @@ class BuildEnvironment(models.Model):
)
TYPE_LOCAL = 0
- TYPE_SSH = 1
TYPE = (
(TYPE_LOCAL, "local"),
- (TYPE_SSH, "ssh"),
)
LOCK_FREE = 0
@@ -42,13 +44,17 @@ class BuildEnvironment(models.Model):
def get_artifact(self, path):
if self.betype == BuildEnvironment.TYPE_LOCAL:
return open(path, "r")
- raise Exception("FIXME: artifact download not implemented for build environment type %s" % self.get_betype_display())
+ raise NotImplementedError("FIXME: artifact download not implemented "\
+ "for build environment type %s" % \
+ self.get_betype_display())
def has_artifact(self, path):
import os
if self.betype == BuildEnvironment.TYPE_LOCAL:
return os.path.exists(path)
- raise Exception("FIXME: has artifact not implemented for build environment type %s" % self.get_betype_display())
+ raise NotImplementedError("FIXME: has artifact not implemented for "\
+ "build environment type %s" % \
+ self.get_betype_display())
# a BuildRequest is a request that the scheduler will build using a BuildEnvironment
# the build request queue is the table itself, ordered by state
@@ -60,7 +66,8 @@ class BuildRequest(models.Model):
REQ_COMPLETED = 3
REQ_FAILED = 4
REQ_DELETED = 5
- REQ_ARCHIVE = 6
+ REQ_CANCELLING = 6
+ REQ_ARCHIVE = 7
REQUEST_STATE = (
(REQ_CREATED, "created"),
@@ -69,6 +76,7 @@ class BuildRequest(models.Model):
(REQ_COMPLETED, "completed"),
(REQ_FAILED, "failed"),
(REQ_DELETED, "deleted"),
+ (REQ_CANCELLING, "cancelling"),
(REQ_ARCHIVE, "archive"),
)
@@ -81,6 +89,27 @@ class BuildRequest(models.Model):
created = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
+ def __init__(self, *args, **kwargs):
+ super(BuildRequest, self).__init__(*args, **kwargs)
+ # Save the old state incase it's about to be modified
+ self.old_state = self.state
+
+ def save(self, *args, **kwargs):
+ # Check that the state we're trying to set is not going backwards
+ # e.g. from REQ_FAILED to REQ_INPROGRESS
+ if self.old_state != self.state and self.old_state > self.state:
+ logger.warn("Invalid state change requested: "
+ "Cannot go from %s to %s - ignoring request" %
+ (BuildRequest.REQUEST_STATE[self.old_state][1],
+ BuildRequest.REQUEST_STATE[self.state][1])
+ )
+ # Set property back to the old value
+ self.state = self.old_state
+ return
+
+ super(BuildRequest, self).save(*args, **kwargs)
+
+
def get_duration(self):
return (self.updated - self.created).total_seconds()
@@ -92,7 +121,7 @@ class BuildRequest(models.Model):
return self.brvariable_set.get(name="MACHINE").value
def __str__(self):
- return "%s %s" % (self.project, self.get_state_display())
+ return force_bytes('%s %s' % (self.project, self.get_state_display()))
# These tables specify the settings for running an actual build.
# They MUST be kept in sync with the tables in orm.models.Project*
@@ -106,7 +135,7 @@ class BRLayer(models.Model):
layer_version = models.ForeignKey(Layer_Version, null=True)
class BRBitbake(models.Model):
- req = models.ForeignKey(BuildRequest, unique = True) # only one bitbake for a request
+ req = models.OneToOneField(BuildRequest) # only one bitbake for a request
giturl = models.CharField(max_length =254)
commit = models.CharField(max_length = 254)
dirpath = models.CharField(max_length = 254)
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/sshbecontroller.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/sshbecontroller.py
deleted file mode 100644
index 8ef434baf..000000000
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/sshbecontroller.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#
-# ex:ts=4:sw=4:sts=4:et
-# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
-#
-# BitBake Toaster Implementation
-#
-# Copyright (C) 2014 Intel Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-
-import sys
-import re
-from django.db import transaction
-from django.db.models import Q
-from bldcontrol.models import BuildEnvironment, BRLayer, BRVariable, BRTarget, BRBitbake
-import subprocess
-
-from toastermain import settings
-
-from bbcontroller import BuildEnvironmentController, ShellCmdException, BuildSetupException
-
-class NotImplementedException(Exception):
- pass
-
-def DN(path):
- return "/".join(path.split("/")[0:-1])
-
-class SSHBEController(BuildEnvironmentController):
- """ Implementation of the BuildEnvironmentController for the localhost;
- this controller manages the default build directory,
- the server setup and system start and stop for the localhost-type build environment
-
- """
-
- def __init__(self, be):
- super(SSHBEController, self).__init__(be)
- self.dburl = settings.getDATABASE_URL()
- self.pokydirname = None
- self.islayerset = False
-
- def _shellcmd(self, command, cwd = None):
- if cwd is None:
- cwd = self.be.sourcedir
-
- p = subprocess.Popen("ssh %s 'cd %s && %s'" % (self.be.address, cwd, command), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
- (out,err) = p.communicate()
- if p.returncode:
- if len(err) == 0:
- err = "command: %s \n%s" % (command, out)
- else:
- err = "command: %s \n%s" % (command, err)
- raise ShellCmdException(err)
- else:
- return out.strip()
-
- def _pathexists(self, path):
- try:
- self._shellcmd("test -e \"%s\"" % path)
- return True
- except ShellCmdException as e:
- return False
-
- def _pathcreate(self, path):
- self._shellcmd("mkdir -p \"%s\"" % path)
-
- def _setupBE(self):
- assert self.pokydirname and self._pathexists(self.pokydirname)
- self._pathcreate(self.be.builddir)
- self._shellcmd("bash -c \"source %s/oe-init-build-env %s\"" % (self.pokydirname, self.be.builddir))
-
- def startBBServer(self, brbe):
- assert self.pokydirname and self._pathexists(self.pokydirname)
- assert self.islayerset
- cmd = self._shellcmd("bash -c \"source %s/oe-init-build-env %s && DATABASE_URL=%s source toaster start noweb brbe=%s\"" % (self.pokydirname, self.be.builddir, self.dburl, brbe))
-
- port = "-1"
- for i in cmd.split("\n"):
- if i.startswith("Bitbake server address"):
- port = i.split(" ")[-1]
- print "Found bitbake server port ", port
-
-
- assert self.be.sourcedir and self._pathexists(self.be.builddir)
- self.be.bbaddress = self.be.address.split("@")[-1]
- self.be.bbport = port
- self.be.bbstate = BuildEnvironment.SERVER_STARTED
- self.be.save()
-
- def stopBBServer(self):
- assert self.pokydirname and self._pathexists(self.pokydirname)
- assert self.islayerset
- print self._shellcmd("bash -c \"source %s/oe-init-build-env %s && %s source toaster stop\"" %
- (self.pokydirname, self.be.builddir, (lambda: "" if self.be.bbtoken is None else "BBTOKEN=%s" % self.be.bbtoken)()))
- self.be.bbstate = BuildEnvironment.SERVER_STOPPED
- self.be.save()
- print "Stopped server"
-
-
- def _copyFile(self, filepath1, filepath2):
- p = subprocess.Popen("scp '%s' '%s'" % (filepath1, filepath2), stdout=subprocess.PIPE, stderr = subprocess.PIPE, shell=True)
- (out, err) = p.communicate()
- if p.returncode:
- raise ShellCmdException(err)
-
- def pullFile(self, local_filename, remote_filename):
- _copyFile(local_filename, "%s:%s" % (self.be.address, remote_filename))
-
- def pushFile(self, local_filename, remote_filename):
- _copyFile("%s:%s" % (self.be.address, remote_filename), local_filename)
-
- def setLayers(self, bitbakes, layers):
- """ a word of attention: by convention, the first layer for any build will be poky! """
-
- assert self.be.sourcedir is not None
- assert len(bitbakes) == 1
- # set layers in the layersource
-
-
- raise NotImplementedException("Not implemented: SSH setLayers")
- # 3. configure the build environment, so we have a conf/bblayers.conf
- assert self.pokydirname is not None
- self._setupBE()
-
- # 4. update the bblayers.conf
- bblayerconf = os.path.join(self.be.builddir, "conf/bblayers.conf")
- if not self._pathexists(bblayerconf):
- raise BuildSetupException("BE is not consistent: bblayers.conf file missing at %s" % bblayerconf)
-
- import uuid
- local_bblayerconf = "/tmp/" + uuid.uuid4() + "-bblayer.conf"
-
- self.pullFile(bblayerconf, local_bblayerconf)
-
- BuildEnvironmentController._updateBBLayers(local_bblayerconf, layerlist)
- self.pushFile(local_bblayerconf, bblayerconf)
-
- os.unlink(local_bblayerconf)
-
- self.islayerset = True
- return True
-
- def release(self):
- assert self.be.sourcedir and self._pathexists(self.be.builddir)
- import shutil
- shutil.rmtree(os.path.join(self.be.sourcedir, "build"))
- assert not self._pathexists(self.be.builddir)
-
- def triggerBuild(self, bitbake, layers, variables, targets):
- # set up the buid environment with the needed layers
- self.setLayers(bitbake, layers)
- self.writeConfFile("conf/toaster-pre.conf", )
- self.writeConfFile("conf/toaster.conf", raw = "INHERIT+=\"toaster buildhistory\"")
-
- # get the bb server running with the build req id and build env id
- bbctrl = self.getBBController()
-
- # trigger the build command
- task = reduce(lambda x, y: x if len(y)== 0 else y, map(lambda y: y.task, targets))
- if len(task) == 0:
- task = None
-
- bbctrl.build(list(map(lambda x:x.target, targets)), task)
-
- logger.debug("localhostbecontroller: Build launched, exiting. Follow build logs at %s/toaster_ui.log" % self.be.builddir)
-
- # disconnect from the server
- bbctrl.disconnect()
diff --git a/yocto-poky/bitbake/lib/toaster/bldcontrol/tests.py b/yocto-poky/bitbake/lib/toaster/bldcontrol/tests.py
index 5dbc77fda..f20cc7d4b 100644
--- a/yocto-poky/bitbake/lib/toaster/bldcontrol/tests.py
+++ b/yocto-poky/bitbake/lib/toaster/bldcontrol/tests.py
@@ -9,7 +9,6 @@ from django.test import TestCase
from bldcontrol.bbcontroller import BitbakeController, BuildSetupException
from bldcontrol.localhostbecontroller import LocalhostBEController
-from bldcontrol.sshbecontroller import SSHBEController
from bldcontrol.models import BuildEnvironment, BuildRequest
from bldcontrol.management.commands.runbuilds import Command
@@ -18,7 +17,7 @@ import subprocess
import os
# standard poky data hardcoded for testing
-BITBAKE_LAYERS = [type('bitbake_info', (object,), { "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "", "commit": "HEAD"})]
+BITBAKE_LAYER = type('bitbake_info', (object,), { "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "", "commit": "HEAD"})
POKY_LAYERS = [
type('poky_info', (object,), { "name": "meta", "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "meta", "commit": "HEAD"}),
type('poky_info', (object,), { "name": "meta-yocto", "giturl": "git://git.yoctoproject.org/poky.git", "dirpath": "meta-yocto", "commit": "HEAD"}),
@@ -48,13 +47,12 @@ class BEControllerTests(object):
self.assertTrue(err == '', "bitbake server pid %s not stopped" % err)
def test_serverStartAndStop(self):
- from bldcontrol.sshbecontroller import NotImplementedException
obe = self._getBuildEnvironment()
bc = self._getBEController(obe)
try:
# setting layers, skip any layer info
- bc.setLayers(BITBAKE_LAYERS, POKY_LAYERS)
- except NotImplementedException, e:
+ bc.setLayers(BITBAKE_LAYER, POKY_LAYERS)
+ except NotImplementedError:
print "Test skipped due to command not implemented yet"
return True
# We are ok with the exception as we're handling the git already exists
@@ -71,20 +69,16 @@ class BEControllerTests(object):
self.assertFalse(socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex((hostname, int(bc.be.bbport))), "Server not answering")
- bc.stopBBServer()
- self.assertTrue(socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect_ex((hostname, int(bc.be.bbport))), "Server not stopped")
-
self._serverForceStop(bc)
def test_getBBController(self):
- from bldcontrol.sshbecontroller import NotImplementedException
obe = self._getBuildEnvironment()
bc = self._getBEController(obe)
layerSet = False
try:
# setting layers, skip any layer info
- layerSet = bc.setLayers(BITBAKE_LAYERS, POKY_LAYERS)
- except NotImplementedException:
+ layerSet = bc.setLayers(BITBAKE_LAYER, POKY_LAYERS)
+ except NotImplementedError:
print "Test skipped due to command not implemented yet"
return True
# We are ok with the exception as we're handling the git already exists
@@ -96,7 +90,6 @@ class BEControllerTests(object):
bbc = bc.getBBController()
self.assertTrue(isinstance(bbc, BitbakeController))
- bc.stopBBServer()
self._serverForceStop(bc)
@@ -116,29 +109,6 @@ class LocalhostBEControllerTests(TestCase, BEControllerTests):
def _getBEController(self, obe):
return LocalhostBEController(obe)
-class SSHBEControllerTests(TestCase, BEControllerTests):
- def __init__(self, *args):
- super(SSHBEControllerTests, self).__init__(*args)
-
- def _getBuildEnvironment(self):
- return BuildEnvironment.objects.create(
- lock = BuildEnvironment.LOCK_FREE,
- betype = BuildEnvironment.TYPE_SSH,
- address = test_address,
- sourcedir = test_sourcedir,
- builddir = test_builddir )
-
- def _getBEController(self, obe):
- return SSHBEController(obe)
-
- def test_pathExists(self):
- obe = BuildEnvironment.objects.create(betype = BuildEnvironment.TYPE_SSH, address= test_address)
- sbc = SSHBEController(obe)
- self.assertTrue(sbc._pathexists("/"))
- self.assertFalse(sbc._pathexists("/.deadbeef"))
- self.assertTrue(sbc._pathexists(sbc._shellcmd("pwd")))
-
-
class RunBuildsCommandTests(TestCase):
def test_bec_select(self):
"""
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.gitignore b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.gitignore
deleted file mode 100644
index c45652d29..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-*.pyc
-*.swp
-*.swo
-*.kpf
-*.egg-info/
-.idea
-.tox
-tmp/
-dist/
-.DS_Store
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.travis.yml b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.travis.yml
deleted file mode 100644
index a920f3945..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/.travis.yml
+++ /dev/null
@@ -1,50 +0,0 @@
-language: python
-python:
- - "2.7"
- - "3.4"
-services:
- - mysql
- - postgresql
-env:
- - DJANGO=1.4 DB=sqlite
- - DJANGO=1.4 DB=mysql
- - DJANGO=1.4 DB=postgres
- - DJANGO=1.5 DB=sqlite
- - DJANGO=1.5 DB=mysql
- - DJANGO=1.5 DB=postgres
- - DJANGO=1.6 DB=sqlite
- - DJANGO=1.6 DB=mysql
- - DJANGO=1.6 DB=postgres
- - DJANGO=1.7 DB=sqlite
- - DJANGO=1.7 DB=mysql
- - DJANGO=1.7 DB=postgres
-
-matrix:
- exclude:
- - python: "3.4"
- env: DJANGO=1.4 DB=sqlite
- - python: "3.4"
- env: DJANGO=1.4 DB=mysql
- - python: "3.4"
- env: DJANGO=1.4 DB=postgres
- - python: "3.4"
- env: DJANGO=1.5 DB=sqlite
- - python: "3.4"
- env: DJANGO=1.5 DB=mysql
- - python: "3.4"
- env: DJANGO=1.5 DB=postgres
- - python: "3.4"
- env: DJANGO=1.6 DB=mysql
- - python: "3.4"
- env: DJANGO=1.7 DB=mysql
-
-before_script:
- - mysql -e 'create database aggregation;'
- - psql -c 'create database aggregation;' -U postgres
-install:
- - pip install six
- - if [ "$DB" == "mysql" ]; then pip install mysql-python; fi
- - if [ "$DB" == "postgres" ]; then pip install psycopg2; fi
- - pip install -q Django==$DJANGO --use-mirrors
-script:
- - ./runtests.py --settings=tests.test_$DB
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/LICENSE b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/LICENSE
deleted file mode 100644
index 6b7c3b174..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License
-
-Copyright (c) 2012 Henrique Bastos
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/README.rst b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/README.rst
deleted file mode 100644
index 739d4dacc..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/README.rst
+++ /dev/null
@@ -1,156 +0,0 @@
-Django Aggregate If: Condition aggregates for Django
-====================================================
-
-.. image:: https://travis-ci.org/henriquebastos/django-aggregate-if.png?branch=master
- :target: https://travis-ci.org/henriquebastos/django-aggregate-if
- :alt: Test Status
-
-.. image:: https://landscape.io/github/henriquebastos/django-aggregate-if/master/landscape.png
- :target: https://landscape.io/github/henriquebastos/django-aggregate-if/master
- :alt: Code Helth
-
-.. image:: https://pypip.in/v/django-aggregate-if/badge.png
- :target: https://crate.io/packages/django-aggregate-if/
- :alt: Latest PyPI version
-
-.. image:: https://pypip.in/d/django-aggregate-if/badge.png
- :target: https://crate.io/packages/django-aggregate-if/
- :alt: Number of PyPI downloads
-
-*Aggregate-if* adds conditional aggregates to Django.
-
-Conditional aggregates can help you reduce the ammount of queries to obtain
-aggregated information, like statistics for example.
-
-Imagine you have a model ``Offer`` like this one:
-
-.. code-block:: python
-
- class Offer(models.Model):
- sponsor = models.ForeignKey(User)
- price = models.DecimalField(max_digits=9, decimal_places=2)
- status = models.CharField(max_length=30)
- expire_at = models.DateField(null=True, blank=True)
- created_at = models.DateTimeField(auto_now_add=True)
- updated_at = models.DateTimeField(auto_now=True)
-
- OPEN = "OPEN"
- REVOKED = "REVOKED"
- PAID = "PAID"
-
-Let's say you want to know:
-
-#. How many offers exists in total;
-#. How many of them are OPEN, REVOKED or PAID;
-#. How much money was offered in total;
-#. How much money is in OPEN, REVOKED and PAID offers;
-
-To get these informations, you could query:
-
-.. code-block:: python
-
- from django.db.models import Count, Sum
-
- Offer.objects.count()
- Offer.objects.filter(status=Offer.OPEN).aggregate(Count('pk'))
- Offer.objects.filter(status=Offer.REVOKED).aggregate(Count('pk'))
- Offer.objects.filter(status=Offer.PAID).aggregate(Count('pk'))
- Offer.objects.aggregate(Sum('price'))
- Offer.objects.filter(status=Offer.OPEN).aggregate(Sum('price'))
- Offer.objects.filter(status=Offer.REVOKED).aggregate(Sum('price'))
- Offer.objects.filter(status=Offer.PAID).aggregate(Sum('price'))
-
-In this case, **8 queries** were needed to retrieve the desired information.
-
-With conditional aggregates you can get it all with only **1 query**:
-
-.. code-block:: python
-
- from django.db.models import Q
- from aggregate_if import Count, Sum
-
- Offer.objects.aggregate(
- pk__count=Count('pk'),
- pk__open__count=Count('pk', only=Q(status=Offer.OPEN)),
- pk__revoked__count=Count('pk', only=Q(status=Offer.REVOKED)),
- pk__paid__count=Count('pk', only=Q(status=Offer.PAID)),
- pk__sum=Sum('price'),
- pk__open__sum=Sum('price', only=Q(status=Offer.OPEN)),
- pk__revoked__sum=Sum('price'), only=Q(status=Offer.REVOKED)),
- pk__paid__sum=Sum('price'), only=Q(status=Offer.PAID))
- )
-
-Installation
-------------
-
-*Aggregate-if* works with Django 1.4, 1.5, 1.6 and 1.7.
-
-To install it, simply:
-
-.. code-block:: bash
-
- $ pip install django-aggregate-if
-
-Inspiration
------------
-
-There is a 5 years old `ticket 11305`_ that will (*hopefully*) implement this feature into
-Django 1.8.
-
-Using Django 1.6, I still wanted to avoid creating custom queries for very simple
-conditional aggregations. So I've cherry picked those ideas and others from the
-internet and built this library.
-
-This library uses the same API and tests proposed on `ticket 11305`_, so when the
-new feature is available you can easily replace ``django-aggregate-if``.
-
-Limitations
------------
-
-Conditions involving joins with aliases are not supported yet. If you want to
-help adding this feature, you're welcome to check the `first issue`_.
-
-Contributors
-------------
-
-* `Henrique Bastos <http://github.com/henriquebastos>`_
-* `Iuri de Silvio <https://github.com/iurisilvio>`_
-* `Hampus Stjernhav <https://github.com/champ>`_
-* `Bradley Martsberger <https://github.com/martsberger>`_
-* `Markus Bertheau <https://github.com/mbertheau>`_
-* `end0 <https://github.com/end0>`_
-* `Scott Sexton <https://github.com/scottsexton>`_
-* `Mauler <https://github.com/mauler>`_
-* `trbs <https://github.com/trbs>`_
-
-Changelog
----------
-
-0.5
- - Support for Django 1.7
-
-0.4
- - Use tox to run tests.
- - Add support for Django 1.6.
- - Add support for Python3.
- - The ``only`` parameter now freely supports joins independent of the main query.
- - Adds support for alias relabeling permitting excludes and updates with aggregates filtered on remote foreign key relations.
-
-0.3.1
- - Fix quotation escaping.
- - Fix boolean casts on Postgres.
-
-0.2
- - Fix postgres issue with LIKE conditions.
-
-0.1
- - Initial release.
-
-
-License
-=======
-
-The MIT License.
-
-.. _ticket 11305: https://code.djangoproject.com/ticket/11305
-.. _first issue: https://github.com/henriquebastos/django-aggregate-if/issues/1
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/aggregate_if.py b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/aggregate_if.py
deleted file mode 100644
index d5f342717..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/aggregate_if.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# coding: utf-8
-'''
-Implements conditional aggregates.
-
-This code was based on the work of others found on the internet:
-
-1. http://web.archive.org/web/20101115170804/http://www.voteruniverse.com/Members/jlantz/blog/conditional-aggregates-in-django
-2. https://code.djangoproject.com/ticket/11305
-3. https://groups.google.com/forum/?fromgroups=#!topic/django-users/cjzloTUwmS0
-4. https://groups.google.com/forum/?fromgroups=#!topic/django-users/vVprMpsAnPo
-'''
-from __future__ import unicode_literals
-from django.utils import six
-import django
-from django.db.models.aggregates import Aggregate as DjangoAggregate
-from django.db.models.sql.aggregates import Aggregate as DjangoSqlAggregate
-
-
-VERSION = django.VERSION[:2]
-
-
-class SqlAggregate(DjangoSqlAggregate):
- conditional_template = '%(function)s(CASE WHEN %(condition)s THEN %(field)s ELSE null END)'
-
- def __init__(self, col, source=None, is_summary=False, condition=None, **extra):
- super(SqlAggregate, self).__init__(col, source, is_summary, **extra)
- self.condition = condition
-
- def relabel_aliases(self, change_map):
- if VERSION < (1, 7):
- super(SqlAggregate, self).relabel_aliases(change_map)
- if self.has_condition:
- condition_change_map = dict((k, v) for k, v in \
- change_map.items() if k in self.condition.query.alias_map
- )
- self.condition.query.change_aliases(condition_change_map)
-
- def relabeled_clone(self, change_map):
- self.relabel_aliases(change_map)
- return super(SqlAggregate, self).relabeled_clone(change_map)
-
- def as_sql(self, qn, connection):
- if self.has_condition:
- self.sql_template = self.conditional_template
- self.extra['condition'] = self._condition_as_sql(qn, connection)
-
- return super(SqlAggregate, self).as_sql(qn, connection)
-
- @property
- def has_condition(self):
- # Warning: bool(QuerySet) will hit the database
- return self.condition is not None
-
- def _condition_as_sql(self, qn, connection):
- '''
- Return sql for condition.
- '''
- def escape(value):
- if isinstance(value, bool):
- value = str(int(value))
- if isinstance(value, six.string_types):
- # Escape params used with LIKE
- if '%' in value:
- value = value.replace('%', '%%')
- # Escape single quotes
- if "'" in value:
- value = value.replace("'", "''")
- # Add single quote to text values
- value = "'" + value + "'"
- return value
-
- sql, param = self.condition.query.where.as_sql(qn, connection)
- param = map(escape, param)
-
- return sql % tuple(param)
-
-
-class SqlSum(SqlAggregate):
- sql_function = 'SUM'
-
-
-class SqlCount(SqlAggregate):
- is_ordinal = True
- sql_function = 'COUNT'
- sql_template = '%(function)s(%(distinct)s%(field)s)'
- conditional_template = '%(function)s(%(distinct)sCASE WHEN %(condition)s THEN %(field)s ELSE null END)'
-
- def __init__(self, col, distinct=False, **extra):
- super(SqlCount, self).__init__(col, distinct=distinct and 'DISTINCT ' or '', **extra)
-
-
-class SqlAvg(SqlAggregate):
- is_computed = True
- sql_function = 'AVG'
-
-
-class SqlMax(SqlAggregate):
- sql_function = 'MAX'
-
-
-class SqlMin(SqlAggregate):
- sql_function = 'MIN'
-
-
-class Aggregate(DjangoAggregate):
- def __init__(self, lookup, only=None, **extra):
- super(Aggregate, self).__init__(lookup, **extra)
- self.only = only
- self.condition = None
-
- def _get_fields_from_Q(self, q):
- fields = []
- for child in q.children:
- if hasattr(child, 'children'):
- fields.extend(self._get_fields_from_Q(child))
- else:
- fields.append(child)
- return fields
-
- def add_to_query(self, query, alias, col, source, is_summary):
- if self.only:
- self.condition = query.model._default_manager.filter(self.only)
- for child in self._get_fields_from_Q(self.only):
- field_list = child[0].split('__')
- # Pop off the last field if it's a query term ('gte', 'contains', 'isnull', etc.)
- if field_list[-1] in query.query_terms:
- field_list.pop()
- # setup_joins have different returns in Django 1.5 and 1.6, but the order of what we need remains.
- result = query.setup_joins(field_list, query.model._meta, query.get_initial_alias(), None)
- join_list = result[3]
-
- fname = 'promote_alias_chain' if VERSION < (1, 5) else 'promote_joins'
- args = (join_list, True) if VERSION < (1, 7) else (join_list,)
-
- promote = getattr(query, fname)
- promote(*args)
-
- aggregate = self.sql_klass(col, source=source, is_summary=is_summary, condition=self.condition, **self.extra)
- query.aggregates[alias] = aggregate
-
-
-class Sum(Aggregate):
- name = 'Sum'
- sql_klass = SqlSum
-
-
-class Count(Aggregate):
- name = 'Count'
- sql_klass = SqlCount
-
-
-class Avg(Aggregate):
- name = 'Avg'
- sql_klass = SqlAvg
-
-
-class Max(Aggregate):
- name = 'Max'
- sql_klass = SqlMax
-
-
-class Min(Aggregate):
- name = 'Min'
- sql_klass = SqlMin
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/runtests.py b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/runtests.py
deleted file mode 100755
index 2e55864e3..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/runtests.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-from optparse import OptionParser
-
-
-def parse_args():
- parser = OptionParser()
- parser.add_option('-s', '--settings', help='Define settings.')
- parser.add_option('-t', '--unittest', help='Define which test to run. Default all.')
- options, args = parser.parse_args()
-
- if not options.settings:
- parser.print_help()
- sys.exit(1)
-
- if not options.unittest:
- options.unittest = ['aggregation']
-
- return options
-
-
-def get_runner(settings_module):
- '''
- Asks Django for the TestRunner defined in settings or the default one.
- '''
- os.environ['DJANGO_SETTINGS_MODULE'] = settings_module
-
- import django
- from django.test.utils import get_runner
- from django.conf import settings
-
- if hasattr(django, 'setup'):
- django.setup()
-
- return get_runner(settings)
-
-
-def runtests():
- options = parse_args()
- TestRunner = get_runner(options.settings)
- runner = TestRunner(verbosity=1, interactive=True, failfast=False)
- sys.exit(runner.run_tests([]))
-
-
-if __name__ == '__main__':
- runtests()
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/setup.py b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/setup.py
deleted file mode 100644
index aed3db14d..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/setup.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# coding: utf-8
-from setuptools import setup
-import os
-
-
-setup(name='django-aggregate-if',
- version='0.5',
- description='Conditional aggregates for Django, just like the famous SumIf in Excel.',
- long_description=open(os.path.join(os.path.dirname(__file__), "README.rst")).read(),
- author="Henrique Bastos", author_email="henrique@bastos.net",
- license="MIT",
- py_modules=['aggregate_if'],
- install_requires=[
- 'six>=1.6.1',
- ],
- zip_safe=False,
- platforms='any',
- include_package_data=True,
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Framework :: Django',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: MIT License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3',
- 'Topic :: Database',
- 'Topic :: Software Development :: Libraries',
- ],
- url='http://github.com/henriquebastos/django-aggregate-if/',
-)
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/tox.ini b/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/tox.ini
deleted file mode 100644
index 78beb148a..000000000
--- a/yocto-poky/bitbake/lib/toaster/contrib/django-aggregate-if-master/tox.ini
+++ /dev/null
@@ -1,198 +0,0 @@
-[tox]
-envlist =
- py27-django1.4-sqlite,
- py27-django1.4-postgres,
- py27-django1.4-mysql,
-
- py27-django1.5-sqlite,
- py27-django1.5-postgres,
- py27-django1.5-mysql,
-
- py27-django1.6-sqlite,
- py27-django1.6-postgres,
- py27-django1.6-mysql,
-
- py27-django1.7-sqlite,
- py27-django1.7-postgres,
- py27-django1.7-mysql,
-
- py34-django1.6-sqlite,
- py34-django1.6-postgres,
- #py34-django1.6-mysql
-
- py34-django1.7-sqlite,
- py34-django1.7-postgres,
- #py34-django1.7-mysql
-
-[testenv]
-whitelist_externals=
- mysql
- psql
-
-# Python 2.7
-# Django 1.4
-[testenv:py27-django1.4-sqlite]
-basepython = python2.7
-deps =
- django==1.4
-commands = python runtests.py --settings tests.test_sqlite
-
-[testenv:py27-django1.4-postgres]
-basepython = python2.7
-deps =
- django==1.4
- psycopg2
-commands =
- psql -c 'create database aggregation;' postgres
- python runtests.py --settings tests.test_postgres
- psql -c 'drop database aggregation;' postgres
-
-[testenv:py27-django1.4-mysql]
-basepython = python2.7
-deps =
- django==1.4
- mysql-python
-commands =
- mysql -e 'create database aggregation;'
- python runtests.py --settings tests.test_mysql
- mysql -e 'drop database aggregation;'
-
-# Django 1.5
-[testenv:py27-django1.5-sqlite]
-basepython = python2.7
-deps =
- django==1.5
-commands = python runtests.py --settings tests.test_sqlite
-
-[testenv:py27-django1.5-postgres]
-basepython = python2.7
-deps =
- django==1.5
- psycopg2
-commands =
- psql -c 'create database aggregation;' postgres
- python runtests.py --settings tests.test_postgres
- psql -c 'drop database aggregation;' postgres
-
-[testenv:py27-django1.5-mysql]
-basepython = python2.7
-deps =
- django==1.5
- mysql-python
-commands =
- mysql -e 'create database aggregation;'
- python runtests.py --settings tests.test_mysql
- mysql -e 'drop database aggregation;'
-
-# Django 1.6
-[testenv:py27-django1.6-sqlite]
-basepython = python2.7
-deps =
- django==1.6
-commands = python runtests.py --settings tests.test_sqlite
-
-[testenv:py27-django1.6-postgres]
-basepython = python2.7
-deps =
- django==1.6
- psycopg2
-commands =
- psql -c 'create database aggregation;' postgres
- python runtests.py --settings tests.test_postgres
- psql -c 'drop database aggregation;' postgres
-
-[testenv:py27-django1.6-mysql]
-basepython = python2.7
-deps =
- django==1.6
- mysql-python
-commands =
- mysql -e 'create database aggregation;'
- python runtests.py --settings tests.test_mysql
- mysql -e 'drop database aggregation;'
-
-
-# Python 2.7 and Django 1.7
-[testenv:py27-django1.7-sqlite]
-basepython = python2.7
-deps =
- django==1.7
-commands = python runtests.py --settings tests.test_sqlite
-
-[testenv:py27-django1.7-postgres]
-basepython = python2.7
-deps =
- django==1.7
- psycopg2
-commands =
- psql -c 'create database aggregation;' postgres
- python runtests.py --settings tests.test_postgres
- psql -c 'drop database aggregation;' postgres
-
-[testenv:py27-django1.7-mysql]
-basepython = python2.7
-deps =
- django==1.7
- mysql-python
-commands =
- mysql -e 'create database aggregation;'
- python runtests.py --settings tests.test_mysql
- mysql -e 'drop database aggregation;'
-
-
-# Python 3.4
-# Django 1.6
-[testenv:py34-django1.6-sqlite]
-basepython = python3.4
-deps =
- django==1.6
-commands = python runtests.py --settings tests.test_sqlite
-
-[testenv:py34-django1.6-postgres]
-basepython = python3.4
-deps =
- django==1.6
- psycopg2
-commands =
- psql -c 'create database aggregation;' postgres
- python runtests.py --settings tests.test_postgres
- psql -c 'drop database aggregation;' postgres
-
-[testenv:py34-django1.6-mysql]
-basepython = python3.4
-deps =
- django==1.6
- mysql-python3
-commands =
- mysql -e 'create database aggregation;'
- python runtests.py --settings tests.test_mysql
- mysql -e 'drop database aggregation;'
-
-
-# Python 3.4
-# Django 1.7
-[testenv:py34-django1.7-sqlite]
-basepython = python3.4
-deps =
- django==1.7
-commands = python runtests.py --settings tests.test_sqlite
-
-[testenv:py34-django1.7-postgres]
-basepython = python3.4
-deps =
- django==1.7
- psycopg2
-commands =
- psql -c 'create database aggregation;' postgres
- python runtests.py --settings tests.test_postgres
- psql -c 'drop database aggregation;' postgres
-
-[testenv:py34-django1.7-mysql]
-basepython = python3.4
-deps =
- django==1.7
- mysql-python3
-commands =
- mysql -e 'create database aggregation;'
- python runtests.py --settings tests.test_mysql
- mysql -e 'drop database aggregation;'
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py b/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py
index 880487cb6..754636f0f 100755
--- a/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py
+++ b/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/run_toastertests.py
@@ -28,60 +28,128 @@
# put chromedriver in PATH, (e.g. /usr/bin/, bear in mind to chmod)
# For windows host, you may put chromedriver.exe in the same directory as chrome.exe
-
-import unittest, time, re, sys, getopt, os, logging, platform
+import unittest, sys, os, platform
import ConfigParser
-import subprocess
-
-
-class toaster_run_all():
- def __init__(self):
- # in case this script is called from other directory
- os.chdir(os.path.abspath(sys.path[0]))
- self.starttime = time.strptime(time.ctime())
- self.parser = ConfigParser.SafeConfigParser()
- found = self.parser.read('toaster_test.cfg')
- self.host_os = platform.system().lower()
- self.run_all_cases()
- self.collect_log()
-
- def get_test_cases(self):
- # we have config groups for different os type in toaster_test.cfg
- cases_to_run = eval(self.parser.get('toaster_test_' + self.host_os, 'test_cases'))
- return cases_to_run
-
-
- def run_all_cases(self):
- cases_temp = self.get_test_cases()
- for case in cases_temp:
- single_case_cmd = "python -m unittest toaster_automation_test.toaster_cases.test_" + str(case)
- print single_case_cmd
- subprocess.call(single_case_cmd, shell=True)
-
- def collect_log(self):
+import argparse
+from toaster_automation_test import toaster_cases
+
+
+def get_args_parser():
+ description = "Script that runs toaster auto tests."
+ parser = argparse.ArgumentParser(description=description)
+ parser.add_argument('--run-all-tests', required=False, action="store_true", dest="run_all_tests", default=False,
+ help='Run all tests.')
+ parser.add_argument('--run-suite', required=False, dest='run_suite', default=False,
+ help='run suite (defined in cfg file)')
+
+ return parser
+
+
+def get_tests():
+ testslist = []
+
+ prefix = 'toaster_automation_test.toaster_cases'
+
+ for t in dir(toaster_cases):
+ if t.startswith('test_'):
+ testslist.append('.'.join((prefix, t)))
+
+ return testslist
+
+
+def get_tests_from_cfg(suite=None):
+
+ testslist = []
+ config = ConfigParser.SafeConfigParser()
+ config.read('toaster_test.cfg')
+
+ if suite is not None:
+ target_suite = suite.lower()
+
+ # TODO: if suite is valid suite
+
+ else:
+ target_suite = platform.system().lower()
+
+ try:
+ tests_from_cfg = eval(config.get('toaster_test_' + target_suite, 'test_cases'))
+ except:
+ print 'Failed to get test cases from cfg file. Make sure the format is correct.'
+ return None
+
+ prefix = 'toaster_automation_test.toaster_cases.test_'
+ for t in tests_from_cfg:
+ testslist.append(prefix + str(t))
+
+ return testslist
+
+def main():
+
+ # In case this script is called from other directory
+ os.chdir(os.path.abspath(sys.path[0]))
+
+ parser = get_args_parser()
+ args = parser.parse_args()
+
+ if args.run_all_tests:
+ testslist = get_tests()
+ elif args.run_suite:
+ testslist = get_tests_from_cfg(args.run_suite)
+ os.environ['TOASTER_SUITE'] = args.run_suite
+ else:
+ testslist = get_tests_from_cfg()
+
+ if not testslist:
+ print 'Failed to get test cases.'
+ exit(1)
+
+ suite = unittest.TestSuite()
+ loader = unittest.TestLoader()
+ loader.sortTestMethodsUsing = None
+ runner = unittest.TextTestRunner(verbosity=2, resultclass=buildResultClass(args))
+
+ for test in testslist:
+ try:
+ suite.addTests(loader.loadTestsFromName(test))
+ except:
+ return 1
+
+ result = runner.run(suite)
+
+ if result.wasSuccessful():
+ return 0
+ else:
+ return 1
+
+
+def buildResultClass(args):
+ """Build a Result Class to use in the testcase execution"""
+
+ class StampedResult(unittest.TextTestResult):
"""
- the log files are temporarily stored in ./log/tmp/..
- After all cases are done, they should be transfered to ./log/$TIMESTAMP/
+ Custom TestResult that prints the time when a test starts. As toaster-auto
+ can take a long time (ie a few hours) to run, timestamps help us understand
+ what tests are taking a long time to execute.
"""
- def comple(number):
- if number < 10:
- return str(0) + str(number)
- else:
- return str(number)
- now = self.starttime
- now_str = comple(now.tm_year) + comple(now.tm_mon) + comple(now.tm_mday) + \
- comple(now.tm_hour) + comple(now.tm_min) + comple(now.tm_sec)
- log_dir = os.path.abspath(sys.path[0]) + os.sep + 'log' + os.sep + now_str
- log_tmp_dir = os.path.abspath(sys.path[0]) + os.sep + 'log' + os.sep + 'tmp'
- try:
- os.renames(log_tmp_dir, log_dir)
- except OSError :
- logging.error(" Cannot create log dir(timestamp) under log, please check your privilege")
+ def startTest(self, test):
+ import time
+ self.stream.write(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " - ")
+ super(StampedResult, self).startTest(test)
+ return StampedResult
-if __name__ == "__main__":
- toaster_run_all()
+if __name__ == "__main__":
+ try:
+ ret = main()
+ except:
+ ret = 1
+ import traceback
+ traceback.print_exc()
+ finally:
+ if os.getenv('TOASTER_SUITE'):
+ del os.environ['TOASTER_SUITE']
+ sys.exit(ret)
diff --git a/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py b/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py
index eac167b2e..d8f838aea 100755
--- a/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py
+++ b/yocto-poky/bitbake/lib/toaster/contrib/tts/toasteruitest/toaster_automation_test.py
@@ -23,13 +23,14 @@
# step 2 - 3 needs to be run manually
import unittest, time, re, sys, getopt, os, logging, string, errno, exceptions
-import shutil, argparse, ConfigParser, platform
+import shutil, argparse, ConfigParser, platform, json
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium import selenium
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
+import sqlite3 as sqlite
###########################################
@@ -229,60 +230,70 @@ class NoParsingFilter(logging.Filter):
def LogResults(original_class):
orig_method = original_class.run
+ from time import strftime, gmtime
+ caller = 'toaster'
+ timestamp = strftime('%Y%m%d%H%M%S',gmtime())
+ logfile = os.path.join(os.getcwd(),'results-'+caller+'.'+timestamp+'.log')
+ linkfile = os.path.join(os.getcwd(),'results-'+caller+'.log')
+
#rewrite the run method of unittest.TestCase to add testcase logging
def run(self, result, *args, **kws):
orig_method(self, result, *args, **kws)
passed = True
testMethod = getattr(self, self._testMethodName)
-
#if test case is decorated then use it's number, else use it's name
try:
test_case = testMethod.test_case
except AttributeError:
test_case = self._testMethodName
+ class_name = str(testMethod.im_class).split("'")[1]
+
#create custom logging level for filtering.
custom_log_level = 100
logging.addLevelName(custom_log_level, 'RESULTS')
- caller = os.path.basename(sys.argv[0])
def results(self, message, *args, **kws):
if self.isEnabledFor(custom_log_level):
self.log(custom_log_level, message, *args, **kws)
logging.Logger.results = results
- logging.basicConfig(filename=os.path.join(os.getcwd(),'results-'+caller+'.log'),
+ logging.basicConfig(filename=logfile,
filemode='w',
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%H:%M:%S',
level=custom_log_level)
for handler in logging.root.handlers:
handler.addFilter(NoParsingFilter())
-# local_log = logging.getLogger(caller)
- local_log = logging.getLogger()
+ local_log = logging.getLogger(caller)
#check status of tests and record it
+
for (name, msg) in result.errors:
- if self._testMethodName == str(name).split(' ')[0]:
+ if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
local_log.results("Testcase "+str(test_case)+": ERROR")
- local_log.results("Testcase "+str(test_case)+":\n"+msg+"\n\n\n")
+ local_log.results("Testcase "+str(test_case)+":\n"+msg)
passed = False
for (name, msg) in result.failures:
- if self._testMethodName == str(name).split(' ')[0]:
+ if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
local_log.results("Testcase "+str(test_case)+": FAILED")
- local_log.results("Testcase "+str(test_case)+":\n"+msg+"\n\n\n")
+ local_log.results("Testcase "+str(test_case)+":\n"+msg)
passed = False
for (name, msg) in result.skipped:
- if self._testMethodName == str(name).split(' ')[0]:
- local_log.results("Testcase "+str(test_case)+": SKIPPED"+"\n\n\n")
+ if (self._testMethodName == str(name).split(' ')[0]) and (class_name in str(name).split(' ')[1]):
+ local_log.results("Testcase "+str(test_case)+": SKIPPED")
passed = False
if passed:
- local_log.results("Testcase "+str(test_case)+": PASSED"+"\n\n\n")
+ local_log.results("Testcase "+str(test_case)+": PASSED")
- original_class.run = run
- return original_class
+ # Create symlink to the current log
+ if os.path.exists(linkfile):
+ os.remove(linkfile)
+ os.symlink(logfile, linkfile)
+ original_class.run = run
+ return original_class
###########################################
@@ -291,16 +302,26 @@ def LogResults(original_class):
# #
###########################################
+@LogResults
class toaster_cases_base(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.log = cls.logger_create()
+
def setUp(self):
self.screenshot_sequence = 1
self.verificationErrors = []
self.accept_next_alert = True
self.host_os = platform.system().lower()
+ if os.getenv('TOASTER_SUITE'):
+ self.target_suite = os.getenv('TOASTER_SUITE')
+ else:
+ self.target_suite = self.host_os
+
self.parser = ConfigParser.SafeConfigParser()
- configs = self.parser.read('toaster_test.cfg')
- self.base_url = eval(self.parser.get('toaster_test_' + self.host_os, 'toaster_url'))
+ self.parser.read('toaster_test.cfg')
+ self.base_url = eval(self.parser.get('toaster_test_' + self.target_suite, 'toaster_url'))
# create log dir . Currently , we put log files in log/tmp. After all
# test cases are done, move them to log/$datetime dir
@@ -309,37 +330,37 @@ class toaster_cases_base(unittest.TestCase):
mkdir_p(self.log_tmp_dir)
except OSError :
logging.error("%(asctime)s Cannot create tmp dir under log, please check your privilege")
- self.log = self.logger_create()
+ # self.log = self.logger_create()
# driver setup
self.setup_browser()
- def logger_create(self):
- """
- we use root logger for every testcase.
- The reason why we don't use TOASTERXXX_logger is to avoid setting respective level for
- root logger and TOASTERXXX_logger
- To Be Discussed
- """
- log_level_dict = {'CRITICAL':logging.CRITICAL, 'ERROR':logging.ERROR, 'WARNING':logging.WARNING, \
- 'INFO':logging.INFO, 'DEBUG':logging.DEBUG, 'NOTSET':logging.NOTSET}
- log = logging.getLogger()
-# log = logging.getLogger('TOASTER_' + str(self.case_no))
- self.logging_level = eval(self.parser.get('toaster_test_' + self.host_os, 'logging_level'))
- key = self.logging_level.upper()
- log.setLevel(log_level_dict[key])
- fh = logging.FileHandler(filename=self.log_tmp_dir + os.sep + 'case_all' + '.log', mode='a')
+ @staticmethod
+ def logger_create():
+ log_file = "toaster-auto-" + time.strftime("%Y%m%d%H%M%S") + ".log"
+ if os.path.exists("toaster-auto.log"): os.remove("toaster-auto.log")
+ os.symlink(log_file, "toaster-auto.log")
+
+ log = logging.getLogger("toaster")
+ log.setLevel(logging.DEBUG)
+
+ fh = logging.FileHandler(filename=log_file, mode='w')
+ fh.setLevel(logging.DEBUG)
+
ch = logging.StreamHandler(sys.stdout)
- formatter = logging.Formatter('%(pathname)s - %(lineno)d - %(asctime)s \n \
- %(name)s - %(levelname)s - %(message)s')
+ ch.setLevel(logging.INFO)
+
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
+
log.addHandler(fh)
log.addHandler(ch)
+
return log
def setup_browser(self, *browser_path):
- self.browser = eval(self.parser.get('toaster_test_' + self.host_os, 'test_browser'))
+ self.browser = eval(self.parser.get('toaster_test_' + self.target_suite, 'test_browser'))
print self.browser
if self.browser == "firefox":
driver = webdriver.Firefox()
@@ -596,7 +617,7 @@ class toaster_cases_base(unittest.TestCase):
def is_text_present (self, patterns):
for pattern in patterns:
if str(pattern) not in self.driver.page_source:
- print pattern
+ print 'Text "'+pattern+'" is missing'
return False
return True
@@ -605,6 +626,7 @@ class toaster_cases_base(unittest.TestCase):
try:
self.driver.find_element(how, what)
except NoSuchElementException, e:
+ print 'Could not find element '+str(what)+' by ' + str(how)
return False
return True
@@ -658,7 +680,7 @@ class toaster_cases_base(unittest.TestCase):
# Note: to comply with the unittest framework, we call these test_xxx functions
# from run_toastercases.py to avoid calling setUp() and tearDown() multiple times
-@LogResults
+
class toaster_cases(toaster_cases_base):
##############
# CASE 901 #
@@ -743,7 +765,7 @@ class toaster_cases(toaster_cases_base):
self.driver.find_element_by_id("started_on").click()
self.driver.find_element_by_id("edit-columns-button").click()
# step 4
- items = ["Outcome", "Completed on", "Started on", "Failed tasks", "Errors", "Warnings"]
+ items = ["Outcome", "Completed on", "Started on"]
for item in items:
try:
temp_element = self.find_element_by_text_in_table('otable', item)
@@ -787,8 +809,6 @@ class toaster_cases(toaster_cases_base):
self.driver.get(self.base_url)
self.driver.find_element_by_partial_link_text("core-image").click()
self.driver.find_element_by_link_text("Tasks").click()
-# self.driver.find_element_by_link_text("All builds").click()
-# self.driver.back()
self.table_name = 'otable'
# This is how we find the "default" rows-number!
rows_displayed = int(Select(self.driver.find_element_by_css_selector("select.pagesize")).first_selected_option.text)
@@ -811,24 +831,23 @@ class toaster_cases(toaster_cases_base):
self.driver.find_element_by_id("edit-columns-button").click()
self.driver.find_element_by_id("cpu_used").click()
self.driver.find_element_by_id("disk_io").click()
- self.driver.find_element_by_id("task_log").click()
self.driver.find_element_by_id("recipe_version").click()
self.driver.find_element_by_id("time_taken").click()
- self.driver.find_element_by_css_selector("edit-columns-button").click()
+ self.driver.find_element_by_id("edit-columns-button").click()
# The operation is the same as case901
# dict: {lint text name : actual class name}
table_head_dict = {'Order':'order', 'Recipe':'recipe_name', 'Task':'task_name', 'Executed':'executed', \
'Outcome':'outcome', 'Cache attempt':'cache_attempt', 'Time (secs)':'time_taken', 'CPU usage':'cpu_used', \
'Disk I/O (ms)':'disk_io'}
for key in table_head_dict:
-# This is tricky here: we are doing so because there may be more than 1
-# same-name link_text in one page. So we only find element inside the table
+ # This is tricky here: we are doing so because there may be more than 1
+ # same-name link_text in one page. So we only find element inside the table
self.find_element_by_link_text_in_table(self.table_name, key).click()
column_list = self.get_table_column_text("class", table_head_dict[key])
-# after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here
-# the point is, after another click, it should be another order
-# the first case is special:this means every item in column_list is the same, so
-# after one click, either sequenced or inverted will be fine
+ # after 1st click, the list should be either sequenced or inverted, but we don't have a "default order" here
+ # the point is, after another click, it should be another order
+ # the first case is special:this means every item in column_list is the same, so
+ # after one click, either sequenced or inverted will be fine
if (is_list_inverted(column_list) and is_list_sequenced(column_list)) \
or (not column_list) :
self.find_element_by_link_text_in_table(self.table_name, key).click()
@@ -844,7 +863,7 @@ class toaster_cases(toaster_cases_base):
self.find_element_by_link_text_in_table(self.table_name, key).click()
column_list = self.get_table_column_text("class", table_head_dict[key])
self.assertTrue(is_list_inverted(column_list), msg=("%s column not inverted" % key))
-# step 8-10
+ # step 8-10
# filter dict: {link text name : filter table name in xpath}
filter_dict = {'Executed':'filter_executed', 'Outcome':'filter_outcome', 'Cache attempt':'filter_cache_attempt'}
for key in filter_dict:
@@ -864,11 +883,19 @@ class toaster_cases(toaster_cases_base):
self.save_screenshot(screenshot_type='selenium', append_name='step8')
# after the last option was clicked, we don't need operation below anymore
if number < len(avail_options)-1:
- temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
- temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
- avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
+ try:
+ temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
+ temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
+ avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
+ except:
+ print "in exception"
+ self.find_element_by_text("Show all tasks").click()
+# self.driver.find_element_by_xpath("//*[@id='searchform']/button[2]").click()
+ temp_element = self.find_element_by_link_text_in_table(self.table_name, key)
+ temp_element.find_element_by_xpath("..//*[@class='icon-filter filtered']").click()
+ avail_options = self.driver.find_elements_by_xpath("//*[@id='" + filter_dict[key] + "']//*[@name='filter'][not(@disabled)]")
self.browser_delay()
-# step 11
+ # step 11
for item in ['order', 'task_name', 'executed', 'outcome', 'recipe_name', 'recipe_version']:
try:
self.find_element_by_xpath_in_table(self.table_name, "./tbody/tr[1]/*[@class='" + item + "']/a").click()
@@ -878,7 +905,7 @@ class toaster_cases(toaster_cases_base):
# insert screen shot here
self.save_screenshot(screenshot_type='selenium', append_name='step11')
self.driver.back()
-# step 12-14
+ # step 12-14
# about test_dict: please refer to testcase 904 requirement step 12-14
test_dict = {
'Time':{
@@ -926,14 +953,14 @@ class toaster_cases(toaster_cases_base):
# find "bash" in first column (Packages)
self.driver.find_element_by_xpath("//*[@id='otable']//td[1]//*[text()='bash']").click()
# save sceen here to observe...
-# step 6
+ # step 6
self.driver.find_element_by_partial_link_text("Generated files").click()
head_list = self.get_table_head_text('otable')
for item in ['File', 'Size']:
self.assertTrue(item in head_list, msg=("%s not in head row" % item))
c_list = self.get_table_column_text('class', 'path')
self.assertTrue(is_list_sequenced(c_list), msg=("column not in order"))
-# step 7
+ # step 7
self.driver.find_element_by_partial_link_text("Runtime dependencies").click()
# save sceen here to observe...
# note that here table name is not 'otable'
@@ -943,11 +970,8 @@ class toaster_cases(toaster_cases_base):
c_list = self.get_table_column_text_by_column_number('dependencies', 1)
self.assertTrue(is_list_sequenced(c_list), msg=("list not in order"))
texts = ['Size', 'License', 'Recipe', 'Recipe version', 'Layer', \
- 'Layer branch', 'Layer commit']
- time.sleep(1)
-# for text in texts:
-# self.assertTrue(self.is_text_present(text), msg=("text %s not in page" % text))
- self.assertTrue(self.is_text_present(texts), msg=("text not in page"))
+ 'Layer commit']
+ self.failUnless(self.is_text_present(texts))
##############
@@ -1049,7 +1073,7 @@ class toaster_cases(toaster_cases_base):
self.assertTrue(is_list_sequenced(column_search_list))
self.driver.find_element_by_css_selector("i.icon-remove").click()
else:
- self.assertTrue(is_list_sequenced(column_list))
+ self.assertTrue(is_list_sequenced(column_list), msg=("list %s not sequenced" % key))
self.find_element_by_link_text_in_table(self.table_name, key).click()
column_list = self.get_table_column_text("class", table_head_dict[key])
self.assertTrue(is_list_inverted(column_list))
@@ -1102,21 +1126,22 @@ class toaster_cases(toaster_cases_base):
self.driver.get(self.base_url)
self.driver.find_element_by_link_text("core-image-minimal").click()
self.find_element_by_link_text_in_table('nav', 'Recipes').click()
-# step 3-5
+ # step 3-5
self.driver.find_element_by_id("search").clear()
self.driver.find_element_by_id("search").send_keys("lib")
self.driver.find_element_by_id("search-button").click()
# save screen here for observation
self.save_screenshot(screenshot_type='selenium', append_name='step5')
-# step 6
+ # step 6
self.driver.find_element_by_css_selector("i.icon-remove").click()
self.driver.find_element_by_id("search").clear()
# we deliberately want "no result" here
self.driver.find_element_by_id("search").send_keys("no such input")
self.driver.find_element_by_id("search-button").click()
- self.find_element_by_text("Show all recipes").click()
- self.driver.quit()
-
+ try:
+ self.find_element_by_text("Show all recipes").click()
+ except:
+ self.fail(msg='Could not identify blank page elements')
##############
# CASE 912 #
@@ -1124,7 +1149,6 @@ class toaster_cases(toaster_cases_base):
def test_912(self):
self.case_no = self.get_case_number()
self.log.info(' CASE %s log: ' % str(self.case_no))
- self.driver = self.setup_browser(self)
self.driver.maximize_window()
self.driver.get(self.base_url)
self.driver.find_element_by_link_text("core-image-minimal").click()
@@ -1200,10 +1224,10 @@ class toaster_cases(toaster_cases_base):
self.table_name = 'information'
- tasks_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr/td[1]"))
- tasks_column_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr[1]/td"))
- print tasks_row_count
- print tasks_column_count
+ tasks_row_count = len(driver.find_elements_by_xpath("//*[@id='"+self.table_name+"']/table/tbody/tr/td[1]"))
+ tasks_column_count = len(driver.find_elements_by_xpath("//*[@id='"+self.table_name+"']/table/tbody/tr[1]/td"))
+ print 'rows: '+str(tasks_row_count)
+ print 'columns: '+str(tasks_column_count)
Tasks_column = self.get_table_column_text_by_column_number(self.table_name, 2)
print ("Tasks_column=", Tasks_column)
@@ -1230,21 +1254,26 @@ class toaster_cases(toaster_cases_base):
driver.find_element_by_partial_link_text("Packages (").click()
packages_name = driver.find_element_by_partial_link_text("Packages (").text
print packages_name
- packages_num = string.atoi(filter(str.isdigit, repr(packages_name)))
+ packages_num = int(filter(str.isdigit, repr(packages_name)))
print packages_num
- packages_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[2]/table/tbody/tr/td[1]"))
+ #switch the table to show more than 10 rows at a time
+ self.driver.find_element_by_xpath("//*[@id='packages-built']/div[1]/div/select").click()
+ Select(driver.find_element_by_xpath("//*[@id='packages-built']/div[1]/div/select")).select_by_value('150')
+ self.driver.find_element_by_xpath("//*[@id='packages-built']/div[1]/div/select").send_keys(Keys.ENTER)
+
+ packages_row_count = len(driver.find_elements_by_xpath("//*[@id='otable']/tbody/tr/td[1]"))
print packages_row_count
if packages_num != packages_row_count:
print ("Error! The packages number is not correct")
else:
- print ("The pakcages number is correct")
+ print ("The packages number is correct")
driver.find_element_by_partial_link_text("Build dependencies (").click()
depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text
print depends_name
- depends_num = string.atoi(filter(str.isdigit, repr(depends_name)))
+ depends_num = int(filter(str.isdigit, repr(depends_name)))
print depends_num
if depends_num == 0:
@@ -1255,7 +1284,7 @@ class toaster_cases(toaster_cases_base):
else:
print ("The message is expected")
else:
- depends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[3]/table/tbody/tr/td[1]"))
+ depends_row_count = len(driver.find_elements_by_xpath("//*[@id='dependencies']/table/tbody/tr/td[1]"))
print depends_row_count
if depends_num != depends_row_count:
print ("Error! The dependent packages number is not correct")
@@ -1265,7 +1294,7 @@ class toaster_cases(toaster_cases_base):
driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text
print rdepends_name
- rdepends_num = string.atoi(filter(str.isdigit, repr(rdepends_name)))
+ rdepends_num = int(filter(str.isdigit, repr(rdepends_name)))
print rdepends_num
if rdepends_num == 0:
@@ -1288,8 +1317,8 @@ class toaster_cases(toaster_cases_base):
driver.find_element_by_link_text("Recipes").click()
driver.find_element_by_link_text(test_package3).click()
- native_tasks_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr/td[1]"))
- native_tasks_column_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[1]/table/tbody/tr[1]/td"))
+ native_tasks_row_count = len(driver.find_elements_by_xpath("//*[@id='information']/table/tbody/tr/td[1]"))
+ native_tasks_column_count = len(driver.find_elements_by_xpath("//*[@id='information']/table/tbody/tr[1]/td"))
print native_tasks_row_count
print native_tasks_column_count
@@ -1318,13 +1347,13 @@ class toaster_cases(toaster_cases_base):
driver.find_element_by_partial_link_text("Packages (").click()
native_packages_name = driver.find_element_by_partial_link_text("Packages (").text
print native_packages_name
- native_packages_num = string.atoi(filter(str.isdigit, repr(native_packages_name)))
+ native_packages_num = int(filter(str.isdigit, repr(native_packages_name)))
print native_packages_num
if native_packages_num != 0:
print ("Error! Native task shouldn't have any packages.")
else:
- native_package_message = repr(driver.find_element_by_css_selector("div.alert.alert-info").text)
+ native_package_message = repr(driver.find_element_by_css_selector("#packages-built > div.alert.alert-info").text)
print native_package_message
if native_package_message.find("does not build any packages.") < 0:
print ("Error! The message for native task isn't expected.")
@@ -1334,10 +1363,10 @@ class toaster_cases(toaster_cases_base):
driver.find_element_by_partial_link_text("Build dependencies (").click()
native_depends_name = driver.find_element_by_partial_link_text("Build dependencies (").text
print native_depends_name
- native_depends_num = string.atoi(filter(str.isdigit, repr(native_depends_name)))
+ native_depends_num = int(filter(str.isdigit, repr(native_depends_name)))
print native_depends_num
- native_depends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[3]/table/tbody/tr/td[1]"))
+ native_depends_row_count = len(driver.find_elements_by_xpath("//*[@id='dependencies']/table/tbody/tr/td[1]"))
print native_depends_row_count
if native_depends_num != native_depends_row_count:
@@ -1348,10 +1377,10 @@ class toaster_cases(toaster_cases_base):
driver.find_element_by_partial_link_text("Reverse build dependencies (").click()
native_rdepends_name = driver.find_element_by_partial_link_text("Reverse build dependencies (").text
print native_rdepends_name
- native_rdepends_num = string.atoi(filter(str.isdigit, repr(native_rdepends_name)))
+ native_rdepends_num = int(filter(str.isdigit, repr(native_rdepends_name)))
print native_rdepends_num
- native_rdepends_row_count = len(driver.find_elements_by_xpath("/html/body/div[2]/div/div[3]/div/div[4]/table/tbody/tr/td[1]"))
+ native_rdepends_row_count = len(driver.find_elements_by_xpath("//*[@id='brought-in-by']/table/tbody/tr/td[1]"))
print native_rdepends_row_count
if native_rdepends_num != native_rdepends_row_count:
@@ -1371,24 +1400,24 @@ class toaster_cases(toaster_cases_base):
self.driver.maximize_window()
self.driver.get(self.base_url)
self.driver.find_element_by_link_text("core-image-minimal").click()
-# step 3
+ # step 3
self.find_element_by_link_text_in_table('nav', 'Configuration').click()
self.driver.find_element_by_link_text("BitBake variables").click()
-# step 4
+ # step 4
self.driver.find_element_by_id("search").clear()
self.driver.find_element_by_id("search").send_keys("lib")
self.driver.find_element_by_id("search-button").click()
# save screen to see result
self.browser_delay()
self.save_screenshot(screenshot_type='selenium', append_name='step4')
-# step 5
+ # step 5
self.driver.find_element_by_css_selector("i.icon-remove").click()
head_list = self.get_table_head_text('otable')
print head_list
print len(head_list)
self.assertTrue(head_list == ['Variable', 'Value', 'Set in file', 'Description'], \
msg=("head row contents wrong"))
-# step 8
+ # step 8
# search other string. and click "Variable" to re-sort, check if table
# head is still the same
self.driver.find_element_by_id("search").clear()
@@ -1413,17 +1442,17 @@ class toaster_cases(toaster_cases_base):
self.driver.maximize_window()
self.driver.get(self.base_url)
self.driver.find_element_by_link_text("core-image-minimal").click()
-# step 2-3
+ # step 2-3
self.find_element_by_link_text_in_table('nav', 'Configuration').click()
self.driver.find_element_by_link_text("BitBake variables").click()
variable_list = self.get_table_column_text('class', 'variable_name')
self.assertTrue(is_list_sequenced(variable_list), msg=("list not in order"))
-# step 4
+ # step 4
self.find_element_by_link_text_in_table('otable', 'Variable').click()
variable_list = self.get_table_column_text('class', 'variable_name')
self.assertTrue(is_list_inverted(variable_list), msg=("list not inverted"))
self.find_element_by_link_text_in_table('otable', 'Variable').click()
-# step 5
+ # step 5
# searching won't change the sequentiality
self.driver.find_element_by_id("search").clear()
self.driver.find_element_by_id("search").send_keys("lib")
@@ -1447,12 +1476,11 @@ class toaster_cases(toaster_cases_base):
# step 3
self.driver.find_element_by_id("edit-columns-button").click()
self.driver.find_element_by_id("started_on").click()
- self.driver.find_element_by_id("log").click()
self.driver.find_element_by_id("time").click()
self.driver.find_element_by_id("edit-columns-button").click()
head_list = self.get_table_head_text('otable')
- for item in ['Outcome', 'Recipe', 'Machine', 'Started on', 'Completed on', 'Failed tasks', 'Errors', 'Warnings', 'Warnings', 'Time']:
- self.assertTrue(item in head_list, msg=("item %s not in head row" % item))
+ for item in ['Outcome', 'Recipe', 'Machine', 'Started on', 'Completed on', 'Failed tasks', 'Errors', 'Warnings', 'Time', "Image files", "Project"]:
+ self.failUnless(item in head_list, msg=item+' is missing from table head.')
##############
@@ -1470,10 +1498,11 @@ class toaster_cases(toaster_cases_base):
# Step 4
# click Errors , order in "Completed on" should be disturbed. Then hide
# error column to check if order in "Completed on" can be restored
- self.find_element_by_link_text_in_table('otable', 'Errors').click()
- self.driver.find_element_by_id("edit-columns-button").click()
- self.driver.find_element_by_id("errors_no").click()
- self.driver.find_element_by_id("edit-columns-button").click()
+#THIS TEST IS NO LONGER VALID DUE TO DESIGN CHANGES. LEAVING IN PENDING UPDATES TO DESIGN
+ #self.find_element_by_link_text_in_table('otable', 'Errors').click()
+ #self.driver.find_element_by_id("edit-columns-button").click()
+ #self.driver.find_element_by_id("errors_no").click()
+ #self.driver.find_element_by_id("edit-columns-button").click()
# Note: without time.sleep here, there'll be unpredictable error..TBD
time.sleep(1)
c_list = self.get_table_column_text('class', 'completed_on')
@@ -1489,12 +1518,12 @@ class toaster_cases(toaster_cases_base):
self.driver.maximize_window()
self.driver.get(self.base_url)
self.driver.find_element_by_link_text("core-image-minimal").click()
-# Step 2-3
+ # Step 2-3
self.find_element_by_link_text_in_table('nav', 'Packages').click()
check_head_list = ['Package', 'Package version', 'Size', 'Recipe']
head_list = self.get_table_head_text('otable')
self.assertTrue(head_list == check_head_list, msg=("head row not as expected"))
-# Step 4
+ # Step 4
# pulldown menu
option_ids = ['recipe__layer_version__layer__name', 'recipe__layer_version__branch', \
'recipe__layer_version__layer__commit', 'license', 'recipe__version']
@@ -1583,7 +1612,7 @@ class toaster_cases(toaster_cases_base):
# otable is the recipes table here
otable_head_text = self.get_table_head_text('otable')
for item in ["Layer", "Layer branch", "Layer commit"]:
- self.assertFalse(item not in otable_head_text, msg=("item %s should be in head row" % item))
+ self.failIf(item not in otable_head_text, msg=item+' not in table head.')
# click the fist recipe, whatever it is
self.get_table_element("otable", 1, 1).click()
self.assertTrue(self.is_text_present(["Layer", "Layer branch", "Layer commit", "Recipe file"]), \
@@ -1626,8 +1655,8 @@ class toaster_cases(toaster_cases_base):
self.driver.back()
self.driver.find_element_by_link_text("Configuration").click()
otable_head_text = self.get_table_head_text()
- for item in ["Layer", "Layer branch", "Layer commit"]:
- self.assertTrue(item not in otable_head_text, msg=("item %s should not be in head row" % item))
+ self.assertTrue(self.is_text_present(["Layer", "Layer branch", "Layer commit"]), \
+ msg=("text not in web page"))
##############
@@ -1637,14 +1666,14 @@ class toaster_cases(toaster_cases_base):
self.case_no = self.get_case_number()
self.log.info(' CASE %s log: ' % str(self.case_no))
self.driver.maximize_window()
- for items in ["Packages", "Recipes", "Tasks"]:
+ for item in ["Packages", "Recipes", "Tasks"]:
self.driver.get(self.base_url)
self.driver.find_element_by_link_text("core-image-minimal").click()
self.driver.find_element_by_link_text(items).click()
# this may be page specific. If future page content changes, try to replace it with new xpath
- xpath_showrows = "/html/body/div[2]/div/div[2]/div[2]/div[2]/div/div/div[2]/select"
- xpath_table = "/html/body/div[2]/div/div[2]/div[2]/table/tbody"
+ xpath_showrows = "/html/body/div[4]/div/div/div[2]/div[2]/div[2]/div/div/div[2]/select"
+ xpath_table = "html/body/div[4]/div/div/div[2]/div[2]/table/tbody"#"id=('otable')/tbody"
self.driver.find_element_by_xpath(xpath_showrows).click()
rows_displayed = int(self.driver.find_element_by_xpath(xpath_showrows + "/option[2]").text)
@@ -1652,14 +1681,18 @@ class toaster_cases(toaster_cases_base):
# Sure we can use driver.get(url) to refresh page, but since page will vary, we use click link text here
self.driver.find_element_by_link_text(items).click()
Select(self.driver.find_element_by_css_selector("select.pagesize")).select_by_visible_text(str(rows_displayed))
- self.assertTrue(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]"))
- self.assertFalse(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]"))
+ self.failUnless(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]"))
+ self.failIf(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]"))
# click 1st package, then go back to check if it's still those rows shown.
- self.driver.find_element_by_xpath(xpath_table + "/tr[1]/td[1]").click()
- self.driver.find_element_by_link_text(items).click()
- self.assertTrue(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed) +"]"))
- self.assertFalse(self.is_element_present(By.XPATH, xpath_table + "/tr[" + str(rows_displayed+1) +"]"))
+ self.driver.find_element_by_xpath(xpath_otable + "/tr[1]/td[1]/a").click()
+ time.sleep(3)
+ self.driver.find_element_by_link_text(item).click()
+ self.assertTrue(self.is_element_present(By.XPATH, xpath_otable + "/tr[" + str(option_tobeselected) +"]"),\
+ msg=("Row %d should exist" %option_tobeselected))
+ self.assertFalse(self.is_element_present(By.XPATH, xpath_otable + "/tr[" + str(option_tobeselected+1) +"]"),\
+ msg=("Row %d should not exist" %(option_tobeselected+1)))
+
##############
@@ -1944,7 +1977,400 @@ class toaster_cases(toaster_cases_base):
# step 2-3 need to run manually
self.log.info("step 2-3: checking the help message when you hover on help icon of target,\
tasks, recipes, packages need to run manually")
- self.driver.find_element_by_partial_link_text("Toaster manual").click()
- if not self.is_text_present("Toaster Manual"):
- self.assertFalse(True, msg=("please check [Toaster manual] link on page"))
+ self.driver.find_element_by_partial_link_text("Manual").click()
+ if not self.is_text_present("Manual"):
+ self.log.error("please check [Toaster manual] link on page")
+ self.failIf(True)
+
+####################################################################################################
+# Starting backend tests ###########################################################################
+####################################################################################################
+
+ ##############
+ # CASE 1066 #
+ ##############
+ def test_1066(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select count(name) from orm_project a, auth_user b where a.user_id = b.id and b.username='_anonuser';"
+ cursor.execute(query)
+ data = cursor.fetchone()
+ self.failUnless(data >= 1)
+
+
+ ##############
+ # CASE 1071 #
+ ##############
+ def test_1071(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select name from orm_release;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ for i in range(0,4):
+ data[i] = data[i][0]
+ data.sort()
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_data = []
+ for i in range (0,4):
+ json_data.append(json_parse['releases'][i]['name'])
+ json_data.sort()
+ print json_data
+ self.failUnless(data == json_data)
+
+ ##############
+ # CASE 1072 #
+ ##############
+ def test_1072(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select value from orm_toastersetting where name like 'DEFCONF%';"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ for i in range(0,6):
+ data[i] = data[i][0]
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_data=json_parse['config']
+ json_data = json_data.values()
+ print json_data
+ self.failUnless(data == json_data)
+
+
+ ##############
+ # CASE 1074 #
+ ##############
+ def test_1074(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select name from orm_layersource;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ for i in range(0,3):
+ data[i] = data[i][0]
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_data = []
+ for i in range(0,3):
+ json_data.append(json_parse['layersources'][i]['name'])
+ print json_data
+ self.failUnless(set(data) == set(json_data))
+
+ ##############
+ # CASE 1075 #
+ ##############
+ def test_1075(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select value from orm_toastersetting where name like 'DEFAULT_RELEASE';"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ data = data[0][0]
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_data = json_parse['defaultrelease']
+ print json_data
+ self.failUnless(set(data) == set(json_data))
+ ##############
+ # CASE 1076 #
+ ##############
+ def test_1076(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+
+ print 'Checking branches for "Local Yocto Project"'
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select name from orm_branch where layer_source_id=1;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ lenght = len(data)
+ try:
+ for i in range(0,lenght):
+ data[i] = data[i][0]
+ except:
+ pass
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_location = json_parse['layersources'][0]['name']
+ print json_location
+ json_data = json_parse['layersources'][0]['branches']
+ print json_data
+ self.failUnless(set(data) == set(json_data))
+
+ print 'Checking branches for "OpenEmbedded"'
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select name from orm_branch where layer_source_id=3;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ lenght = len(data)
+ for i in range(0,lenght):
+ data[i] = data[i][0]
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_location = json_parse['layersources'][1]['name']
+ print json_location
+ json_data = json_parse['layersources'][1]['branches']
+ print json_data
+ self.failUnless(set(data) == set(json_data))
+
+ print 'Checking branches for "Imported layers"'
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select name from orm_branch where layer_source_id=2;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ lenght = len(data)
+ for i in range(0,lenght):
+ data[i] = data[i][0]
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_location = json_parse['layersources'][2]['name']
+ print json_location
+ json_data = json_parse['layersources'][2]['branches']
+ print json_data
+ self.failUnless(set(data) == set(json_data))
+
+
+ ##############
+ # CASE 1077 #
+ ##############
+ def test_1077(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select name from orm_bitbakeversion;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ for i in range(0,4):
+ data[i] = data[i][0]
+ print data
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_data = []
+ for i in range(0,4):
+ json_data.append(json_parse['bitbake'][i]['name'])
+ print json_data
+ self.failUnless(set(data) == set(json_data))
+
+ ##############
+ # CASE 1083 #
+ ##############
+ def test_1083(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ self.driver.maximize_window()
+ self.driver.get(self.base_url)
+ self.driver.find_element_by_id("new-project-button").click()
+ self.driver.find_element_by_id("new-project-name").send_keys("new-test-project")
+ self.driver.find_element_by_id("create-project-button").click()
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select count(name) from orm_project where name = 'new-test-project';"
+ cursor.execute(query)
+ data = cursor.fetchone()
+ print 'data: %s' % data
+ self.failUnless(data >= 1)
+
+ ##############
+ # CASE 1084 #
+ ##############
+ def test_1084(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ self.driver.maximize_window()
+ self.driver.get(self.base_url)
+ self.driver.find_element_by_id("new-project-button").click()
+ self.driver.find_element_by_id("new-project-name").send_keys("new-default-project")
+ self.driver.find_element_by_id("create-project-button").click()
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select a.name from orm_release a, orm_project b where a.id = b.release_id and b.name = 'new-default-project' limit 1;"
+ cursor.execute(query)
+ db_data = str(cursor.fetchone()[0])
+ json_parse = json.loads(open('toasterconf.json').read())
+ json_data = str(json_parse['defaultrelease'])
+ self.failUnless(db_data == json_data)
+
+ ##############
+ # CASE 1088 #
+ ##############
+ def test_1088(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ self.driver.maximize_window()
+ self.driver.get(self.base_url)
+ self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
+ self.driver.find_element_by_link_text('new-default-project').click()
+ self.driver.find_element_by_id('project-change-form-toggle').click()
+ self.driver.find_element_by_id('project-name-change-input').clear()
+ self.driver.find_element_by_id('project-name-change-input').send_keys('new-name')
+ self.driver.find_element_by_id('project-name-change-btn').click()
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select count(name) from orm_project where name = 'new-name';"
+ cursor.execute(query)
+ data = cursor.fetchone()[0]
+ self.failUnless(data == 1)
+ #reseting project name
+ self.driver.find_element_by_id('project-change-form-toggle').click()
+ self.driver.find_element_by_id('project-name-change-input').clear()
+ self.driver.find_element_by_id('project-name-change-input').send_keys('new-default-project')
+ self.driver.find_element_by_id('project-name-change-btn').click()
+
+
+ ##############
+ # CASE 1089 #
+ ##############
+ def test_1089(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ self.driver.maximize_window()
+ self.driver.get(self.base_url)
+ self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
+ self.driver.find_element_by_link_text('new-default-project').click()
+ self.driver.find_element_by_id('change-machine-toggle').click()
+ self.driver.find_element_by_id('machine-change-input').clear()
+ self.driver.find_element_by_id('machine-change-input').send_keys('qemuarm64')
+# self.driver.find_element_by_id('machine-change-input').send_keys(Keys.RETURN)
+ self.driver.find_element_by_id('machine-change-btn').click()
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select count(id) from orm_projectvariable where name like 'machine' and value like 'qemuarm64';"
+ cursor.execute(query)
+ data = cursor.fetchone()[0]
+ self.failUnless(data == 1)
+ #resetting machine to default value
+ self.driver.find_element_by_id('change-machine-toggle').click()
+ self.driver.find_element_by_id('machine-change-input').clear()
+ self.driver.find_element_by_id('machine-change-input').send_keys('qemux86')
+ self.driver.find_element_by_id('machine-change-input').send_keys(Keys.RETURN)
+ self.driver.find_element_by_id('machine-change-btn').click()
+
+ ##############
+ # CASE 1090 #
+ ##############
+ def test_1090(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select username from auth_user where is_superuser = 1;"
+ cursor.execute(query)
+ data = cursor.fetchall()
+ try:
+ data = data[0][0]
+ except:
+ pass
+ print data
+ self.failUnless(data == 'toaster_admin')
+
+ ##############
+ # CASE 1091 #
+ ##############
+ def test_1091(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ self.driver.maximize_window()
+ self.driver.get(self.base_url)
+ self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
+ self.driver.find_element_by_link_text('new-default-project').click()
+ self.driver.find_element_by_id('release-change-toggle').click()
+ dropdown = self.driver.find_element_by_css_selector('select')
+ for option in dropdown.find_elements_by_tag_name('option'):
+ if option.text == 'Local Yocto Project':
+ option.click()
+ self.driver.find_element_by_id('change-release-btn').click()
+ #wait for the changes to register in the DB
+ time.sleep(1)
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select count(*) from orm_layer_version a, orm_projectlayer b, orm_project c where a.\"commit\"=\"HEAD\" and a.id = b.layercommit_id and b.project_id=c.id and c.name='new-default-project';"
+ cursor.execute(query)
+ data = cursor.fetchone()[0]
+ #resetting release to default
+ self.driver.find_element_by_id('release-change-toggle').click()
+ dropdown = self.driver.find_element_by_css_selector('select')
+ for option in dropdown.find_elements_by_tag_name('option'):
+ if option.text == 'Yocto Project master':
+ option.click()
+ self.driver.find_element_by_id('change-release-btn').click()
+ #wait for the changes to register in the DB
+ time.sleep(1)
+ self.failUnless(data == 3)
+
+ ##############
+ # CASE 1092 #
+ ##############
+ def test_1092(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+ self.driver.maximize_window()
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select a.name, a.value from orm_projectvariable a, orm_project b where a.project_id = b.id and b.name = 'new-default-project';"
+ cursor.execute(query)
+ data = dict(cursor.fetchall())
+ print data
+ default_values = {u'IMAGE_INSTALL_append': u'', u'PACKAGE_CLASSES': u'package_rpm', u'MACHINE': u'qemux86', u'SDKMACHINE': u'x86_64', u'DISTRO': u'poky', u'IMAGE_FSTYPES': u'ext3 jffs2 tar.bz2'}
+ self.failUnless(data == default_values)
+
+ ##############
+ # CASE 1093 #
+ ##############
+ def test_1093(self):
+ self.case_no = self.get_case_number()
+ self.log.info(' CASE %s log: ' % str(self.case_no))
+
+ #get initial values
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select layercommit_id from orm_projectlayer a, orm_project b where a.project_id=b.id and b.name='new-default-project';"
+ cursor.execute(query)
+ data_initial = cursor.fetchall()
+ print data_initial
+
+ self.driver.maximize_window()
+ self.driver.get('localhost:8000')#self.base_url)
+ self.driver.find_element_by_css_selector("a[href='/toastergui/projects/']").click()
+ self.driver.find_element_by_link_text('new-default-project').click()
+ self.driver.find_element_by_id('release-change-toggle').click()
+ dropdown = self.driver.find_element_by_css_selector('select')
+ for option in dropdown.find_elements_by_tag_name('option'):
+ if option.text == 'Local Yocto Project':
+ option.click()
+ self.driver.find_element_by_id('change-release-btn').click()
+ #wait for the changes to register in the DB
+ time.sleep(1)
+
+ #get changed values
+ con=sqlite.connect('toaster.sqlite')
+ cursor = con.cursor()
+ query = "select layercommit_id from orm_projectlayer a, orm_project b where a.project_id=b.id and b.name='new-default-project';"
+ cursor.execute(query)
+ data_changed = cursor.fetchall()
+ print data_changed
+
+ #resetting release to default
+ self.driver.find_element_by_id('release-change-toggle').click()
+ dropdown = self.driver.find_element_by_css_selector('select')
+ for option in dropdown.find_elements_by_tag_name('option'):
+ if option.text == 'Yocto Project master':
+ option.click()
+ self.driver.find_element_by_id('change-release-btn').click()
+ #wait for the changes to register in the DB
+ time.sleep(1)
+ self.failUnless(data_initial != data_changed)
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0001_initial.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0001_initial.py
index dedeef8bf..760462f6b 100644
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0001_initial.py
+++ b/yocto-poky/bitbake/lib/toaster/orm/migrations/0001_initial.py
@@ -1,400 +1,504 @@
# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Build'
- db.create_table(u'orm_build', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('machine', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('image_fstypes', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('distro', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('distro_version', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('started_on', self.gf('django.db.models.fields.DateTimeField')()),
- ('completed_on', self.gf('django.db.models.fields.DateTimeField')()),
- ('outcome', self.gf('django.db.models.fields.IntegerField')(default=2)),
- ('errors_no', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('warnings_no', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('cooker_log_path', self.gf('django.db.models.fields.CharField')(max_length=500)),
- ('build_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('bitbake_version', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ))
- db.send_create_signal(u'orm', ['Build'])
-
- # Adding model 'Target'
- db.create_table(u'orm_target', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
- ('target', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('is_image', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('file_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('file_size', self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'orm', ['Target'])
-
- # Adding model 'Task'
- db.create_table(u'orm_task', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='task_build', to=orm['orm.Build'])),
- ('order', self.gf('django.db.models.fields.IntegerField')(null=True)),
- ('task_executed', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('outcome', self.gf('django.db.models.fields.IntegerField')(default=5)),
- ('sstate_checksum', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('path_to_sstate_obj', self.gf('django.db.models.fields.FilePathField')(max_length=500, blank=True)),
- ('recipe', self.gf('django.db.models.fields.related.ForeignKey')(related_name='build_recipe', to=orm['orm.Recipe'])),
- ('task_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('source_url', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
- ('work_directory', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
- ('script_type', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('line_number', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('disk_io', self.gf('django.db.models.fields.IntegerField')(null=True)),
- ('cpu_usage', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=6, decimal_places=2)),
- ('elapsed_time', self.gf('django.db.models.fields.CharField')(default=0, max_length=50)),
- ('sstate_result', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('message', self.gf('django.db.models.fields.CharField')(max_length=240)),
- ('logfile', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
- ))
- db.send_create_signal(u'orm', ['Task'])
-
- # Adding model 'Task_Dependency'
- db.create_table(u'orm_task_dependency', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('task', self.gf('django.db.models.fields.related.ForeignKey')(related_name='task_dependencies_task', to=orm['orm.Task'])),
- ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='task_dependencies_depends', to=orm['orm.Task'])),
- ))
- db.send_create_signal(u'orm', ['Task_Dependency'])
-
- # Adding model 'Package'
- db.create_table(u'orm_package', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
- ('recipe', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Recipe'], null=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('version', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('revision', self.gf('django.db.models.fields.CharField')(max_length=32, blank=True)),
- ('summary', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
- ('description', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
- ('size', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('installed_size', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('section', self.gf('django.db.models.fields.CharField')(max_length=80, blank=True)),
- ('license', self.gf('django.db.models.fields.CharField')(max_length=80, blank=True)),
- ))
- db.send_create_signal(u'orm', ['Package'])
-
- # Adding model 'Package_Dependency'
- db.create_table(u'orm_package_dependency', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('package', self.gf('django.db.models.fields.related.ForeignKey')(related_name='package_dependencies_source', to=orm['orm.Package'])),
- ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='package_dependencies_target', to=orm['orm.Package'])),
- ('dep_type', self.gf('django.db.models.fields.IntegerField')()),
- ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target'], null=True)),
- ))
- db.send_create_signal(u'orm', ['Package_Dependency'])
-
- # Adding model 'Target_Installed_Package'
- db.create_table(u'orm_target_installed_package', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target'])),
- ('package', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Package'])),
- ))
- db.send_create_signal(u'orm', ['Target_Installed_Package'])
-
- # Adding model 'Package_File'
- db.create_table(u'orm_package_file', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('package', self.gf('django.db.models.fields.related.ForeignKey')(related_name='buildfilelist_package', to=orm['orm.Package'])),
- ('path', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
- ('size', self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'orm', ['Package_File'])
-
- # Adding model 'Recipe'
- db.create_table(u'orm_recipe', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('version', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('layer_version', self.gf('django.db.models.fields.related.ForeignKey')(related_name='recipe_layer_version', to=orm['orm.Layer_Version'])),
- ('summary', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('description', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('section', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
- ('license', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
- ('licensing_info', self.gf('django.db.models.fields.TextField')(blank=True)),
- ('homepage', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
- ('bugtracker', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
- ('file_path', self.gf('django.db.models.fields.FilePathField')(max_length=255)),
- ))
- db.send_create_signal(u'orm', ['Recipe'])
-
- # Adding model 'Recipe_Dependency'
- db.create_table(u'orm_recipe_dependency', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('recipe', self.gf('django.db.models.fields.related.ForeignKey')(related_name='r_dependencies_recipe', to=orm['orm.Recipe'])),
- ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='r_dependencies_depends', to=orm['orm.Recipe'])),
- ('dep_type', self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'orm', ['Recipe_Dependency'])
-
- # Adding model 'Layer'
- db.create_table(u'orm_layer', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('local_path', self.gf('django.db.models.fields.FilePathField')(max_length=255)),
- ('layer_index_url', self.gf('django.db.models.fields.URLField')(max_length=200)),
- ))
- db.send_create_signal(u'orm', ['Layer'])
-
- # Adding model 'Layer_Version'
- db.create_table(u'orm_layer_version', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='layer_version_build', to=orm['orm.Build'])),
- ('layer', self.gf('django.db.models.fields.related.ForeignKey')(related_name='layer_version_layer', to=orm['orm.Layer'])),
- ('branch', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('commit', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('priority', self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'orm', ['Layer_Version'])
-
- # Adding model 'Variable'
- db.create_table(u'orm_variable', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='variable_build', to=orm['orm.Build'])),
- ('variable_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('variable_value', self.gf('django.db.models.fields.TextField')(blank=True)),
- ('changed', self.gf('django.db.models.fields.BooleanField')(default=False)),
- ('human_readable_name', self.gf('django.db.models.fields.CharField')(max_length=200)),
- ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
- ))
- db.send_create_signal(u'orm', ['Variable'])
-
- # Adding model 'VariableHistory'
- db.create_table(u'orm_variablehistory', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('variable', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Variable'])),
- ('file_name', self.gf('django.db.models.fields.FilePathField')(max_length=255)),
- ('line_number', self.gf('django.db.models.fields.IntegerField')(null=True)),
- ('operation', self.gf('django.db.models.fields.CharField')(max_length=16)),
- ))
- db.send_create_signal(u'orm', ['VariableHistory'])
-
- # Adding model 'LogMessage'
- db.create_table(u'orm_logmessage', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
- ('level', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ('message', self.gf('django.db.models.fields.CharField')(max_length=240)),
- ('pathname', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
- ('lineno', self.gf('django.db.models.fields.IntegerField')(null=True)),
- ))
- db.send_create_signal(u'orm', ['LogMessage'])
-
-
- def backwards(self, orm):
- # Deleting model 'Build'
- db.delete_table(u'orm_build')
-
- # Deleting model 'Target'
- db.delete_table(u'orm_target')
-
- # Deleting model 'Task'
- db.delete_table(u'orm_task')
-
- # Deleting model 'Task_Dependency'
- db.delete_table(u'orm_task_dependency')
-
- # Deleting model 'Package'
- db.delete_table(u'orm_package')
-
- # Deleting model 'Package_Dependency'
- db.delete_table(u'orm_package_dependency')
-
- # Deleting model 'Target_Installed_Package'
- db.delete_table(u'orm_target_installed_package')
-
- # Deleting model 'Package_File'
- db.delete_table(u'orm_package_file')
-
- # Deleting model 'Recipe'
- db.delete_table(u'orm_recipe')
-
- # Deleting model 'Recipe_Dependency'
- db.delete_table(u'orm_recipe_dependency')
-
- # Deleting model 'Layer'
- db.delete_table(u'orm_layer')
-
- # Deleting model 'Layer_Version'
- db.delete_table(u'orm_layer_version')
-
- # Deleting model 'Variable'
- db.delete_table(u'orm_variable')
-
- # Deleting model 'VariableHistory'
- db.delete_table(u'orm_variablehistory')
-
- # Deleting model 'LogMessage'
- db.delete_table(u'orm_logmessage')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_fstypes': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'licensing_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.CharField', [], {'default': '0', 'max_length': '50'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '5'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='BitbakeVersion',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(unique=True, max_length=32)),
+ ('giturl', models.URLField()),
+ ('branch', models.CharField(max_length=32)),
+ ('dirpath', models.CharField(max_length=255)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Branch',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('up_id', models.IntegerField(default=None, null=True)),
+ ('up_date', models.DateTimeField(default=None, null=True)),
+ ('name', models.CharField(max_length=50)),
+ ('short_description', models.CharField(max_length=50, blank=True)),
+ ],
+ options={
+ 'verbose_name_plural': 'Branches',
+ },
+ ),
+ migrations.CreateModel(
+ name='Build',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('machine', models.CharField(max_length=100)),
+ ('distro', models.CharField(max_length=100)),
+ ('distro_version', models.CharField(max_length=100)),
+ ('started_on', models.DateTimeField()),
+ ('completed_on', models.DateTimeField()),
+ ('outcome', models.IntegerField(default=2, choices=[(0, b'Succeeded'), (1, b'Failed'), (2, b'In Progress')])),
+ ('cooker_log_path', models.CharField(max_length=500)),
+ ('build_name', models.CharField(max_length=100)),
+ ('bitbake_version', models.CharField(max_length=50)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BuildArtifact',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('file_name', models.FilePathField()),
+ ('file_size', models.IntegerField()),
+ ('build', models.ForeignKey(to='orm.Build')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='HelpText',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('area', models.IntegerField(choices=[(0, b'variable')])),
+ ('key', models.CharField(max_length=100)),
+ ('text', models.TextField()),
+ ('build', models.ForeignKey(related_name='helptext_build', to='orm.Build')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Layer',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('up_id', models.IntegerField(default=None, null=True)),
+ ('up_date', models.DateTimeField(default=None, null=True)),
+ ('name', models.CharField(max_length=100)),
+ ('layer_index_url', models.URLField()),
+ ('vcs_url', models.URLField(default=None, null=True)),
+ ('vcs_web_url', models.URLField(default=None, null=True)),
+ ('vcs_web_tree_base_url', models.URLField(default=None, null=True)),
+ ('vcs_web_file_base_url', models.URLField(default=None, null=True)),
+ ('summary', models.TextField(default=None, help_text=b'One-line description of the layer', null=True)),
+ ('description', models.TextField(default=None, null=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Layer_Version',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('up_id', models.IntegerField(default=None, null=True)),
+ ('up_date', models.DateTimeField(default=None, null=True)),
+ ('branch', models.CharField(max_length=80)),
+ ('commit', models.CharField(max_length=100)),
+ ('dirpath', models.CharField(default=None, max_length=255, null=True)),
+ ('priority', models.IntegerField(default=0)),
+ ('local_path', models.FilePathField(default=b'/', max_length=1024)),
+ ('build', models.ForeignKey(related_name='layer_version_build', default=None, to='orm.Build', null=True)),
+ ('layer', models.ForeignKey(related_name='layer_version_layer', to='orm.Layer')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LayerSource',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(unique=True, max_length=63)),
+ ('sourcetype', models.IntegerField(choices=[(0, b'local'), (1, b'layerindex'), (2, b'imported')])),
+ ('apiurl', models.CharField(default=None, max_length=255, null=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LayerVersionDependency',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('up_id', models.IntegerField(default=None, null=True)),
+ ('depends_on', models.ForeignKey(related_name='dependees', to='orm.Layer_Version')),
+ ('layer_source', models.ForeignKey(default=None, to='orm.LayerSource', null=True)),
+ ('layer_version', models.ForeignKey(related_name='dependencies', to='orm.Layer_Version')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LogMessage',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('level', models.IntegerField(default=0, choices=[(0, b'info'), (1, b'warn'), (2, b'error'), (3, b'critical'), (-1, b'toaster exception')])),
+ ('message', models.TextField(null=True, blank=True)),
+ ('pathname', models.FilePathField(max_length=255, blank=True)),
+ ('lineno', models.IntegerField(null=True)),
+ ('build', models.ForeignKey(to='orm.Build')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Machine',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('up_id', models.IntegerField(default=None, null=True)),
+ ('up_date', models.DateTimeField(default=None, null=True)),
+ ('name', models.CharField(max_length=255)),
+ ('description', models.CharField(max_length=255)),
+ ('layer_source', models.ForeignKey(default=None, to='orm.LayerSource', null=True)),
+ ('layer_version', models.ForeignKey(to='orm.Layer_Version')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Package',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=100)),
+ ('installed_name', models.CharField(default=b'', max_length=100)),
+ ('version', models.CharField(max_length=100, blank=True)),
+ ('revision', models.CharField(max_length=32, blank=True)),
+ ('summary', models.TextField(blank=True)),
+ ('description', models.TextField(blank=True)),
+ ('size', models.IntegerField(default=0)),
+ ('installed_size', models.IntegerField(default=0)),
+ ('section', models.CharField(max_length=80, blank=True)),
+ ('license', models.CharField(max_length=80, blank=True)),
+ ('build', models.ForeignKey(to='orm.Build', null=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Package_Dependency',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('dep_type', models.IntegerField(choices=[(0, b'depends'), (1, b'depends'), (3, b'recommends'), (2, b'recommends'), (4, b'suggests'), (5, b'provides'), (6, b'replaces'), (7, b'conflicts')])),
+ ('depends_on', models.ForeignKey(related_name='package_dependencies_target', to='orm.Package')),
+ ('package', models.ForeignKey(related_name='package_dependencies_source', to='orm.Package')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Package_File',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('path', models.FilePathField(max_length=255, blank=True)),
+ ('size', models.IntegerField()),
+ ('package', models.ForeignKey(related_name='buildfilelist_package', to='orm.Package')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Project',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=100)),
+ ('short_description', models.CharField(max_length=50, blank=True)),
+ ('created', models.DateTimeField(auto_now_add=True)),
+ ('updated', models.DateTimeField(auto_now=True)),
+ ('user_id', models.IntegerField(null=True)),
+ ('is_default', models.BooleanField(default=False)),
+ ('bitbake_version', models.ForeignKey(to='orm.BitbakeVersion', null=True)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProjectLayer',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('optional', models.BooleanField(default=True)),
+ ('layercommit', models.ForeignKey(to='orm.Layer_Version', null=True)),
+ ('project', models.ForeignKey(to='orm.Project')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProjectTarget',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('target', models.CharField(max_length=100)),
+ ('task', models.CharField(max_length=100, null=True)),
+ ('project', models.ForeignKey(to='orm.Project')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ProjectVariable',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=100)),
+ ('value', models.TextField(blank=True)),
+ ('project', models.ForeignKey(to='orm.Project')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Recipe',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('up_id', models.IntegerField(default=None, null=True)),
+ ('up_date', models.DateTimeField(default=None, null=True)),
+ ('name', models.CharField(max_length=100, blank=True)),
+ ('version', models.CharField(max_length=100, blank=True)),
+ ('summary', models.TextField(blank=True)),
+ ('description', models.TextField(blank=True)),
+ ('section', models.CharField(max_length=100, blank=True)),
+ ('license', models.CharField(max_length=200, blank=True)),
+ ('homepage', models.URLField(blank=True)),
+ ('bugtracker', models.URLField(blank=True)),
+ ('file_path', models.FilePathField(max_length=255)),
+ ('pathflags', models.CharField(max_length=200, blank=True)),
+ ('is_image', models.BooleanField(default=False)),
+ ('layer_source', models.ForeignKey(default=None, to='orm.LayerSource', null=True)),
+ ('layer_version', models.ForeignKey(related_name='recipe_layer_version', to='orm.Layer_Version')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Recipe_Dependency',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('dep_type', models.IntegerField(choices=[(0, b'depends'), (1, b'rdepends')])),
+ ('depends_on', models.ForeignKey(related_name='r_dependencies_depends', to='orm.Recipe')),
+ ('recipe', models.ForeignKey(related_name='r_dependencies_recipe', to='orm.Recipe')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Release',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(unique=True, max_length=32)),
+ ('description', models.CharField(max_length=255)),
+ ('branch_name', models.CharField(default=b'', max_length=50)),
+ ('helptext', models.TextField(null=True)),
+ ('bitbake_version', models.ForeignKey(to='orm.BitbakeVersion')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ReleaseDefaultLayer',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('layer_name', models.CharField(default=b'', max_length=100)),
+ ('release', models.ForeignKey(to='orm.Release')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ReleaseLayerSourcePriority',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('priority', models.IntegerField(default=0)),
+ ('layer_source', models.ForeignKey(to='orm.LayerSource')),
+ ('release', models.ForeignKey(to='orm.Release')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Target',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('target', models.CharField(max_length=100)),
+ ('task', models.CharField(max_length=100, null=True)),
+ ('is_image', models.BooleanField(default=False)),
+ ('image_size', models.IntegerField(default=0)),
+ ('license_manifest_path', models.CharField(max_length=500, null=True)),
+ ('build', models.ForeignKey(to='orm.Build')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Target_File',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('path', models.FilePathField()),
+ ('size', models.IntegerField()),
+ ('inodetype', models.IntegerField(choices=[(1, b'regular'), (2, b'directory'), (3, b'symlink'), (4, b'socket'), (5, b'fifo'), (6, b'character'), (7, b'block')])),
+ ('permission', models.CharField(max_length=16)),
+ ('owner', models.CharField(max_length=128)),
+ ('group', models.CharField(max_length=128)),
+ ('directory', models.ForeignKey(related_name='directory_set', to='orm.Target_File', null=True)),
+ ('sym_target', models.ForeignKey(related_name='symlink_set', to='orm.Target_File', null=True)),
+ ('target', models.ForeignKey(to='orm.Target')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Target_Image_File',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('file_name', models.FilePathField(max_length=254)),
+ ('file_size', models.IntegerField()),
+ ('target', models.ForeignKey(to='orm.Target')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Target_Installed_Package',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('package', models.ForeignKey(related_name='buildtargetlist_package', to='orm.Package')),
+ ('target', models.ForeignKey(to='orm.Target')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Task',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('order', models.IntegerField(null=True)),
+ ('task_executed', models.BooleanField(default=False)),
+ ('outcome', models.IntegerField(default=-1, choices=[(-1, b'Not Available'), (0, b'Succeeded'), (1, b'Covered'), (2, b'Cached'), (3, b'Prebuilt'), (4, b'Failed'), (5, b'Empty')])),
+ ('sstate_checksum', models.CharField(max_length=100, blank=True)),
+ ('path_to_sstate_obj', models.FilePathField(max_length=500, blank=True)),
+ ('task_name', models.CharField(max_length=100)),
+ ('source_url', models.FilePathField(max_length=255, blank=True)),
+ ('work_directory', models.FilePathField(max_length=255, blank=True)),
+ ('script_type', models.IntegerField(default=0, choices=[(0, b'N/A'), (2, b'Python'), (3, b'Shell')])),
+ ('line_number', models.IntegerField(default=0)),
+ ('disk_io', models.IntegerField(null=True)),
+ ('cpu_usage', models.DecimalField(null=True, max_digits=8, decimal_places=2)),
+ ('elapsed_time', models.DecimalField(null=True, max_digits=8, decimal_places=2)),
+ ('sstate_result', models.IntegerField(default=0, choices=[(0, b'Not Applicable'), (1, b'File not in cache'), (2, b'Failed'), (3, b'Succeeded')])),
+ ('message', models.CharField(max_length=240)),
+ ('logfile', models.FilePathField(max_length=255, blank=True)),
+ ('build', models.ForeignKey(related_name='task_build', to='orm.Build')),
+ ('recipe', models.ForeignKey(related_name='tasks', to='orm.Recipe')),
+ ],
+ options={
+ 'ordering': ('order', 'recipe'),
+ },
+ ),
+ migrations.CreateModel(
+ name='Task_Dependency',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('depends_on', models.ForeignKey(related_name='task_dependencies_depends', to='orm.Task')),
+ ('task', models.ForeignKey(related_name='task_dependencies_task', to='orm.Task')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='ToasterSetting',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=63)),
+ ('helptext', models.TextField()),
+ ('value', models.CharField(max_length=255)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Variable',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('variable_name', models.CharField(max_length=100)),
+ ('variable_value', models.TextField(blank=True)),
+ ('changed', models.BooleanField(default=False)),
+ ('human_readable_name', models.CharField(max_length=200)),
+ ('description', models.TextField(blank=True)),
+ ('build', models.ForeignKey(related_name='variable_build', to='orm.Build')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='VariableHistory',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('value', models.TextField(blank=True)),
+ ('file_name', models.FilePathField(max_length=255)),
+ ('line_number', models.IntegerField(null=True)),
+ ('operation', models.CharField(max_length=64)),
+ ('variable', models.ForeignKey(related_name='vhistory', to='orm.Variable')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='project',
+ name='release',
+ field=models.ForeignKey(to='orm.Release', null=True),
+ ),
+ migrations.AddField(
+ model_name='package_dependency',
+ name='target',
+ field=models.ForeignKey(to='orm.Target', null=True),
+ ),
+ migrations.AddField(
+ model_name='package',
+ name='recipe',
+ field=models.ForeignKey(to='orm.Recipe', null=True),
+ ),
+ migrations.AddField(
+ model_name='logmessage',
+ name='task',
+ field=models.ForeignKey(blank=True, to='orm.Task', null=True),
+ ),
+ migrations.AlterUniqueTogether(
+ name='layersource',
+ unique_together=set([('sourcetype', 'apiurl')]),
+ ),
+ migrations.AddField(
+ model_name='layer_version',
+ name='layer_source',
+ field=models.ForeignKey(default=None, to='orm.LayerSource', null=True),
+ ),
+ migrations.AddField(
+ model_name='layer_version',
+ name='project',
+ field=models.ForeignKey(default=None, to='orm.Project', null=True),
+ ),
+ migrations.AddField(
+ model_name='layer_version',
+ name='up_branch',
+ field=models.ForeignKey(default=None, to='orm.Branch', null=True),
+ ),
+ migrations.AddField(
+ model_name='layer',
+ name='layer_source',
+ field=models.ForeignKey(default=None, to='orm.LayerSource', null=True),
+ ),
+ migrations.AddField(
+ model_name='build',
+ name='project',
+ field=models.ForeignKey(to='orm.Project'),
+ ),
+ migrations.AddField(
+ model_name='branch',
+ name='layer_source',
+ field=models.ForeignKey(default=True, to='orm.LayerSource', null=True),
+ ),
+ migrations.CreateModel(
+ name='ImportedLayerSource',
+ fields=[
+ ],
+ options={
+ 'proxy': True,
+ },
+ bases=('orm.layersource',),
+ ),
+ migrations.CreateModel(
+ name='LayerIndexLayerSource',
+ fields=[
+ ],
+ options={
+ 'proxy': True,
+ },
+ bases=('orm.layersource',),
+ ),
+ migrations.CreateModel(
+ name='LocalLayerSource',
+ fields=[
+ ],
+ options={
+ 'proxy': True,
+ },
+ bases=('orm.layersource',),
+ ),
+ migrations.AlterUniqueTogether(
+ name='task',
+ unique_together=set([('build', 'recipe', 'task_name')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='releaselayersourcepriority',
+ unique_together=set([('release', 'layer_source')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='recipe',
+ unique_together=set([('layer_version', 'file_path', 'pathflags')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='projectlayer',
+ unique_together=set([('project', 'layercommit')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='machine',
+ unique_together=set([('layer_source', 'up_id')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='layerversiondependency',
+ unique_together=set([('layer_source', 'up_id')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='layer_version',
+ unique_together=set([('layer_source', 'up_id')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='layer',
+ unique_together=set([('layer_source', 'up_id'), ('layer_source', 'name')]),
+ ),
+ migrations.AlterUniqueTogether(
+ name='branch',
+ unique_together=set([('layer_source', 'up_id'), ('layer_source', 'name')]),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0002_auto__add_field_build_timespent.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0002_auto__add_field_build_timespent.py
deleted file mode 100644
index 61421cacd..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0002_auto__add_field_build_timespent.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Build.timespent'
- db.add_column(u'orm_build', 'timespent',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Build.timespent'
- db.delete_column(u'orm_build', 'timespent')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_fstypes': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'licensing_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.CharField', [], {'default': '0', 'max_length': '50'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '5'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0002_customimagerecipe.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0002_customimagerecipe.py
new file mode 100644
index 000000000..9cec82e8d
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/orm/migrations/0002_customimagerecipe.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('orm', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='CustomImageRecipe',
+ fields=[
+ ('recipe_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orm.Recipe')),
+ ('last_updated', models.DateTimeField(default=None, null=True)),
+ ('base_recipe', models.ForeignKey(related_name='based_on_recipe', to='orm.Recipe')),
+ ('project', models.ForeignKey(to='orm.Project')),
+ ],
+ bases=('orm.recipe',),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0003_customimagepackage.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0003_customimagepackage.py
new file mode 100644
index 000000000..b027f6613
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/orm/migrations/0003_customimagepackage.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('orm', '0002_customimagerecipe'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='CustomImagePackage',
+ fields=[
+ ('package_ptr', models.OneToOneField(parent_link=True, auto_created=True, primary_key=True, serialize=False, to='orm.Package')),
+ ('recipe_appends', models.ManyToManyField(related_name='appends_set', to='orm.CustomImageRecipe')),
+ ('recipe_excludes', models.ManyToManyField(related_name='excludes_set', to='orm.CustomImageRecipe')),
+ ('recipe_includes', models.ManyToManyField(related_name='includes_set', to='orm.CustomImageRecipe')),
+ ],
+ bases=('orm.package',),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0003_timespent.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0003_timespent.py
deleted file mode 100644
index 9600f9e29..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0003_timespent.py
+++ /dev/null
@@ -1,182 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import DataMigration
-from django.db import models
-
-class Migration(DataMigration):
-
- def forwards(self, orm):
- "Write your forwards methods here."
- # Note: Don't use "from appname.models import ModelName".
- # Use orm.ModelName to refer to models in this application,
- # and orm['appname.ModelName'] for models in other applications.
-
- for build in orm.Build.objects.all():
- build.timespent = int((build.completed_on - build.started_on).total_seconds())
- build.save()
-
- def backwards(self, orm):
- "Write your backwards methods here."
- raise RuntimeError("Cannot reverse this migration.")
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_fstypes': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'licensing_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.CharField', [], {'default': '0', 'max_length': '50'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '5'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
- symmetrical = True
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0004_auto__add_field_package_installed_name.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0004_auto__add_field_package_installed_name.py
deleted file mode 100644
index 134445b56..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0004_auto__add_field_package_installed_name.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Package.installed_name'
- db.add_column(u'orm_package', 'installed_name',
- self.gf('django.db.models.fields.CharField')(default='', max_length=100),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Package.installed_name'
- db.delete_column(u'orm_package', 'installed_name')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_fstypes': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'licensing_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.CharField', [], {'default': '0', 'max_length': '50'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '5'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0004_provides.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0004_provides.py
new file mode 100644
index 000000000..dfde2d136
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/orm/migrations/0004_provides.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('orm', '0003_customimagepackage'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Provides',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('name', models.CharField(max_length=100)),
+ ('recipe', models.ForeignKey(to='orm.Recipe')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='recipe_dependency',
+ name='via',
+ field=models.ForeignKey(null=True, default=None, to='orm.Provides'),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0005_auto__add_target_image_file__add_target_file__add_field_variablehistor.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0005_auto__add_target_image_file__add_target_file__add_field_variablehistor.py
deleted file mode 100644
index 7be7ac3be..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0005_auto__add_target_image_file__add_target_file__add_field_variablehistor.py
+++ /dev/null
@@ -1,281 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Target_File'
- db.create_table(u'orm_target_file', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target'])),
- ('path', self.gf('django.db.models.fields.FilePathField')(max_length=100)),
- ('size', self.gf('django.db.models.fields.IntegerField')()),
- ('inodetype', self.gf('django.db.models.fields.IntegerField')()),
- ('permission', self.gf('django.db.models.fields.IntegerField')()),
- ('owner', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('group', self.gf('django.db.models.fields.CharField')(max_length=128)),
- ('directory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='directory_set', to=orm['orm.Target_File'])),
- ('sym_target', self.gf('django.db.models.fields.related.ForeignKey')(related_name='symlink_set', blank=True, to=orm['orm.Target_File'])),
- ))
- db.send_create_signal(u'orm', ['Target_File'])
-
- # Adding model 'Target_Image_File'
- db.create_table(u'orm_target_image_file', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target'])),
- ('file_name', self.gf('django.db.models.fields.FilePathField')(max_length=100)),
- ('file_size', self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'orm', ['Target_Image_File'])
-
- # Adding field 'VariableHistory.value'
- db.add_column(u'orm_variablehistory', 'value',
- self.gf('django.db.models.fields.TextField')(default='', blank=True),
- keep_default=False)
-
- # Deleting field 'Recipe.licensing_info'
- db.delete_column(u'orm_recipe', 'licensing_info')
-
- # Deleting field 'Target.file_name'
- db.delete_column(u'orm_target', 'file_name')
-
- # Deleting field 'Target.file_size'
- db.delete_column(u'orm_target', 'file_size')
-
- # Deleting field 'Build.image_fstypes'
- db.delete_column(u'orm_build', 'image_fstypes')
-
- # Adding field 'LogMessage.task'
- db.add_column(u'orm_logmessage', 'task',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Task'], null=True, blank=True),
- keep_default=False)
-
-
- # Changing field 'Task.elapsed_time'
- db.alter_column(u'orm_task', 'elapsed_time', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=6, decimal_places=2))
- # Adding unique constraint on 'Task', fields ['build', 'recipe', 'task_name']
- db.create_unique(u'orm_task', ['build_id', 'recipe_id', 'task_name'])
-
-
- def backwards(self, orm):
- # Removing unique constraint on 'Task', fields ['build', 'recipe', 'task_name']
- db.delete_unique(u'orm_task', ['build_id', 'recipe_id', 'task_name'])
-
- # Deleting model 'Target_File'
- db.delete_table(u'orm_target_file')
-
- # Deleting model 'Target_Image_File'
- db.delete_table(u'orm_target_image_file')
-
- # Deleting field 'VariableHistory.value'
- db.delete_column(u'orm_variablehistory', 'value')
-
- # Adding field 'Recipe.licensing_info'
- db.add_column(u'orm_recipe', 'licensing_info',
- self.gf('django.db.models.fields.TextField')(default='', blank=True),
- keep_default=False)
-
- # Adding field 'Target.file_name'
- db.add_column(u'orm_target', 'file_name',
- self.gf('django.db.models.fields.CharField')(default='', max_length=100),
- keep_default=False)
-
- # Adding field 'Target.file_size'
- db.add_column(u'orm_target', 'file_size',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
- # Adding field 'Build.image_fstypes'
- db.add_column(u'orm_build', 'image_fstypes',
- self.gf('django.db.models.fields.CharField')(default='', max_length=100),
- keep_default=False)
-
- # Deleting field 'LogMessage.task'
- db.delete_column(u'orm_logmessage', 'task_id')
-
-
- # Changing field 'Task.elapsed_time'
- db.alter_column(u'orm_task', 'elapsed_time', self.gf('django.db.models.fields.CharField')(max_length=50))
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.IntegerField', [], {}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'blank': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0005_task_field_separation.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0005_task_field_separation.py
new file mode 100644
index 000000000..fb1196b56
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/orm/migrations/0005_task_field_separation.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('orm', '0004_provides'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='task',
+ name='cpu_usage',
+ ),
+ migrations.AddField(
+ model_name='task',
+ name='cpu_time_system',
+ field=models.DecimalField(null=True, max_digits=8, decimal_places=2),
+ ),
+ migrations.AddField(
+ model_name='task',
+ name='cpu_time_user',
+ field=models.DecimalField(null=True, max_digits=8, decimal_places=2),
+ ),
+ migrations.AddField(
+ model_name='task',
+ name='disk_io_read',
+ field=models.IntegerField(null=True),
+ ),
+ migrations.AddField(
+ model_name='task',
+ name='disk_io_write',
+ field=models.IntegerField(null=True),
+ ),
+ migrations.AddField(
+ model_name='task',
+ name='ended',
+ field=models.DateTimeField(null=True),
+ ),
+ migrations.AddField(
+ model_name='task',
+ name='started',
+ field=models.DateTimeField(null=True),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py
new file mode 100644
index 000000000..91a32a9e0
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('orm', '0005_task_field_separation'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='build',
+ name='outcome',
+ field=models.IntegerField(default=2, choices=[(0, b'Succeeded'), (1, b'Failed'), (2, b'In Progress'), (3, b'Cancelled')]),
+ ),
+ ]
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0006_auto__add_field_target_image_size__add_field_target_license_manifest_p.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0006_auto__add_field_target_image_size__add_field_target_license_manifest_p.py
deleted file mode 100644
index b2be30a4a..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0006_auto__add_field_target_image_size__add_field_target_license_manifest_p.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Target.image_size'
- db.add_column(u'orm_target', 'image_size',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
- # Adding field 'Target.license_manifest_path'
- db.add_column(u'orm_target', 'license_manifest_path',
- self.gf('django.db.models.fields.CharField')(max_length=500, null=True),
- keep_default=False)
-
-
- # Changing field 'Target_File.permission'
- db.alter_column(u'orm_target_file', 'permission', self.gf('django.db.models.fields.CharField')(max_length=16))
-
- # Changing field 'Target_File.sym_target'
- db.alter_column(u'orm_target_file', 'sym_target_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['orm.Target_File']))
-
- # Changing field 'Target_File.directory'
- db.alter_column(u'orm_target_file', 'directory_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['orm.Target_File']))
-
- def backwards(self, orm):
- # Deleting field 'Target.image_size'
- db.delete_column(u'orm_target', 'image_size')
-
- # Deleting field 'Target.license_manifest_path'
- db.delete_column(u'orm_target', 'license_manifest_path')
-
-
- # Changing field 'Target_File.permission'
- db.alter_column(u'orm_target_file', 'permission', self.gf('django.db.models.fields.IntegerField')())
-
- # User chose to not deal with backwards NULL issues for 'Target_File.sym_target'
- raise RuntimeError("Cannot reverse this migration. 'Target_File.sym_target' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration
- # Changing field 'Target_File.sym_target'
- db.alter_column(u'orm_target_file', 'sym_target_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target_File']))
-
- # User chose to not deal with backwards NULL issues for 'Target_File.directory'
- raise RuntimeError("Cannot reverse this migration. 'Target_File.directory' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration
- # Changing field 'Target_File.directory'
- db.alter_column(u'orm_target_file', 'directory_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target_File']))
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0007_auto__add_helptext.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0007_auto__add_helptext.py
deleted file mode 100644
index 1e4c5369d..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0007_auto__add_helptext.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'HelpText'
- db.create_table(u'orm_helptext', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='helptext_build', to=orm['orm.Build'])),
- ('area', self.gf('django.db.models.fields.IntegerField')()),
- ('key', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('text', self.gf('django.db.models.fields.TextField')()),
- ))
- db.send_create_signal(u'orm', ['HelpText'])
-
-
- def backwards(self, orm):
- # Deleting model 'HelpText'
- db.delete_table(u'orm_helptext')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0008_auto__chg_field_variablehistory_operation__chg_field_recipe_descriptio.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0008_auto__chg_field_variablehistory_operation__chg_field_recipe_descriptio.py
deleted file mode 100644
index ece408a3c..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0008_auto__chg_field_variablehistory_operation__chg_field_recipe_descriptio.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'VariableHistory.operation'
- db.alter_column(u'orm_variablehistory', 'operation', self.gf('django.db.models.fields.CharField')(max_length=64))
-
- # Changing field 'Recipe.description'
- db.alter_column(u'orm_recipe', 'description', self.gf('django.db.models.fields.TextField')())
-
- # Changing field 'Target_Image_File.file_name'
- db.alter_column(u'orm_target_image_file', 'file_name', self.gf('django.db.models.fields.FilePathField')(max_length=254))
-
- # Changing field 'Package.description'
- db.alter_column(u'orm_package', 'description', self.gf('django.db.models.fields.TextField')())
-
- def backwards(self, orm):
-
- # Changing field 'VariableHistory.operation'
- db.alter_column(u'orm_variablehistory', 'operation', self.gf('django.db.models.fields.CharField')(max_length=16))
-
- # Changing field 'Recipe.description'
- db.alter_column(u'orm_recipe', 'description', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- # Changing field 'Target_Image_File.file_name'
- db.alter_column(u'orm_target_image_file', 'file_name', self.gf('django.db.models.fields.FilePathField')(max_length=100))
-
- # Changing field 'Package.description'
- db.alter_column(u'orm_package', 'description', self.gf('django.db.models.fields.CharField')(max_length=200))
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0009_auto__add_projectvariable__add_projectlayer__add_projecttarget__add_pr.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0009_auto__add_projectvariable__add_projectlayer__add_projecttarget__add_pr.py
deleted file mode 100644
index 7a58dc2e6..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0009_auto__add_projectvariable__add_projectlayer__add_projecttarget__add_pr.py
+++ /dev/null
@@ -1,286 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'ProjectVariable'
- db.create_table(u'orm_projectvariable', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'])),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('value', self.gf('django.db.models.fields.TextField')(blank=True)),
- ))
- db.send_create_signal(u'orm', ['ProjectVariable'])
-
- # Adding model 'ProjectLayer'
- db.create_table(u'orm_projectlayer', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'])),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('giturl', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ('commit', self.gf('django.db.models.fields.CharField')(max_length=254)),
- ))
- db.send_create_signal(u'orm', ['ProjectLayer'])
-
- # Adding model 'ProjectTarget'
- db.create_table(u'orm_projecttarget', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'])),
- ('target', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ))
- db.send_create_signal(u'orm', ['ProjectTarget'])
-
- # Adding model 'Project'
- db.create_table(u'orm_project', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
- ('updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
- ))
- db.send_create_signal(u'orm', ['Project'])
-
- # Adding field 'Build.project'
- db.add_column(u'orm_build', 'project',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'], null=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting model 'ProjectVariable'
- db.delete_table(u'orm_projectvariable')
-
- # Deleting model 'ProjectLayer'
- db.delete_table(u'orm_projectlayer')
-
- # Deleting model 'ProjectTarget'
- db.delete_table(u'orm_projecttarget')
-
- # Deleting model 'Project'
- db.delete_table(u'orm_project')
-
- # Deleting field 'Build.project'
- db.delete_column(u'orm_build', 'project_id')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py
deleted file mode 100644
index aa1ce1f4a..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0010_auto__add_field_project_branch__add_field_project_short_description__a.py
+++ /dev/null
@@ -1,257 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Project.branch'
- db.add_column(u'orm_project', 'branch',
- self.gf('django.db.models.fields.CharField')(default='master', max_length=50),
- keep_default=False)
-
- # Adding field 'Project.short_description'
- db.add_column(u'orm_project', 'short_description',
- self.gf('django.db.models.fields.CharField')(default='', max_length=50, blank=True),
- keep_default=False)
-
- # Adding field 'Project.user_id'
- db.add_column(u'orm_project', 'user_id',
- self.gf('django.db.models.fields.IntegerField')(null=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Project.branch'
- db.delete_column(u'orm_project', 'branch')
-
- # Deleting field 'Project.short_description'
- db.delete_column(u'orm_project', 'short_description')
-
- # Deleting field 'Project.user_id'
- db.delete_column(u'orm_project', 'user_id')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0011_auto__add_field_projectlayer_dirpath.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0011_auto__add_field_projectlayer_dirpath.py
deleted file mode 100644
index 8a6522159..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0011_auto__add_field_projectlayer_dirpath.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'ProjectLayer.dirpath'
- db.add_column(u'orm_projectlayer', 'dirpath',
- self.gf('django.db.models.fields.CharField')(default='', max_length=254),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'ProjectLayer.dirpath'
- db.delete_column(u'orm_projectlayer', 'dirpath')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py
deleted file mode 100644
index 9e483f5da..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0012_auto__add_field_projectlayer_optional__add_field_projecttarget_task.py
+++ /dev/null
@@ -1,252 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'ProjectLayer.optional'
- db.add_column(u'orm_projectlayer', 'optional',
- self.gf('django.db.models.fields.BooleanField')(default=True),
- keep_default=False)
-
- # Adding field 'ProjectTarget.task'
- db.add_column(u'orm_projecttarget', 'task',
- self.gf('django.db.models.fields.CharField')(max_length=100, null=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'ProjectLayer.optional'
- db.delete_column(u'orm_projectlayer', 'optional')
-
- # Deleting field 'ProjectTarget.task'
- db.delete_column(u'orm_projecttarget', 'task')
-
-
- models = {
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'object_name': 'Layer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.layer_version': {
- 'Meta': {'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- 'giturl': ('django.db.models.fields.CharField', [], {'max_length': '254'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0013_auto__add_release__add_layerversiondependency__add_unique_layerversion.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0013_auto__add_release__add_layerversiondependency__add_unique_layerversion.py
deleted file mode 100644
index 7c954e6be..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0013_auto__add_release__add_layerversiondependency__add_unique_layerversion.py
+++ /dev/null
@@ -1,710 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'Release'
- db.create_table(u'orm_release', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=32)),
- ('description', self.gf('django.db.models.fields.CharField')(max_length=255)),
- ('bitbake_version', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.BitbakeVersion'])),
- ('branch', self.gf('django.db.models.fields.CharField')(max_length=32)),
- ))
- db.send_create_signal(u'orm', ['Release'])
-
- # Adding model 'LayerVersionDependency'
- db.create_table(u'orm_layerversiondependency', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('layer_source', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.LayerSource'], null=True)),
- ('up_id', self.gf('django.db.models.fields.IntegerField')(default=None, null=True)),
- ('layer_version', self.gf('django.db.models.fields.related.ForeignKey')(related_name='dependencies', to=orm['orm.Layer_Version'])),
- ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='dependees', to=orm['orm.Layer_Version'])),
- ))
- db.send_create_signal(u'orm', ['LayerVersionDependency'])
-
- # Adding unique constraint on 'LayerVersionDependency', fields ['layer_source', 'up_id']
- db.create_unique(u'orm_layerversiondependency', ['layer_source_id', 'up_id'])
-
- # Adding model 'ToasterSetting'
- db.create_table(u'orm_toastersetting', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=63)),
- ('helptext', self.gf('django.db.models.fields.TextField')()),
- ('value', self.gf('django.db.models.fields.CharField')(max_length=255)),
- ))
- db.send_create_signal(u'orm', ['ToasterSetting'])
-
- # Adding model 'Machine'
- db.create_table(u'orm_machine', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('layer_source', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.LayerSource'], null=True)),
- ('up_id', self.gf('django.db.models.fields.IntegerField')(default=None, null=True)),
- ('up_date', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)),
- ('layer_version', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer_Version'])),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
- ('description', self.gf('django.db.models.fields.CharField')(max_length=255)),
- ))
- db.send_create_signal(u'orm', ['Machine'])
-
- # Adding unique constraint on 'Machine', fields ['layer_source', 'up_id']
- db.create_unique(u'orm_machine', ['layer_source_id', 'up_id'])
-
- # Adding model 'ReleaseDefaultLayer'
- db.create_table(u'orm_releasedefaultlayer', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('release', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Release'])),
- ('layer', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer'])),
- ))
- db.send_create_signal(u'orm', ['ReleaseDefaultLayer'])
-
- # Adding model 'BitbakeVersion'
- db.create_table(u'orm_bitbakeversion', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=32)),
- ('giturl', self.gf('django.db.models.fields.URLField')(max_length=200)),
- ('branch', self.gf('django.db.models.fields.CharField')(max_length=32)),
- ('dirpath', self.gf('django.db.models.fields.CharField')(max_length=255)),
- ))
- db.send_create_signal(u'orm', ['BitbakeVersion'])
-
- # Adding model 'Branch'
- db.create_table(u'orm_branch', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('layer_source', self.gf('django.db.models.fields.related.ForeignKey')(default=True, to=orm['orm.LayerSource'], null=True)),
- ('up_id', self.gf('django.db.models.fields.IntegerField')(default=None, null=True)),
- ('up_date', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('bitbake_branch', self.gf('django.db.models.fields.CharField')(max_length=50, blank=True)),
- ('short_description', self.gf('django.db.models.fields.CharField')(max_length=50, blank=True)),
- ))
- db.send_create_signal(u'orm', ['Branch'])
-
- # Adding unique constraint on 'Branch', fields ['layer_source', 'name']
- db.create_unique(u'orm_branch', ['layer_source_id', 'name'])
-
- # Adding unique constraint on 'Branch', fields ['layer_source', 'up_id']
- db.create_unique(u'orm_branch', ['layer_source_id', 'up_id'])
-
- # Adding model 'ToasterSettingDefaultLayer'
- db.create_table(u'orm_toastersettingdefaultlayer', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('layer_version', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer_Version'])),
- ))
- db.send_create_signal(u'orm', ['ToasterSettingDefaultLayer'])
-
- # Adding model 'LayerSource'
- db.create_table(u'orm_layersource', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=63)),
- ('sourcetype', self.gf('django.db.models.fields.IntegerField')()),
- ('apiurl', self.gf('django.db.models.fields.CharField')(default=None, max_length=255, null=True)),
- ))
- db.send_create_signal(u'orm', ['LayerSource'])
-
- # Adding unique constraint on 'LayerSource', fields ['sourcetype', 'apiurl']
- db.create_unique(u'orm_layersource', ['sourcetype', 'apiurl'])
-
- # Deleting field 'ProjectLayer.name'
- db.delete_column(u'orm_projectlayer', 'name')
-
- # Deleting field 'ProjectLayer.dirpath'
- db.delete_column(u'orm_projectlayer', 'dirpath')
-
- # Deleting field 'ProjectLayer.commit'
- db.delete_column(u'orm_projectlayer', 'commit')
-
- # Deleting field 'ProjectLayer.giturl'
- db.delete_column(u'orm_projectlayer', 'giturl')
-
- # Adding field 'ProjectLayer.layercommit'
- db.add_column(u'orm_projectlayer', 'layercommit',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer_Version'], null=True),
- keep_default=False)
-
- # Adding field 'Layer_Version.layer_source'
- db.add_column(u'orm_layer_version', 'layer_source',
- self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.LayerSource'], null=True),
- keep_default=False)
-
- # Adding field 'Layer_Version.up_id'
- db.add_column(u'orm_layer_version', 'up_id',
- self.gf('django.db.models.fields.IntegerField')(default=None, null=True),
- keep_default=False)
-
- # Adding field 'Layer_Version.up_date'
- db.add_column(u'orm_layer_version', 'up_date',
- self.gf('django.db.models.fields.DateTimeField')(default=None, null=True),
- keep_default=False)
-
- # Adding field 'Layer_Version.up_branch'
- db.add_column(u'orm_layer_version', 'up_branch',
- self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.Branch'], null=True),
- keep_default=False)
-
- # Adding field 'Layer_Version.dirpath'
- db.add_column(u'orm_layer_version', 'dirpath',
- self.gf('django.db.models.fields.CharField')(default=None, max_length=255, null=True),
- keep_default=False)
-
-
- # Changing field 'Layer_Version.build'
- db.alter_column(u'orm_layer_version', 'build_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['orm.Build']))
-
- # Changing field 'Layer_Version.branch'
- db.alter_column(u'orm_layer_version', 'branch', self.gf('django.db.models.fields.CharField')(max_length=80))
- # Adding unique constraint on 'Layer_Version', fields ['layer_source', 'up_id']
- db.create_unique(u'orm_layer_version', ['layer_source_id', 'up_id'])
-
- # Adding field 'Recipe.layer_source'
- db.add_column(u'orm_recipe', 'layer_source',
- self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.LayerSource'], null=True),
- keep_default=False)
-
- # Adding field 'Recipe.up_id'
- db.add_column(u'orm_recipe', 'up_id',
- self.gf('django.db.models.fields.IntegerField')(default=None, null=True),
- keep_default=False)
-
- # Adding field 'Recipe.up_date'
- db.add_column(u'orm_recipe', 'up_date',
- self.gf('django.db.models.fields.DateTimeField')(default=None, null=True),
- keep_default=False)
-
- # Adding field 'Layer.layer_source'
- db.add_column(u'orm_layer', 'layer_source',
- self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.LayerSource'], null=True),
- keep_default=False)
-
- # Adding field 'Layer.up_id'
- db.add_column(u'orm_layer', 'up_id',
- self.gf('django.db.models.fields.IntegerField')(default=None, null=True),
- keep_default=False)
-
- # Adding field 'Layer.up_date'
- db.add_column(u'orm_layer', 'up_date',
- self.gf('django.db.models.fields.DateTimeField')(default=None, null=True),
- keep_default=False)
-
- # Adding field 'Layer.vcs_url'
- db.add_column(u'orm_layer', 'vcs_url',
- self.gf('django.db.models.fields.URLField')(default=None, max_length=200, null=True),
- keep_default=False)
-
- # Adding field 'Layer.vcs_web_file_base_url'
- db.add_column(u'orm_layer', 'vcs_web_file_base_url',
- self.gf('django.db.models.fields.URLField')(default=None, max_length=200, null=True),
- keep_default=False)
-
- # Adding field 'Layer.summary'
- db.add_column(u'orm_layer', 'summary',
- self.gf('django.db.models.fields.CharField')(default=None, max_length=200, null=True),
- keep_default=False)
-
- # Adding field 'Layer.description'
- db.add_column(u'orm_layer', 'description',
- self.gf('django.db.models.fields.TextField')(default=None, null=True),
- keep_default=False)
-
-
- # Changing field 'Layer.local_path'
- db.alter_column(u'orm_layer', 'local_path', self.gf('django.db.models.fields.FilePathField')(max_length=255, null=True))
- # Adding unique constraint on 'Layer', fields ['layer_source', 'up_id']
- db.create_unique(u'orm_layer', ['layer_source_id', 'up_id'])
-
- # Adding unique constraint on 'Layer', fields ['layer_source', 'name']
- db.create_unique(u'orm_layer', ['layer_source_id', 'name'])
-
- # Deleting field 'Project.branch'
- db.delete_column(u'orm_project', 'branch')
-
- # Adding field 'Project.bitbake_version'
- db.add_column(u'orm_project', 'bitbake_version',
- self.gf('django.db.models.fields.related.ForeignKey')(default=-1, to=orm['orm.BitbakeVersion']),
- keep_default=False)
-
- # Adding field 'Project.release'
- db.add_column(u'orm_project', 'release',
- self.gf('django.db.models.fields.related.ForeignKey')(default=-1, to=orm['orm.Release']),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Removing unique constraint on 'Layer', fields ['layer_source', 'name']
- db.delete_unique(u'orm_layer', ['layer_source_id', 'name'])
-
- # Removing unique constraint on 'Layer', fields ['layer_source', 'up_id']
- db.delete_unique(u'orm_layer', ['layer_source_id', 'up_id'])
-
- # Removing unique constraint on 'Layer_Version', fields ['layer_source', 'up_id']
- db.delete_unique(u'orm_layer_version', ['layer_source_id', 'up_id'])
-
- # Removing unique constraint on 'LayerSource', fields ['sourcetype', 'apiurl']
- db.delete_unique(u'orm_layersource', ['sourcetype', 'apiurl'])
-
- # Removing unique constraint on 'Branch', fields ['layer_source', 'up_id']
- db.delete_unique(u'orm_branch', ['layer_source_id', 'up_id'])
-
- # Removing unique constraint on 'Branch', fields ['layer_source', 'name']
- db.delete_unique(u'orm_branch', ['layer_source_id', 'name'])
-
- # Removing unique constraint on 'Machine', fields ['layer_source', 'up_id']
- db.delete_unique(u'orm_machine', ['layer_source_id', 'up_id'])
-
- # Removing unique constraint on 'LayerVersionDependency', fields ['layer_source', 'up_id']
- db.delete_unique(u'orm_layerversiondependency', ['layer_source_id', 'up_id'])
-
- # Deleting model 'Release'
- db.delete_table(u'orm_release')
-
- # Deleting model 'LayerVersionDependency'
- db.delete_table(u'orm_layerversiondependency')
-
- # Deleting model 'ToasterSetting'
- db.delete_table(u'orm_toastersetting')
-
- # Deleting model 'Machine'
- db.delete_table(u'orm_machine')
-
- # Deleting model 'ReleaseDefaultLayer'
- db.delete_table(u'orm_releasedefaultlayer')
-
- # Deleting model 'BitbakeVersion'
- db.delete_table(u'orm_bitbakeversion')
-
- # Deleting model 'Branch'
- db.delete_table(u'orm_branch')
-
- # Deleting model 'ToasterSettingDefaultLayer'
- db.delete_table(u'orm_toastersettingdefaultlayer')
-
- # Deleting model 'LayerSource'
- db.delete_table(u'orm_layersource')
-
-
- # User chose to not deal with backwards NULL issues for 'ProjectLayer.name'
- raise RuntimeError("Cannot reverse this migration. 'ProjectLayer.name' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'ProjectLayer.name'
- db.add_column(u'orm_projectlayer', 'name',
- self.gf('django.db.models.fields.CharField')(max_length=100),
- keep_default=False)
-
-
- # User chose to not deal with backwards NULL issues for 'ProjectLayer.dirpath'
- raise RuntimeError("Cannot reverse this migration. 'ProjectLayer.dirpath' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'ProjectLayer.dirpath'
- db.add_column(u'orm_projectlayer', 'dirpath',
- self.gf('django.db.models.fields.CharField')(max_length=254),
- keep_default=False)
-
-
- # User chose to not deal with backwards NULL issues for 'ProjectLayer.commit'
- raise RuntimeError("Cannot reverse this migration. 'ProjectLayer.commit' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'ProjectLayer.commit'
- db.add_column(u'orm_projectlayer', 'commit',
- self.gf('django.db.models.fields.CharField')(max_length=254),
- keep_default=False)
-
-
- # User chose to not deal with backwards NULL issues for 'ProjectLayer.giturl'
- raise RuntimeError("Cannot reverse this migration. 'ProjectLayer.giturl' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'ProjectLayer.giturl'
- db.add_column(u'orm_projectlayer', 'giturl',
- self.gf('django.db.models.fields.CharField')(max_length=254),
- keep_default=False)
-
- # Deleting field 'ProjectLayer.layercommit'
- db.delete_column(u'orm_projectlayer', 'layercommit_id')
-
- # Deleting field 'Layer_Version.layer_source'
- db.delete_column(u'orm_layer_version', 'layer_source_id')
-
- # Deleting field 'Layer_Version.up_id'
- db.delete_column(u'orm_layer_version', 'up_id')
-
- # Deleting field 'Layer_Version.up_date'
- db.delete_column(u'orm_layer_version', 'up_date')
-
- # Deleting field 'Layer_Version.up_branch'
- db.delete_column(u'orm_layer_version', 'up_branch_id')
-
- # Deleting field 'Layer_Version.dirpath'
- db.delete_column(u'orm_layer_version', 'dirpath')
-
-
- # User chose to not deal with backwards NULL issues for 'Layer_Version.build'
- raise RuntimeError("Cannot reverse this migration. 'Layer_Version.build' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration
- # Changing field 'Layer_Version.build'
- db.alter_column(u'orm_layer_version', 'build_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build']))
-
- # Changing field 'Layer_Version.branch'
- db.alter_column(u'orm_layer_version', 'branch', self.gf('django.db.models.fields.CharField')(max_length=50))
- # Deleting field 'Recipe.layer_source'
- db.delete_column(u'orm_recipe', 'layer_source_id')
-
- # Deleting field 'Recipe.up_id'
- db.delete_column(u'orm_recipe', 'up_id')
-
- # Deleting field 'Recipe.up_date'
- db.delete_column(u'orm_recipe', 'up_date')
-
- # Deleting field 'Layer.layer_source'
- db.delete_column(u'orm_layer', 'layer_source_id')
-
- # Deleting field 'Layer.up_id'
- db.delete_column(u'orm_layer', 'up_id')
-
- # Deleting field 'Layer.up_date'
- db.delete_column(u'orm_layer', 'up_date')
-
- # Deleting field 'Layer.vcs_url'
- db.delete_column(u'orm_layer', 'vcs_url')
-
- # Deleting field 'Layer.vcs_web_file_base_url'
- db.delete_column(u'orm_layer', 'vcs_web_file_base_url')
-
- # Deleting field 'Layer.summary'
- db.delete_column(u'orm_layer', 'summary')
-
- # Deleting field 'Layer.description'
- db.delete_column(u'orm_layer', 'description')
-
-
- # User chose to not deal with backwards NULL issues for 'Layer.local_path'
- raise RuntimeError("Cannot reverse this migration. 'Layer.local_path' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration
- # Changing field 'Layer.local_path'
- db.alter_column(u'orm_layer', 'local_path', self.gf('django.db.models.fields.FilePathField')(max_length=255))
-
- # User chose to not deal with backwards NULL issues for 'Project.branch'
- raise RuntimeError("Cannot reverse this migration. 'Project.branch' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'Project.branch'
- db.add_column(u'orm_project', 'branch',
- self.gf('django.db.models.fields.CharField')(max_length=50),
- keep_default=False)
-
- # Deleting field 'Project.bitbake_version'
- db.delete_column(u'orm_project', 'bitbake_version_id')
-
- # Deleting field 'Project.release'
- db.delete_column(u'orm_project', 'release_id')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- 'bitbake_branch': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer']"}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.toastersettingdefaultlayer': {
- 'Meta': {'object_name': 'ToasterSettingDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0014_auto__chg_field_package_summary__chg_field_layer_summary__chg_field_re.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0014_auto__chg_field_package_summary__chg_field_layer_summary__chg_field_re.py
deleted file mode 100644
index 7945f15a1..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0014_auto__chg_field_package_summary__chg_field_layer_summary__chg_field_re.py
+++ /dev/null
@@ -1,336 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'Package.summary'
- db.alter_column(u'orm_package', 'summary', self.gf('django.db.models.fields.TextField')())
-
- # Changing field 'Layer.summary'
- db.alter_column(u'orm_layer', 'summary', self.gf('django.db.models.fields.TextField')(null=True))
-
- # Changing field 'Recipe.summary'
- db.alter_column(u'orm_recipe', 'summary', self.gf('django.db.models.fields.TextField')())
-
- def backwards(self, orm):
-
- # Changing field 'Package.summary'
- db.alter_column(u'orm_package', 'summary', self.gf('django.db.models.fields.CharField')(max_length=200))
-
- # Changing field 'Layer.summary'
- db.alter_column(u'orm_layer', 'summary', self.gf('django.db.models.fields.CharField')(max_length=200, null=True))
-
- # Changing field 'Recipe.summary'
- db.alter_column(u'orm_recipe', 'summary', self.gf('django.db.models.fields.CharField')(max_length=100))
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- 'bitbake_branch': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer']"}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.toastersettingdefaultlayer': {
- 'Meta': {'object_name': 'ToasterSettingDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0015_auto__add_field_layer_vcs_web_url__add_field_layer_vcs_web_tree_base_u.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0015_auto__add_field_layer_vcs_web_url__add_field_layer_vcs_web_tree_base_u.py
deleted file mode 100644
index 6e664c9fc..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0015_auto__add_field_layer_vcs_web_url__add_field_layer_vcs_web_tree_base_u.py
+++ /dev/null
@@ -1,336 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Layer.vcs_web_url'
- db.add_column(u'orm_layer', 'vcs_web_url',
- self.gf('django.db.models.fields.URLField')(default=None, max_length=200, null=True),
- keep_default=False)
-
- # Adding field 'Layer.vcs_web_tree_base_url'
- db.add_column(u'orm_layer', 'vcs_web_tree_base_url',
- self.gf('django.db.models.fields.URLField')(default=None, max_length=200, null=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Layer.vcs_web_url'
- db.delete_column(u'orm_layer', 'vcs_web_url')
-
- # Deleting field 'Layer.vcs_web_tree_base_url'
- db.delete_column(u'orm_layer', 'vcs_web_tree_base_url')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- 'bitbake_branch': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer']"}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.toastersettingdefaultlayer': {
- 'Meta': {'object_name': 'ToasterSettingDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0016_auto__add_field_release_helptext__chg_field_release_branch__add_index_.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0016_auto__add_field_release_helptext__chg_field_release_branch__add_index_.py
deleted file mode 100644
index 545c0ba58..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0016_auto__add_field_release_helptext__chg_field_release_branch__add_index_.py
+++ /dev/null
@@ -1,359 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Release.helptext'
- db.add_column(u'orm_release', 'helptext',
- self.gf('django.db.models.fields.TextField')(null=True),
- keep_default=False)
-
-
- # Renaming column for 'Release.branch' to match new field type.
- db.delete_column(u'orm_release', 'branch')
-
- # Changing field 'Release.branch'
- db.add_column(u'orm_release', 'branch', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Branch'], default=-1))
-
- # Deleting field 'Branch.bitbake_branch'
- db.delete_column(u'orm_branch', 'bitbake_branch')
-
- # Adding unique constraint on 'Recipe', fields ['layer_version', 'file_path']
- db.create_unique(u'orm_recipe', ['layer_version_id', 'file_path'])
-
- # Adding unique constraint on 'ProjectLayer', fields ['project', 'layercommit']
- db.create_unique(u'orm_projectlayer', ['project_id', 'layercommit_id'])
-
-
- def backwards(self, orm):
- # Removing unique constraint on 'ProjectLayer', fields ['project', 'layercommit']
- db.delete_unique(u'orm_projectlayer', ['project_id', 'layercommit_id'])
-
- # Removing unique constraint on 'Recipe', fields ['layer_version', 'file_path']
- db.delete_unique(u'orm_recipe', ['layer_version_id', 'file_path'])
-
- # Deleting field 'Release.helptext'
- db.delete_column(u'orm_release', 'helptext')
-
- # Renaming column for 'Release.branch' to match new field type.
- db.rename_column(u'orm_release', 'branch_id', 'branch')
- # Changing field 'Release.branch'
- db.alter_column(u'orm_release', 'branch', self.gf('django.db.models.fields.CharField')(max_length=32))
- # Adding field 'Branch.bitbake_branch'
- db.add_column(u'orm_branch', 'bitbake_branch',
- self.gf('django.db.models.fields.CharField')(default='', max_length=50, blank=True),
- keep_default=False)
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Branch']"}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer']"}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.toastersettingdefaultlayer': {
- 'Meta': {'object_name': 'ToasterSettingDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py
deleted file mode 100644
index 6685b5564..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0017_auto__del_toastersettingdefaultlayer__add_releaselayersourcepriority__.py
+++ /dev/null
@@ -1,396 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Deleting model 'ToasterSettingDefaultLayer'
- db.delete_table(u'orm_toastersettingdefaultlayer')
-
- # Adding model 'ReleaseLayerSourcePriority'
- db.create_table(u'orm_releaselayersourcepriority', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('release', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Release'])),
- ('layer_source', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.LayerSource'])),
- ('priority', self.gf('django.db.models.fields.IntegerField')(default=0)),
- ))
- db.send_create_signal(u'orm', ['ReleaseLayerSourcePriority'])
-
- # Adding unique constraint on 'ReleaseLayerSourcePriority', fields ['release', 'layer_source']
- db.create_unique(u'orm_releaselayersourcepriority', ['release_id', 'layer_source_id'])
-
- # Deleting field 'Release.branch'
- db.delete_column(u'orm_release', 'branch_id')
-
- # Adding field 'Release.branch_name'
- db.add_column(u'orm_release', 'branch_name',
- self.gf('django.db.models.fields.CharField')(default='', max_length=50),
- keep_default=False)
-
- # Adding unique constraint on 'LayerSource', fields ['name']
- db.create_unique(u'orm_layersource', ['name'])
-
- # Deleting field 'ReleaseDefaultLayer.layer'
- db.delete_column(u'orm_releasedefaultlayer', 'layer_id')
-
- # Adding field 'ReleaseDefaultLayer.layer_name'
- db.add_column(u'orm_releasedefaultlayer', 'layer_name',
- self.gf('django.db.models.fields.CharField')(default='', max_length=100),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Removing unique constraint on 'LayerSource', fields ['name']
- db.delete_unique(u'orm_layersource', ['name'])
-
- # Removing unique constraint on 'ReleaseLayerSourcePriority', fields ['release', 'layer_source']
- db.delete_unique(u'orm_releaselayersourcepriority', ['release_id', 'layer_source_id'])
-
- # Adding model 'ToasterSettingDefaultLayer'
- db.create_table(u'orm_toastersettingdefaultlayer', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('layer_version', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer_Version'])),
- ))
- db.send_create_signal(u'orm', ['ToasterSettingDefaultLayer'])
-
- # Deleting model 'ReleaseLayerSourcePriority'
- db.delete_table(u'orm_releaselayersourcepriority')
-
-
- # User chose to not deal with backwards NULL issues for 'Release.branch'
- raise RuntimeError("Cannot reverse this migration. 'Release.branch' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'Release.branch'
- db.add_column(u'orm_release', 'branch',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Branch']),
- keep_default=False)
-
- # Deleting field 'Release.branch_name'
- db.delete_column(u'orm_release', 'branch_name')
-
-
- # User chose to not deal with backwards NULL issues for 'ReleaseDefaultLayer.layer'
- raise RuntimeError("Cannot reverse this migration. 'ReleaseDefaultLayer.layer' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration # Adding field 'ReleaseDefaultLayer.layer'
- db.add_column(u'orm_releasedefaultlayer', 'layer',
- self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Layer']),
- keep_default=False)
-
- # Deleting field 'ReleaseDefaultLayer.layer_name'
- db.delete_column(u'orm_releasedefaultlayer', 'layer_name')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0018_auto__add_field_layer_version_project.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0018_auto__add_field_layer_version_project.py
deleted file mode 100644
index 7284bb842..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0018_auto__add_field_layer_version_project.py
+++ /dev/null
@@ -1,331 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Layer_Version.project'
- db.add_column(u'orm_layer_version', 'project',
- self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.Project'], null=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Layer_Version.project'
- db.delete_column(u'orm_layer_version', 'project_id')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py
deleted file mode 100644
index 0dce9ead2..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0019_auto__add_buildartifact.py
+++ /dev/null
@@ -1,342 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'BuildArtifact'
- db.create_table(u'orm_buildartifact', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
- ('file_name', self.gf('django.db.models.fields.FilePathField')(max_length=100)),
- ('file_size', self.gf('django.db.models.fields.IntegerField')()),
- ))
- db.send_create_signal(u'orm', ['BuildArtifact'])
-
-
- def backwards(self, orm):
- # Deleting model 'BuildArtifact'
- db.delete_table(u'orm_buildartifact')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']", 'null': 'True'}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0020_auto__add_field_layer_version_local_path__add_field_recipe_pathflags__.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0020_auto__add_field_layer_version_local_path__add_field_recipe_pathflags__.py
deleted file mode 100644
index 0ec579597..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0020_auto__add_field_layer_version_local_path__add_field_recipe_pathflags__.py
+++ /dev/null
@@ -1,361 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Removing unique constraint on 'Recipe', fields ['layer_version', 'file_path']
- db.delete_unique(u'orm_recipe', ['layer_version_id', 'file_path'])
-
- # Adding field 'Layer_Version.local_path'
- db.add_column(u'orm_layer_version', 'local_path',
- self.gf('django.db.models.fields.FilePathField')(default="/", max_length=1024),
- keep_default=False)
-
- # Adding field 'Recipe.pathflags'
- db.add_column(u'orm_recipe', 'pathflags',
- self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True),
- keep_default=False)
-
- # Adding unique constraint on 'Recipe', fields ['layer_version', 'file_path', 'pathflags']
- db.create_unique(u'orm_recipe', ['layer_version_id', 'file_path', 'pathflags'])
-
- # Migrate data from Layer.local_path to Layer_Version.local_path
- if not db.dry_run:
- for lv in orm.Layer_Version.objects.all():
- if lv.layer.local_path is not None:
- lv.local_path = lv.layer.local_path
- else:
- lv.local_path = "/"
- lv.save()
-
- db.delete_column(u'orm_layer', 'local_path')
-
-
- def backwards(self, orm):
- raise RuntimeError("Cannot reverse this migration")
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'), ('file_path', 'pathflags'))", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0021_auto__chg_field_build_project__chg_field_project_bitbake_version__chg_.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0021_auto__chg_field_build_project__chg_field_project_bitbake_version__chg_.py
deleted file mode 100644
index a62ddb7ee..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0021_auto__chg_field_build_project__chg_field_project_bitbake_version__chg_.py
+++ /dev/null
@@ -1,371 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- no_dry_run = True
-
- def forwards(self, orm):
-
- # Changing field 'Build.project'
- db.alter_column(u'orm_build', 'project_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project']))
-
- # Changing field 'Project.bitbake_version'
- db.alter_column(u'orm_project', 'bitbake_version_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.BitbakeVersion'], null=True))
-
- # Changing field 'Project.release'
- db.alter_column(u'orm_project', 'release_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Release'], null=True))
-
- # Changing field 'Task.cpu_usage'
- db.alter_column(u'orm_task', 'cpu_usage', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=8, decimal_places=2))
-
- # Changing field 'Task.elapsed_time'
- db.alter_column(u'orm_task', 'elapsed_time', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=8, decimal_places=2))
-
- def backwards(self, orm):
-
- # Changing field 'Build.project'
- db.alter_column(u'orm_build', 'project_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'], null=True))
-
- # User chose to not deal with backwards NULL issues for 'Project.bitbake_version'
- raise RuntimeError("Cannot reverse this migration. 'Project.bitbake_version' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration
- # Changing field 'Project.bitbake_version'
- db.alter_column(u'orm_project', 'bitbake_version_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.BitbakeVersion']))
-
- # User chose to not deal with backwards NULL issues for 'Project.release'
- raise RuntimeError("Cannot reverse this migration. 'Project.release' and its values cannot be restored.")
-
- # The following code is provided here to aid in writing a correct migration
- # Changing field 'Project.release'
- db.alter_column(u'orm_project', 'release_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Release']))
-
- # Changing field 'Task.cpu_usage'
- db.alter_column(u'orm_task', 'cpu_usage', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=6, decimal_places=2))
-
- # Changing field 'Task.elapsed_time'
- db.alter_column(u'orm_task', 'elapsed_time', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=6, decimal_places=2))
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0022_auto__add_field_target_task__add_field_layer_version_local_path__del_f.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0022_auto__add_field_target_task__add_field_layer_version_local_path__del_f.py
deleted file mode 100644
index 3dec3912e..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0022_auto__add_field_target_task__add_field_layer_version_local_path__del_f.py
+++ /dev/null
@@ -1,343 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Target.task'
- db.add_column(u'orm_target', 'task',
- self.gf('django.db.models.fields.CharField')(max_length=100, null=True),
- keep_default=False)
-
-
-
-
-
- def backwards(self, orm):
- # Deleting field 'Target.task'
- db.delete_column(u'orm_target', 'task')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'timespent': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0023_auto__del_field_build_warnings_no__del_field_build_errors_no__del_fiel.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0023_auto__del_field_build_warnings_no__del_field_build_errors_no__del_fiel.py
deleted file mode 100644
index b5b200cdd..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0023_auto__del_field_build_warnings_no__del_field_build_errors_no__del_fiel.py
+++ /dev/null
@@ -1,353 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Deleting field 'Build.warnings_no'
- db.delete_column(u'orm_build', 'warnings_no')
-
- # Deleting field 'Build.errors_no'
- db.delete_column(u'orm_build', 'errors_no')
-
- # Deleting field 'Build.timespent'
- db.delete_column(u'orm_build', 'timespent')
-
-
- def backwards(self, orm):
- # Adding field 'Build.warnings_no'
- db.add_column(u'orm_build', 'warnings_no',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
- # Adding field 'Build.errors_no'
- db.add_column(u'orm_build', 'errors_no',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
- # Adding field 'Build.timespent'
- db.add_column(u'orm_build', 'timespent',
- self.gf('django.db.models.fields.IntegerField')(default=0),
- keep_default=False)
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0024_auto__add_field_recipe_is_image.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0024_auto__add_field_recipe_is_image.py
deleted file mode 100644
index 88f60a946..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0024_auto__add_field_recipe_is_image.py
+++ /dev/null
@@ -1,338 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding field 'Recipe.is_image'
- db.add_column(u'orm_recipe', 'is_image',
- self.gf('django.db.models.fields.BooleanField')(default=False),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Recipe.is_image'
- db.delete_column(u'orm_recipe', 'is_image')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0025_auto__add_field_project_is_default.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0025_auto__add_field_project_is_default.py
deleted file mode 100644
index e76990d7a..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0025_auto__add_field_project_is_default.py
+++ /dev/null
@@ -1,346 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # work-around for http://south.aeracode.org/ticket/578:
- # SQLite boolean fields aren't set to the correct default value
- # (needs to be 0 or 1, rather than True or False)
- default = False
- if db.backend_name == 'sqlite3':
- default = 0
-
- # Adding field 'Project.is_default'
- db.add_column(u'orm_project', 'is_default',
- self.gf('django.db.models.fields.BooleanField')(default=default),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Project.is_default'
- db.delete_column(u'orm_project', 'is_default')
-
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0026_set_default_project.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0026_set_default_project.py
deleted file mode 100644
index 6240abd85..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0026_set_default_project.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-# data-only migration to set the is_default field correctly
-# across all projects, so it has the correct value on a single
-# record only; this will add or amend default project (marked with
-# is_default = True)
-class Migration(SchemaMigration):
-
- no_dry_run = True
-
- # work-around for http://south.aeracode.org/ticket/578:
- # SQLite boolean fields aren't set to the correct default value
- # when added to existing records (value needs to be 0 or 1, rather
- # than True or False), so manually update that field for all
- # existing records
- def _sqlite_update_all_projects_is_default(self, orm):
- if db.backend_name == 'sqlite3':
- for project in orm.Project.objects.all():
- project.is_default = 0
- project.save()
-
- def forwards(self, orm):
- # fix is_default field
- self._sqlite_update_all_projects_is_default(orm)
-
- # now create or modify the default project
- project = None
-
- # check for existing default project with ID 0 which has
- # already been added in code
- projects = orm.Project.objects.filter(pk = 0)
-
- if len(projects) == 1:
- project = projects[0]
- else:
- # create default project
- options = {
- "name": "Command line builds",
- "short_description": "Project for builds started outside Toaster"
- }
- project = orm.Project.objects.create(**options)
-
- project.is_default = True
- project.save()
-
- def backwards(self, orm):
- # don't do anything when reversing this migration, as we can safely
- # keep any generated default project which has builds attached;
- # it's just that the old code won't use that project as the
- # container for any new builds, as it doesn't have an ID of 0
- pass
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm']
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0027_auto__add_customimagerecipe__add_unique_customimagerecipe_name_project.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0027_auto__add_customimagerecipe__add_unique_customimagerecipe_name_project.py
deleted file mode 100644
index 603060514..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0027_auto__add_customimagerecipe__add_unique_customimagerecipe_name_project.py
+++ /dev/null
@@ -1,375 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
- # Adding model 'CustomImageRecipe'
- db.create_table(u'orm_customimagerecipe', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
- ('base_recipe', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Recipe'])),
- ('project', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Project'])),
- ))
- db.send_create_signal(u'orm', ['CustomImageRecipe'])
-
- # Adding M2M table for field packages on 'CustomImageRecipe'
- m2m_table_name = db.shorten_name(u'orm_customimagerecipe_packages')
- db.create_table(m2m_table_name, (
- ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
- ('customimagerecipe', models.ForeignKey(orm[u'orm.customimagerecipe'], null=False)),
- ('package', models.ForeignKey(orm[u'orm.package'], null=False))
- ))
- db.create_unique(m2m_table_name, ['customimagerecipe_id', 'package_id'])
-
- # Adding unique constraint on 'CustomImageRecipe', fields ['name', 'project']
- db.create_unique(u'orm_customimagerecipe', ['name', 'project_id'])
-
-
- # Changing field 'Package.build'
- db.alter_column(u'orm_package', 'build_id', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'], null=True))
-
- def backwards(self, orm):
- # Removing unique constraint on 'CustomImageRecipe', fields ['name', 'project']
- db.delete_unique(u'orm_customimagerecipe', ['name', 'project_id'])
-
- # Deleting model 'CustomImageRecipe'
- db.delete_table(u'orm_customimagerecipe')
-
- # Removing M2M table for field packages on 'CustomImageRecipe'
- db.delete_table(db.shorten_name(u'orm_customimagerecipe_packages'))
-
-
- # Changing field 'Package.build'
- db.alter_column(u'orm_package', 'build_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['orm.Build']))
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.customimagerecipe': {
- 'Meta': {'unique_together': "(('name', 'project'),)", 'object_name': 'CustomImageRecipe'},
- 'base_recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'packages': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['orm.Package']", 'symmetrical': 'False'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/migrations/0028_auto__chg_field_logmessage_message.py b/yocto-poky/bitbake/lib/toaster/orm/migrations/0028_auto__chg_field_logmessage_message.py
deleted file mode 100644
index a2f8661af..000000000
--- a/yocto-poky/bitbake/lib/toaster/orm/migrations/0028_auto__chg_field_logmessage_message.py
+++ /dev/null
@@ -1,345 +0,0 @@
-# -*- coding: utf-8 -*-
-from south.utils import datetime_utils as datetime
-from south.db import db
-from south.v2 import SchemaMigration
-from django.db import models
-
-
-class Migration(SchemaMigration):
-
- def forwards(self, orm):
-
- # Changing field 'LogMessage.message'
- db.alter_column(u'orm_logmessage', 'message', self.gf('django.db.models.fields.TextField')(null=True))
-
- def backwards(self, orm):
-
- # Changing field 'LogMessage.message'
- db.alter_column(u'orm_logmessage', 'message', self.gf('django.db.models.fields.CharField')(default='', max_length=240))
-
- models = {
- u'orm.bitbakeversion': {
- 'Meta': {'object_name': 'BitbakeVersion'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'giturl': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.branch': {
- 'Meta': {'unique_together': "(('layer_source', 'name'), ('layer_source', 'up_id'))", 'object_name': 'Branch'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'True', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.build': {
- 'Meta': {'object_name': 'Build'},
- 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
- 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
- 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'started_on': ('django.db.models.fields.DateTimeField', [], {})
- },
- u'orm.buildartifact': {
- 'Meta': {'object_name': 'BuildArtifact'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
- },
- u'orm.customimagerecipe': {
- 'Meta': {'unique_together': "(('name', 'project'),)", 'object_name': 'CustomImageRecipe'},
- 'base_recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'packages': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['orm.Package']", 'symmetrical': 'False'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.helptext': {
- 'Meta': {'object_name': 'HelpText'},
- 'area': ('django.db.models.fields.IntegerField', [], {}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'helptext_build'", 'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'key': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'text': ('django.db.models.fields.TextField', [], {})
- },
- u'orm.layer': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'), ('layer_source', 'name'))", 'object_name': 'Layer'},
- 'description': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'summary': ('django.db.models.fields.TextField', [], {'default': 'None', 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'vcs_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_file_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_tree_base_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'}),
- 'vcs_web_url': ('django.db.models.fields.URLField', [], {'default': 'None', 'max_length': '200', 'null': 'True'})
- },
- u'orm.layer_version': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Layer_Version'},
- 'branch': ('django.db.models.fields.CharField', [], {'max_length': '80'}),
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'layer_version_build'", 'null': 'True', 'to': u"orm['orm.Build']"}),
- 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'dirpath': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'local_path': ('django.db.models.fields.FilePathField', [], {'default': "'/'", 'max_length': '1024'}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Project']", 'null': 'True'}),
- 'up_branch': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.Branch']", 'null': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.layersource': {
- 'Meta': {'unique_together': "(('sourcetype', 'apiurl'),)", 'object_name': 'LayerSource'},
- 'apiurl': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '63'}),
- 'sourcetype': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.layerversiondependency': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'LayerVersionDependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependees'", 'to': u"orm['orm.Layer_Version']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'dependencies'", 'to': u"orm['orm.Layer_Version']"}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.logmessage': {
- 'Meta': {'object_name': 'LogMessage'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'message': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
- 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Task']", 'null': 'True', 'blank': 'True'})
- },
- u'orm.machine': {
- 'Meta': {'unique_together': "(('layer_source', 'up_id'),)", 'object_name': 'Machine'},
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']"}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'})
- },
- u'orm.package': {
- 'Meta': {'object_name': 'Package'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']", 'null': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'installed_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
- 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.package_dependency': {
- 'Meta': {'object_name': 'Package_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
- },
- u'orm.package_file': {
- 'Meta': {'object_name': 'Package_File'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'size': ('django.db.models.fields.IntegerField', [], {})
- },
- u'orm.project': {
- 'Meta': {'object_name': 'Project'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']", 'null': 'True'}),
- 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_default': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']", 'null': 'True'}),
- 'short_description': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
- 'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
- 'user_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
- },
- u'orm.projectlayer': {
- 'Meta': {'unique_together': "(('project', 'layercommit'),)", 'object_name': 'ProjectLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layercommit': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Layer_Version']", 'null': 'True'}),
- 'optional': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"})
- },
- u'orm.projecttarget': {
- 'Meta': {'object_name': 'ProjectTarget'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.projectvariable': {
- 'Meta': {'object_name': 'ProjectVariable'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'project': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Project']"}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.recipe': {
- 'Meta': {'unique_together': "(('layer_version', 'file_path', 'pathflags'),)", 'object_name': 'Recipe'},
- 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': u"orm['orm.LayerSource']", 'null': 'True'}),
- 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
- 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'pathflags': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
- 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'up_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}),
- 'up_id': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'null': 'True'}),
- 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
- },
- u'orm.recipe_dependency': {
- 'Meta': {'object_name': 'Recipe_Dependency'},
- 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
- },
- u'orm.release': {
- 'Meta': {'object_name': 'Release'},
- 'bitbake_version': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.BitbakeVersion']"}),
- 'branch_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '50'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'helptext': ('django.db.models.fields.TextField', [], {'null': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '32'})
- },
- u'orm.releasedefaultlayer': {
- 'Meta': {'object_name': 'ReleaseDefaultLayer'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.releaselayersourcepriority': {
- 'Meta': {'unique_together': "(('release', 'layer_source'),)", 'object_name': 'ReleaseLayerSourcePriority'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'layer_source': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.LayerSource']"}),
- 'priority': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'release': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Release']"})
- },
- u'orm.target': {
- 'Meta': {'object_name': 'Target'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'image_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'license_manifest_path': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
- 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'task': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'})
- },
- u'orm.target_file': {
- 'Meta': {'object_name': 'Target_File'},
- 'directory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'directory_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'group': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'inodetype': ('django.db.models.fields.IntegerField', [], {}),
- 'owner': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
- 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '100'}),
- 'permission': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
- 'size': ('django.db.models.fields.IntegerField', [], {}),
- 'sym_target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'symlink_set'", 'null': 'True', 'to': u"orm['orm.Target_File']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_image_file': {
- 'Meta': {'object_name': 'Target_Image_File'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '254'}),
- 'file_size': ('django.db.models.fields.IntegerField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.target_installed_package': {
- 'Meta': {'object_name': 'Target_Installed_Package'},
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildtargetlist_package'", 'to': u"orm['orm.Package']"}),
- 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
- },
- u'orm.task': {
- 'Meta': {'ordering': "('order', 'recipe')", 'unique_together': "(('build', 'recipe', 'task_name'),)", 'object_name': 'Task'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
- 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'elapsed_time': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '8', 'decimal_places': '2'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
- 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
- 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
- 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'to': u"orm['orm.Recipe']"}),
- 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
- 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
- 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
- },
- u'orm.task_dependency': {
- 'Meta': {'object_name': 'Task_Dependency'},
- 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
- },
- u'orm.toastersetting': {
- 'Meta': {'object_name': 'ToasterSetting'},
- 'helptext': ('django.db.models.fields.TextField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '63'}),
- 'value': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'orm.variable': {
- 'Meta': {'object_name': 'Variable'},
- 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
- 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
- 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
- },
- u'orm.variablehistory': {
- 'Meta': {'object_name': 'VariableHistory'},
- 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
- 'operation': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
- 'value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'variable': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'vhistory'", 'to': u"orm['orm.Variable']"})
- }
- }
-
- complete_apps = ['orm'] \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/orm/models.py b/yocto-poky/bitbake/lib/toaster/orm/models.py
index 383290583..0b83b991b 100644
--- a/yocto-poky/bitbake/lib/toaster/orm/models.py
+++ b/yocto-poky/bitbake/lib/toaster/orm/models.py
@@ -19,9 +19,12 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+from __future__ import unicode_literals
+
from django.db import models, IntegrityError
-from django.db.models import F, Q, Avg, Max
+from django.db.models import F, Q, Avg, Max, Sum
from django.utils import timezone
+from django.utils.encoding import force_bytes
from django.core.urlresolvers import reverse
@@ -29,10 +32,62 @@ from django.core import validators
from django.conf import settings
import django.db.models.signals
+import os.path
+import re
+import itertools
import logging
logger = logging.getLogger("toaster")
+if 'sqlite' in settings.DATABASES['default']['ENGINE']:
+ from django.db import transaction, OperationalError
+ from time import sleep
+
+ _base_save = models.Model.save
+ def save(self, *args, **kwargs):
+ while True:
+ try:
+ with transaction.atomic():
+ return _base_save(self, *args, **kwargs)
+ except OperationalError as err:
+ if 'database is locked' in str(err):
+ logger.warning("%s, model: %s, args: %s, kwargs: %s",
+ err, self.__class__, args, kwargs)
+ sleep(0.5)
+ continue
+ raise
+
+ models.Model.save = save
+
+ # HACK: Monkey patch Django to fix 'database is locked' issue
+
+ from django.db.models.query import QuerySet
+ _base_insert = QuerySet._insert
+ def _insert(self, *args, **kwargs):
+ with transaction.atomic(using=self.db, savepoint=False):
+ return _base_insert(self, *args, **kwargs)
+ QuerySet._insert = _insert
+
+ from django.utils import six
+ def _create_object_from_params(self, lookup, params):
+ """
+ Tries to create an object using passed params.
+ Used by get_or_create and update_or_create
+ """
+ try:
+ obj = self.create(**params)
+ return obj, True
+ except IntegrityError:
+ exc_info = sys.exc_info()
+ try:
+ return self.get(**lookup), False
+ except self.model.DoesNotExist:
+ pass
+ six.reraise(*exc_info)
+
+ QuerySet._create_object_from_params = _create_object_from_params
+
+ # end of HACK
class GitURLValidator(validators.URLValidator):
import re
@@ -91,18 +146,25 @@ class ProjectManager(models.Manager):
return prj
- def create(self, *args, **kwargs):
- raise Exception("Invalid call to Project.objects.create. Use Project.objects.create_project() to create a project")
-
# return single object with is_default = True
- def get_default_project(self):
+ def get_or_create_default_project(self):
projects = super(ProjectManager, self).filter(is_default = True)
+
if len(projects) > 1:
- raise Exception("Inconsistent project data: multiple " +
- "default projects (i.e. with is_default=True)")
+ raise Exception('Inconsistent project data: multiple ' +
+ 'default projects (i.e. with is_default=True)')
elif len(projects) < 1:
- raise Exception("Inconsistent project data: no default project found")
- return projects[0]
+ options = {
+ 'name': 'Command line builds',
+ 'short_description': 'Project for builds started outside Toaster',
+ 'is_default': True
+ }
+ project = Project.objects.create(**options)
+ project.save()
+
+ return project
+ else:
+ return projects[0]
class Project(models.Model):
search_allowed_fields = ['name', 'short_description', 'release__name', 'release__branch_name']
@@ -130,13 +192,15 @@ class Project(models.Model):
try:
return self.projectvariable_set.get(name="MACHINE").value
except (ProjectVariable.DoesNotExist,IndexError):
- return( "None" );
+ return None;
def get_number_of_builds(self):
- try:
- return len(Build.objects.filter( project = self.id ))
- except (Build.DoesNotExist,IndexError):
- return( 0 )
+ """Return the number of builds which have ended"""
+
+ return self.build_set.exclude(
+ Q(outcome=Build.IN_PROGRESS) |
+ Q(outcome=Build.CANCELLED)
+ ).count()
def get_last_build_id(self):
try:
@@ -180,6 +244,14 @@ class Project(models.Model):
except (Build.DoesNotExist,IndexError):
return( "not_found" )
+ def get_last_build_extensions(self):
+ """
+ Get list of file name extensions for images produced by the most
+ recent build
+ """
+ last_build = Build.objects.get(pk = self.get_last_build_id())
+ return last_build.get_image_file_extensions()
+
def get_last_imgfiles(self):
build_id = self.get_last_build_id
if (-1 == build_id):
@@ -189,40 +261,32 @@ class Project(models.Model):
except (Variable.DoesNotExist,IndexError):
return( "not_found" )
- # returns a queryset of compatible layers for a project
- def compatible_layerversions(self, release = None, layer_name = None):
- logger.warning("This function is deprecated")
- if release == None:
- release = self.release
- # layers on the same branch or layers specifically set for this project
- queryset = Layer_Version.objects.filter(((Q(up_branch__name = release.branch_name) & Q(project = None)) | Q(project = self)) & Q(build__isnull=True))
-
- if layer_name is not None:
- # we select only a layer name
- queryset = queryset.filter(layer__name = layer_name)
-
- # order by layer version priority
- queryset = queryset.filter(Q(layer_source=None) | Q(layer_source__releaselayersourcepriority__release = release)).select_related('layer_source', 'layer', 'up_branch', "layer_source__releaselayersourcepriority__priority").order_by("-layer_source__releaselayersourcepriority__priority")
-
- return queryset
-
def get_all_compatible_layer_versions(self):
""" Returns Queryset of all Layer_Versions which are compatible with
this project"""
- queryset = Layer_Version.objects.filter(
- (Q(up_branch__name=self.release.branch_name) & Q(build=None))
- | Q(project=self))
+ queryset = None
+
+ # guard on release, as it can be null
+ if self.release:
+ queryset = Layer_Version.objects.filter(
+ (Q(up_branch__name=self.release.branch_name) &
+ Q(build=None) &
+ Q(project=None)) |
+ Q(project=self))
+ else:
+ queryset = Layer_Version.objects.none()
return queryset
def get_project_layer_versions(self, pk=False):
""" Returns the Layer_Versions currently added to this project """
- layer_versions = self.projectlayer_set.all().values('layercommit')
+ layer_versions = self.projectlayer_set.all().values_list('layercommit',
+ flat=True)
if pk is False:
- return layer_versions
+ return Layer_Version.objects.filter(pk__in=layer_versions)
else:
- return layer_versions.values_list('layercommit__pk', flat=True)
+ return layer_versions
def get_available_machines(self):
@@ -303,11 +367,13 @@ class Build(models.Model):
SUCCEEDED = 0
FAILED = 1
IN_PROGRESS = 2
+ CANCELLED = 3
BUILD_OUTCOME = (
(SUCCEEDED, 'Succeeded'),
(FAILED, 'Failed'),
(IN_PROGRESS, 'In Progress'),
+ (CANCELLED, 'Cancelled'),
)
search_allowed_fields = ['machine', 'cooker_log_path', "target__target", "target__target_image_file__file_name"]
@@ -323,11 +389,40 @@ class Build(models.Model):
build_name = models.CharField(max_length=100)
bitbake_version = models.CharField(max_length=50)
+ @staticmethod
+ def get_recent(project=None):
+ """
+ Return recent builds as a list; if project is set, only return
+ builds for that project
+ """
+
+ builds = Build.objects.all()
+
+ if project:
+ builds = builds.filter(project=project)
+
+ finished_criteria = \
+ Q(outcome=Build.SUCCEEDED) | \
+ Q(outcome=Build.FAILED) | \
+ Q(outcome=Build.CANCELLED)
+
+ recent_builds = list(itertools.chain(
+ builds.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"),
+ builds.filter(finished_criteria).order_by("-completed_on")[:3]
+ ))
+
+ # add percentage done property to each build; this is used
+ # to show build progress in mrb_section.html
+ for build in recent_builds:
+ build.percentDone = build.completeper()
+
+ return recent_builds
+
def completeper(self):
tf = Task.objects.filter(build = self)
tfc = tf.count()
if tfc > 0:
- completeper = tf.exclude(order__isnull=True).count()*100/tf.count()
+ completeper = tf.exclude(order__isnull=True).count()*100/tfc
else:
completeper = 0
return completeper
@@ -339,15 +434,117 @@ class Build(models.Model):
eta += ((eta - self.started_on)*(100-completeper))/completeper
return eta
+ def get_image_file_extensions(self):
+ """
+ Get list of file name extensions for images produced by this build
+ """
+ targets = Target.objects.filter(build_id = self.id)
+ extensions = []
+
+ # pattern to match against file path for building extension string
+ pattern = re.compile('\.([^\.]+?)$')
+
+ for target in targets:
+ if (not target.is_image):
+ continue
+
+ target_image_files = Target_Image_File.objects.filter(target_id = target.id)
+
+ for target_image_file in target_image_files:
+ file_name = os.path.basename(target_image_file.file_name)
+ suffix = ''
+
+ continue_matching = True
+
+ # incrementally extract the suffix from the file path,
+ # checking it against the list of valid suffixes at each
+ # step; if the path is stripped of all potential suffix
+ # parts without matching a valid suffix, this returns all
+ # characters after the first '.' in the file name
+ while continue_matching:
+ matches = pattern.search(file_name)
+
+ if None == matches:
+ continue_matching = False
+ suffix = re.sub('^\.', '', suffix)
+ continue
+ else:
+ suffix = matches.group(1) + suffix
+
+ if suffix in Target_Image_File.SUFFIXES:
+ continue_matching = False
+ continue
+ else:
+ # reduce the file name and try to find the next
+ # segment from the path which might be part
+ # of the suffix
+ file_name = re.sub('.' + matches.group(1), '', file_name)
+ suffix = '.' + suffix
+
+ if not suffix in extensions:
+ extensions.append(suffix)
+
+ return ', '.join(extensions)
def get_sorted_target_list(self):
tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
return( tgts );
+ def get_recipes(self):
+ """
+ Get the recipes related to this build;
+ note that the related layer versions and layers are also prefetched
+ by this query, as this queryset can be sorted by these objects in the
+ build recipes view; prefetching them here removes the need
+ for another query in that view
+ """
+ layer_versions = Layer_Version.objects.filter(build=self)
+ criteria = Q(layer_version__id__in=layer_versions)
+ return Recipe.objects.filter(criteria) \
+ .select_related('layer_version', 'layer_version__layer')
+
+ def get_image_recipes(self):
+ """
+ Returns a list of image Recipes (custom and built-in) related to this
+ build, sorted by name; note that this has to be done in two steps, as
+ there's no way to get all the custom image recipes and image recipes
+ in one query
+ """
+ custom_image_recipes = self.get_custom_image_recipes()
+ custom_image_recipe_names = custom_image_recipes.values_list('name', flat=True)
+
+ not_custom_image_recipes = ~Q(name__in=custom_image_recipe_names) & \
+ Q(is_image=True)
+
+ built_image_recipes = self.get_recipes().filter(not_custom_image_recipes)
+
+ # append to the custom image recipes and sort
+ customisable_image_recipes = list(
+ itertools.chain(custom_image_recipes, built_image_recipes)
+ )
+
+ return sorted(customisable_image_recipes, key=lambda recipe: recipe.name)
+
+ def get_custom_image_recipes(self):
+ """
+ Returns a queryset of CustomImageRecipes related to this build,
+ sorted by name
+ """
+ built_recipe_names = self.get_recipes().values_list('name', flat=True)
+ criteria = Q(name__in=built_recipe_names) & Q(project=self.project)
+ queryset = CustomImageRecipe.objects.filter(criteria).order_by('name')
+ return queryset
+
def get_outcome_text(self):
return Build.BUILD_OUTCOME[int(self.outcome)][1]
@property
+ def failed_tasks(self):
+ """ Get failed tasks for the build """
+ tasks = self.task_build.all()
+ return tasks.filter(order__gt=0, outcome=Task.OUTCOME_FAILED)
+
+ @property
def errors(self):
return (self.logmessage_set.filter(level=LogMessage.ERROR) |
self.logmessage_set.filter(level=LogMessage.EXCEPTION) |
@@ -358,8 +555,26 @@ class Build(models.Model):
return self.logmessage_set.filter(level=LogMessage.WARNING)
@property
+ def timespent(self):
+ return self.completed_on - self.started_on
+
+ @property
def timespent_seconds(self):
- return (self.completed_on - self.started_on).total_seconds()
+ return self.timespent.total_seconds()
+
+ @property
+ def target_labels(self):
+ """
+ Sorted (a-z) "target1:task, target2, target3" etc. string for all
+ targets in this build
+ """
+ targets = self.target_set.all()
+ target_labels = [target.target +
+ (':' + target.task if target.task else '')
+ for target in targets]
+ target_labels.sort()
+
+ return target_labels
def get_current_status(self):
"""
@@ -399,6 +614,8 @@ class BuildArtifact(models.Model):
return self.file_name
+ def get_basename(self):
+ return os.path.basename(self.file_name)
def is_available(self):
return self.build.buildrequest.environment.has_artifact(self.file_name)
@@ -424,10 +641,25 @@ class Target(models.Model):
return self.target
class Target_Image_File(models.Model):
+ # valid suffixes for image files produced by a build
+ SUFFIXES = {
+ 'btrfs', 'cpio', 'cpio.gz', 'cpio.lz4', 'cpio.lzma', 'cpio.xz',
+ 'cramfs', 'elf', 'ext2', 'ext2.bz2', 'ext2.gz', 'ext2.lzma', 'ext4',
+ 'ext4.gz', 'ext3', 'ext3.gz', 'hddimg', 'iso', 'jffs2', 'jffs2.sum',
+ 'squashfs', 'squashfs-lzo', 'squashfs-xz', 'tar.bz2', 'tar.lz4',
+ 'tar.xz', 'tartar.gz', 'ubi', 'ubifs', 'vmdk'
+ }
+
target = models.ForeignKey(Target)
file_name = models.FilePathField(max_length=254)
file_size = models.IntegerField()
+ @property
+ def suffix(self):
+ filename, suffix = os.path.splitext(self.file_name)
+ suffix = suffix.lstrip('.')
+ return suffix
+
class Target_File(models.Model):
ITYPE_REGULAR = 1
ITYPE_DIRECTORY = 2
@@ -552,9 +784,23 @@ class Task(models.Model):
work_directory = models.FilePathField(max_length=255, blank=True)
script_type = models.IntegerField(choices=TASK_CODING, default=CODING_NA)
line_number = models.IntegerField(default=0)
- disk_io = models.IntegerField(null=True)
- cpu_usage = models.DecimalField(max_digits=8, decimal_places=2, null=True)
+
+ # start/end times
+ started = models.DateTimeField(null=True)
+ ended = models.DateTimeField(null=True)
+
+ # in seconds; this is stored to enable sorting
elapsed_time = models.DecimalField(max_digits=8, decimal_places=2, null=True)
+
+ # in bytes; note that disk_io is stored to enable sorting
+ disk_io = models.IntegerField(null=True)
+ disk_io_read = models.IntegerField(null=True)
+ disk_io_write = models.IntegerField(null=True)
+
+ # in seconds
+ cpu_time_user = models.DecimalField(max_digits=8, decimal_places=2, null=True)
+ cpu_time_system = models.DecimalField(max_digits=8, decimal_places=2, null=True)
+
sstate_result = models.IntegerField(choices=SSTATE_RESULT, default=SSTATE_NA)
message = models.CharField(max_length=240)
logfile = models.FilePathField(max_length=255, blank=True)
@@ -589,11 +835,55 @@ class Package(models.Model):
section = models.CharField(max_length=80, blank=True)
license = models.CharField(max_length=80, blank=True)
+ @property
+ def is_locale_package(self):
+ """ Returns True if this package is identifiable as a locale package """
+ if self.name.find('locale') != -1:
+ return True
+ return False
+
+ @property
+ def is_packagegroup(self):
+ """ Returns True is this package is identifiable as a packagegroup """
+ if self.name.find('packagegroup') != -1:
+ return True
+ return False
+
+class CustomImagePackage(Package):
+ # CustomImageRecipe fields to track pacakges appended,
+ # included and excluded from a CustomImageRecipe
+ recipe_includes = models.ManyToManyField('CustomImageRecipe',
+ related_name='includes_set')
+ recipe_excludes = models.ManyToManyField('CustomImageRecipe',
+ related_name='excludes_set')
+ recipe_appends = models.ManyToManyField('CustomImageRecipe',
+ related_name='appends_set')
+
+
+
class Package_DependencyManager(models.Manager):
use_for_related_fields = True
- def get_query_set(self):
- return super(Package_DependencyManager, self).get_query_set().exclude(package_id = F('depends_on__id'))
+ def get_queryset(self):
+ return super(Package_DependencyManager, self).get_queryset().exclude(package_id = F('depends_on__id'))
+
+ def get_total_source_deps_size(self):
+ """ Returns the total file size of all the packages that depend on
+ thispackage.
+ """
+ return self.all().aggregate(Sum('depends_on__size'))
+
+ def get_total_revdeps_size(self):
+ """ Returns the total file size of all the packages that depend on
+ this package.
+ """
+ return self.all().aggregate(Sum('package_id__size'))
+
+
+ def all_depends(self):
+ """ Returns just the depends packages and not any other dep_type """
+ return self.filter(Q(dep_type=Package_Dependency.TYPE_RDEPENDS) |
+ Q(dep_type=Package_Dependency.TYPE_TRDEPENDS))
class Package_Dependency(models.Model):
TYPE_RDEPENDS = 0
@@ -693,8 +983,12 @@ class Recipe(models.Model):
class Recipe_DependencyManager(models.Manager):
use_for_related_fields = True
- def get_query_set(self):
- return super(Recipe_DependencyManager, self).get_query_set().exclude(recipe_id = F('depends_on__id'))
+ def get_queryset(self):
+ return super(Recipe_DependencyManager, self).get_queryset().exclude(recipe_id = F('depends_on__id'))
+
+class Provides(models.Model):
+ name = models.CharField(max_length=100)
+ recipe = models.ForeignKey(Recipe)
class Recipe_Dependency(models.Model):
TYPE_DEPENDS = 0
@@ -706,6 +1000,7 @@ class Recipe_Dependency(models.Model):
)
recipe = models.ForeignKey(Recipe, related_name='r_dependencies_recipe')
depends_on = models.ForeignKey(Recipe, related_name='r_dependencies_depends')
+ via = models.ForeignKey(Provides, null=True, default=None)
dep_type = models.IntegerField(choices=DEPENDS_TYPE)
objects = Recipe_DependencyManager()
@@ -895,8 +1190,7 @@ class LayerIndexLayerSource(LayerSource):
# update layers
layers_info = _get_json_response(apilinks['layerItems'])
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(False)
+
for li in layers_info:
# Special case for the openembedded-core layer
if li['name'] == oe_core_layer:
@@ -928,17 +1222,12 @@ class LayerIndexLayerSource(LayerSource):
l.description = li['description']
l.save()
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(True)
-
# update layerbranches/layer_versions
logger.debug("Fetching layer information")
layerbranches_info = _get_json_response(apilinks['layerBranches']
+ "?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] ))
)
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(False)
for lbi in layerbranches_info:
lv, created = Layer_Version.objects.get_or_create(layer_source = self,
up_id = lbi['id'],
@@ -951,14 +1240,10 @@ class LayerIndexLayerSource(LayerSource):
lv.commit = lbi['actual_branch']
lv.dirpath = lbi['vcs_subdir']
lv.save()
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(True)
# update layer dependencies
layerdependencies_info = _get_json_response(apilinks['layerDependencies'])
dependlist = {}
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(False)
for ldi in layerdependencies_info:
try:
lv = Layer_Version.objects.get(layer_source = self, up_id = ldi['layerbranch'])
@@ -976,8 +1261,6 @@ class LayerIndexLayerSource(LayerSource):
LayerVersionDependency.objects.filter(layer_version = lv).delete()
for lvd in dependlist[lv]:
LayerVersionDependency.objects.get_or_create(layer_version = lv, depends_on = lvd)
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(True)
# update machines
@@ -986,8 +1269,6 @@ class LayerIndexLayerSource(LayerSource):
+ "?filter=layerbranch:%s" % "OR".join(map(lambda x: str(x.up_id), Layer_Version.objects.filter(layer_source = self)))
)
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(False)
for mi in machines_info:
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']))
mo.up_date = mi['updated']
@@ -995,16 +1276,11 @@ class LayerIndexLayerSource(LayerSource):
mo.description = mi['description']
mo.save()
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(True)
-
# update recipes; paginate by layer version / layer branch
logger.debug("Fetching target information")
recipes_info = _get_json_response(apilinks['recipes']
+ "?filter=layerbranch:%s" % "OR".join(map(lambda x: str(x.up_id), Layer_Version.objects.filter(layer_source = self)))
)
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(False)
for ri in recipes_info:
try:
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']))
@@ -1026,8 +1302,6 @@ class LayerIndexLayerSource(LayerSource):
except IntegrityError as e:
logger.debug("Failed saving recipe, ignoring: %s (%s:%s)" % (e, ro.layer_version, ri['filepath']+"/"+ri['filename']))
ro.delete()
- if not connection.features.autocommits_when_autocommit_is_off:
- transaction.set_autocommit(True)
class BitbakeVersion(models.Model):
@@ -1110,6 +1384,9 @@ class Layer(models.Model):
# LayerCommit class is synced with layerindex.LayerBranch
class Layer_Version(models.Model):
+ """
+ A Layer_Version either belongs to a single project or no project
+ """
search_allowed_fields = ["layer__name", "layer__summary", "layer__description", "layer__vcs_url", "dirpath", "up_branch__name", "commit", "branch"]
build = models.ForeignKey(Build, related_name='layer_version_build', default = None, null = True)
layer = models.ForeignKey(Layer, related_name='layer_version_layer')
@@ -1178,7 +1455,9 @@ class Layer_Version(models.Model):
return self._handle_url_path(self.layer.vcs_web_tree_base_url, '')
def get_equivalents_wpriority(self, project):
- return project.compatible_layerversions(layer_name = self.layer.name)
+ layer_versions = project.get_all_compatible_layer_versions()
+ filtered = layer_versions.filter(layer__name = self.layer.name)
+ return filtered.order_by("-layer_source__releaselayersourcepriority__priority")
def get_vcs_reference(self):
if self.branch is not None and len(self.branch) > 0:
@@ -1187,7 +1466,7 @@ class Layer_Version(models.Model):
return self.up_branch.name
if self.commit is not None and len(self.commit) > 0:
return self.commit
- return ("Cannot determine the vcs_reference for layer version %s" % vars(self))
+ return 'N/A'
def get_detailspage_url(self, project_id):
return reverse('layerdetails', args=(project_id, self.pk))
@@ -1238,14 +1517,142 @@ class ProjectLayer(models.Model):
class Meta:
unique_together = (("project", "layercommit"),)
-class CustomImageRecipe(models.Model):
- name = models.CharField(max_length=100)
- base_recipe = models.ForeignKey(Recipe)
- packages = models.ManyToManyField(Package)
+class CustomImageRecipe(Recipe):
+
+ # CustomImageRecipe's belong to layers called:
+ LAYER_NAME = "toaster-custom-images"
+
+ search_allowed_fields = ['name']
+ base_recipe = models.ForeignKey(Recipe, related_name='based_on_recipe')
project = models.ForeignKey(Project)
+ last_updated = models.DateTimeField(null=True, default=None)
+
+ def get_last_successful_built_target(self):
+ """ Return the last successful built target object if one exists
+ otherwise return None """
+ return Target.objects.filter(Q(build__outcome=Build.SUCCEEDED) &
+ Q(build__project=self.project) &
+ Q(target=self.name)).last()
+
+ def update_package_list(self):
+ """ Update the package list from the last good build of this
+ CustomImageRecipe
+ """
+ # Check if we're aldready up-to-date or not
+ target = self.get_last_successful_built_target()
+ if target == None:
+ # So we've never actually built this Custom recipe but what about
+ # the recipe it's based on?
+ target = \
+ Target.objects.filter(Q(build__outcome=Build.SUCCEEDED) &
+ Q(build__project=self.project) &
+ Q(target=self.base_recipe.name)).last()
+ if target == None:
+ return
+
+ if target.build.completed_on == self.last_updated:
+ return
- class Meta:
- unique_together = ("name", "project")
+ self.includes_set.clear()
+
+ excludes_list = self.excludes_set.values_list('name', flat=True)
+ appends_list = self.appends_set.values_list('name', flat=True)
+
+ built_packages_list = \
+ target.target_installed_package_set.values_list('package__name',
+ flat=True)
+ for built_package in built_packages_list:
+ # Is the built package in the custom packages list?
+ if built_package in excludes_list:
+ continue
+
+ if built_package in appends_list:
+ continue
+
+ cust_img_p = \
+ CustomImagePackage.objects.get(name=built_package)
+ self.includes_set.add(cust_img_p)
+
+
+ self.last_updated = target.build.completed_on
+ self.save()
+
+ def get_all_packages(self):
+ """Get the included packages and any appended packages"""
+ self.update_package_list()
+
+ return CustomImagePackage.objects.filter((Q(recipe_appends=self) |
+ Q(recipe_includes=self)) &
+ ~Q(recipe_excludes=self))
+
+
+ def generate_recipe_file_contents(self):
+ """Generate the contents for the recipe file."""
+ # If we have no excluded packages we only need to _append
+ if self.excludes_set.count() == 0:
+ packages_conf = "IMAGE_INSTALL_append = \" "
+
+ for pkg in self.appends_set.all():
+ packages_conf += pkg.name+' '
+ else:
+ packages_conf = "IMAGE_FEATURES =\"\"\nIMAGE_INSTALL = \""
+ # We add all the known packages to be built by this recipe apart
+ # from locale packages which are are controlled with IMAGE_LINGUAS.
+ for pkg in self.get_all_packages().exclude(
+ name__icontains="locale"):
+ packages_conf += pkg.name+' '
+
+ packages_conf += "\""
+ try:
+ base_recipe = open("%s/%s" %
+ (self.base_recipe.layer_version.dirpath,
+ self.base_recipe.file_path), 'r').read()
+ except IOError:
+ # The path may now be the full path if the recipe has been built
+ base_recipe = open(self.base_recipe.file_path, 'r').read()
+
+ # Add a special case for when the recipe we have based a custom image
+ # recipe on requires another recipe.
+ # For example:
+ # "require core-image-minimal.bb" is changed to:
+ # "require recipes-core/images/core-image-minimal.bb"
+
+ req_search = re.search(r'(require\s+)(.+\.bb\s*$)',
+ base_recipe,
+ re.MULTILINE)
+ if req_search:
+ require_filename = req_search.group(2).strip()
+
+ corrected_location = Recipe.objects.filter(
+ Q(layer_version=self.base_recipe.layer_version) &
+ Q(file_path__icontains=require_filename)).last().file_path
+
+ new_require_line = "require %s" % corrected_location
+
+ base_recipe = \
+ base_recipe.replace(req_search.group(0), new_require_line)
+
+
+ info = {"date" : timezone.now().strftime("%Y-%m-%d %H:%M:%S"),
+ "base_recipe" : base_recipe,
+ "recipe_name" : self.name,
+ "base_recipe_name" : self.base_recipe.name,
+ "license" : self.license,
+ "summary" : self.summary,
+ "description" : self.description,
+ "packages_conf" : packages_conf.strip(),
+ }
+
+ recipe_contents = ("# Original recipe %(base_recipe_name)s \n"
+ "%(base_recipe)s\n\n"
+ "# Recipe %(recipe_name)s \n"
+ "# Customisation Generated by Toaster on %(date)s\n"
+ "SUMMARY = \"%(summary)s\"\n"
+ "DESCRIPTION = \"%(description)s\"\n"
+ "LICENSE = \"%(license)s\"\n"
+ "%(packages_conf)s") % info
+
+ return recipe_contents
class ProjectVariable(models.Model):
project = models.ForeignKey(Project)
@@ -1301,7 +1708,7 @@ class LogMessage(models.Model):
lineno = models.IntegerField(null=True)
def __str__(self):
- return "%s %s %s" % (self.get_level_display(), self.message, self.build)
+ return force_bytes('%s %s %s' % (self.get_level_display(), self.message, self.build))
def invalidate_cache(**kwargs):
from django.core.cache import cache
@@ -1312,3 +1719,4 @@ def invalidate_cache(**kwargs):
django.db.models.signals.post_save.connect(invalidate_cache)
django.db.models.signals.post_delete.connect(invalidate_cache)
+django.db.models.signals.m2m_changed.connect(invalidate_cache)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/__init__.py b/yocto-poky/bitbake/lib/toaster/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/__init__.py
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/README b/yocto-poky/bitbake/lib/toaster/tests/browser/README
new file mode 100644
index 000000000..63e8169c1
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/README
@@ -0,0 +1,41 @@
+# Running Toaster's browser-based test suite
+
+These tests require Selenium to be installed in your Python environment.
+
+The simplest way to install this is via pip:
+
+ pip install selenium
+
+Alternatively, if you used pip to install the libraries required by Toaster,
+selenium will already be installed.
+
+To run tests against Chrome:
+
+* Download chromedriver for your host OS from
+ https://code.google.com/p/chromedriver/downloads/list
+* On *nix systems, put chromedriver on PATH
+* On Windows, put chromedriver.exe in the same directory as chrome.exe
+
+To run tests against PhantomJS (headless):
+
+* Download and install PhantomJS:
+ http://phantomjs.org/download.html
+* On *nix systems, put phantomjs on PATH
+* Not tested on Windows
+
+Firefox should work without requiring additional software to be installed.
+
+The test case will instantiate a Selenium driver set by the
+TOASTER_TESTS_BROWSER environment variable, or Chrome if this is not specified.
+
+Available drivers:
+
+* chrome (default)
+* firefox
+* ie
+* phantomjs
+
+e.g. to run the test suite with phantomjs where you have phantomjs installed
+in /home/me/apps/phantomjs:
+
+PATH=/home/me/apps/phantomjs/bin:$PATH TOASTER_TESTS_BROWSER=phantomjs manage.py test tests.browser
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/__init__.py b/yocto-poky/bitbake/lib/toaster/tests/browser/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/__init__.py
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/selenium_helpers.py b/yocto-poky/bitbake/lib/toaster/tests/browser/selenium_helpers.py
new file mode 100644
index 000000000..56dbe2b34
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/selenium_helpers.py
@@ -0,0 +1,204 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# The Wait class and some of SeleniumDriverHelper and SeleniumTestCase are
+# modified from Patchwork, released under the same licence terms as Toaster:
+# https://github.com/dlespiau/patchwork/blob/master/patchwork/tests.browser.py
+
+"""
+Helper methods for creating Toaster Selenium tests which run within
+the context of Django unit tests.
+"""
+
+import os
+import time
+
+from django.contrib.staticfiles.testing import StaticLiveServerTestCase
+from selenium import webdriver
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.common.exceptions import NoSuchElementException, \
+ StaleElementReferenceException, TimeoutException
+
+def create_selenium_driver(browser='chrome'):
+ # set default browser string based on env (if available)
+ env_browser = os.environ.get('TOASTER_TESTS_BROWSER')
+ if env_browser:
+ browser = env_browser
+
+ if browser == 'chrome':
+ return webdriver.Chrome(
+ service_args=["--verbose", "--log-path=selenium.log"]
+ )
+ elif browser == 'firefox':
+ return webdriver.Firefox()
+ elif browser == 'ie':
+ return webdriver.Ie()
+ elif browser == 'phantomjs':
+ return webdriver.PhantomJS()
+ else:
+ msg = 'Selenium driver for browser %s is not available' % browser
+ raise RuntimeError(msg)
+
+class Wait(WebDriverWait):
+ """
+ Subclass of WebDriverWait with predetermined timeout and poll
+ frequency. Also deals with a wider variety of exceptions.
+ """
+ _TIMEOUT = 10
+ _POLL_FREQUENCY = 0.5
+
+ def __init__(self, driver):
+ super(Wait, self).__init__(driver, self._TIMEOUT, self._POLL_FREQUENCY)
+
+ def until(self, method, message=''):
+ """
+ Calls the method provided with the driver as an argument until the
+ return value is not False.
+ """
+
+ end_time = time.time() + self._timeout
+ while True:
+ try:
+ value = method(self._driver)
+ if value:
+ return value
+ except NoSuchElementException:
+ pass
+ except StaleElementReferenceException:
+ pass
+
+ time.sleep(self._poll)
+ if time.time() > end_time:
+ break
+
+ raise TimeoutException(message)
+
+ def until_not(self, method, message=''):
+ """
+ Calls the method provided with the driver as an argument until the
+ return value is False.
+ """
+
+ end_time = time.time() + self._timeout
+ while True:
+ try:
+ value = method(self._driver)
+ if not value:
+ return value
+ except NoSuchElementException:
+ return True
+ except StaleElementReferenceException:
+ pass
+
+ time.sleep(self._poll)
+ if time.time() > end_time:
+ break
+
+ raise TimeoutException(message)
+
+class SeleniumTestCase(StaticLiveServerTestCase):
+ """
+ NB StaticLiveServerTestCase is used as the base test case so that
+ static files are served correctly in a Selenium test run context; see
+ https://docs.djangoproject.com/en/1.9/ref/contrib/staticfiles/#specialized-test-case-to-support-live-testing
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ """ Create a webdriver driver at the class level """
+
+ super(SeleniumTestCase, cls).setUpClass()
+
+ # instantiate the Selenium webdriver once for all the test methods
+ # in this test case
+ cls.driver = create_selenium_driver()
+
+ @classmethod
+ def tearDownClass(cls):
+ """ Clean up webdriver driver """
+
+ cls.driver.quit()
+ super(SeleniumTestCase, cls).tearDownClass()
+
+ def get(self, url):
+ """
+ Selenium requires absolute URLs, so convert Django URLs returned
+ by resolve() or similar to absolute ones and get using the
+ webdriver instance.
+
+ url: a relative URL
+ """
+ abs_url = '%s%s' % (self.live_server_url, url)
+ self.driver.get(abs_url)
+
+ def find(self, selector):
+ """ Find single element by CSS selector """
+ return self.driver.find_element_by_css_selector(selector)
+
+ def find_all(self, selector):
+ """ Find all elements matching CSS selector """
+ return self.driver.find_elements_by_css_selector(selector)
+
+ def focused_element(self):
+ """ Return the element which currently has focus on the page """
+ return self.driver.switch_to.active_element
+
+ def wait_until_present(self, selector):
+ """ Wait until element matching CSS selector is on the page """
+ is_present = lambda driver: self.find(selector)
+ msg = 'An element matching "%s" should be on the page' % selector
+ element = Wait(self.driver).until(is_present, msg)
+ return element
+
+ def wait_until_visible(self, selector):
+ """ Wait until element matching CSS selector is visible on the page """
+ is_visible = lambda driver: self.find(selector).is_displayed()
+ msg = 'An element matching "%s" should be visible' % selector
+ Wait(self.driver).until(is_visible, msg)
+ return self.find(selector)
+
+ def wait_until_focused(self, selector):
+ """ Wait until element matching CSS selector has focus """
+ is_focused = \
+ lambda driver: self.find(selector) == self.focused_element()
+ msg = 'An element matching "%s" should be focused' % selector
+ Wait(self.driver).until(is_focused, msg)
+ return self.find(selector)
+
+ def enter_text(self, selector, value):
+ """ Insert text into element matching selector """
+ # note that keyup events don't occur until the element is clicked
+ # (in the case of <input type="text"...>, for example), so simulate
+ # user clicking the element before inserting text into it
+ field = self.click(selector)
+
+ field.send_keys(value)
+ return field
+
+ def click(self, selector):
+ """ Click on element which matches CSS selector """
+ element = self.wait_until_visible(selector)
+ element.click()
+ return element
+
+ def get_page_source(self):
+ """ Get raw HTML for the current page """
+ return self.driver.page_source
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_all_builds_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_all_builds_page.py
new file mode 100644
index 000000000..e4223f482
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_all_builds_page.py
@@ -0,0 +1,143 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, Build, Target
+
+class TestAllBuildsPage(SeleniumTestCase):
+ """ Tests for all builds page /builds/ """
+
+ PROJECT_NAME = 'test project'
+ CLI_BUILDS_PROJECT_NAME = 'command line builds'
+
+ def setUp(self):
+ bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
+ branch='master', dirpath='')
+ release = Release.objects.create(name='release1',
+ bitbake_version=bbv)
+ self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
+ release=release)
+ self.default_project = Project.objects.create_project(
+ name=self.CLI_BUILDS_PROJECT_NAME,
+ release=release
+ )
+ self.default_project.is_default = True
+ self.default_project.save()
+
+ # parameters for builds to associate with the projects
+ now = timezone.now()
+
+ self.project1_build_success = {
+ 'project': self.project1,
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.SUCCEEDED
+ }
+
+ self.default_project_build_success = {
+ 'project': self.default_project,
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.SUCCEEDED
+ }
+
+ def test_show_tasks_with_suffix(self):
+ """ Task should be shown as suffix on build name """
+ build = Build.objects.create(**self.project1_build_success)
+ target = 'bash'
+ task = 'clean'
+ Target.objects.create(build=build, target=target, task=task)
+
+ url = reverse('all-builds')
+ self.get(url)
+ self.wait_until_present('td[class="target"]')
+
+ cell = self.find('td[class="target"]')
+ content = cell.get_attribute('innerHTML')
+ expected_text = '%s:%s' % (target, task)
+
+ self.assertTrue(re.search(expected_text, content),
+ '"target" cell should contain text %s' % expected_text)
+
+ def test_rebuild_buttons(self):
+ """
+ Test 'Rebuild' buttons in recent builds section
+
+ 'Rebuild' button should not be shown for command-line builds,
+ but should be shown for other builds
+ """
+ build1 = Build.objects.create(**self.project1_build_success)
+ default_build = Build.objects.create(**self.default_project_build_success)
+
+ url = reverse('all-builds')
+ self.get(url)
+
+ # shouldn't see a run again button for command-line builds
+ selector = 'div[data-latest-build-result="%s"] button' % default_build.id
+ run_again_button = self.find_all(selector)
+ self.assertEqual(len(run_again_button), 0,
+ 'should not see a run again button for cli builds')
+
+ # should see a run again button for non-command-line builds
+ selector = 'div[data-latest-build-result="%s"] button' % build1.id
+ run_again_button = self.find_all(selector)
+ self.assertEqual(len(run_again_button), 1,
+ 'should see a run again button for non-cli builds')
+
+ def test_tooltips_on_project_name(self):
+ """
+ Test tooltips shown next to project name in the main table
+
+ A tooltip should be present next to the command line
+ builds project name in the all builds page, but not for
+ other projects
+ """
+ Build.objects.create(**self.project1_build_success)
+ Build.objects.create(**self.default_project_build_success)
+
+ url = reverse('all-builds')
+ self.get(url)
+
+ # get the project name cells from the table
+ cells = self.find_all('#allbuildstable td[class="project"]')
+
+ selector = 'i.get-help'
+
+ for cell in cells:
+ content = cell.get_attribute('innerHTML')
+ help_icons = cell.find_elements_by_css_selector(selector)
+
+ if re.search(self.PROJECT_NAME, content):
+ # no help icon next to non-cli project name
+ msg = 'should not be a help icon for non-cli builds name'
+ self.assertEqual(len(help_icons), 0, msg)
+ elif re.search(self.CLI_BUILDS_PROJECT_NAME, content):
+ # help icon next to cli project name
+ msg = 'should be a help icon for cli builds name'
+ self.assertEqual(len(help_icons), 1, msg)
+ else:
+ msg = 'found unexpected project name cell in all builds table'
+ self.fail(msg)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_all_projects_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_all_projects_page.py
new file mode 100644
index 000000000..ed8e620db
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_all_projects_page.py
@@ -0,0 +1,214 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, Build
+from orm.models import ProjectVariable
+
+class TestAllProjectsPage(SeleniumTestCase):
+ """ Browser tests for projects page /projects/ """
+
+ PROJECT_NAME = 'test project'
+ CLI_BUILDS_PROJECT_NAME = 'command line builds'
+ MACHINE_NAME = 'delorean'
+
+ def setUp(self):
+ """ Add default project manually """
+ project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
+ self.default_project = project
+ self.default_project.is_default = True
+ self.default_project.save()
+
+ # this project is only set for some of the tests
+ self.project = None
+
+ self.release = None
+
+ def _add_build_to_default_project(self):
+ """ Add a build to the default project (not used in all tests) """
+ now = timezone.now()
+ build = Build.objects.create(project=self.default_project,
+ started_on=now,
+ completed_on=now)
+ build.save()
+
+ def _add_non_default_project(self):
+ """ Add another project """
+ bbv = BitbakeVersion.objects.create(name='test bbv', giturl='/tmp/',
+ branch='master', dirpath='')
+ self.release = Release.objects.create(name='test release',
+ branch_name='master',
+ bitbake_version=bbv)
+ self.project = Project.objects.create_project(self.PROJECT_NAME, self.release)
+ self.project.is_default = False
+ self.project.save()
+
+ # fake the MACHINE variable
+ project_var = ProjectVariable.objects.create(project=self.project,
+ name='MACHINE',
+ value=self.MACHINE_NAME)
+ project_var.save()
+
+ def _get_row_for_project(self, project_name):
+ """ Get the HTML row for a project, or None if not found """
+ self.wait_until_present('#projectstable tbody tr')
+ rows = self.find_all('#projectstable tbody tr')
+
+ # find the row with a project name matching the one supplied
+ found_row = None
+ for row in rows:
+ if re.search(project_name, row.get_attribute('innerHTML')):
+ found_row = row
+ break
+
+ return found_row
+
+ def test_default_project_hidden(self):
+ """
+ The default project should be hidden if it has no builds
+ and we should see the "no results" area
+ """
+ url = reverse('all-projects')
+ self.get(url)
+ self.wait_until_visible('#no-results-projectstable')
+
+ rows = self.find_all('#projectstable tbody tr')
+ self.assertEqual(len(rows), 0, 'should be no projects displayed')
+
+ def test_default_project_has_build(self):
+ """ The default project should be shown if it has builds """
+ self._add_build_to_default_project()
+
+ url = reverse('all-projects')
+ self.get(url)
+
+ default_project_row = self._get_row_for_project(self.default_project.name)
+
+ self.assertNotEqual(default_project_row, None,
+ 'default project "cli builds" should be in page')
+
+ def test_default_project_release(self):
+ """
+ The release for the default project should display as
+ 'Not applicable'
+ """
+ # need a build, otherwise project doesn't display at all
+ self._add_build_to_default_project()
+
+ # another project to test, which should show release
+ self._add_non_default_project()
+
+ self.get(reverse('all-projects'))
+
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(self.default_project.name)
+
+ # check the release text for the default project
+ selector = 'span[data-project-field="release"] span.muted'
+ element = default_project_row.find_element_by_css_selector(selector)
+ text = element.text.strip()
+ self.assertEqual(text, 'Not applicable',
+ 'release should be "not applicable" for default project')
+
+ # find the row for the default project
+ other_project_row = self._get_row_for_project(self.project.name)
+
+ # check the link in the release cell for the other project
+ selector = 'span[data-project-field="release"] a'
+ element = other_project_row.find_element_by_css_selector(selector)
+ text = element.text.strip()
+ self.assertEqual(text, self.release.name,
+ 'release name should be shown for non-default project')
+
+ def test_default_project_machine(self):
+ """
+ The machine for the default project should display as
+ 'Not applicable'
+ """
+ # need a build, otherwise project doesn't display at all
+ self._add_build_to_default_project()
+
+ # another project to test, which should show machine
+ self._add_non_default_project()
+
+ self.get(reverse('all-projects'))
+
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(self.default_project.name)
+
+ # check the machine cell for the default project
+ selector = 'span[data-project-field="machine"] span.muted'
+ element = default_project_row.find_element_by_css_selector(selector)
+ text = element.text.strip()
+ self.assertEqual(text, 'Not applicable',
+ 'machine should be not applicable for default project')
+
+ # find the row for the default project
+ other_project_row = self._get_row_for_project(self.project.name)
+
+ # check the link in the machine cell for the other project
+ selector = 'span[data-project-field="machine"] a'
+ element = other_project_row.find_element_by_css_selector(selector)
+ text = element.text.strip()
+ self.assertEqual(text, self.MACHINE_NAME,
+ 'machine name should be shown for non-default project')
+
+ def test_project_page_links(self):
+ """
+ Test that links for the default project point to the builds
+ page /projects/X/builds for that project, and that links for
+ other projects point to their configuration pages /projects/X/
+ """
+
+ # need a build, otherwise project doesn't display at all
+ self._add_build_to_default_project()
+
+ # another project to test
+ self._add_non_default_project()
+
+ self.get(reverse('all-projects'))
+
+ # find the row for the default project
+ default_project_row = self._get_row_for_project(self.default_project.name)
+
+ # check the link on the name field
+ selector = 'span[data-project-field="name"] a'
+ element = default_project_row.find_element_by_css_selector(selector)
+ link_url = element.get_attribute('href').strip()
+ expected_url = reverse('projectbuilds', args=(self.default_project.id,))
+ msg = 'link on default project name should point to builds but was %s' % link_url
+ self.assertTrue(link_url.endswith(expected_url), msg)
+
+ # find the row for the other project
+ other_project_row = self._get_row_for_project(self.project.name)
+
+ # check the link for the other project
+ selector = 'span[data-project-field="name"] a'
+ element = other_project_row.find_element_by_css_selector(selector)
+ link_url = element.get_attribute('href').strip()
+ expected_url = reverse('project', args=(self.project.id,))
+ msg = 'link on project name should point to configuration but was %s' % link_url
+ self.assertTrue(link_url.endswith(expected_url), msg)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py
new file mode 100644
index 000000000..5e0874947
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_builddashboard_page.py
@@ -0,0 +1,251 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+
+from selenium_helpers import SeleniumTestCase
+
+from orm.models import Project, Release, BitbakeVersion, Build, LogMessage
+from orm.models import Layer, Layer_Version, Recipe, CustomImageRecipe
+
+class TestBuildDashboardPage(SeleniumTestCase):
+ """ Tests for the build dashboard /build/X """
+
+ def setUp(self):
+ bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
+ branch='master', dirpath="")
+ release = Release.objects.create(name='release1',
+ bitbake_version=bbv)
+ project = Project.objects.create_project(name='test project',
+ release=release)
+
+ now = timezone.now()
+
+ self.build1 = Build.objects.create(project=project,
+ started_on=now,
+ completed_on=now)
+
+ self.build2 = Build.objects.create(project=project,
+ started_on=now,
+ completed_on=now)
+
+ # exception
+ msg1 = 'an exception was thrown'
+ self.exception_message = LogMessage.objects.create(
+ build=self.build1,
+ level=LogMessage.EXCEPTION,
+ message=msg1
+ )
+
+ # critical
+ msg2 = 'a critical error occurred'
+ self.critical_message = LogMessage.objects.create(
+ build=self.build1,
+ level=LogMessage.CRITICAL,
+ message=msg2
+ )
+
+ # recipes related to the build, for testing the edit custom image/new
+ # custom image buttons
+ layer = Layer.objects.create(name='alayer')
+ layer_version = Layer_Version.objects.create(
+ layer=layer, build=self.build1
+ )
+
+ # image recipes
+ self.image_recipe1 = Recipe.objects.create(
+ name='recipeA',
+ layer_version=layer_version,
+ file_path='/foo/recipeA.bb',
+ is_image=True
+ )
+ self.image_recipe2 = Recipe.objects.create(
+ name='recipeB',
+ layer_version=layer_version,
+ file_path='/foo/recipeB.bb',
+ is_image=True
+ )
+
+ # custom image recipes for this project
+ self.custom_image_recipe1 = CustomImageRecipe.objects.create(
+ name='customRecipeY',
+ project=project,
+ layer_version=layer_version,
+ file_path='/foo/customRecipeY.bb',
+ base_recipe=self.image_recipe1,
+ is_image=True
+ )
+ self.custom_image_recipe2 = CustomImageRecipe.objects.create(
+ name='customRecipeZ',
+ project=project,
+ layer_version=layer_version,
+ file_path='/foo/customRecipeZ.bb',
+ base_recipe=self.image_recipe2,
+ is_image=True
+ )
+
+ # custom image recipe for a different project (to test filtering
+ # of image recipes and custom image recipes is correct: this shouldn't
+ # show up in either query against self.build1)
+ self.custom_image_recipe3 = CustomImageRecipe.objects.create(
+ name='customRecipeOmega',
+ project=Project.objects.create(name='baz', release=release),
+ layer_version=Layer_Version.objects.create(
+ layer=layer, build=self.build2
+ ),
+ file_path='/foo/customRecipeOmega.bb',
+ base_recipe=self.image_recipe2,
+ is_image=True
+ )
+
+ # another non-image recipe (to test filtering of image recipes and
+ # custom image recipes is correct: this shouldn't show up in either
+ # for any build)
+ self.non_image_recipe = Recipe.objects.create(
+ name='nonImageRecipe',
+ layer_version=layer_version,
+ file_path='/foo/nonImageRecipe.bb',
+ is_image=False
+ )
+
+ def _get_build_dashboard(self, build):
+ """
+ Navigate to the build dashboard for build
+ """
+ url = reverse('builddashboard', args=(build.id,))
+ self.get(url)
+
+ def _get_build_dashboard_errors(self, build):
+ """
+ Get a list of HTML fragments representing the errors on the
+ dashboard for the Build object build
+ """
+ self._get_build_dashboard(build)
+ return self.find_all('#errors div.alert-error')
+
+ def _check_for_log_message(self, build, log_message):
+ """
+ Check whether the LogMessage instance <log_message> is
+ represented as an HTML error in the dashboard page for the Build object
+ build
+ """
+ errors = self._get_build_dashboard_errors(build)
+ self.assertEqual(len(errors), 2)
+
+ expected_text = log_message.message
+ expected_id = str(log_message.id)
+
+ found = False
+ for error in errors:
+ error_text = error.find_element_by_tag_name('pre').text
+ text_matches = (error_text == expected_text)
+
+ error_id = error.get_attribute('data-error')
+ id_matches = (error_id == expected_id)
+
+ if text_matches and id_matches:
+ found = True
+ break
+
+ template_vars = (expected_text, error_text,
+ expected_id, error_id)
+ assertion_error_msg = 'exception not found as error: ' \
+ 'expected text "%s" and got "%s"; ' \
+ 'expected ID %s and got %s' % template_vars
+ self.assertTrue(found, assertion_error_msg)
+
+ def _check_labels_in_modal(self, modal, expected):
+ """
+ Check that the text values of the <label> elements inside
+ the WebElement modal match the list of text values in expected
+ """
+ # labels containing the radio buttons we're testing for
+ labels = modal.find_elements_by_tag_name('label')
+
+ # because the label content has the structure
+ # label text
+ # <input...>
+ # we have to regex on its innerHTML, as we can't just retrieve the
+ # "label text" on its own via the Selenium API
+ labels_text = sorted(map(
+ lambda label: label.get_attribute('innerHTML'), labels
+ ))
+
+ expected = sorted(expected)
+
+ self.assertEqual(len(labels_text), len(expected))
+
+ for idx, label_text in enumerate(labels_text):
+ self.assertRegexpMatches(label_text, expected[idx])
+
+ def test_exceptions_show_as_errors(self):
+ """
+ LogMessages with level EXCEPTION should display in the errors
+ section of the page
+ """
+ self._check_for_log_message(self.build1, self.exception_message)
+
+ def test_criticals_show_as_errors(self):
+ """
+ LogMessages with level CRITICAL should display in the errors
+ section of the page
+ """
+ self._check_for_log_message(self.build1, self.critical_message)
+
+ def test_edit_custom_image_button(self):
+ """
+ A build which built two custom images should present a modal which lets
+ the user choose one of them to edit
+ """
+ self._get_build_dashboard(self.build1)
+ modal = self.driver.find_element_by_id('edit-custom-image-modal')
+
+ # recipes we expect to see in the edit custom image modal
+ expected_recipes = [
+ self.custom_image_recipe1.name,
+ self.custom_image_recipe2.name
+ ]
+
+ self._check_labels_in_modal(modal, expected_recipes)
+
+ def test_new_custom_image_button(self):
+ """
+ Check that a build with multiple images and custom images presents
+ all of them as options for creating a new custom image from
+ """
+ self._get_build_dashboard(self.build1)
+
+ # click the "new custom image" button, which populates the modal
+ selector = '[data-role="new-custom-image-trigger"] button'
+ self.click(selector)
+
+ modal = self.driver.find_element_by_id('new-custom-image-modal')
+
+ # recipes we expect to see in the new custom image modal
+ expected_recipes = [
+ self.image_recipe1.name,
+ self.image_recipe2.name,
+ self.custom_image_recipe1.name,
+ self.custom_image_recipe2.name
+ ]
+
+ self._check_labels_in_modal(modal, expected_recipes)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_js_unit_tests.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_js_unit_tests.py
new file mode 100644
index 000000000..e63da8e7a
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_js_unit_tests.py
@@ -0,0 +1,57 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""
+Run the js unit tests
+"""
+
+from django.core.urlresolvers import reverse
+from tests.browser.selenium_helpers import SeleniumTestCase
+import logging
+
+logger = logging.getLogger("toaster")
+
+
+class TestJsUnitTests(SeleniumTestCase):
+ """ Test landing page shows the Toaster brand """
+
+ fixtures = ['toastergui-unittest-data']
+
+ def test_that_js_unit_tests_pass(self):
+ url = reverse('js-unit-tests')
+ self.get(url)
+ self.wait_until_present('#tests-failed')
+
+ failed = self.find("#tests-failed").text
+ passed = self.find("#tests-passed").text
+ total = self.find("#tests-total").text
+
+ logger.info("Js unit tests completed %s out of %s passed, %s failed",
+ passed,
+ total,
+ failed)
+
+ failed_tests = self.find_all("li .fail .test-message")
+ for fail in failed_tests:
+ logger.error("JS unit test failed: %s" % fail.text)
+
+ self.assertEqual(failed, '0',
+ "%s JS unit tests failed" % failed)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_landing_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_landing_page.py
new file mode 100644
index 000000000..4d4cd660f
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_landing_page.py
@@ -0,0 +1,108 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import Project, Build
+
+class TestLandingPage(SeleniumTestCase):
+ """ Tests for redirects on the landing page """
+
+ PROJECT_NAME = 'test project'
+ LANDING_PAGE_TITLE = 'This is Toaster'
+ CLI_BUILDS_PROJECT_NAME = 'command line builds'
+
+ def setUp(self):
+ """ Add default project manually """
+ self.project = Project.objects.create_project(
+ self.CLI_BUILDS_PROJECT_NAME,
+ None
+ )
+ self.project.is_default = True
+ self.project.save()
+
+ def test_only_default_project(self):
+ """
+ No projects except default
+ => should see the landing page
+ """
+ self.get(reverse('landing'))
+ self.assertTrue(self.LANDING_PAGE_TITLE in self.get_page_source())
+
+ def test_default_project_has_build(self):
+ """
+ Default project has a build, no other projects
+ => should see the builds page
+ """
+ now = timezone.now()
+ build = Build.objects.create(project=self.project,
+ started_on=now,
+ completed_on=now)
+ build.save()
+
+ self.get(reverse('landing'))
+
+ elements = self.find_all('#allbuildstable')
+ self.assertEqual(len(elements), 1, 'should redirect to builds')
+ content = self.get_page_source()
+ self.assertFalse(self.PROJECT_NAME in content,
+ 'should not show builds for project %s' % self.PROJECT_NAME)
+ self.assertTrue(self.CLI_BUILDS_PROJECT_NAME in content,
+ 'should show builds for cli project')
+
+ def test_user_project_exists(self):
+ """
+ User has added a project (without builds)
+ => should see the projects page
+ """
+ user_project = Project.objects.create_project('foo', None)
+ user_project.save()
+
+ self.get(reverse('landing'))
+
+ elements = self.find_all('#projectstable')
+ self.assertEqual(len(elements), 1, 'should redirect to projects')
+
+ def test_user_project_has_build(self):
+ """
+ User has added a project (with builds), command line builds doesn't
+ => should see the builds page
+ """
+ user_project = Project.objects.create_project(self.PROJECT_NAME, None)
+ user_project.save()
+
+ now = timezone.now()
+ build = Build.objects.create(project=user_project,
+ started_on=now,
+ completed_on=now)
+ build.save()
+
+ self.get(reverse('landing'))
+
+ elements = self.find_all('#allbuildstable')
+ self.assertEqual(len(elements), 1, 'should redirect to builds')
+ content = self.get_page_source()
+ self.assertTrue(self.PROJECT_NAME in content,
+ 'should show builds for project %s' % self.PROJECT_NAME)
+ self.assertFalse(self.CLI_BUILDS_PROJECT_NAME in content,
+ 'should not show builds for cli project')
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py
new file mode 100644
index 000000000..8906cb27d
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_new_custom_image_page.py
@@ -0,0 +1,160 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.urlresolvers import reverse
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, ProjectLayer, Layer
+from orm.models import Layer_Version, Recipe, CustomImageRecipe
+
+class TestNewCustomImagePage(SeleniumTestCase):
+ CUSTOM_IMAGE_NAME = 'roopa-doopa'
+
+ def setUp(self):
+ release = Release.objects.create(
+ name='baz',
+ bitbake_version=BitbakeVersion.objects.create(name='v1')
+ )
+
+ # project to add new custom images to
+ self.project = Project.objects.create(name='foo', release=release)
+
+ # layer associated with the project
+ layer = Layer.objects.create(name='bar')
+ layer_version = Layer_Version.objects.create(
+ layer=layer,
+ project=self.project
+ )
+
+ # properly add the layer to the project
+ ProjectLayer.objects.create(
+ project=self.project,
+ layercommit=layer_version,
+ optional=False
+ )
+
+ # add a fake image recipe to the layer that can be customised
+ self.recipe = Recipe.objects.create(
+ name='core-image-minimal',
+ layer_version=layer_version,
+ is_image=True
+ )
+
+ # another project with a custom image already in it
+ project2 = Project.objects.create(name='whoop', release=release)
+ layer_version2 = Layer_Version.objects.create(
+ layer=layer,
+ project=project2
+ )
+ ProjectLayer.objects.create(
+ project=project2,
+ layercommit=layer_version2,
+ optional=False
+ )
+ recipe2 = Recipe.objects.create(
+ name='core-image-minimal',
+ layer_version=layer_version2,
+ is_image=True
+ )
+ CustomImageRecipe.objects.create(
+ name=self.CUSTOM_IMAGE_NAME,
+ base_recipe=recipe2,
+ layer_version=layer_version2,
+ file_path='/1/2',
+ project=project2
+ )
+
+ def _create_custom_image(self, new_custom_image_name):
+ """
+ 1. Go to the 'new custom image' page
+ 2. Click the button for the fake core-image-minimal
+ 3. Wait for the dialog box for setting the name of the new custom
+ image
+ 4. Insert new_custom_image_name into that dialog's text box
+ """
+ url = reverse('newcustomimage', args=(self.project.id,))
+ self.get(url)
+
+ self.click('button[data-recipe="%s"]' % self.recipe.id)
+
+ selector = '#new-custom-image-modal input[type="text"]'
+ self.enter_text(selector, new_custom_image_name)
+
+ self.click('#create-new-custom-image-btn')
+
+ def _check_for_custom_image(self, image_name):
+ """
+ Fetch the list of custom images for the project and check the
+ image with name image_name is listed there
+ """
+ url = reverse('projectcustomimages', args=(self.project.id,))
+ self.get(url)
+
+ self.wait_until_visible('#customimagestable')
+
+ element = self.find('#customimagestable td[class="name"] a')
+ msg = 'should be a custom image link with text %s' % image_name
+ self.assertEqual(element.text.strip(), image_name, msg)
+
+ def test_new_image(self):
+ """
+ Should be able to create a new custom image
+ """
+ custom_image_name = 'boo-image'
+ self._create_custom_image(custom_image_name)
+ self.wait_until_visible('#image-created-notification')
+ self._check_for_custom_image(custom_image_name)
+
+ def test_new_duplicates_other_project_image(self):
+ """
+ Should be able to create a new custom image if its name is the same
+ as a custom image in another project
+ """
+ self._create_custom_image(self.CUSTOM_IMAGE_NAME)
+ self.wait_until_visible('#image-created-notification')
+ self._check_for_custom_image(self.CUSTOM_IMAGE_NAME)
+
+ def test_new_duplicates_non_image_recipe(self):
+ """
+ Should not be able to create a new custom image whose name is the
+ same as an existing non-image recipe
+ """
+ self._create_custom_image(self.recipe.name)
+ element = self.wait_until_visible('#invalid-name-help')
+ self.assertRegexpMatches(element.text.strip(),
+ 'recipe with this name already exists')
+
+ def test_new_duplicates_project_image(self):
+ """
+ Should not be able to create a new custom image whose name is the same
+ as a custom image in this project
+ """
+ # create the image
+ custom_image_name = 'doh-image'
+ self._create_custom_image(custom_image_name)
+ self.wait_until_visible('#image-created-notification')
+ self._check_for_custom_image(custom_image_name)
+
+ # try to create an image with the same name
+ self._create_custom_image(custom_image_name)
+ element = self.wait_until_visible('#invalid-name-help')
+ expected = 'An image with this name already exists in this project'
+ self.assertRegexpMatches(element.text.strip(), expected)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_project_builds_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_project_builds_page.py
new file mode 100644
index 000000000..9fe91ab06
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_project_builds_page.py
@@ -0,0 +1,168 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import re
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import BitbakeVersion, Release, Project, Build, Target
+
+class TestProjectBuildsPage(SeleniumTestCase):
+ """ Test data at /project/X/builds is displayed correctly """
+
+ PROJECT_NAME = 'test project'
+ CLI_BUILDS_PROJECT_NAME = 'command line builds'
+
+ def setUp(self):
+ bbv = BitbakeVersion.objects.create(name='bbv1', giturl='/tmp/',
+ branch='master', dirpath='')
+ release = Release.objects.create(name='release1',
+ bitbake_version=bbv)
+ self.project1 = Project.objects.create_project(name=self.PROJECT_NAME,
+ release=release)
+ self.project1.save()
+
+ self.project2 = Project.objects.create_project(name=self.PROJECT_NAME,
+ release=release)
+ self.project2.save()
+
+ self.default_project = Project.objects.create_project(
+ name=self.CLI_BUILDS_PROJECT_NAME,
+ release=release
+ )
+ self.default_project.is_default = True
+ self.default_project.save()
+
+ # parameters for builds to associate with the projects
+ now = timezone.now()
+
+ self.project1_build_success = {
+ 'project': self.project1,
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.SUCCEEDED
+ }
+
+ self.project1_build_in_progress = {
+ 'project': self.project1,
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.IN_PROGRESS
+ }
+
+ self.project2_build_success = {
+ 'project': self.project2,
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.SUCCEEDED
+ }
+
+ self.project2_build_in_progress = {
+ 'project': self.project2,
+ 'started_on': now,
+ 'completed_on': now,
+ 'outcome': Build.IN_PROGRESS
+ }
+
+ def _get_rows_for_project(self, project_id):
+ """
+ Helper to retrieve HTML rows for a project's builds,
+ as shown in the main table of the page
+ """
+ url = reverse('projectbuilds', args=(project_id,))
+ self.get(url)
+ self.wait_until_present('#projectbuildstable tbody tr')
+ return self.find_all('#projectbuildstable tbody tr')
+
+ def test_show_builds_for_project(self):
+ """ Builds for a project should be displayed in the main table """
+ Build.objects.create(**self.project1_build_success)
+ Build.objects.create(**self.project1_build_success)
+ build_rows = self._get_rows_for_project(self.project1.id)
+ self.assertEqual(len(build_rows), 2)
+
+ def test_show_builds_project_only(self):
+ """ Builds for other projects should be excluded """
+ Build.objects.create(**self.project1_build_success)
+ Build.objects.create(**self.project1_build_success)
+ Build.objects.create(**self.project1_build_success)
+
+ # shouldn't see these two
+ Build.objects.create(**self.project2_build_success)
+ Build.objects.create(**self.project2_build_in_progress)
+
+ build_rows = self._get_rows_for_project(self.project1.id)
+ self.assertEqual(len(build_rows), 3)
+
+ def test_builds_exclude_in_progress(self):
+ """ "in progress" builds should not be shown in main table """
+ Build.objects.create(**self.project1_build_success)
+ Build.objects.create(**self.project1_build_success)
+
+ # shouldn't see this one
+ Build.objects.create(**self.project1_build_in_progress)
+
+ # shouldn't see these two either, as they belong to a different project
+ Build.objects.create(**self.project2_build_success)
+ Build.objects.create(**self.project2_build_in_progress)
+
+ build_rows = self._get_rows_for_project(self.project1.id)
+ self.assertEqual(len(build_rows), 2)
+
+ def test_show_tasks_with_suffix(self):
+ """ Task should be shown as suffixes on build names """
+ build = Build.objects.create(**self.project1_build_success)
+ target = 'bash'
+ task = 'clean'
+ Target.objects.create(build=build, target=target, task=task)
+
+ url = reverse('projectbuilds', args=(self.project1.id,))
+ self.get(url)
+ self.wait_until_present('td[class="target"]')
+
+ cell = self.find('td[class="target"]')
+ content = cell.get_attribute('innerHTML')
+ expected_text = '%s:%s' % (target, task)
+
+ self.assertTrue(re.search(expected_text, content),
+ '"target" cell should contain text %s' % expected_text)
+
+ def test_cli_builds_hides_tabs(self):
+ """
+ Display for command line builds should hide tabs
+ """
+ url = reverse('projectbuilds', args=(self.default_project.id,))
+ self.get(url)
+ tabs = self.find_all('#project-topbar')
+ self.assertEqual(len(tabs), 0,
+ 'should be no top bar shown for command line builds')
+
+ def test_non_cli_builds_has_tabs(self):
+ """
+ Non-command-line builds projects should show the tabs
+ """
+ url = reverse('projectbuilds', args=(self.project1.id,))
+ self.get(url)
+ tabs = self.find_all('#project-topbar')
+ self.assertEqual(len(tabs), 1,
+ 'should be a top bar shown for non-command-line builds')
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_project_page.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_project_page.py
new file mode 100644
index 000000000..786bef1c6
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_project_page.py
@@ -0,0 +1,59 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.core.urlresolvers import reverse
+from django.utils import timezone
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+from orm.models import Build, Project
+
+class TestProjectPage(SeleniumTestCase):
+ """ Test project data at /project/X/ is displayed correctly """
+
+ CLI_BUILDS_PROJECT_NAME = 'Command line builds'
+
+ def test_cli_builds_in_progress(self):
+ """
+ In progress builds should not cause an error to be thrown
+ when navigating to "command line builds" project page;
+ see https://bugzilla.yoctoproject.org/show_bug.cgi?id=8277
+ """
+
+ # add the "command line builds" default project; this mirrors what
+ # we do with get_or_create_default_project()
+ default_project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
+ default_project.is_default = True
+ default_project.save()
+
+ # add an "in progress" build for the default project
+ now = timezone.now()
+ Build.objects.create(project=default_project,
+ started_on=now,
+ completed_on=now,
+ outcome=Build.IN_PROGRESS)
+
+ # navigate to the project page for the default project
+ url = reverse("project", args=(default_project.id,))
+ self.get(url)
+
+ # check that we get a project page with the correct heading
+ project_name = self.find('#project-name').text.strip()
+ self.assertEqual(project_name, self.CLI_BUILDS_PROJECT_NAME)
diff --git a/yocto-poky/bitbake/lib/toaster/tests/browser/test_sample.py b/yocto-poky/bitbake/lib/toaster/tests/browser/test_sample.py
new file mode 100644
index 000000000..7bb8b97e8
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/browser/test_sample.py
@@ -0,0 +1,41 @@
+#! /usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2013-2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""
+A small example test demonstrating the basics of writing a test with
+Toaster's SeleniumTestCase; this just fetches the Toaster home page
+and checks it has the word "Toaster" in the brand link
+
+New test files should follow this structure, should be named "test_*.py",
+and should be in the same directory as this sample.
+"""
+
+from django.core.urlresolvers import reverse
+from tests.browser.selenium_helpers import SeleniumTestCase
+
+class TestSample(SeleniumTestCase):
+ """ Test landing page shows the Toaster brand """
+
+ def test_landing_page_has_brand(self):
+ url = reverse('landing')
+ self.get(url)
+ brand_link = self.find('span.brand a')
+ self.assertEqual(brand_link.text.strip(), 'Toaster')
diff --git a/yocto-poky/bitbake/lib/toaster/tests/toaster-tests-requirements.txt b/yocto-poky/bitbake/lib/toaster/tests/toaster-tests-requirements.txt
new file mode 100644
index 000000000..4f9fcc46d
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/tests/toaster-tests-requirements.txt
@@ -0,0 +1 @@
+selenium==2.49.2
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/api.py b/yocto-poky/bitbake/lib/toaster/toastergui/api.py
new file mode 100644
index 000000000..42901f750
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/api.py
@@ -0,0 +1,110 @@
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2016 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+# Temporary home for the UI's misc API
+
+from orm.models import Project, ProjectTarget, Build
+from bldcontrol.models import BuildRequest
+from bldcontrol import bbcontroller
+from django.http import HttpResponse, JsonResponse
+from django.views.generic import View
+
+
+class XhrBuildRequest(View):
+
+ def get(self, request, *args, **kwargs):
+ return HttpResponse()
+
+ def post(self, request, *args, **kwargs):
+ """
+ Build control
+
+ Entry point: /xhr_buildrequest/<project_id>
+ Method: POST
+
+ Args:
+ id: id of build to change
+ buildCancel = build_request_id ...
+ buildDelete = id ...
+ targets = recipe_name ...
+
+ Returns:
+ {"error": "ok"}
+ or
+ {"error": <error message>}
+ """
+
+ project = Project.objects.get(pk=kwargs['pid'])
+
+ if 'buildCancel' in request.POST:
+ for i in request.POST['buildCancel'].strip().split(" "):
+ try:
+ br = BuildRequest.objects.get(project=project, pk=i)
+
+ try:
+ bbctrl = bbcontroller.BitbakeController(br.environment)
+ bbctrl.forceShutDown()
+ except:
+ # We catch a bunch of exceptions here because
+ # this is where the server has not had time to start up
+ # and the build request or build is in transit between
+ # processes.
+ # We can safely just set the build as cancelled
+ # already as it never got started
+ build = br.build
+ build.outcome = Build.CANCELLED
+ build.save()
+
+ # We now hand over to the buildinfohelper to update the
+ # build state once we've finished cancelling
+ br.state = BuildRequest.REQ_CANCELLING
+ br.save()
+
+ except BuildRequest.DoesNotExist:
+ return JsonResponse({'error':'No such build id %s' % i})
+
+ return JsonResponse({'error': 'ok'})
+
+ if 'buildDelete' in request.POST:
+ for i in request.POST['buildDelete'].strip().split(" "):
+ try:
+ BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
+ except BuildRequest.DoesNotExist:
+ pass
+ return JsonResponse({'error': 'ok' })
+
+ if 'targets' in request.POST:
+ ProjectTarget.objects.filter(project = project).delete()
+ s = str(request.POST['targets'])
+ for t in s.translate(None, ";%|\"").split(" "):
+ if ":" in t:
+ target, task = t.split(":")
+ else:
+ target = t
+ task = ""
+ ProjectTarget.objects.create(project = project,
+ target = target,
+ task = task)
+ project.schedule_build()
+
+ return JsonResponse({'error': 'ok' })
+
+ response = HttpResponse()
+ response.status_code = 500
+ return response
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/fixtures/toastergui-unittest-data.xml b/yocto-poky/bitbake/lib/toaster/toastergui/fixtures/toastergui-unittest-data.xml
new file mode 100644
index 000000000..cf35be4be
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/fixtures/toastergui-unittest-data.xml
@@ -0,0 +1,446 @@
+<?xml version="1.0" encoding="utf-8"?>
+<django-objects version="1.0">
+ <object pk="1" model="orm.project">
+ <field type="CharField" name="name">a test project</field>
+ <field type="CharField" name="short_description"></field>
+ <field to="orm.bitbakeversion" name="bitbake_version" rel="ManyToOneRel">1</field>
+ <field to="orm.release" name="release" rel="ManyToOneRel">1</field>
+ <field type="DateTimeField" name="created">2016-02-15T18:46:20.098248+00:00</field>
+ <field type="DateTimeField" name="updated">2016-02-15T18:46:20.098392+00:00</field>
+ <field type="IntegerField" name="user_id"><None></None></field>
+ <field type="BooleanField" name="is_default">False</field>
+ </object>
+ <object pk="2" model="orm.project">
+ <field type="CharField" name="name">z test project</field>
+ <field type="CharField" name="short_description"></field>
+ <field to="orm.bitbakeversion" name="bitbake_version" rel="ManyToOneRel">1</field>
+ <field to="orm.release" name="release" rel="ManyToOneRel">2</field>
+ <field type="DateTimeField" name="created">2016-02-15T18:46:20.107936+00:00</field>
+ <field type="DateTimeField" name="updated">2016-02-15T18:46:20.108066+00:00</field>
+ <field type="IntegerField" name="user_id"><None></None></field>
+ <field type="BooleanField" name="is_default">False</field>
+ </object>
+ <object pk="1" model="orm.ProjectVariable">
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="name">MACHINE</field>
+ <field type="TextField" name="value">qemux86</field>
+ </object>
+ <object pk="2" model="orm.ProjectVariable">
+ <field to="orm.project" name="project" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="name">MACHINE</field>
+ <field type="TextField" name="value">qemux86</field>
+ </object>
+ <object pk="1" model="orm.build">
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="machine">x12</field>
+ <field type="CharField" name="distro"></field>
+ <field type="CharField" name="distro_version"></field>
+ <field type="DateTimeField" name="started_on">2016-02-14T18:46:20.114530+00:00</field>
+ <field type="DateTimeField" name="completed_on">2016-02-14T18:46:20.114530+00:00</field>
+ <field type="IntegerField" name="outcome">0</field>
+ <field type="CharField" name="cooker_log_path"></field>
+ <field type="CharField" name="build_name">a</field>
+ <field type="CharField" name="bitbake_version"></field>
+ </object>
+ <object pk="2" model="orm.build">
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="machine">raspberrypi2</field>
+ <field type="CharField" name="distro"></field>
+ <field type="CharField" name="distro_version"></field>
+ <field type="DateTimeField" name="started_on">2016-02-13T18:46:20.114530+00:00</field>
+ <field type="DateTimeField" name="completed_on">2016-02-13T18:46:20.114530+00:00</field>
+ <field type="IntegerField" name="outcome">0</field>
+ <field type="CharField" name="cooker_log_path"></field>
+ <field type="CharField" name="build_name">b</field>
+ <field type="CharField" name="bitbake_version"></field>
+ </object>
+ <object pk="3" model="orm.build">
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="machine">qemux86</field>
+ <field type="CharField" name="distro"></field>
+ <field type="CharField" name="distro_version"></field>
+ <field type="DateTimeField" name="started_on">2016-02-12T18:46:20.114530+00:00</field>
+ <field type="DateTimeField" name="completed_on">2016-02-12T18:46:20.114530+00:00</field>
+ <field type="IntegerField" name="outcome">1</field>
+ <field type="CharField" name="cooker_log_path"></field>
+ <field type="CharField" name="build_name">c</field>
+ <field type="CharField" name="bitbake_version"></field>
+ </object>
+ <object pk="4" model="orm.build">
+ <field to="orm.project" name="project" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="machine">qemux86</field>
+ <field type="CharField" name="distro"></field>
+ <field type="CharField" name="distro_version"></field>
+ <field type="DateTimeField" name="started_on">2016-02-11T18:46:20.114530+00:00</field>
+ <field type="DateTimeField" name="completed_on">2016-02-11T18:46:20.114530+00:00</field>
+ <field type="IntegerField" name="outcome">0</field>
+ <field type="CharField" name="cooker_log_path"></field>
+ <field type="CharField" name="build_name">d</field>
+ <field type="CharField" name="bitbake_version"></field>
+ </object>
+ <object pk="1" model="orm.target">
+ <field to="orm.build" name="build" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="target">a image recipe</field>
+ <field type="CharField" name="task"><None></None></field>
+ <field type="BooleanField" name="is_image">False</field>
+ <field type="IntegerField" name="image_size">0</field>
+ <field type="CharField" name="license_manifest_path"><None></None></field>
+ </object>
+ <object pk="2" model="orm.target">
+ <field to="orm.build" name="build" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="target">z something</field>
+ <field type="CharField" name="task"><None></None></field>
+ <field type="BooleanField" name="is_image">False</field>
+ <field type="IntegerField" name="image_size">0</field>
+ <field type="CharField" name="license_manifest_path"><None></None></field>
+ </object>
+ <object pk="3" model="orm.target">
+ <field to="orm.build" name="build" rel="ManyToOneRel">3</field>
+ <field type="CharField" name="target">h recipe</field>
+ <field type="CharField" name="task"><None></None></field>
+ <field type="BooleanField" name="is_image">False</field>
+ <field type="IntegerField" name="image_size">0</field>
+ <field type="CharField" name="license_manifest_path"><None></None></field>
+ </object>
+ <object pk="1" model="orm.package">
+ <field to="orm.build" name="build" rel="ManyToOneRel">1</field>
+ <field to="orm.recipe" name="recipe" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="name">b pkg</field>
+ <field type="CharField" name="installed_name"></field>
+ <field type="CharField" name="version"></field>
+ <field type="CharField" name="revision"></field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="IntegerField" name="size">777</field>
+ <field type="IntegerField" name="installed_size">0</field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license">a license</field>
+ </object>
+ <object pk="2" model="orm.package">
+ <field to="orm.build" name="build" rel="ManyToOneRel">1</field>
+ <field to="orm.recipe" name="recipe" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="name">f pkg</field>
+ <field type="CharField" name="installed_name"></field>
+ <field type="CharField" name="version"></field>
+ <field type="CharField" name="revision"></field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="IntegerField" name="size">4</field>
+ <field type="IntegerField" name="installed_size">10</field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license">z license</field>
+ </object>
+ <object pk="3" model="orm.package">
+ <field to="orm.build" name="build" rel="ManyToOneRel"><None></None></field>
+ <field to="orm.recipe" name="recipe" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="name">a custom image pkg</field>
+ <field type="CharField" name="installed_name"></field>
+ <field type="CharField" name="version"></field>
+ <field type="CharField" name="revision"></field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="IntegerField" name="size">10</field>
+ <field type="IntegerField" name="installed_size">0</field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license">h license</field>
+ </object>
+ <object pk="4" model="orm.package">
+ <field to="orm.build" name="build" rel="ManyToOneRel"><None></None></field>
+ <field to="orm.recipe" name="recipe" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="name">z custom image pkg</field>
+ <field type="CharField" name="installed_name"></field>
+ <field type="CharField" name="version"></field>
+ <field type="CharField" name="revision"></field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="IntegerField" name="size">5</field>
+ <field type="IntegerField" name="installed_size">0</field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license">z license</field>
+ </object>
+ <object pk="5" model="orm.package">
+ <field to="orm.build" name="build" rel="ManyToOneRel">1</field>
+ <field to="orm.recipe" name="recipe" rel="ManyToOneRel">4</field>
+ <field type="CharField" name="name">a custom image pkg</field>
+ <field type="CharField" name="installed_name"></field>
+ <field type="CharField" name="version"></field>
+ <field type="CharField" name="revision"></field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="IntegerField" name="size">2</field>
+ <field type="IntegerField" name="installed_size">0</field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license">h licence</field>
+ </object>
+ <object pk="1" model="orm.target_installed_package">
+ <field to="orm.target" name="target" rel="ManyToOneRel">1</field>
+ <field to="orm.package" name="package" rel="ManyToOneRel">1</field>
+ </object>
+ <object pk="2" model="orm.target_installed_package">
+ <field to="orm.target" name="target" rel="ManyToOneRel">1</field>
+ <field to="orm.package" name="package" rel="ManyToOneRel">2</field>
+ </object>
+ <object pk="3" model="orm.target_installed_package">
+ <field to="orm.target" name="target" rel="ManyToOneRel">1</field>
+ <field to="orm.package" name="package" rel="ManyToOneRel">3</field>
+ </object>
+ <!-- Note that these augment the existing orm.package of the same pk -->
+ <object pk="4" model="orm.customimagepackage">
+ <field to="orm.customimagerecipe" name="recipe_includes" rel="ManyToManyRel"></field>
+ <field to="orm.customimagerecipe" name="recipe_excludes" rel="ManyToManyRel"></field>
+ <field to="orm.customimagerecipe" name="recipe_appends" rel="ManyToManyRel"><object pk="3"></object></field>
+ </object>
+ <object pk="5" model="orm.customimagepackage">
+ <field to="orm.customimagerecipe" name="recipe_includes" rel="ManyToManyRel"></field>
+ <field to="orm.customimagerecipe" name="recipe_excludes" rel="ManyToManyRel"></field>
+ <field to="orm.customimagerecipe" name="recipe_appends" rel="ManyToManyRel"><object pk="3"></object></field>
+ </object>
+ <object pk="1" model="orm.recipe">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">z recipe</field>
+ <field type="CharField" name="version">5.2</field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">2</field>
+ <field type="TextField" name="summary">z recipe</field>
+ <field type="TextField" name="description">z recipe</field>
+ <field type="CharField" name="section">z section</field>
+ <field type="CharField" name="license">z license</field>
+ <field type="CharField" name="homepage"></field>
+ <field type="CharField" name="bugtracker"></field>
+ <field type="FilePathField" name="file_path"></field>
+ <field type="CharField" name="pathflags"></field>
+ <field type="BooleanField" name="is_image">False</field>
+ </object>
+ <object pk="2" model="orm.recipe">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">a recipe</field>
+ <field type="CharField" name="version">1.2</field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">1</field>
+ <field type="TextField" name="summary">a recipe</field>
+ <field type="TextField" name="description">a recipe</field>
+ <field type="CharField" name="section">a section</field>
+ <field type="CharField" name="license">a license</field>
+ <field type="CharField" name="homepage"></field>
+ <field type="CharField" name="bugtracker"></field>
+ <field type="FilePathField" name="file_path">a_recipe.bb</field>
+ <field type="CharField" name="pathflags"></field>
+ <field type="BooleanField" name="is_image">False</field>
+ </object>
+ <object pk="3" model="orm.recipe">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">a custom recipe</field>
+ <field type="CharField" name="version"></field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">2</field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license"></field>
+ <field type="CharField" name="homepage"></field>
+ <field type="CharField" name="bugtracker"></field>
+ <field type="FilePathField" name="file_path">custr</field>
+ <field type="CharField" name="pathflags"></field>
+ <field type="BooleanField" name="is_image">False</field>
+ </object>
+ <object pk="4" model="orm.recipe">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">a image recipe</field>
+ <field type="CharField" name="version">1.2</field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">1</field>
+ <field type="TextField" name="summary">one recipe</field>
+ <field type="TextField" name="description">recipe</field>
+ <field type="CharField" name="section">A</field>
+ <field type="CharField" name="license">A</field>
+ <field type="CharField" name="homepage"></field>
+ <field type="CharField" name="bugtracker"></field>
+ <field type="FilePathField" name="file_path">/one/</field>
+ <field type="CharField" name="pathflags"></field>
+ <field type="BooleanField" name="is_image">True</field>
+ </object>
+ <object pk="5" model="orm.recipe">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">z image recipe</field>
+ <field type="CharField" name="version">1.3</field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">2</field>
+ <field type="TextField" name="summary">two image recipe</field>
+ <field type="TextField" name="description">recipe two</field>
+ <field type="CharField" name="section">B</field>
+ <field type="CharField" name="license">Z</field>
+ <field type="CharField" name="homepage"></field>
+ <field type="CharField" name="bugtracker"></field>
+ <field type="FilePathField" name="file_path">/two/</field>
+ <field type="CharField" name="pathflags"></field>
+ <field type="BooleanField" name="is_image">True</field>
+ </object>
+ <object pk="6" model="orm.recipe">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">z custom recipe</field>
+ <field type="CharField" name="version"></field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">2</field>
+ <field type="TextField" name="summary"></field>
+ <field type="TextField" name="description"></field>
+ <field type="CharField" name="section"></field>
+ <field type="CharField" name="license"></field>
+ <field type="CharField" name="homepage"></field>
+ <field type="CharField" name="bugtracker"></field>
+ <field type="FilePathField" name="file_path">zzzz</field>
+ <field type="CharField" name="pathflags"></field>
+ <field type="BooleanField" name="is_image">False</field>
+ </object>
+ <object pk="1" model="orm.machine">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="name">a machine</field>
+ <field type="CharField" name="description">a machine</field>
+ </object>
+ <object pk="2" model="orm.machine">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">2</field>
+ <field type="CharField" name="name">z machine</field>
+ <field type="CharField" name="description">z machine</field>
+ </object>
+ <object pk="3" model="orm.machine">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field to="orm.layer_version" name="layer_version" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="name">g machine</field>
+ <field type="CharField" name="description">g machine</field>
+ </object>
+ <object pk="1" model="orm.layersource">
+ <field type="CharField" name="name">local</field>
+ <field type="IntegerField" name="sourcetype">1</field>
+ <field type="CharField" name="apiurl"></field>
+ </object>
+ <object pk="1" model="orm.bitbakeversion">
+ <field type="CharField" name="name">test bbv</field>
+ <field type="CharField" name="giturl">/tmp/</field>
+ <field type="CharField" name="branch">master</field>
+ <field type="CharField" name="dirpath"></field>
+ </object>
+ <object pk="1" model="orm.release">
+ <field type="CharField" name="name">test release</field>
+ <field type="CharField" name="description"></field>
+ <field to="orm.bitbakeversion" name="bitbake_version" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="branch_name">master</field>
+ <field type="TextField" name="helptext"><None></None></field>
+ </object>
+ <object pk="2" model="orm.release">
+ <field type="CharField" name="name">test release 2</field>
+ <field type="CharField" name="description"></field>
+ <field to="orm.bitbakeversion" name="bitbake_version" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="branch_name">master</field>
+ <field type="TextField" name="helptext"><None></None></field>
+ </object>
+ <object pk="1" model="orm.releaselayersourcepriority">
+ <field to="orm.release" name="release" rel="ManyToOneRel">1</field>
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="priority">0</field>
+ </object>
+ <object pk="1" model="orm.branch">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">master</field>
+ <field type="CharField" name="short_description"></field>
+ </object>
+ <object pk="1" model="orm.layer">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">a layer</field>
+ <field type="CharField" name="layer_index_url"></field>
+ <field type="CharField" name="vcs_url">/tmp/</field>
+ <field type="CharField" name="vcs_web_url"><None></None></field>
+ <field type="CharField" name="vcs_web_tree_base_url"><None></None></field>
+ <field type="CharField" name="vcs_web_file_base_url"><None></None></field>
+ <field type="TextField" name="summary"><None></None></field>
+ <field type="TextField" name="description"><None></None></field>
+ </object>
+ <object pk="2" model="orm.layer">
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field type="CharField" name="name">z layer</field>
+ <field type="CharField" name="layer_index_url"></field>
+ <field type="CharField" name="vcs_url">git://two/</field>
+ <field type="CharField" name="vcs_web_url"><None></None></field>
+ <field type="CharField" name="vcs_web_tree_base_url"><None></None></field>
+ <field type="CharField" name="vcs_web_file_base_url"><None></None></field>
+ <field type="TextField" name="summary"><None></None></field>
+ <field type="TextField" name="description"><None></None></field>
+ </object>
+ <object pk="1" model="orm.layer_version">
+ <field to="orm.build" name="build" rel="ManyToOneRel"><None></None></field>
+ <field to="orm.layer" name="layer" rel="ManyToOneRel">1</field>
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field to="orm.branch" name="up_branch" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="branch"></field>
+ <field type="CharField" name="commit">master</field>
+ <field type="CharField" name="dirpath">/tmp/</field>
+ <field type="IntegerField" name="priority">0</field>
+ <field type="FilePathField" name="local_path">/</field>
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ </object>
+ <object pk="2" model="orm.layer_version">
+ <field to="orm.build" name="build" rel="ManyToOneRel"><None></None></field>
+ <field to="orm.layer" name="layer" rel="ManyToOneRel">2</field>
+ <field to="orm.layersource" name="layer_source" rel="ManyToOneRel">1</field>
+ <field type="IntegerField" name="up_id"><None></None></field>
+ <field type="DateTimeField" name="up_date"><None></None></field>
+ <field to="orm.branch" name="up_branch" rel="ManyToOneRel">1</field>
+ <field type="CharField" name="branch"></field>
+ <field type="CharField" name="commit">master</field>
+ <field type="CharField" name="dirpath"><None></None></field>
+ <field type="IntegerField" name="priority">0</field>
+ <field type="FilePathField" name="local_path">/</field>
+ <field to="orm.project" name="project" rel="ManyToOneRel"><None></None></field>
+ </object>
+ <object pk="1" model="orm.projectlayer">
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field to="orm.layer_version" name="layercommit" rel="ManyToOneRel">1</field>
+ <field type="BooleanField" name="optional">True</field>
+ </object>
+ <object pk="3" model="orm.customimagerecipe">
+ <field to="orm.recipe" name="base_recipe" rel="ManyToOneRel">2</field>
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field type="DateTimeField" name="last_updated"><None></None></field>
+ </object>
+ <object pk="6" model="orm.customimagerecipe">
+ <field to="orm.recipe" name="base_recipe" rel="ManyToOneRel">4</field>
+ <field to="orm.project" name="project" rel="ManyToOneRel">1</field>
+ <field type="DateTimeField" name="last_updated"><None></None></field>
+ </object>
+ <object pk="1" model="orm.logmessage">
+ <field to="orm.build" name="build" rel="ManyToOneRel">2</field>
+ <field to="orm.task" name="task" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="level">1</field>
+ <field type="TextField" name="message"><None></None></field>
+ <field type="FilePathField" name="pathname"></field>
+ <field type="IntegerField" name="lineno"><None></None></field>
+ </object>
+ <object pk="2" model="orm.logmessage">
+ <field to="orm.build" name="build" rel="ManyToOneRel">2</field>
+ <field to="orm.task" name="task" rel="ManyToOneRel"><None></None></field>
+ <field type="IntegerField" name="level">2</field>
+ <field type="TextField" name="message"><None></None></field>
+ <field type="FilePathField" name="pathname"></field>
+ <field type="IntegerField" name="lineno"><None></None></field>
+ </object>
+</django-objects>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/css/default.css b/yocto-poky/bitbake/lib/toaster/toastergui/static/css/default.css
index bc8a97bed..b024d962a 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/css/default.css
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/css/default.css
@@ -10,7 +10,6 @@
/* Style the breadcrumb */
.breadcrumb { display: inline-block; background-color: transparent; }
-.breadcrumb li:first-child { padding-right: 10px; }
/* Styles for the help information */
.get-help { color: #CCCCCC; }
@@ -51,6 +50,7 @@ dd li { line-height: 25px; }
/* Style the filter modal dialogs */
.modal { width: 800px; margin-left: -400px; }
.modal-footer .btn { float: left; }
+.modal-body { max-height: 300px; }
/* Hover style for the clear search icon */
.icon-remove-sign:hover { color: #999999; cursor: pointer; }
@@ -114,6 +114,7 @@ th > a, th > span { font-weight: normal; }
/* Styles for the navbar actions */
.btn-group + .btn-group { margin-right: 10px; }
.navbar-inner > .btn-group { margin-top: 6px; }
+[id^="search-input-"], #search { width: 80%; }
/* Styles for the parent item in the left navigation */
@@ -153,6 +154,9 @@ select { width: auto; }
/* make tables Chrome-happy (me, not so much) */
table { table-layout: fixed; word-wrap: break-word; }
+table p { margin-bottom: 0 }
+.table td { vertical-align: middle; }
+
/* styles for the new build button */
.new-build .btn-primary { padding: 4px 30px; }
.new-build .alert { margin-top: 10px; }
@@ -194,7 +198,7 @@ table { table-layout: fixed; word-wrap: break-word; }
.configuration-alert p { margin-bottom: 0px; }
.project-form { margin-top: 10px; }
.add-layers .btn-block + .btn-block, .build .btn-block + .btn-block { margin-top: 0px; }
-input.huge { font-size: 17.5px; padding: 11px 19px; }
+input.huge { font-size: 17.5px; padding: 11px; min-width: 60%; }
.build-form { margin-bottom: 0px; }
.build-form .input-append { margin-bottom: 0px; }
.build-form .btn-large { padding: 11px 35px; }
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/css/qunit-1.18.0.css b/yocto-poky/bitbake/lib/toaster/toastergui/static/css/qunit-1.18.0.css
new file mode 100644
index 000000000..28cca1cc1
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/css/qunit-1.18.0.css
@@ -0,0 +1 @@
+/**//**/#qunit-tests,#qunit-header,#qunit-banner,#qunit-testrunner-toolbar,#qunit-userAgent,#qunit-testresult{font-family:"Helvetica Neue Light","HelveticaNeue-Light","Helvetica Neue",Calibri,Helvetica,Arial,sans-serif;}#qunit-testrunner-toolbar,#qunit-userAgent,#qunit-testresult,#qunit-tests li{font-size:small;}#qunit-tests{font-size:smaller;}/**/#qunit-tests,#qunit-header,#qunit-banner,#qunit-userAgent,#qunit-testresult,#qunit-modulefilter{margin:0;padding:0;}/**/#qunit-header{padding:0.5em 0 0.5em 1em;color:#8699A4;background-color:#0D3349;font-size:1.5em;line-height:1em;font-weight:400;border-radius:5px 5px 0 0;}#qunit-header a{text-decoration:none;color:#C2CCD1;}#qunit-header a:hover,#qunit-header a:focus{color:#FFF;}#qunit-testrunner-toolbar label{display:inline-block;padding:0 0.5em 0 0.1em;}#qunit-banner{height:5px;}#qunit-testrunner-toolbar{padding:0.5em 1em 0.5em 1em;color:#5E740B;background-color:#EEE;overflow:hidden;}#qunit-userAgent{padding:0.5em 1em 0.5em 1em;background-color:#2B81AF;color:#FFF;text-shadow:rgba(0,0,0,0.5) 2px 2px 1px;}#qunit-modulefilter-container{float:right;padding:0.2em;}.qunit-url-config{display:inline-block;padding:0.1em;}.qunit-filter{display:block;float:right;margin-left:1em;}/**/#qunit-tests{list-style-position:inside;}#qunit-tests li{padding:0.4em 1em 0.4em 1em;border-bottom:1px solid #FFF;list-style-position:inside;}#qunit-tests>li{display:none;}#qunit-tests li.running,#qunit-tests li.pass,#qunit-tests li.fail,#qunit-tests li.skipped{display:list-item;}#qunit-tests.hidepass li.running,#qunit-tests.hidepass li.pass{visibility:hidden;position:absolute;width:0px;height:0px;padding:0;border:0;margin:0;}#qunit-tests li strong{cursor:pointer;}#qunit-tests li.skipped strong{cursor:default;}#qunit-tests li a{padding:0.5em;color:#C2CCD1;text-decoration:none;}#qunit-tests li p a{padding:0.25em;color:#6B6464;}#qunit-tests li a:hover,#qunit-tests li a:focus{color:#000;}#qunit-tests li .runtime{float:right;font-size:smaller;}.qunit-assert-list{margin-top:0.5em;padding:0.5em;background-color:#FFF;border-radius:5px;}.qunit-collapsed{display:none;}#qunit-tests table{border-collapse:collapse;margin-top:0.2em;}#qunit-tests th{text-align:right;vertical-align:top;padding:0 0.5em 0 0;}#qunit-tests td{vertical-align:top;}#qunit-tests pre{margin:0;white-space:pre-wrap;word-wrap:break-word;}#qunit-tests del{background-color:#E0F2BE;color:#374E0C;text-decoration:none;}#qunit-tests ins{background-color:#FFCACA;color:#500;text-decoration:none;}/**/#qunit-tests b.counts{color:#000;}#qunit-tests b.passed{color:#5E740B;}#qunit-tests b.failed{color:#710909;}#qunit-tests li li{padding:5px;background-color:#FFF;border-bottom:none;list-style-position:inside;}/**/#qunit-tests li li.pass{color:#3C510C;background-color:#FFF;border-left:10px solid #C6E746;}#qunit-tests .pass{color:#528CE0;background-color:#D2E0E6;}#qunit-tests .pass .test-name{color:#366097;}#qunit-tests .pass .test-actual,#qunit-tests .pass .test-expected{color:#999;}#qunit-banner.qunit-pass{background-color:#C6E746;}/**/#qunit-tests li li.fail{color:#710909;background-color:#FFF;border-left:10px solid #EE5757;white-space:pre;}#qunit-tests>li:last-child{border-radius:0 0 5px 5px;}#qunit-tests .fail{color:#000;background-color:#EE5757;}#qunit-tests .fail .test-name,#qunit-tests .fail .module-name{color:#000;}#qunit-tests .fail .test-actual{color:#EE5757;}#qunit-tests .fail .test-expected{color:#008000;}#qunit-banner.qunit-fail{background-color:#EE5757;}/**/#qunit-tests .skipped{background-color:#EBECE9;}#qunit-tests .qunit-skipped-label{background-color:#F4FF77;display:inline-block;font-style:normal;color:#366097;line-height:1.8em;padding:0 0.5em;margin:-0.4em 0.4em -0.4em 0;}/**/#qunit-testresult{padding:0.5em 1em 0.5em 1em;color:#2B81AF;background-color:#D2E0E6;border-bottom:1px solid #FFF;}#qunit-testresult .module-name{font-weight:700;}/**/#qunit-fixture{position:absolute;top:-10000px;left:-10000px;width:1000px;height:1000px;} \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/base.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/base.js
deleted file mode 100644
index ed22a4ebc..000000000
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/base.js
+++ /dev/null
@@ -1,229 +0,0 @@
-'use strict';
-
-function basePageInit(ctx) {
-
- var newBuildButton = $("#new-build-button");
- var newBuildTargetInput;
- var newBuildTargetBuildBtn;
- var projectNameForm = $("#project-name-change-form");
- var projectNameContainer = $("#project-name-container");
- var projectName = $("#project-name");
- var projectNameFormToggle = $("#project-change-form-toggle");
- var projectNameChangeCancel = $("#project-name-change-cancel");
-
- /* initially the current project is used unless overridden by the new build
- * button in top right nav
- */
- var selectedProject = libtoaster.ctx;
-
- var selectedTarget;
-
- var newBuildProjectInput = $("#new-build-button #project-name-input");
- var newBuildProjectSaveBtn = $("#new-build-button #save-project-button");
-
- /* Project name change functionality */
- projectNameFormToggle.click(function(e){
- e.preventDefault();
- projectNameContainer.hide();
- projectNameForm.fadeIn();
- });
-
- projectNameChangeCancel.click(function(e){
- e.preventDefault();
- projectNameForm.hide();
- projectNameContainer.fadeIn();
- });
-
- $("#project-name-change-btn").click(function(e){
- var newProjectName = $("#project-name-change-input").val();
-
- libtoaster.editCurrentProject({ projectName: newProjectName }, function (){
- projectName.html(newProjectName);
- libtoaster.ctx.projectName = newProjectName;
- projectNameChangeCancel.click();
- });
- });
-
- _checkProjectBuildable();
-
- $("#project-topbar .nav li a").each(function(){
- if (window.location.pathname === $(this).attr('href'))
- $(this).parent().addClass('active');
- else
- $(this).parent().removeClass('active');
- });
-
- if ($(".total-builds").length !== 0){
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
- if (prjInfo.completedbuilds)
- $(".total-builds").text(prjInfo.completedbuilds.length);
- });
- }
-
- /* Hide the button if we're on the project,newproject or importlyaer page
- * or if there are no projects yet defined
- * only show if there isn't already a build-target-input already
- */
- if (ctx.numProjects > 0 &&
- ctx.currentUrl.search('newproject') < 0 &&
- $(".build-target-input").length === 1) {
-
- newBuildTargetInput = $("#new-build-button .build-target-input");
- newBuildTargetBuildBtn = $("#new-build-button").find(".build-button");
-
- _setupNewBuildButton();
- newBuildButton.show();
- } else if ($(".build-target-input").length > 0) {
- newBuildTargetInput = $("#project-topbar .build-target-input");
- newBuildTargetBuildBtn = $("#project-topbar .build-button");
- } else {
- return;
- }
-
- /* Hide the change project icon when there is only one project */
- if (ctx.numProjects === 1) {
- $('#project .icon-pencil').hide();
- }
-
- /* If we have a project setup the typeahead */
- if (selectedProject.recipesTypeAheadUrl){
- libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.recipesTypeAheadUrl, { format: "json" }, function (item) {
- selectedTarget = item;
- newBuildTargetBuildBtn.removeAttr("disabled");
- });
- }
-
- newBuildTargetInput.on('input', function () {
- if ($(this).val().length === 0) {
- newBuildTargetBuildBtn.attr("disabled", "disabled");
- } else {
- newBuildTargetBuildBtn.removeAttr("disabled");
- }
- });
-
- newBuildTargetBuildBtn.click(function (e) {
- e.preventDefault();
-
- if (!newBuildTargetInput.val()) {
- return;
- }
-
- /* We use the value of the input field so as to maintain any command also
- * added e.g. core-image-minimal:clean
- */
- selectedTarget = { name: newBuildTargetInput.val() };
-
- /* Fire off the build */
- libtoaster.startABuild(selectedProject.projectBuildsUrl,
- selectedProject.projectId, selectedTarget.name, function(){
- window.location.replace(selectedProject.projectBuildsUrl);
- }, null);
- });
-
- function _checkProjectBuildable() {
- if (selectedProject.projectId === undefined || selectedProject.projectIsDefault) {
- return;
- }
-
- libtoaster.getProjectInfo(selectedProject.projectPageUrl,
- function (data) {
- if (data.machine === null || data.machine.name === undefined || data.layers.length === 0) {
- /* we can't build anything without a machine and some layers */
- $("#new-build-button #targets-form").hide();
- $("#new-build-button .alert").show();
- } else {
- $("#new-build-button #targets-form").show();
- $("#new-build-button .alert").hide();
-
- /* we can build this project; enable input fields */
- newBuildTargetInput.removeAttr("disabled");
- }
- }, null);
- }
-
- /* Setup New build button in the top nav bar */
- function _setupNewBuildButton() {
-
- /* If we don't have a current project then present the set project
- * form.
- */
- if (selectedProject.projectId === undefined || selectedProject.projectIsDefault) {
- $('#change-project-form').show();
- $('#project .icon-pencil').hide();
- }
-
- libtoaster.makeTypeahead(newBuildProjectInput, selectedProject.projectsTypeAheadUrl, { format : "json" }, function (item) {
- /* successfully selected a project */
- newBuildProjectSaveBtn.removeAttr("disabled");
- selectedProject = item;
- });
-
- /* Any typing in the input apart from enter key is going to invalidate
- * the value that has been set by selecting a suggestion from the typeahead
- */
- newBuildProjectInput.on('input', function (event) {
- if (event.keyCode === 13) {
- return;
- }
- newBuildProjectSaveBtn.attr("disabled", "disabled");
- });
-
-
- newBuildProjectSaveBtn.click(function () {
- selectedProject.projectId = selectedProject.id;
- /* Update the typeahead project_id paramater */
- _checkProjectBuildable();
-
- newBuildTargetInput.removeAttr("disabled");
-
- /* We've got a new project so now we need to update the
- * target urls. We can get this from the new project's info
- */
- $.getJSON(selectedProject.projectPageUrl, { format: "json" },
- function(projectInfo){
- /* Update the typeahead to use the new selectedProject */
- selectedProject = projectInfo;
-
- libtoaster.makeTypeahead(newBuildTargetInput, selectedProject.recipesTypeAheadUrl, { format: "json" }, function (item) {
- /* successfully selected a target */
- selectedTarget = item;
- newBuildTargetBuildBtn.removeAttr("disabled");
- });
-
- });
- newBuildTargetInput.val("");
-
- /* set up new form aspect */
- $("#new-build-button #project a").text(selectedProject.name).attr('href', selectedProject.projectPageUrl);
- $("#new-build-button .alert a").attr('href', selectedProject.projectPageUrl);
- $("#project .icon-pencil").show();
-
- $("#change-project-form").slideUp({ 'complete' : function () {
- $("#new-build-button #project").show();
- }});
- });
-
- $('#new-build-button #project .icon-pencil').click(function () {
- newBuildProjectSaveBtn.attr("disabled", "disabled");
- newBuildProjectInput.val($("#new-build-button #project a").text());
- $("#cancel-change-project").show();
- $(this).parent().hide();
- $("#change-project-form").slideDown();
- });
-
- $("#new-build-button #cancel-change-project").click(function () {
- $("#change-project-form").hide(function () {
- $('#new-build-button #project').show();
- });
-
- newBuildProjectInput.val("");
- newBuildProjectSaveBtn.attr("disabled", "disabled");
- });
-
- /* Keep the dropdown open even unless we click outside the dropdown area */
- $(".new-build").click (function (event) {
- event.stopPropagation();
- });
- };
-
-}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
index 4f6b304dd..1c0ef9e37 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
@@ -3,48 +3,282 @@
function customRecipePageInit(ctx) {
var urlParams = libtoaster.parseUrlParams();
+ var customiseTable = $("#selectpackagestable");
+ var addPkgDepsModalBtn = $("#add-package-deps-modal-btn");
+ var rmdPkgReverseDepsModalBtn = $("#rm-package-reverse-deps-modal-btn");
- (function notificationRequest(){
- if (urlParams.hasOwnProperty('notify') && urlParams.notify === 'new'){
- $("#image-created-notification").show();
- }
- })();
+ if (urlParams.hasOwnProperty('notify') && urlParams.notify === 'new'){
+ $("#image-created-notification").show();
+ }
- $("#recipeselection").on('table-done', function(e, total, tableParams){
+ customiseTable.on('table-done', function(e, total){
/* Table is done so now setup the click handler for the package buttons */
$(".add-rm-package-btn").click(function(e){
e.preventDefault();
- addRemovePackage($(this), tableParams);
+ var targetPkg = $(this).data();
+
+ checkPackageDeps(targetPkg, function(pkgData){
+ if (targetPkg.directive === 'add'){
+ /* If we're adding a package we may need to show the modal to advise
+ * on dependencies for this package.
+ */
+ if (pkgData.unsatisfied_dependencies.length === 0){
+ addRemovePackage(targetPkg);
+ } else {
+ showPackageDepsModal(targetPkg, pkgData);
+ }
+ } else if (targetPkg.directive === 'remove') {
+ if (pkgData.reverse_dependencies.length === 0){
+ addRemovePackage(targetPkg);
+ } else {
+ showPackageReverseDepsModal(targetPkg, pkgData);
+ }
+ }
+ });
+ });
+ });
+
+ function checkPackageDeps(targetPkg, doneCb){
+ $.ajax({
+ type: 'GET',
+ url: targetPkg.packageUrl,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function(data){
+ if (data.error !== 'ok'){
+ console.warn(data.error);
+ return;
+ }
+ doneCb(data);
+ }
});
+ }
+
+ function showPackageDepsModal(targetPkg, pkgData){
+ var modal = $("#package-deps-modal");
+ var depsList = modal.find("#package-add-dep-list");
+ var deps = pkgData.unsatisfied_dependencies;
+
+ modal.find(".package-to-add-name").text(targetPkg.name);
+
+ depsList.text("");
+
+ for (var i in deps){
+ var li = $('<li></li>').text(deps[i].name);
+ li.append($('<span></span>').text(" ("+
+ deps[i].size_formatted+")"));
+ depsList.append(li);
+ }
+
+ modal.find("#package-deps-total-size").text(
+ pkgData.unsatisfied_dependencies_size_formatted);
+
+ targetPkg.depsAdded = deps;
+
+ addPkgDepsModalBtn.data(targetPkg);
+ modal.modal('show');
+ }
+
+ addPkgDepsModalBtn.click(function(e){
+ e.preventDefault();
+
+ addRemovePackage($(this).data(), null);
+ });
+
+ function showPackageReverseDepsModal(targetPkg, pkgData){
+ var modal = $("#package-reverse-deps-modal");
+ var depsList = modal.find("#package-reverse-dep-list");
+ var deps = pkgData.reverse_dependencies;
+
+ var depsCount = deps.length;
+ var vDepends = "depends";
+ var vPackage = "package";
+ var vThis = "this";
+ if (depsCount > 1) {
+ vDepends = "depend";
+ vPackage = "packages";
+ vThis = "these";
+ }
+ modal.find(".package-to-rm-name").text(targetPkg.name);
+ modal.find(".reverse-deps-count").text(depsCount);
+ modal.find(".reverse-deps-count-plus1").text((depsCount+1) + " packages");
+ modal.find(".reverse-deps-depends").text(vDepends);
+ modal.find(".reverse-deps-package").text(vPackage);
+ modal.find(".reverse-deps-this").text(vThis);
+
+ depsList.text("");
+
+ for (var i in deps){
+ var li = $('<li></li>').text(deps[i].name);
+ li.append($('<span></span>').text(" ("+
+ deps[i].size_formatted+")"));
+ depsList.append(li);
+ }
+
+ modal.find("#package-reverse-deps-total-size").text(
+ pkgData.reverse_dependencies_size_formatted);
+
+ targetPkg.depsRemoved = deps;
+
+ rmdPkgReverseDepsModalBtn.data(targetPkg);
+ modal.modal('show');
+ }
+
+ rmdPkgReverseDepsModalBtn.click(function(e){
+ e.preventDefault();
+
+ addRemovePackage($(this).data(), null);
});
- function addRemovePackage(pkgBtn, tableParams){
- var pkgBtnData = pkgBtn.data();
+
+ function addRemovePackage(targetPkg, tableParams){
var method;
- var buttonToShow;
+ var msg = "You have ";
+
+ var btnCell = $("#package-btn-cell-" + targetPkg.id);
+ var inlineNotify = btnCell.children(".inline-notification");
- if (pkgBtnData.directive == 'add') {
+ var i;
+ var dep;
+ var depBtnCell;
+
+ if (targetPkg.directive === 'add') {
method = 'PUT';
- buttonToShow = '#package-rm-btn-' + pkgBtnData.package;
- } else if (pkgBtnData.directive == 'remove') {
+ /* If the package had dependencies also notify that they were added */
+ if (targetPkg.hasOwnProperty('depsAdded') &&
+ targetPkg.depsAdded.length > 0) {
+
+ msg += "added ";
+ msg += "<strong>" + (targetPkg.depsAdded.length + 1) + "</strong>";
+ msg += " packages to " + ctx.recipe.name + ": ";
+ msg += "<strong>" + targetPkg.name + "</strong> and its dependencies";
+
+ for (i in targetPkg.depsAdded){
+ dep = targetPkg.depsAdded[i];
+
+ msg += " <strong>" + dep.name + "</strong>";
+
+ /* Add any cells currently in view to the list of cells which get
+ * an inline notification inside them and which change add/rm state
+ */
+ depBtnCell = $("#package-btn-cell-" + dep.pk);
+ btnCell = btnCell.add(depBtnCell);
+
+ inlineNotify = inlineNotify.add(
+ depBtnCell.children(".inline-notification"));
+ }
+
+ inlineNotify.text(
+ (targetPkg.depsAdded.length + 1) + " packages added");
+
+ } else {
+ msg += "added <strong>1</strong>";
+ msg += " package to " + ctx.recipe.name + ": ";
+ msg += "<strong>" + targetPkg.name + "</strong>";
+ inlineNotify.text("1 package added");
+ }
+
+ } else if (targetPkg.directive === 'remove') {
method = 'DELETE';
- buttonToShow = '#package-add-btn-' + pkgBtnData.package;
+ var numPackageString = "1 package ";
+ var revDepList = "";
+ if (targetPkg.hasOwnProperty('depsRemoved') &&
+ targetPkg.depsRemoved.length > 0) {
+ var depsRemovedLength = targetPkg.depsRemoved.length;
+ var ending = "y: ";
+ var maxRevDepsDisplayed = 5;
+ var d = 0;
+ if (depsRemovedLength > 1) {
+ ending = "ies: ";
+ }
+ numPackageString = (depsRemovedLength + 1) + " packages";
+ revDepList = " and its " + depsRemovedLength + " reverse dependenc" + ending;
+ for (i in targetPkg.depsRemoved){
+ /* include up to maxRevDepsDisplayed rev deps on the page notification */
+ var notShownCount = depsRemovedLength - maxRevDepsDisplayed;
+ dep = targetPkg.depsRemoved[i];
+ if (d < maxRevDepsDisplayed) {
+ if (d > 0) {
+ revDepList += ", ";
+ }
+ revDepList += dep.name;
+ d++;
+ if ((d === maxRevDepsDisplayed) && (notShownCount > 0)) {
+ revDepList += " and " + notShownCount + " more";
+ }
+ }
+
+ /* Add any cells currently in view to the list of cells which get
+ * an inline notification inside them and which change add/rm state
+ */
+ depBtnCell = $("#package-btn-cell-" + dep.pk);
+ btnCell = btnCell.add(depBtnCell);
+
+ inlineNotify = inlineNotify.add(
+ depBtnCell.children(".inline-notification"));
+ }
+ }
+ msg+= "removed " + numPackageString + " from " + ctx.recipe.name + ":";
+ msg += " <strong>" + targetPkg.name + "</strong>";
+ msg += revDepList;
+
+ inlineNotify.text(numPackageString + " removed");
} else {
throw("Unknown package directive: should be add or remove");
}
$.ajax({
type: method,
- url: pkgBtnData.packageUrl,
+ url: targetPkg.packageUrl,
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function(data){
- /* Invalidate the Add | Rm package table's current cache */
- tableParams.nocache = true;
- $.get(ctx.tableApiUrl, tableParams);
- /* Swap the buttons around */
- pkgBtn.hide();
- $(buttonToShow).show();
+ if (data.error !== 'ok'){
+ console.warn(data.error);
+ return;
+ }
+
+ libtoaster.showChangeNotification(msg);
+
+ /* do the in-cell/inline notification to swap buttoms from add to
+ * remove
+ */
+ btnCell.children("button").fadeOut().promise().done(function(){
+ inlineNotify.fadeIn().delay(500).fadeOut(function(){
+ if (targetPkg.directive === 'add')
+ btnCell.children("button[data-directive=remove]").fadeIn();
+ else
+ btnCell.children("button[data-directive=add]").fadeIn();
+ });
+ });
+
+ /* Update the total num packages */
+ $.ajax({
+ type: "GET",
+ url: ctx.recipe.xhrPackageListUrl,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function(data){
+ console.log(data);
+ $("#total-num-packages").text(data.total);
+ $("#total-size-packages").text(data.total_size_formatted);
+ }
+ });
}
});
}
+
+ $("#no-results-show-all-packages").click(function(){
+ $(".no-results-search-input").val("");
+ });
+
+ $("#no-results-remove-search-btn").click(function(){
+ $(".no-results-search-input").val("");
+ $(this).hide();
+ });
+
+ /* Trigger a build of your custom image */
+ $(".build-custom-image").click(function(){
+ libtoaster.startABuild(null, ctx.recipe.name,
+ function(){
+ window.location.replace(libtoaster.ctx.projectBuildsUrl);
+ });
+ });
}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js
index c68f3669f..5a59799bc 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js
@@ -18,10 +18,38 @@ function importLayerPageInit (ctx) {
libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.layersTypeAheadUrl, { include_added: "true" }, function(item){
currentLayerDepSelection = item;
+ });
+
+ // choices available in the typeahead
+ var layerDepsChoices = {};
+
+ // when the typeahead choices change, store an array of the available layer
+ // choices locally, to use for enabling/disabling the "Add layer" button
+ layerDepInput.on("typeahead-choices-change", function (event, data) {
+ layerDepsChoices = {};
- layerDepBtn.removeAttr("disabled");
+ if (data.choices) {
+ data.choices.forEach(function (item) {
+ layerDepsChoices[item.name] = item;
+ });
+ }
});
+ // disable the "Add layer" button when the layer input typeahead is empty
+ // or not in the typeahead choices
+ layerDepInput.on("input change", function () {
+ // get the choices from the typeahead
+ var choice = layerDepsChoices[$(this).val()];
+
+ if (choice) {
+ layerDepBtn.removeAttr("disabled");
+ currentLayerDepSelection = choice;
+ }
+ else {
+ layerDepBtn.attr("disabled", "disabled");
+ currentLayerDepSelection = undefined;
+ }
+ });
/* We automatically add "openembedded-core" layer for convenience as a
* dependency as pretty much all layers depend on this one
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
index 7318b3f50..259271df3 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
@@ -42,7 +42,7 @@ function layerBtnsInit() {
});
});
} else {
- notification.text("1 layer deleted");
+ notification.text("1 layer removed");
/* Deleting a layer we only hanlde the one button */
thisBtn.fadeOut(function(){
notification.fadeIn().delay(500).fadeOut(function(){
@@ -60,8 +60,7 @@ function layerBtnsInit() {
e.preventDefault();
var recipe = $(this).data('recipe-name');
- libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
- libtoaster.ctx.projectId, recipe,
+ libtoaster.startABuild(null, recipe,
function(){
/* Success */
window.location.replace(libtoaster.ctx.projectBuildsUrl);
@@ -77,7 +76,8 @@ function layerBtnsInit() {
if (imgCustomModal.length == 0)
throw("Modal new-custom-image not found");
- imgCustomModal.data('recipe', $(this).data('recipe'));
+ var recipe = {id: $(this).data('recipe'), name: null}
+ newCustomImageModalSetRecipes([recipe]);
imgCustomModal.modal('show');
});
}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
index 8c2ec4cdd..d54540626 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
@@ -32,21 +32,6 @@ function layerDetailsPageInit (ctx) {
}
});
-
- $(".breadcrumb li:first a").click(function(e){
- e.preventDefault();
- /* By default this link goes to the project configuration page. However
- * if we have some builds we go there instead of the default href
- */
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
- if (prjInfo.builds && prjInfo.builds.length > 0) {
- window.location.replace(libtoaster.ctx.projectBuildsUrl);
- } else {
- window.location.replace(libtoaster.ctx.projectPageUrl);
- }
- });
- });
-
function addRemoveDep(depLayerId, add, doneCb) {
var data = { layer_version_id : ctx.layerVersion.id };
if (add)
@@ -258,7 +243,7 @@ function layerDetailsPageInit (ctx) {
$(".select-machine-btn").removeAttr("disabled");
addRmLayerBtn.addClass("btn-danger");
addRmLayerBtn.data('directive', "remove");
- addRmLayerBtn.text(" Delete the "+ctx.layerVersion.name+" layer from your project");
+ addRmLayerBtn.text(" Remove the "+ctx.layerVersion.name+" layer from your project");
addRmLayerBtn.prepend("<span class=\"icon-trash\"></span>");
} else {
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
index c04f7aba2..43930a2c3 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
@@ -21,6 +21,9 @@ var libtoaster = (function (){
var xhrReq;
jQElement.typeahead({
+ // each time the typeahead's choices change, a
+ // "typeahead-choices-change" event is fired with an object
+ // containing the available choices in a "choices" property
source: function(query, process){
xhrParams.search = query;
@@ -36,6 +39,8 @@ var libtoaster = (function (){
xhrReq = null;
+ jQElement.trigger("typeahead-choices-change", {choices: data.results});
+
return process(data.results);
});
},
@@ -90,27 +95,35 @@ var libtoaster = (function (){
jQElement.data('typeahead').render = customRenderFunc;
}
- /*
- * url - the url of the xhr build */
- function _startABuild (url, project_id, targets, onsuccess, onfail) {
+ /* startABuild:
+ * url: xhr_buildrequest or null for current project
+ * targets: an array or space separated list of targets to build
+ * onsuccess: callback for successful execution
+ * onfail: callback for failed execution
+ */
+ function _startABuild (url, targets, onsuccess, onfail) {
- var data = {
- project_id : project_id,
- targets : targets,
+ if (!url)
+ url = libtoaster.ctx.xhrBuildRequestUrl;
+
+ /* Flatten the array of targets into a space spearated list */
+ if (targets instanceof Array){
+ targets = targets.reduce(function(prevV, nextV){
+ return prev + ' ' + next;
+ });
}
$.ajax( {
type: "POST",
url: url,
- data: data,
+ data: { 'targets' : targets },
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function (_data) {
- /* No proper reponse YOCTO #7995
if (_data.error !== "ok") {
console.warn(_data.error);
- } else { */
+ } else {
if (onsuccess !== undefined) onsuccess(_data);
- // }
+ }
},
error: function (_data) {
console.warn("Call failed");
@@ -120,22 +133,25 @@ var libtoaster = (function (){
}
/* cancelABuild:
- * url: projectbuilds
- * builds_ids: space separated list of build request ids
+ * url: xhr_buildrequest url or null for current project
+ * buildRequestIds: space separated list of build request ids
* onsuccess: callback for successful execution
* onfail: callback for failed execution
*/
- function _cancelABuild(url, build_ids, onsuccess, onfail){
+ function _cancelABuild(url, buildRequestIds, onsuccess, onfail){
+ if (!url)
+ url = libtoaster.ctx.xhrBuildRequestUrl;
+
$.ajax( {
type: "POST",
url: url,
- data: { 'buildCancel': build_ids },
+ data: { 'buildCancel': buildRequestIds },
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function (_data) {
if (_data.error !== "ok") {
console.warn(_data.error);
} else {
- if (onsuccess !== undefined) onsuccess(_data);
+ if (onsuccess) onsuccess(_data);
}
},
error: function (_data) {
@@ -316,7 +332,7 @@ var libtoaster = (function (){
} else if (layerDepsList.length === 0 && add === true) {
alertMsg = $("<span>You have added <strong>1</strong> layer to your project: <a id=\"layer-affected-name\"></a></span></span>");
} else if (add === false) {
- alertMsg = $("<span>You have deleted <strong>1</strong> layer from your project: <a id=\"layer-affected-name\"></a></span>");
+ alertMsg = $("<span>You have removed <strong>1</strong> layer from your project: <a id=\"layer-affected-name\"></a></span>");
}
alertMsg.children("#layer-affected-name").text(layer.name);
@@ -332,6 +348,32 @@ var libtoaster = (function (){
$("#change-notification, #change-notification *").fadeIn();
}
+ function _createCustomRecipe(name, baseRecipeId, doneCb){
+ var data = {
+ 'name' : name,
+ 'project' : libtoaster.ctx.projectId,
+ 'base' : baseRecipeId,
+ };
+
+ $.ajax({
+ type: "POST",
+ url: libtoaster.ctx.xhrCustomRecipeUrl,
+ data: data,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function (ret) {
+ if (doneCb){
+ doneCb(ret);
+ } else if (ret.error !== "ok") {
+ console.warn(ret.error);
+ }
+ },
+ error: function (ret) {
+ console.warn("Call failed");
+ console.warn(ret);
+ }
+ });
+ }
+
return {
reload_params : reload_params,
@@ -347,6 +389,7 @@ var libtoaster = (function (){
addRmLayer : _addRmLayer,
makeLayerAddRmAlertMsg : _makeLayerAddRmAlertMsg,
showChangeNotification : _showChangeNotification,
+ createCustomRecipe: _createCustomRecipe,
};
})();
@@ -443,15 +486,21 @@ $(document).ready(function() {
$('.tooltip').hide();
});
- // enable help information tooltip
- $(".get-help").tooltip({container:'body', html:true, delay:{show:300}});
+ /* Initialise bootstrap tooltips */
+ $(".get-help, [data-toggle=tooltip]").tooltip({
+ container : 'body',
+ html : true,
+ delay: { show : 300 }
+ });
// show help bubble only on hover inside tables
$(".hover-help").css("visibility","hidden");
- $("th, td").hover(function () {
+
+ $("table").on("mouseover", "th, td", function () {
$(this).find(".hover-help").css("visibility","visible");
});
- $("th, td").mouseleave(function () {
+
+ $("table").on("mouseleave", "th, td", function () {
$(this).find(".hover-help").css("visibility","hidden");
});
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js
new file mode 100644
index 000000000..09117e1da
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js
@@ -0,0 +1,95 @@
+
+function mrbSectionInit(ctx){
+
+ var projectBuilds;
+
+ if (ctx.mrbType === 'project')
+ projectBuilds = true;
+
+ $(".cancel-build-btn").click(function(e){
+ e.preventDefault();
+
+ var url = $(this).data('request-url');
+ var buildReqIds = $(this).data('buildrequest-id');
+ var banner = $(this).parents(".alert");
+
+ banner.find(".progress-info").fadeOut().promise().done(function(){
+ $("#cancelling-msg-" + buildReqIds).show();
+ console.log("cancel build");
+ libtoaster.cancelABuild(url, buildReqIds, function(){
+ if (projectBuilds == false){
+ /* the all builds page is not 'self updating' like thei
+ * project Builds
+ */
+ window.location.reload();
+ }
+ }, null);
+ });
+ });
+
+ $(".run-again-btn").click(function(e){
+ e.preventDefault();
+
+ var url = $(this).data('request-url');
+ var target = $(this).data('target');
+
+ libtoaster.startABuild(url, target, function(){
+ window.location.reload();
+ }, null);
+ });
+
+
+ var progressTimer;
+
+ if (projectBuilds === true){
+ progressTimer = window.setInterval(function() {
+ libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,
+ function(prjInfo){
+ /* These two are needed because a build can be 100% and still
+ * in progress due to the fact that the % done is updated at the
+ * start of a task so it can be doing the last task at 100%
+ */
+ var inProgress = 0;
+ var allPercentDone = 0;
+ if (prjInfo.builds.length === 0)
+ return
+
+ for (var i in prjInfo.builds){
+ var build = prjInfo.builds[i];
+
+ if (build.outcome === "In Progress" ||
+ $(".progress .bar").length > 0){
+ /* Update the build progress */
+ var percentDone;
+
+ if (build.outcome !== "In Progress"){
+ /* We have to ignore the value when it's Succeeded because it
+ * goes back to 0
+ */
+ percentDone = 100;
+ } else {
+ percentDone = build.percentDone;
+ inProgress++;
+ }
+
+ $("#build-pc-done-" + build.id).text(percentDone);
+ $("#build-pc-done-title-" + build.id).attr("title", percentDone);
+ $("#build-pc-done-bar-" + build.id).css("width",
+ String(percentDone) + "%");
+
+ allPercentDone += percentDone;
+ }
+ }
+
+ if (allPercentDone === (100 * prjInfo.builds.length) && !inProgress)
+ window.location.reload();
+
+ /* Our progress bar is not still showing so shutdown the polling. */
+ if ($(".progress .bar").length === 0)
+ window.clearInterval(progressTimer);
+
+ });
+ }, 1500);
+ }
+}
+
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage.js
deleted file mode 100644
index 935b21ede..000000000
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage.js
+++ /dev/null
@@ -1,49 +0,0 @@
-"use strict";
-
-function newCustomImagePageInit(ctx){
-
- var newCustomImgBtn = $("#create-new-custom-image-btn");
- var imgCustomModal = $("#new-custom-image-modal");
-
- newCustomImgBtn.click(function(e){
- e.preventDefault();
-
- var name = imgCustomModal.find('input').val();
- var baseRecipeId = imgCustomModal.data('recipe');
-
- if (name.length > 0) {
- createCustomRecipe(name, baseRecipeId);
- imgCustomModal.modal('hide');
- } else {
- console.warn("TODO No name supplied");
- }
- });
-
- function createCustomRecipe(name, baseRecipeId){
- var data = {
- 'name' : name,
- 'project' : libtoaster.ctx.projectId,
- 'base' : baseRecipeId,
- };
-
- $.ajax({
- type: "POST",
- url: ctx.xhrCustomRecipeUrl,
- data: data,
- headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
- success: function (ret) {
- if (ret.error !== "ok") {
- console.warn(ret.error);
- } else {
- window.location.replace(ret.url + '?notify=new');
- }
- },
- error: function (ret) {
- console.warn("Call failed");
- console.warn(ret);
- }
- });
- }
-
-
-}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js
new file mode 100644
index 000000000..cb9ed4da0
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js
@@ -0,0 +1,148 @@
+"use strict";
+
+/*
+Used for the newcustomimage_modal actions
+
+The .data('recipe') value on the outer element determines which
+recipe ID is used as the basis for the new custom image recipe created via
+this modal.
+
+Use newCustomImageModalSetRecipes() to set the recipes available as a base
+for the new custom image. This will manage the addition of radio buttons
+to select the base image (or remove the radio buttons, if there is only a
+single base image available).
+*/
+
+function newCustomImageModalInit(){
+
+ var newCustomImgBtn = $("#create-new-custom-image-btn");
+ var imgCustomModal = $("#new-custom-image-modal");
+ var invalidNameHelp = $("#invalid-name-help");
+ var invalidRecipeHelp = $("#invalid-recipe-help");
+ var nameInput = imgCustomModal.find('input');
+
+ var invalidNameMsg = "Image names cannot contain spaces or capital letters. The only allowed special character is dash (-).";
+ var duplicateNameMsg = "A recipe with this name already exists. Image names must be unique.";
+ var duplicateImageInProjectMsg = "An image with this name already exists in this project."
+ var invalidBaseRecipeIdMsg = "Please select an image to customise.";
+
+ // capture clicks on radio buttons inside the modal; when one is selected,
+ // set the recipe on the modal
+ imgCustomModal.on("click", "[name='select-image']", function (e) {
+ clearRecipeError();
+
+ var recipeId = $(e.target).attr('data-recipe');
+ imgCustomModal.data('recipe', recipeId);
+ });
+
+ newCustomImgBtn.click(function(e){
+ e.preventDefault();
+
+ var baseRecipeId = imgCustomModal.data('recipe');
+
+ if (!baseRecipeId) {
+ showRecipeError(invalidBaseRecipeIdMsg);
+ return;
+ }
+
+ if (nameInput.val().length > 0) {
+ libtoaster.createCustomRecipe(nameInput.val(), baseRecipeId,
+ function(ret) {
+ if (ret.error !== "ok") {
+ console.warn(ret.error);
+ if (ret.error === "invalid-name") {
+ showNameError(invalidNameMsg);
+ return;
+ } else if (ret.error === "recipe-already-exists") {
+ showNameError(duplicateNameMsg);
+ return;
+ } else if (ret.error === "image-already-exists") {
+ showNameError(duplicateImageInProjectMsg);
+ return;
+ }
+ } else {
+ imgCustomModal.modal('hide');
+ window.location.replace(ret.url + '?notify=new');
+ }
+ });
+ }
+ });
+
+ function showNameError(text){
+ invalidNameHelp.text(text);
+ invalidNameHelp.show();
+ nameInput.parent().addClass('error');
+ }
+
+ function showRecipeError(text){
+ invalidRecipeHelp.text(text);
+ invalidRecipeHelp.show();
+ }
+
+ function clearRecipeError(){
+ invalidRecipeHelp.hide();
+ }
+
+ nameInput.on('keyup', function(){
+ if (nameInput.val().length === 0){
+ newCustomImgBtn.prop("disabled", true);
+ return
+ }
+
+ if (nameInput.val().search(/[^a-z|0-9|-]/) != -1){
+ showNameError(invalidNameMsg);
+ newCustomImgBtn.prop("disabled", true);
+ nameInput.parent().addClass('error');
+ } else {
+ invalidNameHelp.hide();
+ newCustomImgBtn.prop("disabled", false);
+ nameInput.parent().removeClass('error');
+ }
+ });
+}
+
+// Set the image recipes which can used as the basis for the custom
+// image recipe the user is creating
+//
+// baseRecipes: a list of one or more recipes which can be
+// used as the base for the new custom image recipe in the format:
+// [{'id': <recipe ID>, 'name': <recipe name>'}, ...]
+//
+// if recipes is a single recipe, just show the text box to set the
+// name for the new custom image; if recipes contains multiple recipe objects,
+// show a set of radio buttons so the user can decide which to use as the
+// basis for the new custom image
+function newCustomImageModalSetRecipes(baseRecipes) {
+ var imgCustomModal = $("#new-custom-image-modal");
+ var imageSelector = $('#new-custom-image-modal [data-role="image-selector"]');
+ var imageSelectRadiosContainer = $('#new-custom-image-modal [data-role="image-selector-radios"]');
+
+ // remove any existing radio buttons + labels
+ imageSelector.remove('[data-role="image-radio"]');
+
+ if (baseRecipes.length === 1) {
+ // hide the radio button container
+ imageSelector.hide();
+
+ // set the single recipe ID on the modal as it's the only one
+ // we can build from
+ imgCustomModal.data('recipe', baseRecipes[0].id);
+ }
+ else {
+ // add radio buttons; note that the handlers for the radio buttons
+ // are set in newCustomImageModalInit via event delegation
+ for (var i = 0; i < baseRecipes.length; i++) {
+ var recipe = baseRecipes[i];
+ imageSelectRadiosContainer.append(
+ '<label class="radio" data-role="image-radio">' +
+ recipe.name +
+ '<input type="radio" class="form-control" name="select-image" ' +
+ 'data-recipe="' + recipe.id + '">' +
+ '</label>'
+ );
+ }
+
+ // show the radio button container
+ imageSelector.show();
+ }
+}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js
index e742ef291..3013416dd 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js
@@ -116,6 +116,8 @@ function projectPageInit(ctx) {
addRmLayer(layerObj, true);
/* Reset the text input */
layerAddInput.val("");
+ /* Disable the add layer button*/
+ layerAddBtn.attr("disabled", "disabled");
});
function addRmLayer(layerObj, add){
@@ -143,7 +145,7 @@ function projectPageInit(ctx) {
for (var i in layers){
var layerObj = layers[i];
- var projectLayer = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>");
+ var projectLayer = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Remove\"></span></li>");
projectLayer.data('layer', layerObj);
projectLayer.children("span").tooltip();
@@ -175,11 +177,18 @@ function projectPageInit(ctx) {
function updateLayersCount(){
var count = $("#layers-in-project-list").children().length;
+ var noLayerMsg = $("#no-layers-in-project");
+ var buildInput = $("#build-input");
- if (count === 0)
+
+ if (count === 0) {
+ noLayerMsg.fadeIn();
$("#no-layers-in-project").fadeIn();
- else
- $("#no-layers-in-project").hide();
+ buildInput.attr("disabled", "disabled");
+ } else {
+ noLayerMsg.hide();
+ buildInput.removeAttr("disabled");
+ }
$("#project-layers-count").text(count);
@@ -218,17 +227,19 @@ function projectPageInit(ctx) {
var toBuild = "";
freqBuildList.find(":checked").each(function(){
- toBuild += $(this).val();
+ toBuild += $(this).val() + ' ';
});
- libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl, libtoaster.ctx.projectId, toBuild, function(){
- /* Build started */
- window.location.replace(libtoaster.ctx.projectBuildsUrl);
- },
- function(){
- /* Build start failed */
- /* [YOCTO #7995] */
- window.location.replace(libtoaster.ctx.projectBuildsUrl);
+ toBuild = toBuild.trim();
+
+ libtoaster.startABuild(null, toBuild,
+ function(){
+ /* Build request started */
+ window.location.replace(libtoaster.ctx.projectBuildsUrl);
+ },
+ function(){
+ /* Build request failed */
+ console.warn("Build request failed to be created");
});
});
@@ -380,7 +391,7 @@ function projectPageInit(ctx) {
/* Layers removed */
if (layersToRm && layersToRm.length > 0){
if (layersToRm.length == 1)
- li = '<li><strong>1</strong> layer deleted: '+layersToRm[0].name+'</li>';
+ li = '<li><strong>1</strong> layer removed: '+layersToRm[0].name+'</li>';
else
li = '<li><strong>'+layersToRm.length+'</strong> layers deleted: '+layersDelList+'</li>';
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
new file mode 100644
index 000000000..b09f974e4
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
@@ -0,0 +1,90 @@
+'use strict';
+
+function projectTopBarInit(ctx) {
+
+ var projectNameForm = $("#project-name-change-form");
+ var projectNameContainer = $("#project-name-container");
+ var projectName = $("#project-name");
+ var projectNameFormToggle = $("#project-change-form-toggle");
+ var projectNameChangeCancel = $("#project-name-change-cancel");
+
+ // this doesn't exist for command-line builds
+ var newBuildTargetInput = $("#build-input");
+
+ var newBuildTargetBuildBtn = $("#build-button");
+ var selectedTarget;
+
+ /* Project name change functionality */
+ projectNameFormToggle.click(function(e){
+ e.preventDefault();
+ projectNameContainer.hide();
+ projectNameForm.fadeIn();
+ });
+
+ projectNameChangeCancel.click(function(e){
+ e.preventDefault();
+ projectNameForm.hide();
+ projectNameContainer.fadeIn();
+ });
+
+ $("#project-name-change-btn").click(function(){
+ var newProjectName = $("#project-name-change-input").val();
+
+ libtoaster.editCurrentProject({ projectName: newProjectName }, function (){
+ projectName.html(newProjectName);
+ libtoaster.ctx.projectName = newProjectName;
+ projectNameChangeCancel.click();
+ });
+ });
+
+ /* Nav bar activate state switcher */
+ $("#project-topbar .nav li a").each(function(){
+ if (window.location.pathname === $(this).attr('href'))
+ $(this).parent().addClass('active');
+ else
+ $(this).parent().removeClass('active');
+ });
+
+ if (!newBuildTargetInput.length) {
+ return;
+ }
+
+ /* the following only applies for non-command-line projects */
+
+ /* Recipe build input functionality */
+ if (ctx.numProjectLayers > 0 && ctx.machine){
+ newBuildTargetInput.removeAttr("disabled");
+ }
+
+ libtoaster.makeTypeahead(newBuildTargetInput,
+ libtoaster.ctx.recipesTypeAheadUrl, {}, function (item) {
+ selectedTarget = item;
+ newBuildTargetBuildBtn.removeAttr("disabled");
+ });
+
+ newBuildTargetInput.on('input', function () {
+ if ($(this).val().length === 0) {
+ newBuildTargetBuildBtn.attr("disabled", "disabled");
+ } else {
+ newBuildTargetBuildBtn.removeAttr("disabled");
+ }
+ });
+
+ newBuildTargetBuildBtn.click(function (e) {
+ e.preventDefault();
+ if (!newBuildTargetInput.val()) {
+ return;
+ }
+ /* We use the value of the input field so as to maintain any command also
+ * added e.g. core-image-minimal:clean and because we can build targets
+ * that toaster doesn't yet know about
+ */
+ selectedTarget = { name: newBuildTargetInput.val() };
+
+ /* Fire off the build */
+ libtoaster.startABuild(null, selectedTarget.name,
+ function(){
+ window.location.replace(libtoaster.ctx.projectBuildsUrl);
+ }, null);
+ });
+}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/qunit-1.18.0.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/qunit-1.18.0.js
new file mode 100644
index 000000000..fadd3403a
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/qunit-1.18.0.js
@@ -0,0 +1,347 @@
+(function(window){var QUnit,config,onErrorFnPrev,loggingCallbacks={},fileName=(sourceFromStacktrace(0)||"").replace(/(:\d+)+\)?/,"").replace(/.+\//,""),toString=Object.prototype.toString,hasOwn=Object.prototype.hasOwnProperty,Date=window.Date,now=Date.now||function(){return new Date().getTime();},globalStartCalled=false,runStarted=false,setTimeout=window.setTimeout,clearTimeout=window.clearTimeout,defined={document:window.document!==undefined,setTimeout:window.setTimeout!==undefined,sessionStorage:(function(){var x="qunit-test-string";try{sessionStorage.setItem(x,x);sessionStorage.removeItem(x);return true;}catch(e){return false;}}())},errorString=function(error){var name,message,errorString=error.toString();if(errorString.substring(0,7)==="[object"){name=error.name?error.name.toString():"Error";message=error.message?error.message.toString():"";if(name&&message){return name+": "+message;}else if(name){return name;}else if(message){return message;}else{return "Error";}}else{return errorString;}},objectValues =function(obj){var key,val,vals=QUnit.is("array",obj)?[]:{};for(key in obj){if(hasOwn.call(obj,key)){val=obj[key];vals[key]=val===Object(val)?objectValues(val):val;}}
+return vals;};QUnit={};config={queue:[],blocking:true,reorder:true,altertitle:true,scrolltop:true,requireExpects:false,maxDepth:5,urlConfig:[{id:"hidepassed",label:"Hide passed tests",tooltip:"Only show tests and assertions that fail. Stored as query-strings."},{id:"noglobals",label:"Check for Globals",tooltip:"Enabling this will test if any test introduces new properties on the "+
+"`window` object. Stored as query-strings."},{id:"notrycatch",label:"No try-catch",tooltip:"Enabling this will run tests outside of a try-catch block. Makes debugging "+
+"exceptions in IE reasonable. Stored as query-strings."}],modules:[],currentModule:{name:"",tests:[]},callbacks:{}};config.modules.push(config.currentModule);(function(){var i,current,location=window.location||{search:"",protocol:"file:"},params=location.search.slice(1).split("&"),length=params.length,urlParams={};if(params[0]){for(i=0;i<length;i++){current=params[i].split("=");current[0]=decodeURIComponent(current[0]);current[1]=current[1]?decodeURIComponent(current[1]):true;if(urlParams[current[0]]){urlParams[current[0]]=[].concat(urlParams[current[0]],current[1]);}else{urlParams[current[0]]=current[1];}}}
+if(urlParams.filter===true){delete urlParams.filter;}
+QUnit.urlParams=urlParams;config.filter=urlParams.filter;if(urlParams.maxDepth){config.maxDepth=parseInt(urlParams.maxDepth,10)===-1?Number.POSITIVE_INFINITY:urlParams.maxDepth;}
+config.testId=[];if(urlParams.testId){urlParams.testId=decodeURIComponent(urlParams.testId).split(",");for(i=0;i<urlParams.testId.length;i++){config.testId.push(urlParams.testId[i]);}}
+QUnit.isLocal=location.protocol==="file:";QUnit.version="1.18.0";}());extend(QUnit,{module:function(name,testEnvironment){var currentModule={name:name,testEnvironment:testEnvironment,tests:[]};if(testEnvironment&&testEnvironment.setup){testEnvironment.beforeEach=testEnvironment.setup;delete testEnvironment.setup;}
+if(testEnvironment&&testEnvironment.teardown){testEnvironment.afterEach=testEnvironment.teardown;delete testEnvironment.teardown;}
+config.modules.push(currentModule);config.currentModule=currentModule;},asyncTest:function(testName,expected,callback){if(arguments.length===2){callback=expected;expected=null;}
+QUnit.test(testName,expected,callback,true);},test:function(testName,expected,callback,async){var test;if(arguments.length===2){callback=expected;expected=null;}
+test=new Test({testName:testName,expected:expected,async:async,callback:callback});test.queue();},skip:function(testName){var test=new Test({testName:testName,skip:true});test.queue();},//
+start:function(count){var globalStartAlreadyCalled=globalStartCalled;if(!config.current){globalStartCalled=true;if(runStarted){throw new Error("Called start() outside of a test context while already started");}else if(globalStartAlreadyCalled||count>1){throw new Error("Called start() outside of a test context too many times");}else if(config.autostart){throw new Error("Called start() outside of a test context when "+
+"QUnit.config.autostart was true");}else if(!config.pageLoaded){config.autostart=true;return;}}else{config.current.semaphore-=count||1;if(config.current.semaphore>0){return;}
+if(config.current.semaphore<0){config.current.semaphore=0;QUnit.pushFailure("Called start() while already started (test's semaphore was 0 already)",sourceFromStacktrace(2));return;}}
+resumeProcessing();},stop:function(count){if(!config.current){throw new Error("Called stop() outside of a test context");}
+config.current.semaphore+=count||1;pauseProcessing();},config:config,is:function(type,obj){return QUnit.objectType(obj)===type;},objectType:function(obj){if(typeof obj==="undefined"){return "undefined";}//
+if(obj===null){return "null";}
+var match=toString.call(obj).match(/^\[object\s(.*)\]$/),type=match&&match[1]||"";switch(type){case "Number":if(isNaN(obj)){return "nan";}
+return "number";case "String":case "Boolean":case "Array":case "Date":case "RegExp":case "Function":return type.toLowerCase();}
+if(typeof obj==="object"){return "object";}
+return undefined;},extend:extend,load:function(){config.pageLoaded=true;extend(config,{stats:{all:0,bad:0},moduleStats:{all:0,bad:0},started:0,updateRate:1000,autostart:true,filter:""},true);config.blocking=false;if(config.autostart){resumeProcessing();}}});(function(){var i,l,key,callbacks=["begin","done","log","testStart","testDone","moduleStart","moduleDone"];function registerLoggingCallback(key){var loggingCallback=function(callback){if(QUnit.objectType(callback)!=="function"){throw new Error("QUnit logging methods require a callback function as their first parameters.");}
+config.callbacks[key].push(callback);};loggingCallbacks[key]=loggingCallback;return loggingCallback;}
+for(i=0,l=callbacks.length;i<l;i++){key=callbacks[i];if(QUnit.objectType(config.callbacks[key])==="undefined"){config.callbacks[key]=[];}
+QUnit[key]=registerLoggingCallback(key);}})();onErrorFnPrev=window.onerror;//
+window.onerror=function(error,filePath,linerNr){var ret=false;if(onErrorFnPrev){ret=onErrorFnPrev(error,filePath,linerNr);}
+if(ret!==true){if(QUnit.config.current){if(QUnit.config.current.ignoreGlobalErrors){return true;}
+QUnit.pushFailure(error,filePath+":"+linerNr);}else{QUnit.test("global failure",extend(function(){QUnit.pushFailure(error,filePath+":"+linerNr);},{validTest:true}));}
+return false;}
+return ret;};function done(){var runtime,passed;config.autorun=true;if(config.previousModule){runLoggingCallbacks("moduleDone",{name:config.previousModule.name,tests:config.previousModule.tests,failed:config.moduleStats.bad,passed:config.moduleStats.all-config.moduleStats.bad,total:config.moduleStats.all,runtime:now()-config.moduleStats.started});}
+delete config.previousModule;runtime=now()-config.started;passed=config.stats.all-config.stats.bad;runLoggingCallbacks("done",{failed:config.stats.bad,passed:passed,total:config.stats.all,runtime:runtime});}
+function extractStacktrace(e,offset){offset=offset===undefined?4:offset;var stack,include,i;if(e.stack){stack=e.stack.split("\n");if(/^error$/i.test(stack[0])){stack.shift();}
+if(fileName){include=[];for(i=offset;i<stack.length;i++){if(stack[i].indexOf(fileName)!==-1){break;}
+include.push(stack[i]);}
+if(include.length){return include.join("\n");}}
+return stack[offset];//
+}else if(e.sourceURL){if(/qunit.js$/.test(e.sourceURL)){return;}
+return e.sourceURL+":"+e.line;}}
+function sourceFromStacktrace(offset){var error=new Error();if(!error.stack){try{throw error;}catch(err){error=err;}}
+return extractStacktrace(error,offset);}
+function synchronize(callback,last){if(QUnit.objectType(callback)==="array"){while(callback.length){synchronize(callback.shift());}
+return;}
+config.queue.push(callback);if(config.autorun&&!config.blocking){process(last);}}
+function process(last){function next(){process(last);}
+var start=now();config.depth=(config.depth||0)+1;while(config.queue.length&&!config.blocking){if(!defined.setTimeout||config.updateRate<=0||((now()-start)<config.updateRate)){if(config.current){config.current.usedAsync=false;}
+config.queue.shift()();}else{setTimeout(next,13);break;}}
+config.depth--;if(last&&!config.blocking&&!config.queue.length&&config.depth===0){done();}}
+function begin(){var i,l,modulesLog=[];if(!config.started){config.started=now();verifyLoggingCallbacks();if(config.modules[0].name===""&&config.modules[0].tests.length===0){config.modules.shift();}
+for(i=0,l=config.modules.length;i<l;i++){modulesLog.push({name:config.modules[i].name,tests:config.modules[i].tests});}
+runLoggingCallbacks("begin",{totalTests:Test.count,modules:modulesLog});}
+config.blocking=false;process(true);}
+function resumeProcessing(){runStarted=true;if(defined.setTimeout){setTimeout(function(){if(config.current&&config.current.semaphore>0){return;}
+if(config.timeout){clearTimeout(config.timeout);}
+begin();},13);}else{begin();}}
+function pauseProcessing(){config.blocking=true;if(config.testTimeout&&defined.setTimeout){clearTimeout(config.timeout);config.timeout=setTimeout(function(){if(config.current){config.current.semaphore=0;QUnit.pushFailure("Test timed out",sourceFromStacktrace(2));}else{throw new Error("Test timed out");}
+resumeProcessing();},config.testTimeout);}}
+function saveGlobal(){config.pollution=[];if (config.noglobals){for(var key in window){if(hasOwn.call(window,key)){if(/^qunit-test-output/.test(key)){continue;}
+config.pollution.push(key);}}}}
+function checkPollution(){var newGlobals,deletedGlobals,old=config.pollution;saveGlobal();newGlobals=diff(config.pollution,old);if(newGlobals.length>0){QUnit.pushFailure("Introduced global variable(s): "+newGlobals.join(", "));}
+deletedGlobals=diff(old,config.pollution);if(deletedGlobals.length>0){QUnit.pushFailure("Deleted global variable(s): "+deletedGlobals.join(", "));}}
+function diff(a,b){var i,j,result=a.slice();for(i=0;i<result.length;i++){for(j=0;j<b.length;j++){if(result[i]===b[j]){result.splice(i,1);i--;break;}}}
+return result;}
+function extend(a,b,undefOnly){for(var prop in b){if(hasOwn.call(b,prop)){if(!(prop==="constructor"&&a===window)){if(b[prop]===undefined){delete a[prop];}else if(!(undefOnly&&typeof a[prop]!=="undefined")){a[prop]=b[prop];}}}}
+return a;}
+function runLoggingCallbacks(key,args){var i,l,callbacks;callbacks=config.callbacks[key];for(i=0,l=callbacks.length;i<l;i++){callbacks[i](args);}}
+function verifyLoggingCallbacks(){var loggingCallback,userCallback;for(loggingCallback in loggingCallbacks){if(QUnit[loggingCallback]!==loggingCallbacks[loggingCallback]){userCallback=QUnit[loggingCallback];QUnit[loggingCallback]=loggingCallbacks[loggingCallback];QUnit[loggingCallback](userCallback);if(window.console&&window.console.warn){window.console.warn("QUnit."+loggingCallback+" was replaced with a new value.\n"+
+"Please, check out the documentation on how to apply logging callbacks.\n"+
+"Reference: http://api.qunitjs.com/category/callbacks/");}}}}
+function inArray(elem,array){if(array.indexOf){return array.indexOf(elem);}
+for(var i=0,length=array.length;i<length;i++){if(array[i]===elem){return i;}}
+return-1;}
+function Test(settings){var i,l;++Test.count;extend(this,settings);this.assertions=[];this.semaphore=0;this.usedAsync=false;this.module=config.currentModule;this.stack=sourceFromStacktrace(3);for(i=0,l=this.module.tests;i<l.length;i++){if(this.module.tests[i].name===this.testName){this.testName+=" ";}}
+this.testId=generateHash(this.module.name,this.testName);this.module.tests.push({name:this.testName,testId:this.testId});if(settings.skip){this.callback=function(){};this.async=false;this.expected=0;}else{this.assert=new Assert(this);}}
+Test.count=0;Test.prototype={before:function(){if(this.module!==config.previousModule||//
+!hasOwn.call(config,"previousModule")){if(hasOwn.call(config,"previousModule")){runLoggingCallbacks("moduleDone",{name:config.previousModule.name,tests:config.previousModule.tests,failed:config.moduleStats.bad,passed:config.moduleStats.all-config.moduleStats.bad,total:config.moduleStats.all,runtime:now()-config.moduleStats.started});}
+config.previousModule=this.module;config.moduleStats={all:0,bad:0,started:now()};runLoggingCallbacks("moduleStart",{name:this.module.name,tests:this.module.tests});}
+config.current=this;this.testEnvironment=extend({},this.module.testEnvironment);delete this.testEnvironment.beforeEach;delete this.testEnvironment.afterEach;this.started=now();runLoggingCallbacks("testStart",{name:this.testName,module:this.module.name,testId:this.testId});if(!config.pollution){saveGlobal();}},run:function(){var promise;config.current=this;if(this.async){QUnit.stop();}
+this.callbackStarted=now();if(config.notrycatch){promise=this.callback.call(this.testEnvironment,this.assert);this.resolvePromise(promise);return;}
+try{promise=this.callback.call(this.testEnvironment,this.assert);this.resolvePromise(promise);}catch(e){this.pushFailure("Died on test #"+(this.assertions.length+1)+" "+
+this.stack+": "+(e.message||e),extractStacktrace(e,0));saveGlobal();if(config.blocking){QUnit.start();}}},after:function(){checkPollution();},queueHook:function(hook,hookName){var promise,test=this;return function runHook(){config.current=test;if(config.notrycatch){promise=hook.call(test.testEnvironment,test.assert);test.resolvePromise(promise,hookName);return;}
+try{promise=hook.call(test.testEnvironment,test.assert);test.resolvePromise(promise,hookName);}catch(error){test.pushFailure(hookName+" failed on "+test.testName+": "+(error.message||error),extractStacktrace(error,0));}};},hooks:function(handler){var hooks=[];if(this.skip){return hooks;}
+if(this.module.testEnvironment&&QUnit.objectType(this.module.testEnvironment[handler])==="function"){hooks.push(this.queueHook(this.module.testEnvironment[handler],handler));}
+return hooks;},finish:function(){config.current=this;if(config.requireExpects&&this.expected===null){this.pushFailure("Expected number of assertions to be defined, but expect() was "+
+"not called.",this.stack);}else if(this.expected!==null&&this.expected!==this.assertions.length){this.pushFailure("Expected "+this.expected+" assertions, but "+
+this.assertions.length+" were run",this.stack);}else if(this.expected===null&&!this.assertions.length){this.pushFailure("Expected at least one assertion, but none were run - call "+
+"expect(0) to accept zero assertions.",this.stack);}
+var i,bad=0;this.runtime=now()-this.started;config.stats.all+=this.assertions.length;config.moduleStats.all+=this.assertions.length;for(i=0;i<this.assertions.length;i++){if(!this.assertions[i].result){bad++;config.stats.bad++;config.moduleStats.bad++;}}
+runLoggingCallbacks("testDone",{name:this.testName,module:this.module.name,skipped:!!this.skip,failed:bad,passed:this.assertions.length-bad,total:this.assertions.length,runtime:this.runtime,assertions:this.assertions,testId:this.testId,duration:this.runtime});QUnit.reset();config.current=undefined;},queue:function(){var bad,test=this;if(!this.valid()){return;}
+function run(){synchronize([function(){test.before();},test.hooks("beforeEach"),function(){test.run();},test.hooks("afterEach").reverse(),function(){test.after();},function(){test.finish();}]);}
+bad=QUnit.config.reorder&&defined.sessionStorage&&+sessionStorage.getItem("qunit-test-"+this.module.name+"-"+this.testName);if(bad){run();}else{synchronize(run,true);}},push:function(result,actual,expected,message){var source,details={module:this.module.name,name:this.testName,result:result,message:message,actual:actual,expected:expected,testId:this.testId,runtime:now()-this.started};if(!result){source=sourceFromStacktrace();if(source){details.source=source;}}
+runLoggingCallbacks("log",details);this.assertions.push({result:!!result,message:message});},pushFailure:function(message,source,actual){if(!this instanceof Test){throw new Error("pushFailure() assertion outside test context, was "+
+sourceFromStacktrace(2));}
+var details={module:this.module.name,name:this.testName,result:false,message:message||"error",actual:actual||null,testId:this.testId,runtime:now()-this.started};if(source){details.source=source;}
+runLoggingCallbacks("log",details);this.assertions.push({result:false,message:message});},resolvePromise:function(promise,phase){var then,message,test=this;if(promise!=null){then=promise.then;if(QUnit.objectType(then)==="function"){QUnit.stop();then.call(promise,QUnit.start,function(error){message="Promise rejected "+(!phase?"during":phase.replace(/Each$/,""))+
+" "+test.testName+": "+(error.message||error);test.pushFailure(message,extractStacktrace(error,0));saveGlobal();QUnit.start();});}}},valid:function(){var include,filter=config.filter&&config.filter.toLowerCase(),module=QUnit.urlParams.module&&QUnit.urlParams.module.toLowerCase(),fullName=(this.module.name+": "+this.testName).toLowerCase();if(this.callback&&this.callback.validTest){return true;}
+if(config.testId.length>0&&inArray(this.testId,config.testId)<0){return false;}
+if(module&&(!this.module.name||this.module.name.toLowerCase()!==module)){return false;}
+if(!filter){return true;}
+include=filter.charAt(0)!=="!";if(!include){filter=filter.slice(1);}
+if(fullName.indexOf(filter)!==-1){return include;}
+return!include;}};QUnit.reset=function(){if(typeof window==="undefined"){return;}
+var fixture=defined.document&&document.getElementById&&document.getElementById("qunit-fixture");if(fixture){fixture.innerHTML=config.fixture;}};QUnit.pushFailure=function(){if(!QUnit.config.current){throw new Error("pushFailure() assertion outside test context, in "+
+sourceFromStacktrace(2));}
+var currentTest=QUnit.config.current;return currentTest.pushFailure.apply(currentTest,arguments);};function generateHash(module,testName){var hex,i=0,hash=0,str=module+"\x1C"+testName,len=str.length;for(;i<len;i++){hash=((hash<<5)-hash)+str.charCodeAt(i);hash|=0;}
+hex=(0x100000000+hash).toString(16);if(hex.length<8){hex="0000000"+hex;}
+return hex.slice(-8);}
+function Assert(testContext){this.test=testContext;}
+QUnit.assert=Assert.prototype={expect:function(asserts){if(arguments.length===1){this.test.expected=asserts;}else{return this.test.expected;}},async:function(){var test=this.test,popped=false;test.semaphore+=1;test.usedAsync=true;pauseProcessing();return function done(){if(!popped){test.semaphore-=1;popped=true;resumeProcessing();}else{test.pushFailure("Called the callback returned from `assert.async` more than once",sourceFromStacktrace(2));}};},push:function(){var assert=this,currentTest=(assert instanceof Assert&&assert.test)||QUnit.config.current;if(!currentTest){throw new Error("assertion outside test context, in "+sourceFromStacktrace(2));}
+if(currentTest.usedAsync===true&&currentTest.semaphore===0){currentTest.pushFailure("Assertion after the final `assert.async` was resolved",sourceFromStacktrace(2));}
+if(!(assert instanceof Assert)){assert=currentTest.assert;}
+return assert.test.push.apply(assert.test,arguments);},ok:function(result,message){message=message||(result?"okay":"failed, expected argument to be truthy, was: "+
+QUnit.dump.parse(result));this.push(!!result,result,true,message);},notOk:function(result,message){message=message||(!result?"okay":"failed, expected argument to be falsy, was: "+
+QUnit.dump.parse(result));this.push(!result,result,false,message);},equal:function(actual,expected,message){this.push(expected==actual,actual,expected,message);},notEqual:function(actual,expected,message){this.push(expected!=actual,actual,expected,message);},propEqual:function(actual,expected,message){actual=objectValues(actual);expected=objectValues(expected);this.push(QUnit.equiv(actual,expected),actual,expected,message);},notPropEqual:function(actual,expected,message){actual=objectValues(actual);expected=objectValues(expected);this.push(!QUnit.equiv(actual,expected),actual,expected,message);},deepEqual:function(actual,expected,message){this.push(QUnit.equiv(actual,expected),actual,expected,message);},notDeepEqual:function(actual,expected,message){this.push(!QUnit.equiv(actual,expected),actual,expected,message);},strictEqual:function(actual,expected,message){this.push(expected===actual,actual,expected,message);},notStrictEqual:function(actual,expected,message){this.push(expected!==actual,actual,expected,message);},"throws":function(block,expected,message){var actual,expectedType,expectedOutput=expected,ok=false,currentTest=(this instanceof Assert&&this.test)||QUnit.config.current;if(message==null&&typeof expected==="string"){message=expected;expected=null;}
+currentTest.ignoreGlobalErrors=true;try{block.call(currentTest.testEnvironment);}catch(e){actual=e;}
+currentTest.ignoreGlobalErrors=false;if(actual){expectedType=QUnit.objectType(expected);if(!expected){ok=true;expectedOutput=null;}else if(expectedType==="regexp"){ok=expected.test(errorString(actual));}else if(expectedType==="string"){ok=expected===errorString(actual);}else if(expectedType==="function"&&actual instanceof expected){ok=true;}else if(expectedType==="object"){ok=actual instanceof expected.constructor&&actual.name===expected.name&&actual.message===expected.message;}else if(expectedType==="function"&&expected.call({},actual)===true){expectedOutput= null;ok=true;}}
+currentTest.assert.push(ok,actual,expectedOutput,message);}};(function(){Assert.prototype.raises=Assert.prototype["throws"];}());QUnit.equiv=(function(){function bindCallbacks(o,callbacks,args){var prop=QUnit.objectType(o);if(prop){if(QUnit.objectType(callbacks[prop])==="function"){return callbacks[prop].apply(callbacks,args);}else{return callbacks[prop];}}}
+var innerEquiv,callers=[],parents=[],parentsB=[],getProto=Object.getPrototypeOf||function(obj){return obj.__proto__;},callbacks=(function(){function useStrictEquality(b,a){if(b instanceof a.constructor||a instanceof b.constructor){return a==b;}else{return a===b;}}
+return{"string":useStrictEquality,"boolean":useStrictEquality,"number":useStrictEquality,"null":useStrictEquality,"undefined":useStrictEquality,"nan":function(b){return isNaN(b);},"date":function(b,a){return QUnit.objectType(b)==="date"&&a.valueOf()===b.valueOf();},"regexp":function(b,a){return QUnit.objectType(b)==="regexp"&&a.source===b.source&&a.global===b.global&&a.ignoreCase===b.ignoreCase&&a.multiline===b.multiline&&a.sticky===b.sticky;},"function":function(){var caller=callers[callers.length-1];return caller!==Object&&typeof caller!=="undefined";},"array":function(b,a){var i,j,len,loop,aCircular,bCircular;if(QUnit.objectType(b)!=="array"){return false;}
+len=a.length;if(len!==b.length){return false;}
+parents.push(a);parentsB.push(b);for(i=0;i<len;i++){loop=false;for(j=0;j<parents.length;j++){aCircular=parents[j]===a[i];bCircular=parentsB[j]===b[i];if(aCircular||bCircular){ if(a[i]===b[i]||aCircular&&bCircular){loop=true;}else{parents.pop();parentsB.pop();return false;}}}
+if(!loop&&!innerEquiv(a[i],b[i])){parents.pop();parentsB.pop();return false;}}
+parents.pop();parentsB.pop();return true;},"object":function(b,a){var i,j,loop,aCircular,bCircular,eq=true,aProperties=[],bProperties=[];if(a.constructor!==b.constructor){if(!((getProto(a)===null&&getProto(b)===Object.prototype)||(getProto(b)===null&&getProto(a)===Object.prototype))){return false;}}
+callers.push(a.constructor);parents.push(a);parentsB.push(b);for(i in a){loop=false;for(j=0;j<parents.length;j++){aCircular=parents[j]===a[i];bCircular=parentsB[j]===b[i];if(aCircular||bCircular){if(a[i]===b[i]||aCircular&&bCircular){loop=true;}else{eq=false;break;}}}
+aProperties.push(i);if(!loop&&!innerEquiv(a[i],b[i])){eq=false;break;}}
+parents.pop();parentsB.pop();callers.pop();for(i in b){bProperties.push(i);}
+return eq&&innerEquiv(aProperties.sort(),bProperties.sort());}};}());innerEquiv=function(){var args=[].slice.apply(arguments);if(args.length<2){return true;}
+return((function(a,b){if(a===b){return true;}else if(a===null||b===null||typeof a==="undefined"||typeof b==="undefined"||QUnit.objectType(a)!==QUnit.objectType(b)){return false;}else{return bindCallbacks(a,callbacks,[b,a]);}}(args[0],args[1]))&&innerEquiv.apply(this,args.splice(1,args.length-1)));};return innerEquiv;}());QUnit.dump=(function(){function quote(str){return "\""+str.toString().replace(/"/g,"\\\"")+"\"";}
+function literal(o){return o+"";}
+function join(pre,arr,post){var s=dump.separator(),base=dump.indent(),inner=dump.indent(1);if(arr.join){arr=arr.join(","+s+inner);}
+if(!arr){return pre+post;}
+return[pre,inner+arr,base+post].join(s);}
+function array(arr,stack){var i=arr.length,ret=new Array(i);if(dump.maxDepth&&dump.depth>dump.maxDepth){return "[object Array]";}
+this.up();while(i--){ret[i]=this.parse(arr[i],undefined,stack);}
+this.down();return join("[",ret,"]");}
+var reName=/^function (\w+)/,dump={parse:function(obj,objType,stack){stack=stack||[];var res,parser,parserType,inStack=inArray(obj,stack);if(inStack!==-1){return "recursion("+(inStack-stack.length)+")";}
+objType=objType||this.typeOf(obj);parser=this.parsers[objType];parserType=typeof parser;if(parserType==="function"){stack.push(obj);res=parser.call(this,obj,stack);stack.pop();return res;}
+return(parserType==="string")?parser:this.parsers.error;},typeOf:function(obj){var type;if(obj===null){type="null";}else if(typeof obj==="undefined"){type="undefined";}else if(QUnit.is("regexp",obj)){type="regexp";}else if(QUnit.is("date",obj)){type="date";}else if(QUnit.is("function",obj)){type="function";}else if(obj.setInterval!==undefined&&obj.document!==undefined&&obj.nodeType===undefined){type="window";}else if(obj.nodeType===9){type="document";}else if(obj.nodeType){type="node";}else if(toString.call(obj)==="[object Array]"||(typeof obj.length==="number"&&obj.item!==undefined&&(obj.length?obj.item(0)===obj[ 0]:(obj.item(0)===null&&obj[0]===undefined)))){type="array";}else if(obj.constructor===Error.prototype.constructor){type="error";}else{type=typeof obj;}
+return type;},separator:function(){return this.multiline?this.HTML?"<br />":"\n":this.HTML?"&#160;":" ";},indent:function(extra){if(!this.multiline){return "";}
+var chr=this.indentChar;if(this.HTML){chr=chr.replace(/\t/g," ").replace(/ /g,"&#160;");}
+return new Array(this.depth+(extra||0)).join(chr);},up:function(a){this.depth+=a||1;},down:function(a){this.depth-=a||1;},setParser:function(name,parser){this.parsers[name]=parser;},quote:quote,literal:literal,join:join,depth:1,maxDepth:QUnit.config.maxDepth,parsers:{window:"[Window]",document:"[Document]",error:function(error){return "Error(\""+error.message+"\")";},unknown:"[Unknown]","null":"null","undefined":"undefined","function":function(fn){var ret="function",name="name" in fn?fn.name:(reName.exec(fn)||[])[1];if(name){ret+=" "+name;}
+ret+="( ";ret=[ret,dump.parse(fn,"functionArgs"),"){"].join("");return join(ret,dump.parse(fn,"functionCode"),"}");},array:array,nodelist:array,"arguments":array,object:function(map,stack){var keys,key,val,i,nonEnumerableProperties,ret=[];if(dump.maxDepth&&dump.depth>dump.maxDepth){return "[object Object]";}
+dump.up(); keys=[];for(key in map){keys.push(key);}
+nonEnumerableProperties=["message","name"];for(i in nonEnumerableProperties){key=nonEnumerableProperties[i];if(key in map&&inArray(key,keys)<0){keys.push(key);}}
+keys.sort();for(i=0;i<keys.length;i++){key=keys[i];val=map[key];ret.push(dump.parse(key,"key")+": "+
+dump.parse(val,undefined,stack));}
+dump.down();return join("{",ret,"}");},node:function(node){var len,i,val,open=dump.HTML?"&lt;":"<",close=dump.HTML?"&gt;":">",tag=node.nodeName.toLowerCase(),ret=open+tag,attrs=node.attributes;if(attrs){for(i=0,len=attrs.length;i<len;i++){val=attrs[i].nodeValue;if(val&&val!=="inherit"){ret+=" "+attrs[i].nodeName+"="+
+dump.parse(val,"attribute");}}}
+ret+=close;if(node.nodeType===3||node.nodeType===4){ret+=node.nodeValue;}
+return ret+open+"/"+tag+close;},functionArgs:function(fn){var args,l=fn.length;if(!l){return "";}
+args=new Array(l);while(l--){args[l]=String.fromCharCode(97+l);}
+return " "+args.join(", ")+" ";},key:quote,functionCode:"[code]",attribute:quote,string:quote,date:quote,regexp:literal,number:literal,"boolean":literal},HTML:false,indentChar:" ",multiline:true};return dump;}());QUnit.jsDump=QUnit.dump;if(typeof window!=="undefined"){(function(){var i,assertions=Assert.prototype;function applyCurrent(current){return function(){var assert=new Assert(QUnit.config.current);current.apply(assert,arguments);};}
+for(i in assertions){QUnit[i]=applyCurrent(assertions[i]);}})();(function(){var i,l,keys=["test","module","expect","asyncTest","start","stop","ok","notOk","equal","notEqual","propEqual","notPropEqual","deepEqual","notDeepEqual","strictEqual","notStrictEqual","throws"];for(i=0,l=keys.length;i<l;i++){window[keys[i]]=QUnit[keys[i]];}})();window.QUnit=QUnit;}
+if(typeof module!=="undefined"&&module&&module.exports){module.exports=QUnit;module.exports.QUnit=QUnit;}
+if(typeof exports!=="undefined"&&exports){exports.QUnit=QUnit;}
+if(typeof define==="function"&&define.amd){define(function(){return QUnit;});QUnit.config.autostart=false;}}((function(){return this;})()));//
+/**/
+QUnit.diff=(function(){function DiffMatchPatch(){this.DiffTimeout=1.0;this.DiffEditCost=4;}
+var DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;DiffMatchPatch.prototype.DiffMain=function(text1,text2,optChecklines,optDeadline){var deadline,checklines,commonlength,commonprefix,commonsuffix,diffs;if(typeof optDeadline==="undefined"){if(this.DiffTimeout<=0){optDeadline=Number.MAX_VALUE;}else{ optDeadline=(new Date()).getTime()+this.DiffTimeout*1000;}}
+deadline=optDeadline;if(text1===null||text2===null){throw new Error("Null input. (DiffMain)");}
+if(text1===text2){if(text1){return[[DIFF_EQUAL,text1]];}
+return[];}
+if(typeof optChecklines==="undefined"){optChecklines=true;}
+checklines=optChecklines;commonlength=this.diffCommonPrefix(text1,text2);commonprefix=text1.substring(0,commonlength);text1=text1.substring(commonlength);text2=text2.substring(commonlength);commonlength=this.diffCommonSuffix(text1,text2);commonsuffix=text1.substring(text1.length-commonlength);text1=text1.substring(0,text1.length-commonlength);text2=text2.substring(0,text2.length-commonlength);diffs=this.diffCompute(text1,text2,checklines,deadline);if(commonprefix){diffs.unshift([DIFF_EQUAL,commonprefix]);}
+if(commonsuffix){diffs.push([DIFF_EQUAL,commonsuffix]);}
+this.diffCleanupMerge(diffs);return diffs;};DiffMatchPatch.prototype.diffCleanupEfficiency=function(diffs){var changes,equalities,equalitiesLength,lastequality,pointer,preIns,preDel,postIns,postDel;changes=false;equalities=[];equalitiesLength=0;lastequality=null;pointer=0;preIns=false;preDel=false;postIns=false;postDel=false;while(pointer<diffs.length){if(diffs[pointer][0]===DIFF_EQUAL){if(diffs[pointer][1].length<this.DiffEditCost&&(postIns||postDel)){equalities[equalitiesLength++]=pointer;preIns=postIns;preDel=postDel;lastequality=diffs[pointer][1];}else{equalitiesLength=0;lastequality=null;}
+postIns=postDel=false;}else{if(diffs[pointer][0]===DIFF_DELETE){postDel=true;}else{postIns=true;}
+if(lastequality&&((preIns&&preDel&&postIns&&postDel)||((lastequality.length<this.DiffEditCost/2)&&(preIns+preDel+postIns+postDel)===3))){diffs.splice(equalities[equalitiesLength-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalitiesLength-1]+1][0]=DIFF_INSERT;equalitiesLength--;lastequality=null;if(preIns&&preDel){postIns=postDel=true;equalitiesLength=0;}else{equalitiesLength--;pointer=equalitiesLength>0?equalities[equalitiesLength-1]:-1;postIns=postDel=false;}
+changes=true;}}
+pointer++;}
+if(changes){this.diffCleanupMerge(diffs);}};DiffMatchPatch.prototype.diffPrettyHtml=function(diffs){var op,data,x,html=[];for(x=0;x<diffs.length;x++){op=diffs[x][0];data=diffs[x][1];switch(op){case DIFF_INSERT:html[x]="<ins>"+data+"</ins>";break;case DIFF_DELETE:html[x]="<del>"+data+"</del>";break;case DIFF_EQUAL:html[x]="<span>"+data+"</span>";break;}}
+return html.join("");};DiffMatchPatch.prototype.diffCommonPrefix=function(text1,text2){var pointermid,pointermax,pointermin,pointerstart;if(!text1||!text2||text1.charAt(0)!==text2.charAt(0)){return 0;}
+pointermin=0;pointermax=Math.min(text1.length,text2.length);pointermid=pointermax;pointerstart=0;while(pointermin<pointermid){if(text1.substring(pointerstart,pointermid)===text2.substring(pointerstart,pointermid)){pointermin=pointermid;pointerstart=pointermin;}else{pointermax=pointermid;}
+pointermid=Math.floor((pointermax-pointermin)/2+pointermin);}
+return pointermid;};DiffMatchPatch.prototype.diffCommonSuffix=function(text1,text2){var pointermid,pointermax,pointermin,pointerend;if(!text1||!text2||text1.charAt(text1.length-1)!==text2.charAt(text2.length-1)){return 0;}
+pointermin=0;pointermax=Math.min(text1.length,text2.length);pointermid=pointermax;pointerend=0;while(pointermin<pointermid){if(text1.substring(text1.length-pointermid,text1.length-pointerend)===text2.substring(text2.length-pointermid,text2.length-pointerend)){pointermin=pointermid;pointerend=pointermin;}else{pointermax=pointermid;}
+pointermid=Math.floor((pointermax-pointermin)/2+pointermin);}
+return pointermid;};/**/
+DiffMatchPatch.prototype.diffCompute=function(text1,text2,checklines,deadline){var diffs,longtext,shorttext,i,hm,text1A,text2A,text1B,text2B,midCommon,diffsA,diffsB;if(!text1){return[[DIFF_INSERT,text2]];}
+if(!text2){return[[DIFF_DELETE,text1]];}
+longtext=text1.length>text2.length?text1:text2;shorttext=text1.length>text2.length?text2:text1;i=longtext.indexOf(shorttext);if(i!==-1){diffs=[[DIFF_INSERT,longtext.substring(0,i)],[DIFF_EQUAL,shorttext],[DIFF_INSERT,longtext.substring(i+shorttext.length)]];if(text1.length>text2.length){diffs[0][0]=diffs[2][0]=DIFF_DELETE;}
+return diffs;}
+if(shorttext.length===1){return[[DIFF_DELETE,text1],[DIFF_INSERT,text2]];}
+hm =this.diffHalfMatch(text1,text2);if(hm){text1A=hm[0];text1B=hm[1];text2A=hm[2];text2B=hm[3];midCommon=hm[4];diffsA=this.DiffMain(text1A,text2A,checklines,deadline);diffsB=this.DiffMain(text1B,text2B,checklines,deadline);return diffsA.concat([[DIFF_EQUAL,midCommon]],diffsB);}
+if(checklines&&text1.length>100&&text2.length>100){return this.diffLineMode(text1,text2,deadline);}
+return this.diffBisect(text1,text2,deadline);};DiffMatchPatch.prototype.diffHalfMatch=function(text1,text2){var longtext,shorttext,dmp,text1A,text2B,text2A,text1B,midCommon,hm1,hm2,hm;if(this.DiffTimeout<=0){return null;}
+longtext=text1.length>text2.length?text1:text2;shorttext=text1.length>text2.length?text2:text1;if(longtext.length<4||shorttext.length*2<longtext.length){return null;}
+dmp=this;/**/
+function diffHalfMatchI(longtext,shorttext,i){var seed,j,bestCommon,prefixLength,suffixLength,bestLongtextA,bestLongtextB,bestShorttextA,bestShorttextB;seed=longtext.substring(i,i+Math.floor(longtext.length/4));j=-1;bestCommon="";while((j=shorttext.indexOf(seed,j+1))!==-1){prefixLength=dmp.diffCommonPrefix(longtext.substring(i),shorttext.substring(j));suffixLength=dmp.diffCommonSuffix(longtext.substring(0,i),shorttext.substring(0,j));if(bestCommon.length<suffixLength+prefixLength){bestCommon=shorttext.substring(j-suffixLength,j)+
+shorttext.substring(j,j+prefixLength);bestLongtextA=longtext.substring(0,i-suffixLength);bestLongtextB=longtext.substring(i+prefixLength);bestShorttextA=shorttext.substring(0,j-suffixLength);bestShorttextB=shorttext.substring(j+prefixLength);}}
+if(bestCommon.length*2>=longtext.length){return[bestLongtextA,bestLongtextB,bestShorttextA,bestShorttextB,bestCommon
+];}else{return null;}}
+hm1=diffHalfMatchI(longtext,shorttext,Math.ceil(longtext.length/4));hm2=diffHalfMatchI(longtext,shorttext,Math.ceil(longtext.length/2));if(!hm1&&!hm2){return null;}else if(!hm2){hm=hm1;}else if(!hm1){hm=hm2;}else{hm=hm1[4].length>hm2[4].length?hm1:hm2;}
+text1A,text1B,text2A,text2B;if(text1.length>text2.length){text1A=hm[0];text1B=hm[1];text2A=hm[2];text2B=hm[3];}else{text2A=hm[0];text2B=hm[1];text1A=hm[2];text1B=hm[3];}
+midCommon=hm[4];return[text1A,text1B,text2A,text2B,midCommon];};DiffMatchPatch.prototype.diffLineMode=function(text1,text2,deadline){var a,diffs,linearray,pointer,countInsert,countDelete,textInsert,textDelete,j;a=this.diffLinesToChars(text1,text2);text1=a.chars1;text2=a.chars2;linearray=a.lineArray;diffs=this.DiffMain(text1,text2,false,deadline);
+this.diffCharsToLines(diffs,linearray);this.diffCleanupSemantic(diffs);diffs.push([DIFF_EQUAL,""]);pointer=0;countDelete=0;countInsert=0;textDelete="";textInsert="";while(pointer<diffs.length){switch(diffs[pointer][0]){case DIFF_INSERT:countInsert++;textInsert+=diffs[pointer][1];break;case DIFF_DELETE:countDelete++;textDelete+=diffs[pointer][1];break;case DIFF_EQUAL:if(countDelete>=1&&countInsert>=1){diffs.splice(pointer-countDelete-countInsert,countDelete+countInsert);pointer=pointer-countDelete-countInsert;a=this.DiffMain(textDelete,textInsert,false,deadline);for(j=a.length-1;j>=0;j--){diffs.splice(pointer,0,a[j]);}
+pointer=pointer+a.length;}
+countInsert=0;countDelete=0;textDelete="";textInsert="";break;}
+pointer++;}
+diffs.pop();return diffs;};DiffMatchPatch.prototype.diffBisect=function(text1,text2,deadline){var text1Length,text2Length,maxD,vOffset,vLength,v1,v2,x,delta,front,k1start,k1end,k2start,k2end,k2Offset,k1Offset,x1,x2,y1,y2,d,k1,k2;text1Length=text1.length;text2Length=text2.length;maxD=Math.ceil((text1Length+text2Length)/2);vOffset=maxD;vLength=2*maxD;v1=new Array(vLength);v2=new Array(vLength);for(x=0;x<vLength;x++){v1[x]=-1;v2[x]=-1;}
+ v1[vOffset+1]=0;v2[vOffset+1]=0;delta=text1Length-text2Length;front=(delta%2!==0);k1start=0;k1end=0;k2start=0;k2end=0;for(d=0;d<maxD;d++){if((new Date()).getTime()>deadline){break;}
+for(k1=-d+k1start;k1<=d-k1end;k1+=2){k1Offset=vOffset+k1;if(k1===-d||(k1!==d&&v1[k1Offset-1]<v1[k1Offset+1])){x1=v1[k1Offset+1];}else{x1=v1[k1Offset-1]+1;}
+y1=x1-k1;while(x1<text1Length&&y1<text2Length&&text1.charAt(x1)===text2.charAt(y1)){x1++;y1++;}
+v1[k1Offset]=x1;if(x1>text1Length){k1end+=2;}else if(y1>text2Length){k1start+=2;}else if(front){k2Offset=vOffset+delta-k1;if(k2Offset>=0&&k2Offset<vLength&&v2[k2Offset]!==-1){x2=text1Length-v2[k2Offset];if(x1>=x2){return this.diffBisectSplit(text1,text2,x1,y1,deadline);}}
+}}
+for(k2=-d+k2start;k2<=d-k2end;k2+=2){k2Offset=vOffset+k2;if(k2===-d||(k2!==d&&v2[k2Offset-1]<v2[k2Offset+1])){x2=v2[k2Offset+1];}else{x2=v2[k2Offset-1]+1;}
+y2=x2-k2;while(x2<text1Length&&y2<text2Length&&text1.charAt(text1Length-x2-1)===text2.charAt(text2Length-y2-1)){x2++;y2++;}
+v2[k2Offset]=x2;if(x2>text1Length){k2end+=2;}else if(y2>text2Length){k2start+=2;}else if(!front){k1Offset=vOffset+delta-k2;if(k1Offset>=0&&k1Offset<vLength&&v1[k1Offset]!==-1){x1=v1[k1Offset];y1=vOffset+x1-k1Offset;x2=text1Length-x2;if(x1>=x2){return this.diffBisectSplit(text1,text2,x1,y1,deadline);}}}}}
+return[[DIFF_DELETE,text1],[DIFF_INSERT,text2]];};/**/
+DiffMatchPatch.prototype.diffBisectSplit=function(text1,text2,x,y,deadline){var text1a,text1b,text2a,text2b,diffs,diffsb;text1a=text1.substring(0,x);text2a=text2.substring(0,y);text1b=text1.substring(x);text2b=text2.substring(y);diffs=this.DiffMain(text1a,text2a,false,deadline);diffsb=this.DiffMain(text1b,text2b,false,deadline);return diffs.concat(diffsb);};DiffMatchPatch.prototype.diffCleanupSemantic=function(diffs){var changes,equalities,equalitiesLength,lastequality,pointer,lengthInsertions2,lengthDeletions2,lengthInsertions1,lengthDeletions1,deletion,insertion,overlapLength1,overlapLength2;changes=false;equalities=[];equalitiesLength=0;lastequality=null;pointer=0;lengthInsertions1=0;lengthDeletions1=0;lengthInsertions2=0;lengthDeletions2=0;while(pointer<diffs.length){if(diffs[pointer][0]===DIFF_EQUAL){equalities[equalitiesLength++]=pointer;lengthInsertions1=lengthInsertions2;lengthDeletions1=lengthDeletions2;lengthInsertions2=0;lengthDeletions2=0;lastequality=diffs[pointer][1];}else{if(diffs[pointer][0]===DIFF_INSERT){lengthInsertions2+=diffs[pointer][1].length;}else{lengthDeletions2+=diffs[pointer][1].length;}
+if(lastequality&&(lastequality.length<=Math.max(lengthInsertions1,lengthDeletions1))&&(lastequality.length<=Math.max(lengthInsertions2,lengthDeletions2))){diffs.splice(equalities[equalitiesLength-1],0,[DIFF_DELETE,lastequality]);diffs[equalities[equalitiesLength-1]+1][0]=DIFF_INSERT;equalitiesLength--;equalitiesLength--;pointer=equalitiesLength>0?equalities[equalitiesLength-1]:-1;lengthInsertions1=0;lengthDeletions1=0;lengthInsertions2=0;lengthDeletions2=0;lastequality=null;changes=true;}}
+pointer++;}
+if(changes){this.diffCleanupMerge(diffs);}
+pointer=1;while(pointer<diffs.length){if(diffs[pointer-1][0]===DIFF_DELETE&&diffs[pointer][0]===DIFF_INSERT){deletion=diffs[pointer-1][1];insertion=diffs[pointer][1];overlapLength1=this.diffCommonOverlap(deletion,insertion);overlapLength2=this.diffCommonOverlap(insertion,deletion);if(overlapLength1>=overlapLength2){if(overlapLength1>=deletion.length/2||overlapLength1>=insertion.length/2){diffs.splice(pointer,0,[DIFF_EQUAL,insertion.substring(0,overlapLength1)]);diffs[pointer-1][1]=deletion.substring(0,deletion.length-overlapLength1);diffs[pointer+1][1]=insertion.substring(overlapLength1);pointer++;}}else{if(overlapLength2>=deletion.length/2||overlapLength2>=insertion.length/2){diffs.splice(pointer,0,[DIFF_EQUAL,deletion.substring(0,overlapLength2)]);diffs[pointer-1][0]=DIFF_INSERT;diffs[pointer-1][1]=insertion.substring(0,insertion.length-overlapLength2);diffs[pointer+1][0]=DIFF_DELETE;diffs[pointer+1][1]=deletion.substring(overlapLength2);pointer++;}}
+pointer++;}
+pointer++;}};DiffMatchPatch.prototype.diffCommonOverlap=function(text1,text2){var text1Length,text2Length,textLength,best,length,pattern,found;text1Length=text1.length;text2Length=text2.length;if(text1Length===0||text2Length===0){return 0;}
+if(text1Length>text2Length){text1=text1.substring(text1Length-text2Length);}else if(text1Length<text2Length){ text2=text2.substring(0,text1Length);}
+textLength=Math.min(text1Length,text2Length);if(text1===text2){return textLength;}
+best=0;length=1;while(true){pattern=text1.substring(textLength-length);found=text2.indexOf(pattern);if(found===-1){return best;}
+length+=found;if(found===0||text1.substring(textLength-length)===text2.substring(0,length)){best=length;length++;}}};/**/
+DiffMatchPatch.prototype.diffLinesToChars=function(text1,text2){var lineArray,lineHash,chars1,chars2;lineArray=[];lineHash={};lineArray[0]="";function diffLinesToCharsMunge(text){var chars,lineStart,lineEnd,lineArrayLength,line;chars="";lineStart=0;lineEnd=-1;lineArrayLength=lineArray.length;while(lineEnd<text.length-1){lineEnd=text.indexOf("\n",lineStart);if(lineEnd===-1){lineEnd=text.length-1;}
+line=text.substring(lineStart,lineEnd+1);lineStart=lineEnd+1;if(lineHash.hasOwnProperty?lineHash.hasOwnProperty(line):(lineHash[line]!==undefined)){chars+=String.fromCharCode(lineHash[line]);}else{chars+=String.fromCharCode(lineArrayLength);lineHash[line]=lineArrayLength;lineArray[lineArrayLength++]=line;}}
+return chars;}
+chars1=diffLinesToCharsMunge(text1);chars2=diffLinesToCharsMunge(text2);return{chars1:chars1,chars2:chars2,lineArray:lineArray};};DiffMatchPatch.prototype.diffCharsToLines=function(diffs,lineArray){var x,chars,text,y;for(x=0;x<diffs.length;x++){chars=diffs[x][1];text=[];for(y=0;y<chars.length;y++){text[y]=lineArray[chars.charCodeAt(y)];}
+diffs[x][1]=text.join("");}};DiffMatchPatch.prototype.diffCleanupMerge=function(diffs){var pointer,countDelete,countInsert,textInsert,textDelete,commonlength,changes;diffs.push([DIFF_EQUAL,""]);pointer=0;countDelete=0;countInsert=0;textDelete="";textInsert="";commonlength;while(pointer<diffs.length){switch(diffs[pointer][0]){case DIFF_INSERT:countInsert++;textInsert+=diffs[pointer][1];pointer++;break;case DIFF_DELETE:countDelete++;textDelete+=diffs[pointer][1];pointer++;break;case DIFF_EQUAL:if(countDelete+countInsert>1){if(countDelete!==0&&countInsert!==0){commonlength=this.diffCommonPrefix(textInsert,textDelete);if(commonlength!==0){if((pointer-countDelete-countInsert)>0&&diffs[pointer-countDelete-countInsert-1][0]===
+ DIFF_EQUAL){diffs[pointer-countDelete-countInsert-1][1]+=textInsert.substring(0,commonlength);}else{diffs.splice(0,0,[DIFF_EQUAL,textInsert.substring(0,commonlength)]);pointer++;}
+textInsert=textInsert.substring(commonlength);textDelete=textDelete.substring(commonlength);}
+commonlength=this.diffCommonSuffix(textInsert,textDelete);if(commonlength!==0){diffs[pointer][1]=textInsert.substring(textInsert.length-
+commonlength)+diffs[pointer][1];textInsert=textInsert.substring(0,textInsert.length-
+commonlength);textDelete=textDelete.substring(0,textDelete.length-
+commonlength);}}
+if(countDelete===0){diffs.splice(pointer-countInsert,countDelete+countInsert,[DIFF_INSERT,textInsert]);}else if(countInsert===0){diffs.splice(pointer-countDelete,countDelete+countInsert,[DIFF_DELETE,textDelete]);}else{diffs.splice(pointer-countDelete-countInsert, countDelete+countInsert,[DIFF_DELETE,textDelete],[DIFF_INSERT,textInsert]);}
+pointer=pointer-countDelete-countInsert+(countDelete?1:0)+(countInsert?1:0)+1;}else if(pointer!==0&&diffs[pointer-1][0]===DIFF_EQUAL){diffs[pointer-1][1]+=diffs[pointer][1];diffs.splice(pointer,1);}else{pointer++;}
+countInsert=0;countDelete=0;textDelete="";textInsert="";break;}}
+if(diffs[diffs.length-1][1]===""){diffs.pop();}
+changes=false;pointer=1;while(pointer<diffs.length-1){if(diffs[pointer-1][0]===DIFF_EQUAL&&diffs[pointer+1][0]===DIFF_EQUAL){if(diffs[pointer][1].substring(diffs[pointer][1].length-
+diffs[pointer-1][1].length)===diffs[pointer-1][1]){diffs[pointer][1]=diffs[pointer-1][1]+
+diffs[pointer][1].substring(0,diffs[pointer][1].length-
+diffs[pointer-1][1].length);diffs[pointer+1][1]=diffs[pointer-1][1]+diffs[pointer+1][1];diffs.splice(pointer-1,1);changes=true;}else if(diffs[pointer][1].substring(0,diffs[pointer+1][1].length)===diffs[pointer+1][1]){diffs[pointer-1][1]+=diffs[pointer+1][1];diffs[pointer][1]=diffs[pointer][1].substring(diffs[pointer+1][1].length)+
+diffs[pointer+1][1];diffs.splice(pointer+1,1);changes=true;}}
+pointer++;}
+if(changes){this.diffCleanupMerge(diffs);}};return function(o,n){var diff,output,text;diff=new DiffMatchPatch();output=diff.DiffMain(o,n);diff.diffCleanupEfficiency(output);text=diff.diffPrettyHtml(output);return text;};}());//
+(function(){QUnit.init=function(){var tests,banner,result,qunit,config=QUnit.config;config.stats={all:0,bad:0};config.moduleStats={all:0,bad:0};config.started=0;config.updateRate=1000;config.blocking=false;config.autostart=true;config.autorun=false;config.filter="";config.queue=[];if(typeof window==="undefined"){return;}
+qunit=id("qunit");if(qunit){qunit.innerHTML="<h1 id='qunit-header'>"+escapeText(document.title)+"</h1>"+
+"<h2 id='qunit-banner'></h2>"+
+"<div id='qunit-testrunner-toolbar'></div>"+
+"<h2 id='qunit-userAgent'></h2>"+
+"<ol id='qunit-tests'></ol>";}
+tests=id("qunit-tests");banner=id("qunit-banner");result=id("qunit-testresult");if(tests){tests.innerHTML="";}
+if(banner){banner.className="";}
+if(result){result.parentNode.removeChild(result);}
+if(tests){result=document.createElement("p");result.id="qunit-testresult";result.className="result";tests.parentNode.insertBefore(result,tests);result.innerHTML="Running...<br />&#160;";}};if(typeof window==="undefined"){return;}
+var config=QUnit.config,hasOwn=Object.prototype.hasOwnProperty,defined={document:window.document!==undefined,sessionStorage:(function(){var x="qunit-test-string";try{sessionStorage.setItem(x,x);sessionStorage.removeItem(x);return true;}catch(e){return false;}}())},modulesList=[];function escapeText(s){if(!s){return "";}
+s=s+"";return s.replace(/['"<>&]/g,function(s){switch(s){case "'":return "&#039;";case "\"":return "&quot;";case "<":return "&lt;";case ">":return "&gt;";case "&":return "&amp;";}});}
+function addEvent(elem,type,fn){if(elem.addEventListener){elem.addEventListener(type,fn,false);}else if(elem.attachEvent){elem.attachEvent("on"+type,function(){var event=window.event;if(!event.target){event.target=event.srcElement||document;}
+fn.call(elem,event);});}}
+function addEvents(elems,type,fn){var i=elems.length;while(i--){addEvent(elems[i],type,fn);}}
+function hasClass(elem,name){return(" "+elem.className+" ").indexOf(" "+name+" ")>=0;}
+function addClass(elem,name){if(!hasClass(elem,name)){elem.className+=(elem.className?" ":"")+name;}}
+function toggleClass(elem,name){if(hasClass(elem,name)){removeClass(elem,name);}else{addClass(elem,name);}}
+function removeClass(elem,name){var set=" "+elem.className+" ";while(set.indexOf(" "+name+" ")>=0){set=set.replace(" "+name+" "," ");}
+elem.className=typeof set.trim==="function"?set.trim():set.replace(/^\s+|\s+$/g,"");}
+function id(name){return defined.document&&document.getElementById&&document.getElementById(name);}
+function getUrlConfigHtml(){var i,j,val,escaped,escapedTooltip,selection=false,len=config.urlConfig.length,urlConfigHtml="";for(i=0;i<len;i++){val=config.urlConfig[i];if(typeof val==="string"){val={id:val,label:val};}
+escaped=escapeText(val.id);escapedTooltip=escapeText(val.tooltip);if(config[val.id]===undefined){config[val.id]=QUnit.urlParams[val.id];}
+if(!val.value||typeof val.value==="string"){urlConfigHtml+="<input id='qunit-urlconfig-"+escaped+
+"' name='"+escaped+"' type='checkbox'"+(val.value?" value='"+escapeText(val.value)+"'":"")+(config[val.id]?" checked='checked'":"")+
+" title='"+escapedTooltip+"' /><label for='qunit-urlconfig-"+escaped+
+"' title='"+escapedTooltip+"'>"+val.label+"</label>";}else{urlConfigHtml+="<label for='qunit-urlconfig-"+escaped+
+"' title='"+escapedTooltip+"'>"+val.label+
+": </label><select id='qunit-urlconfig-"+escaped+
+"' name='"+escaped+"' title='"+escapedTooltip+"'><option></option>";if(QUnit.is("array",val.value)){for(j=0;j<val.value.length;j++){escaped=escapeText(val.value[j]);urlConfigHtml+="<option value='"+escaped+"'"+(config[val.id]===val.value[j]?(selection=true)&&" selected='selected'":"")+
+">"+escaped+"</option>";}}else{for(j in val.value){if(hasOwn.call(val.value,j)){urlConfigHtml+="<option value='"+escapeText(j)+"'"+(config[val.id]===j?(selection=true)&&" selected='selected'":"")+
+">"+escapeText(val.value[j])+"</option>";}}}
+if(config[val.id]&&!selection){escaped=escapeText(config[val.id]);urlConfigHtml+="<option value='"+escaped+
+"' selected='selected' disabled='disabled'>"+escaped+"</option>";}
+urlConfigHtml+="</select>";}}
+return urlConfigHtml;}
+function toolbarChanged(){var updatedUrl,value,field=this,params={};//
+if("selectedIndex" in field){value=field.options[field.selectedIndex].value||undefined;}else{value=field.checked?(field.defaultValue||true):undefined;}
+params[field.name]=value;updatedUrl=setUrl(params);if("hidepassed"===field.name&&"replaceState" in window.history){config[field.name]=value||false;if(value){addClass(id("qunit-tests"),"hidepass");}else{removeClass(id("qunit-tests"),"hidepass");}
+window.history.replaceState(null,"",updatedUrl);}else{window.location=updatedUrl;}}
+function setUrl(params){var key,querystring="?";params=QUnit.extend(QUnit.extend({},QUnit.urlParams),params);for(key in params){if(hasOwn.call(params,key)){if(params[key]===undefined){continue;}
+querystring+=encodeURIComponent(key);if(params[key]!==true){querystring+="="+encodeURIComponent(params[key]);}
+querystring+="&";}}
+return location.protocol+"//"+location.host+
+location.pathname+querystring.slice(0,-1);}
+function applyUrlParams(){var selectedModule,modulesList=id("qunit-modulefilter"),filter=id("qunit-filter-input").value;selectedModule=modulesList?decodeURIComponent(modulesList.options[modulesList.selectedIndex].value):undefined;window.location=setUrl({module:(selectedModule==="")?undefined:selectedModule,filter:(filter==="")?undefined:filter,testId:undefined});}
+function toolbarUrlConfigContainer(){var urlConfigContainer=document.createElement("span");urlConfigContainer.innerHTML=getUrlConfigHtml();addClass(urlConfigContainer,"qunit-url-config");addEvents(urlConfigContainer.getElementsByTagName("input"),"click",toolbarChanged);addEvents(urlConfigContainer.getElementsByTagName("select"),"change",toolbarChanged);return urlConfigContainer;}
+function toolbarLooseFilter(){var filter=document.createElement("form"),label=document.createElement("label"),input=document.createElement("input"),button=document.createElement("button");addClass(filter,"qunit-filter");label.innerHTML="Filter: ";input.type="text";input.value=config.filter||"";input.name="filter";input.id="qunit-filter-input";button.innerHTML="Go";label.appendChild(input);filter.appendChild(label);filter.appendChild(button);addEvent(filter,"submit",function(ev){applyUrlParams();if(ev&&ev.preventDefault){ev.preventDefault();}
+return false;});return filter;}
+function toolbarModuleFilterHtml(){var i,moduleFilterHtml="";if(!modulesList.length){return false;}
+modulesList.sort(function(a,b){return a.localeCompare(b);});moduleFilterHtml+="<label for='qunit-modulefilter'>Module: </label>"+
+"<select id='qunit-modulefilter' name='modulefilter'><option value='' "+(QUnit.urlParams.module===undefined?"selected='selected'":"")+
+">< All Modules ></option>";for(i=0;i<modulesList.length;i++){moduleFilterHtml+="<option value='"+
+escapeText(encodeURIComponent(modulesList[i]))+"' "+(QUnit.urlParams.module===modulesList[i]?"selected='selected'":"")+
+">"+escapeText(modulesList[i])+"</option>";}
+moduleFilterHtml+="</select>";return moduleFilterHtml;}
+function toolbarModuleFilter(){var toolbar=id("qunit-testrunner-toolbar"),moduleFilter=document.createElement("span"),moduleFilterHtml=toolbarModuleFilterHtml();if(!toolbar||!moduleFilterHtml){return false;}
+moduleFilter.setAttribute("id","qunit-modulefilter-container");moduleFilter.innerHTML=moduleFilterHtml;addEvent(moduleFilter.lastChild,"change",applyUrlParams);toolbar.appendChild(moduleFilter);}
+function appendToolbar(){var toolbar=id("qunit-testrunner-toolbar");if(toolbar){toolbar.appendChild(toolbarUrlConfigContainer());toolbar.appendChild(toolbarLooseFilter());}}
+function appendHeader(){var header=id("qunit-header");if(header){header.innerHTML="<a href='"+
+setUrl({filter:undefined,module:undefined,testId:undefined})+
+"'>"+header.innerHTML+"</a> ";}}
+function appendBanner(){var banner=id("qunit-banner");if(banner){banner.className="";}}
+function appendTestResults(){var tests=id("qunit-tests"),result=id("qunit-testresult");if(result){result.parentNode.removeChild(result);}
+if(tests){tests.innerHTML="";result=document.createElement("p");result.id="qunit-testresult";result.className="result";tests.parentNode.insertBefore(result,tests);result.innerHTML="Running...<br />&#160;";}}
+function storeFixture(){var fixture=id("qunit-fixture");if(fixture){config.fixture=fixture.innerHTML;}}
+function appendUserAgent(){var userAgent=id("qunit-userAgent");if(userAgent){userAgent.innerHTML="";userAgent.appendChild(document.createTextNode("QUnit "+QUnit.version+"; "+navigator.userAgent));}}
+function appendTestsList(modules){var i,l,x,z,test,moduleObj;for(i=0,l=modules.length;i<l;i++){moduleObj=modules[i];if(moduleObj.name){modulesList.push(moduleObj.name);}
+for(x=0,z=moduleObj.tests.length;x<z;x++){test=moduleObj.tests[x];appendTest(test.name,test.testId,moduleObj.name);}}}
+function appendTest(name,testId,moduleName){var title,rerunTrigger,testBlock,assertList,tests=id("qunit-tests");if(!tests){return;}
+title=document.createElement("strong");title.innerHTML=getNameHtml(name,moduleName);rerunTrigger=document.createElement("a");rerunTrigger.innerHTML="Rerun";rerunTrigger.href=setUrl({testId:testId});testBlock=document.createElement("li");testBlock.appendChild(title);testBlock.appendChild(rerunTrigger);testBlock.id="qunit-test-output-"+testId;assertList=document.createElement("ol");assertList.className="qunit-assert-list";testBlock.appendChild(assertList);tests.appendChild(testBlock);}
+QUnit.begin(function(details){var qunit=id("qunit");storeFixture();if(qunit){qunit.innerHTML="<h1 id='qunit-header'>"+escapeText(document.title)+"</h1>"+
+"<h2 id='qunit-banner'></h2>"+
+"<div id='qunit-testrunner-toolbar'></div>"+
+"<h2 id='qunit-userAgent'></h2>"+
+"<ol id='qunit-tests'></ol>";}
+appendHeader();appendBanner();appendTestResults();appendUserAgent();appendToolbar();appendTestsList(details.modules);toolbarModuleFilter();if(qunit&&config.hidepassed){addClass(qunit.lastChild,"hidepass");}});QUnit.done(function(details){var i,key,banner=id("qunit-banner"),tests=id("qunit-tests"),html=["Tests completed in ",details.runtime," milliseconds.<br />","<span class='passed'>",details.passed,"</span> assertions of <span class='total'>",details.total,"</span> passed, <span class='failed'>",details.failed,"</span> failed."].join("");if(banner){banner.className=details.failed?"qunit-fail":"qunit-pass";}
+if(tests){id("qunit-testresult").innerHTML=html;}
+if(config.altertitle&&defined.document&&document.title){document.title=[(details.failed?"\u2716":"\u2714"),document.title.replace(/^[\u2714\u2716] /i,"")].join(" ");}
+if(config.reorder&&defined.sessionStorage&&details.failed===0){for(i=0;i<sessionStorage.length;i++){key=sessionStorage.key(i++);if(key.indexOf("qunit-test-")===0){sessionStorage.removeItem(key);}}}
+if(config.scrolltop&&window.scrollTo){window.scrollTo(0,0);}});function getNameHtml(name,module){var nameHtml="";if(module){nameHtml="<span class='module-name'>"+escapeText(module)+"</span>: ";}
+nameHtml+="<span class='test-name'>"+escapeText(name)+"</span>";return nameHtml;}
+QUnit.testStart(function(details){var running,testBlock,bad;testBlock=id("qunit-test-output-"+details.testId);if(testBlock){testBlock.className="running";}else{appendTest(details.name,details.testId,details.module);}
+running=id("qunit-testresult");if(running){bad=QUnit.config.reorder&&defined.sessionStorage&&+sessionStorage.getItem("qunit-test-"+details.module+"-"+details.name);running.innerHTML=(bad?"Rerunning previously failed test: <br />":"Running: <br />")+
+getNameHtml(details.name,details.module);}});QUnit.log(function(details){var assertList,assertLi,message,expected,actual,testItem=id("qunit-test-output-"+details.testId);if(!testItem){return;}
+message=escapeText(details.message)||(details.result?"okay":"failed");message="<span class='test-message'>"+message+"</span>";message+="<span class='runtime'>@ "+details.runtime+" ms</span>";if(!details.result&&hasOwn.call(details,"expected")){expected=escapeText(QUnit.dump.parse(details.expected));actual=escapeText(QUnit.dump.parse(details.actual));message+="<table><tr class='test-expected'><th>Expected: </th><td><pre>"+
+expected+
+"</pre></td></tr>";if(actual!==expected){message+="<tr class='test-actual'><th>Result: </th><td><pre>"+
+actual+"</pre></td></tr>"+
+"<tr class='test-diff'><th>Diff: </th><td><pre>"+
+QUnit.diff(expected,actual)+"</pre></td></tr>";}else{if(expected.indexOf("[object Array]")!==-1||expected.indexOf("[object Object]")!==-1){message+="<tr class='test-message'><th>Message: </th><td>"+
+"Diff suppressed as the depth of object is more than current max depth ("+
+QUnit.config.maxDepth+").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to "+
+" run with a higher max depth or <a href='"+setUrl({maxDepth:-1})+"'>"+
+"Rerun</a> without max depth.</p></td></tr>";}}
+if(details.source){message+="<tr class='test-source'><th>Source: </th><td><pre>"+
+escapeText(details.source)+"</pre></td></tr>";}
+message+="</table>";}else if(!details.result&&details.source){message+="<table>"+
+"<tr class='test-source'><th>Source: </th><td><pre>"+
+escapeText(details.source)+"</pre></td></tr>"+
+"</table>";}
+assertList=testItem.getElementsByTagName("ol")[0];assertLi=document.createElement("li");assertLi.className=details.result?"pass":"fail";assertLi.innerHTML=message;assertList.appendChild(assertLi);});QUnit.testDone(function(details){var testTitle,time,testItem,assertList,good,bad,testCounts,skipped,tests=id("qunit-tests");if(!tests){return;}
+testItem=id("qunit-test-output-"+details.testId);assertList=testItem.getElementsByTagName("ol")[0];good=details.passed;bad=details.failed;if(config.reorder&&defined.sessionStorage){if(bad){sessionStorage.setItem("qunit-test-"+details.module+"-"+details.name,bad);}else{sessionStorage.removeItem("qunit-test-"+ details.module+"-"+details.name);}}
+if(bad===0){addClass(assertList,"qunit-collapsed");}
+testTitle=testItem.firstChild;testCounts=bad?"<b class='failed'>"+bad+"</b>, "+"<b class='passed'>"+good+"</b>, ":"";testTitle.innerHTML+=" <b class='counts'>("+testCounts+
+details.assertions.length+")</b>";if(details.skipped){testItem.className="skipped";skipped=document.createElement("em");skipped.className="qunit-skipped-label";skipped.innerHTML="skipped";testItem.insertBefore(skipped,testTitle);}else{addEvent(testTitle,"click",function(){toggleClass(assertList,"qunit-collapsed");});testItem.className=bad?"fail":"pass";time=document.createElement("span");time.className="runtime";time.innerHTML=details.runtime+" ms";testItem.insertBefore(time,assertList);}});if(defined.document){if(document.readyState==="complete"){QUnit.load();}else{addEvent(window,"load",QUnit.load);}}else{config.pageLoaded=true;config.autorun=true;}})(); \ No newline at end of file
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/recipedetails.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
new file mode 100644
index 000000000..604db5f03
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
@@ -0,0 +1,51 @@
+"use strict";
+
+function recipeDetailsPageInit(ctx){
+
+ $(".customise-btn").click(function(e){
+ e.preventDefault();
+ var imgCustomModal = $("#new-custom-image-modal");
+
+ if (imgCustomModal.length === 0)
+ throw("Modal new-custom-image not found");
+
+ var recipe = {id: $(this).data('recipe'), name: null}
+ newCustomImageModalSetRecipes([recipe]);
+ imgCustomModal.modal('show');
+ });
+
+ $("#add-layer-btn").click(function(){
+ var btn = $(this);
+
+ libtoaster.addRmLayer(ctx.recipe.layer_version,
+ true,
+ function (layersList){
+ var msg = libtoaster.makeLayerAddRmAlertMsg(ctx.recipe.layer_version,
+ layersList,
+ true);
+
+ libtoaster.showChangeNotification(msg);
+
+ var toShow = $("#customise-build-btns");
+
+ /* If we have no packages built yet also fade in the build packages
+ * hint message
+ */
+ if (ctx.recipe.totalPackages === 0){
+ toShow = toShow.add("#build-to-get-packages-msg");
+ }
+
+ $("#packages-alert").add(btn).fadeOut(function(){
+ toShow.fadeIn();
+ });
+ });
+ });
+
+ /* Trigger a build of your custom image */
+ $(".build-recipe-btn").click(function(){
+ libtoaster.startABuild(null, ctx.recipe.name,
+ function(){
+ window.location.replace(libtoaster.ctx.projectBuildsUrl);
+ });
+ });
+}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js
index 40b5022de..f738144ae 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js
@@ -33,6 +33,10 @@ function tableInit(ctx){
loadData(tableParams);
+ // clicking on this set of elements removes the search
+ var clearSearchElements = $('.remove-search-btn-'+ctx.tableName +
+ ', .show-all-'+ctx.tableName);
+
function loadData(tableParams){
$.ajax({
type: "GET",
@@ -62,31 +66,27 @@ function tableInit(ctx){
paginationBtns.html("");
if (tableParams.search)
- $('.remove-search-btn-'+ctx.tableName).show();
+ clearSearchElements.show();
else
- $('.remove-search-btn-'+ctx.tableName).hide();
+ clearSearchElements.hide();
$('.table-count-' + ctx.tableName).text(tableData.total);
tableTotal = tableData.total;
if (tableData.total === 0){
tableContainer.hide();
- /* If we were searching show the new search bar and return */
- if (tableParams.search){
+ if ($("#no-results-special-"+ctx.tableName).length > 0) {
+ /* use this page's special no-results form instead of the default */
+ $("#no-results-search-input-"+ctx.tableName).val(tableParams.search);
+ $("#no-results-special-"+ctx.tableName).show();
+ $("#results-found-"+ctx.tableName).hide();
+ } else {
$("#new-search-input-"+ctx.tableName).val(tableParams.search);
$("#no-results-"+ctx.tableName).show();
}
table.trigger("table-done", [tableData.total, tableParams]);
return;
-
- /* We don't want to clutter the place with the table chrome if there
- * are only a few results */
- } else if (tableData.total <= 10 &&
- !tableParams.filter &&
- !tableParams.search){
- $("#table-chrome-"+ctx.tableName).hide();
- pagination.hide();
} else {
tableContainer.show();
$("#no-results-"+ctx.tableName).hide();
@@ -239,16 +239,19 @@ function tableInit(ctx){
}
}
+ if (col.field_name === tableData.default_orderby){
+ title.addClass("default-orderby");
+ }
+
} else {
/* Not orderable */
- header.addClass("muted");
header.css("font-weight", "normal");
- header.append(col.title+' ');
+ header.append('<span class="muted">' + col.title + '</span> ');
}
/* Setup the filter button */
if (col.filter_name){
- var filterBtn = $('<a href="#" role="button" class="pull-right btn btn-mini" data-toggle="modal"><i class="icon-filter filtered"></i></a>');
+ var filterBtn = $('<a href="#" role="button" data-filter-on="' + col.filter_name + '" class="pull-right btn btn-mini" data-toggle="modal"><i class="icon-filter filtered"></i></a>');
filterBtn.data('filter-name', col.filter_name);
filterBtn.prop('id', col.filter_name);
@@ -324,7 +327,7 @@ function tableInit(ctx){
$("#"+ctx.tableName+" th").each(function(){
for (var i in cols_hidden){
if ($(this).hasClass(cols_hidden[i])){
- $("."+cols_hidden[i]).hide();
+ table.find("."+cols_hidden[i]).hide();
$("#checkbox-"+cols_hidden[i]).removeAttr("checked");
}
}
@@ -334,13 +337,14 @@ function tableInit(ctx){
* user setting.
*/
for (var i in defaultHiddenCols) {
- $("."+defaultHiddenCols[i]).hide();
+ table.find("."+defaultHiddenCols[i]).hide();
$("#checkbox-"+defaultHiddenCols[i]).removeAttr("checked");
}
}
}
- function sortColumnClicked(){
+ function sortColumnClicked(e){
+ e.preventDefault();
/* We only have one sort at a time so remove any existing sort indicators */
$("#"+ctx.tableName+" th .icon-caret-down").hide();
@@ -377,14 +381,14 @@ function tableInit(ctx){
var disabled_cols = [];
if ($(this).prop("checked")) {
- $("."+col).show();
+ table.find("."+col).show();
} else {
- $("."+col).hide();
+ table.find("."+col).hide();
/* If we're ordered by the column we're hiding remove the order by */
if (col === tableParams.orderby ||
'-' + col === tableParams.orderby){
tableParams.orderby = null;
- loadData(tableParams);
+ $("#"+ctx.tableName +" .default-orderby").click();
}
}
@@ -396,11 +400,182 @@ function tableInit(ctx){
$.cookie("cols", JSON.stringify(disabled_cols));
}
+ /**
+ * Create the DOM/JS for the client side of a TableFilterActionToggle
+ * or TableFilterActionDay
+ *
+ * filterName: (string) internal name for the filter action
+ * filterActionData: (object)
+ * filterActionData.count: (number) The number of items this filter will
+ * show when selected
+ *
+ * NB this triggers a filtervalue event each time its radio button is checked
+ */
+ function createActionRadio(filterName, filterActionData) {
+ var hasNoRecords = (Number(filterActionData.count) == 0);
+
+ var actionStr = '<div class="radio">' +
+ '<input type="radio" name="filter"' +
+ ' value="' + filterName + '"';
+
+ if (hasNoRecords) {
+ actionStr += ' disabled="disabled"';
+ }
+
+ actionStr += ' id="' + filterName + '">' +
+ '<input type="hidden" name="filter_value" value="on"' +
+ ' data-value-for="' + filterName + '">' +
+ '<label class="filter-title' +
+ (hasNoRecords ? ' muted' : '') + '"' +
+ ' for="' + filterName + '">' +
+ filterActionData.title +
+ ' (' + filterActionData.count + ')' +
+ '</label>' +
+ '</div>';
+
+ var action = $(actionStr);
+
+ // fire the filtervalue event from this action when the radio button
+ // is active so that the apply button can be enabled
+ action.find('[type="radio"]').change(function () {
+ if ($(this).is(':checked')) {
+ action.trigger('filtervalue', 'on');
+ }
+ });
+
+ return action;
+ }
+
+ /**
+ * Create the DOM/JS for the client side of a TableFilterActionDateRange
+ *
+ * filterName: (string) internal name for the filter action
+ * filterValue: (string) from,to date range in format yyyy-mm-dd,yyyy-mm-dd;
+ * used to select the current values for the from/to datepickers;
+ * if this is partial (e.g. "yyyy-mm-dd,") only the applicable datepicker
+ * will have a date pre-selected; if empty, neither will
+ * filterActionData: (object) data for generating the action's HTML
+ * filterActionData.title: label for the radio button
+ * filterActionData.max: (string) maximum date for the pickers, in ISO 8601
+ * datetime format
+ * filterActionData.min: (string) minimum date for the pickers, ISO 8601
+ * datetime
+ *
+ * NB this triggers a filtervalue event each time its radio button is checked
+ */
+ function createActionDateRange(filterName, filterValue, filterActionData) {
+ var action = $('<div class="radio">' +
+ '<input type="radio" name="filter"' +
+ ' value="' + filterName + '" ' +
+ ' id="' + filterName + '">' +
+ '<input type="hidden" name="filter_value" value=""' +
+ ' data-value-for="' + filterName + '">' +
+ '<label class="filter-title"' +
+ ' for="' + filterName + '">' +
+ filterActionData.title +
+ '</label>' +
+ '<input type="text" maxlength="10" class="input-small"' +
+ ' data-date-from-for="' + filterName + '">' +
+ '<span class="help-inline">to</span>' +
+ '<input type="text" maxlength="10" class="input-small"' +
+ ' data-date-to-for="' + filterName + '">' +
+ '<span class="help-inline get-help">(yyyy-mm-dd)</span>' +
+ '</div>');
+
+ var radio = action.find('[type="radio"]');
+ var value = action.find('[data-value-for]');
+
+ // make the datepickers for the range
+ var options = {
+ dateFormat: 'yy-mm-dd',
+ maxDate: new Date(filterActionData.max),
+ minDate: new Date(filterActionData.min)
+ };
+
+ // create date pickers, setting currently-selected from and to dates
+ var selectedFrom = null;
+ var selectedTo = null;
+
+ var selectedFromAndTo = [];
+ if (filterValue) {
+ selectedFromAndTo = filterValue.split(',');
+ }
+
+ if (selectedFromAndTo.length == 2) {
+ selectedFrom = selectedFromAndTo[0];
+ selectedTo = selectedFromAndTo[1];
+ }
+
+ options.defaultDate = selectedFrom;
+ var inputFrom =
+ action.find('[data-date-from-for]').datepicker(options);
+ inputFrom.val(selectedFrom);
+
+ options.defaultDate = selectedTo;
+ var inputTo =
+ action.find('[data-date-to-for]').datepicker(options);
+ inputTo.val(selectedTo);
+
+ // set filter_value based on date pickers when
+ // one of their values changes; if either from or to are unset,
+ // the new value is null;
+ // this triggers a 'filter_value-change' event on the action's element,
+ // which is used to determine the disabled/enabled state of the "Apply"
+ // button
+ var changeHandler = function () {
+ var fromValue = inputFrom.val();
+ var toValue = inputTo.val();
+
+ var newValue = undefined;
+ if (fromValue !== '' && toValue !== '') {
+ newValue = fromValue + ',' + toValue;
+ }
+
+ value.val(newValue);
+
+ // if this action is selected, fire an event for the new range
+ if (radio.is(':checked')) {
+ action.trigger('filtervalue', newValue);
+ }
+ };
+
+ inputFrom.change(changeHandler);
+ inputTo.change(changeHandler);
+
+ // check the associated radio button on clicking a date picker
+ var checkRadio = function () {
+ radio.prop('checked', 'checked');
+
+ // checking the radio button this way doesn't cause the "change"
+ // event to fire, so we manually call the changeHandler
+ changeHandler();
+ };
+
+ inputFrom.focus(checkRadio);
+ inputTo.focus(checkRadio);
+
+ // selecting a date in a picker constrains the date you can
+ // set in the other picker
+ inputFrom.change(function () {
+ inputTo.datepicker('option', 'minDate', inputFrom.val());
+ });
+
+ inputTo.change(function () {
+ inputFrom.datepicker('option', 'maxDate', inputTo.val());
+ });
+
+ // checking the radio input causes the "Apply" button disabled state to
+ // change, depending on which from/to dates are supplied
+ radio.change(changeHandler);
+
+ return action;
+ }
+
function filterOpenClicked(){
var filterName = $(this).data('filter-name');
- /* We need to pass in the curren search so that the filter counts take
- * into account the current search filter
+ /* We need to pass in the current search so that the filter counts take
+ * into account the current search term
*/
var params = {
'name' : filterName,
@@ -414,38 +589,92 @@ function tableInit(ctx){
data: params,
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function (filterData) {
- var filterActionRadios = $('#filter-actions-'+ctx.tableName);
+ /*
+ filterData structure:
+
+ {
+ title: '<title for the filter popup>',
+ filter_actions: [
+ {
+ title: '<label for radio button inside the popup>',
+ name: '<name of the filter action>',
+ count: <number of items this filter will show>,
+ ... additional data for the action ...
+ }
+ ]
+ }
- $('#filter-modal-title-'+ctx.tableName).text(filterData.title);
+ each filter_action gets a radio button; the value of this is
+ set to filterName + ':' + filter_action.name; e.g.
- filterActionRadios.text("");
+ in_current_project:in_project
- for (var i in filterData.filter_actions){
- var filterAction = filterData.filter_actions[i];
+ specifies the "in_project" action of the "in_current_project"
+ filter
- var action = $('<label class="radio"><input type="radio" name="filter" value=""><span class="filter-title"></span></label>');
- var actionTitle = filterAction.title + ' (' + filterAction.count + ')';
+ the filterName is set on the column filter icon, and corresponds
+ to a value in the table's filter map
- var radioInput = action.children("input");
+ when the filter popup's "Apply" button is clicked, the
+ value for the radio button which is checked is passed in the
+ querystring, along with a filter_value, and applied to the
+ queryset on the table
+ */
+ var filterActionRadios = $('#filter-actions-' + ctx.tableName);
+ var filterApplyBtn = $('[data-role="filter-apply"]');
- if (Number(filterAction.count) == 0){
- radioInput.attr("disabled", "disabled");
+ var setApplyButtonState = function (e, filterActionValue) {
+ if (filterActionValue !== undefined) {
+ filterApplyBtn.removeAttr('disabled');
}
+ else {
+ filterApplyBtn.attr('disabled', 'disabled');
+ }
+ };
+
+ $('#filter-modal-title-' + ctx.tableName).text(filterData.title);
- action.children(".filter-title").text(actionTitle);
+ filterActionRadios.empty();
- radioInput.val(filterName + ':' + filterAction.name);
+ // create a radio button + form elements for each action associated
+ // with the filter on this column of the table
+ for (var i in filterData.filter_actions) {
+ var action = null;
+ var filterActionData = filterData.filter_actions[i];
+ var filterName = filterData.name + ':' +
+ filterActionData.action_name;
- /* Setup the current selected filter, default to 'all' if
- * no current filter selected.
- */
- if ((tableParams.filter &&
- tableParams.filter === radioInput.val()) ||
- filterAction.name == 'all') {
- radioInput.attr("checked", "checked");
+ if (filterActionData.type === 'toggle' ||
+ filterActionData.type === 'day') {
+ action = createActionRadio(filterName, filterActionData);
+ }
+ else if (filterActionData.type === 'daterange') {
+ // current values for the from/to dates
+ var filterValue = tableParams.filter_value;
+
+ action = createActionDateRange(
+ filterName,
+ filterValue,
+ filterActionData
+ );
}
- filterActionRadios.append(action);
+ if (action) {
+ // Setup the current selected filter; default to 'all' if
+ // no current filter selected
+ var radioInput = action.children('input[name="filter"]');
+ if ((tableParams.filter &&
+ tableParams.filter === radioInput.val()) ||
+ filterActionData.action_name == 'all') {
+ radioInput.prop("checked", "checked");
+ }
+
+ filterActionRadios.append(action);
+
+ // if the action's filter_value changes but is falsy, disable
+ // the "Apply" button
+ action.on('filtervalue', setApplyButtonState);
+ }
}
$('#filter-modal-'+ctx.tableName).modal('show');
@@ -453,6 +682,13 @@ function tableInit(ctx){
});
}
+ /* Allow pages to trigger reload event */
+ table.on('reload', function(e, newTableParams){
+ if (newTableParams)
+ loadData(newTableParams);
+ else
+ loadData(tableParams)
+ });
$(".get-help").tooltip({container:'body', html:true, delay:{show:300}});
@@ -476,6 +712,7 @@ function tableInit(ctx){
});
$("#search-submit-"+ctx.tableName).click(function(e){
+ e.preventDefault();
var searchTerm = $("#search-input-"+ctx.tableName).val();
tableParams.page = 1;
@@ -489,11 +726,9 @@ function tableInit(ctx){
}
loadData(tableParams);
-
- e.preventDefault();
});
- $('.remove-search-btn-'+ctx.tableName).click(function(e){
+ clearSearchElements.click(function(e){
e.preventDefault();
tableParams.page = 1;
@@ -514,7 +749,9 @@ function tableInit(ctx){
e.preventDefault();
});
- $("#clear-filter-btn-"+ctx.tableName).click(function(){
+ $("#clear-filter-btn-"+ctx.tableName).click(function(e){
+ e.preventDefault();
+
var filterBtn = $("#" + tableParams.filter.split(":")[0]);
filterBtnActive(filterBtn, false);
@@ -525,15 +762,27 @@ function tableInit(ctx){
$("#filter-modal-form-"+ctx.tableName).submit(function(e){
e.preventDefault();
- tableParams.filter = $(this).find("input[type='radio']:checked").val();
+ /* remove active status from all filter buttons so that only one filter
+ can be active at a time */
+ $('[data-filter-on]').each(function (index, filterBtn) {
+ filterBtnActive($(filterBtn), false);
+ });
- var filterBtn = $("#" + tableParams.filter.split(":")[0]);
+ // checked radio button
+ var checkedFilter = $(this).find("input[name='filter']:checked");
+ tableParams.filter = checkedFilter.val();
+
+ // hidden field holding the value for the checked filter
+ var checkedFilterValue = $(this).find("input[data-value-for='" +
+ tableParams.filter + "']");
+ tableParams.filter_value = checkedFilterValue.val();
/* All === remove filter */
if (tableParams.filter.match(":all$")) {
tableParams.filter = null;
- filterBtnActive(filterBtn, false);
+ tableParams.filter_value = null;
} else {
+ var filterBtn = $("#" + tableParams.filter.split(":")[0]);
filterBtnActive(filterBtn, true);
}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/tablefilter.py b/yocto-poky/bitbake/lib/toaster/toastergui/tablefilter.py
new file mode 100644
index 000000000..9d15bcff0
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/tablefilter.py
@@ -0,0 +1,292 @@
+#
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2015 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from django.db.models import Q, Max, Min
+from django.utils import dateparse, timezone
+from datetime import timedelta
+
+class TableFilter(object):
+ """
+ Stores a filter for a named field, and can retrieve the action
+ requested from the set of actions for that filter;
+ the order in which actions are added governs the order in which they
+ are returned in the JSON for the filter
+ """
+
+ def __init__(self, name, title):
+ self.name = name
+ self.title = title
+ self.__filter_action_map = {}
+
+ # retains the ordering of actions
+ self.__filter_action_keys = []
+
+ def add_action(self, action):
+ self.__filter_action_keys.append(action.name)
+ self.__filter_action_map[action.name] = action
+
+ def get_action(self, action_name):
+ return self.__filter_action_map[action_name]
+
+ def to_json(self, queryset):
+ """
+ Dump all filter actions as an object which can be JSON serialised;
+ this is used to generate the JSON for processing in
+ table.js / filterOpenClicked()
+ """
+ filter_actions = []
+
+ # add the "all" pseudo-filter action, which just selects the whole
+ # queryset
+ filter_actions.append({
+ 'action_name' : 'all',
+ 'title' : 'All',
+ 'type': 'toggle',
+ 'count' : queryset.count()
+ })
+
+ # add other filter actions
+ for action_name in self.__filter_action_keys:
+ filter_action = self.__filter_action_map[action_name]
+ obj = filter_action.to_json(queryset)
+ obj['action_name'] = action_name
+ filter_actions.append(obj)
+
+ return {
+ 'name': self.name,
+ 'title': self.title,
+ 'filter_actions': filter_actions
+ }
+
+class TableFilterQueryHelper(object):
+ def dateStringsToQ(self, field_name, date_from_str, date_to_str):
+ """
+ Convert the date strings from_date_str and to_date_str into a
+ set of args in the form
+
+ {'<field_name>__gte': <date from>, '<field_name>__lte': <date to>}
+
+ where date_from and date_to are Django-timezone-aware dates; then
+ convert that into a Django Q object
+
+ Returns the Q object based on those criteria
+ """
+
+ # one of the values required for the filter is missing, so set
+ # it to the one which was supplied
+ if date_from_str == '':
+ date_from_str = date_to_str
+ elif date_to_str == '':
+ date_to_str = date_from_str
+
+ date_from_naive = dateparse.parse_datetime(date_from_str + ' 00:00:00')
+ date_to_naive = dateparse.parse_datetime(date_to_str + ' 23:59:59')
+
+ tz = timezone.get_default_timezone()
+ date_from = timezone.make_aware(date_from_naive, tz)
+ date_to = timezone.make_aware(date_to_naive, tz)
+
+ args = {}
+ args[field_name + '__gte'] = date_from
+ args[field_name + '__lte'] = date_to
+
+ return Q(**args)
+
+class TableFilterAction(object):
+ """
+ A filter action which displays in the filter popup for a ToasterTable
+ and uses an associated QuerysetFilter to filter the queryset for that
+ ToasterTable
+ """
+
+ def __init__(self, name, title, criteria):
+ self.name = name
+ self.title = title
+ self.criteria = criteria
+
+ # set in subclasses
+ self.type = None
+
+ def set_filter_params(self, params):
+ """
+ params: (str) a string of extra parameters for the action;
+ the structure of this string depends on the type of action;
+ it's ignored for a toggle filter action, which is just on or off
+ """
+ pass
+
+ def filter(self, queryset):
+ if self.criteria:
+ return queryset.filter(self.criteria)
+ else:
+ return queryset
+
+ def to_json(self, queryset):
+ """ Dump as a JSON object """
+ return {
+ 'title': self.title,
+ 'type': self.type,
+ 'count': self.filter(queryset).count()
+ }
+
+class TableFilterActionToggle(TableFilterAction):
+ """
+ A single filter action which will populate one radio button of
+ a ToasterTable filter popup; this filter can either be on or off and
+ has no other parameters
+ """
+
+ def __init__(self, *args):
+ super(TableFilterActionToggle, self).__init__(*args)
+ self.type = 'toggle'
+
+class TableFilterActionDay(TableFilterAction):
+ """
+ A filter action which filters according to the named datetime field and a
+ string representing a day ("today" or "yesterday")
+ """
+
+ TODAY = 'today'
+ YESTERDAY = 'yesterday'
+
+ def __init__(self, name, title, field, day,
+ query_helper = TableFilterQueryHelper()):
+ """
+ field: (string) the datetime field to filter by
+ day: (string) "today" or "yesterday"
+ """
+ super(TableFilterActionDay, self).__init__(name, title, None)
+ self.type = 'day'
+ self.field = field
+ self.day = day
+ self.query_helper = query_helper
+
+ def filter(self, queryset):
+ """
+ Apply the day filtering before returning the queryset;
+ this is done here as the value of the filter criteria changes
+ depending on when the filtering is applied
+ """
+
+ now = timezone.now()
+
+ if self.day == self.YESTERDAY:
+ increment = timedelta(days=1)
+ wanted_date = now - increment
+ else:
+ wanted_date = now
+
+ wanted_date_str = wanted_date.strftime('%Y-%m-%d')
+
+ self.criteria = self.query_helper.dateStringsToQ(
+ self.field,
+ wanted_date_str,
+ wanted_date_str
+ )
+
+ return queryset.filter(self.criteria)
+
+class TableFilterActionDateRange(TableFilterAction):
+ """
+ A filter action which will filter the queryset by a date range.
+ The date range can be set via set_params()
+ """
+
+ def __init__(self, name, title, field,
+ query_helper = TableFilterQueryHelper()):
+ """
+ field: (string) the field to find the max/min range from in the queryset
+ """
+ super(TableFilterActionDateRange, self).__init__(
+ name,
+ title,
+ None
+ )
+
+ self.type = 'daterange'
+ self.field = field
+ self.query_helper = query_helper
+
+ def set_filter_params(self, params):
+ """
+ This filter depends on the user selecting some input, so it needs
+ to have its parameters set before its queryset is filtered
+
+ params: (str) a string of extra parameters for the filtering
+ in the format "2015-12-09,2015-12-11" (from,to); this is passed in the
+ querystring and used to set the criteria on the QuerysetFilter
+ associated with this action
+ """
+
+ # if params are invalid, return immediately, resetting criteria
+ # on the QuerysetFilter
+ try:
+ date_from_str, date_to_str = params.split(',')
+ except ValueError:
+ self.criteria = None
+ return
+
+ # one of the values required for the filter is missing, so set
+ # it to the one which was supplied
+ self.criteria = self.query_helper.dateStringsToQ(
+ self.field,
+ date_from_str,
+ date_to_str
+ )
+
+ def to_json(self, queryset):
+ """ Dump as a JSON object """
+ data = super(TableFilterActionDateRange, self).to_json(queryset)
+
+ # additional data about the date range covered by the queryset's
+ # records, retrieved from its <field> column
+ data['min'] = queryset.aggregate(Min(self.field))[self.field + '__min']
+ data['max'] = queryset.aggregate(Max(self.field))[self.field + '__max']
+
+ # a range filter has a count of None, as the number of records it
+ # will select depends on the date range entered and we don't know
+ # that ahead of time
+ data['count'] = None
+
+ return data
+
+class TableFilterMap(object):
+ """
+ Map from field names to TableFilter objects for those fields
+ """
+
+ def __init__(self):
+ self.__filters = {}
+
+ def add_filter(self, filter_name, table_filter):
+ """ table_filter is an instance of Filter """
+ self.__filters[filter_name] = table_filter
+
+ def get_filter(self, filter_name):
+ return self.__filters[filter_name]
+
+ def to_json(self, queryset):
+ data = {}
+
+ for filter_name, table_filter in self.__filters.iteritems():
+ data[filter_name] = table_filter.to_json()
+
+ return data
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/tables.py b/yocto-poky/bitbake/lib/toaster/toastergui/tables.py
index 9c9cda4e9..2cc2f4eb7 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/tables.py
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/tables.py
@@ -21,29 +21,27 @@
from toastergui.widgets import ToasterTable
from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
-from orm.models import CustomImageRecipe, Package
-from django.db.models import Q, Max
+from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task
+from orm.models import CustomImagePackage
+from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField
from django.conf.urls import url
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, resolve
+from django.http import HttpResponse
from django.views.generic import TemplateView
+from toastergui.tablefilter import TableFilter
+from toastergui.tablefilter import TableFilterActionToggle
+from toastergui.tablefilter import TableFilterActionDateRange
+from toastergui.tablefilter import TableFilterActionDay
-class ProjectFiltersMixin(object):
- """Common mixin for recipe, machine in project filters"""
+class ProjectFilters(object):
+ @staticmethod
+ def in_project(project_layers):
+ return Q(layer_version__in=project_layers)
- def filter_in_project(self, count_only=False):
- query = self.queryset.filter(layer_version__in=self.project_layers)
- if count_only:
- return query.count()
-
- self.queryset = query
-
- def filter_not_in_project(self, count_only=False):
- query = self.queryset.exclude(layer_version__in=self.project_layers)
- if count_only:
- return query.count()
-
- self.queryset = query
+ @staticmethod
+ def not_in_project(project_layers):
+ return ~(ProjectFilters.in_project(project_layers))
class LayersTable(ToasterTable):
"""Table of layers in Toaster"""
@@ -61,33 +59,32 @@ class LayersTable(ToasterTable):
return context
-
def setup_filters(self, *args, **kwargs):
project = Project.objects.get(pk=kwargs['pid'])
self.project_layers = ProjectLayer.objects.filter(project=project)
+ in_current_project_filter = TableFilter(
+ "in_current_project",
+ "Filter by project layers"
+ )
- self.add_filter(title="Filter by project layers",
- name="in_current_project",
- filter_actions=[
- self.make_filter_action("in_project", "Layers added to this project", self.filter_in_project),
- self.make_filter_action("not_in_project", "Layers not added to this project", self.filter_not_in_project)
- ])
-
- def filter_in_project(self, count_only=False):
- query = self.queryset.filter(projectlayer__in=self.project_layers)
- if count_only:
- return query.count()
+ criteria = Q(projectlayer__in=self.project_layers)
- self.queryset = query
+ in_project_action = TableFilterActionToggle(
+ "in_project",
+ "Layers added to this project",
+ criteria
+ )
- def filter_not_in_project(self, count_only=False):
- query = self.queryset.exclude(projectlayer__in=self.project_layers)
- if count_only:
- return query.count()
-
- self.queryset = query
+ not_in_project_action = TableFilterActionToggle(
+ "not_in_project",
+ "Layers not added to this project",
+ ~criteria
+ )
+ in_current_project_filter.add_action(in_project_action)
+ in_current_project_filter.add_action(not_in_project_action)
+ self.add_filter(in_current_project_filter)
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
@@ -161,7 +158,7 @@ class LayersTable(ToasterTable):
{% endwith %}
'''
- self.add_column(title="Revision",
+ self.add_column(title="Git revision",
help_text="The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project",
static_data_name="revision",
static_data_template=revision_template)
@@ -186,8 +183,8 @@ class LayersTable(ToasterTable):
static_data_name="dependencies",
static_data_template=deps_template)
- self.add_column(title="Add | Delete",
- help_text="Add or delete layers to / from your project",
+ self.add_column(title="Add | Remove",
+ help_text="Add or remove layers to / from your project",
hideable=False,
filter_name="in_current_project",
static_data_name="add-del-layers",
@@ -205,7 +202,7 @@ class LayersTable(ToasterTable):
computation = lambda x: x.layer.name)
-class MachinesTable(ToasterTable, ProjectFiltersMixin):
+class MachinesTable(ToasterTable):
"""Table of Machines in Toaster"""
def __init__(self, *args, **kwargs):
@@ -217,25 +214,41 @@ class MachinesTable(ToasterTable, ProjectFiltersMixin):
def get_context_data(self, **kwargs):
context = super(MachinesTable, self).get_context_data(**kwargs)
context['project'] = Project.objects.get(pk=kwargs['pid'])
- context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
return context
def setup_filters(self, *args, **kwargs):
project = Project.objects.get(pk=kwargs['pid'])
- self.project_layers = project.get_project_layer_versions()
- self.add_filter(title="Filter by project machines",
- name="in_current_project",
- filter_actions=[
- self.make_filter_action("in_project", "Machines provided by layers added to this project", self.filter_in_project),
- self.make_filter_action("not_in_project", "Machines provided by layers not added to this project", self.filter_not_in_project)
- ])
+ in_current_project_filter = TableFilter(
+ "in_current_project",
+ "Filter by project machines"
+ )
+
+ in_project_action = TableFilterActionToggle(
+ "in_project",
+ "Machines provided by layers added to this project",
+ ProjectFilters.in_project(self.project_layers)
+ )
+
+ not_in_project_action = TableFilterActionToggle(
+ "not_in_project",
+ "Machines provided by layers not added to this project",
+ ProjectFilters.not_in_project(self.project_layers)
+ )
+
+ in_current_project_filter.add_action(in_project_action)
+ in_current_project_filter.add_action(not_in_project_action)
+ self.add_filter(in_current_project_filter)
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
self.queryset = prj.get_all_compatible_machines()
self.queryset = self.queryset.order_by(self.default_orderby)
+ self.static_context_extra['current_layers'] = \
+ self.project_layers = \
+ prj.get_project_layer_versions(pk=True)
+
def setup_columns(self, *args, **kwargs):
self.add_column(title="Machine",
@@ -256,7 +269,7 @@ class MachinesTable(ToasterTable, ProjectFiltersMixin):
static_data_template=layer_link_template,
orderable=True)
- self.add_column(title="Revision",
+ self.add_column(title="Git revision",
help_text="The Git branch, tag or commit. For the layers from the OpenEmbedded layer source, the revision is always the branch compatible with the Yocto Project version you selected for this project",
hidden=True,
field_name="layer_version__get_vcs_reference")
@@ -293,6 +306,7 @@ class LayerMachinesTable(MachinesTable):
MachinesTable.setup_queryset(self, *args, **kwargs)
self.queryset = self.queryset.filter(layer_version__pk=int(kwargs['layerid']))
+ self.queryset = self.queryset.order_by(self.default_orderby)
self.static_context_extra['in_prj'] = ProjectLayer.objects.filter(Q(project=kwargs['pid']) & Q(layercommit=kwargs['layerid'])).count()
def setup_columns(self, *args, **kwargs):
@@ -311,13 +325,12 @@ class LayerMachinesTable(MachinesTable):
static_data_template=select_btn_template)
-class RecipesTable(ToasterTable, ProjectFiltersMixin):
+class RecipesTable(ToasterTable):
"""Table of All Recipes in Toaster"""
def __init__(self, *args, **kwargs):
super(RecipesTable, self).__init__(*args, **kwargs)
self.empty_state = "Toaster has no recipe information. To generate recipe information you can configure a layer source then run a build."
- self.default_orderby = "name"
build_col = { 'title' : "Build",
'help_text' : "Add or delete recipes to and from your project",
@@ -337,12 +350,26 @@ class RecipesTable(ToasterTable, ProjectFiltersMixin):
return context
def setup_filters(self, *args, **kwargs):
- self.add_filter(title="Filter by project recipes",
- name="in_current_project",
- filter_actions=[
- self.make_filter_action("in_project", "Recipes provided by layers added to this project", self.filter_in_project),
- self.make_filter_action("not_in_project", "Recipes provided by layers not added to this project", self.filter_not_in_project)
- ])
+ table_filter = TableFilter(
+ 'in_current_project',
+ 'Filter by project recipes'
+ )
+
+ in_project_action = TableFilterActionToggle(
+ 'in_project',
+ 'Recipes provided by layers added to this project',
+ ProjectFilters.in_project(self.project_layers)
+ )
+
+ not_in_project_action = TableFilterActionToggle(
+ 'not_in_project',
+ 'Recipes provided by layers not added to this project',
+ ProjectFilters.not_in_project(self.project_layers)
+ )
+
+ table_filter.add_action(in_project_action)
+ table_filter.add_action(not_in_project_action)
+ self.add_filter(table_filter)
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
@@ -354,7 +381,6 @@ class RecipesTable(ToasterTable, ProjectFiltersMixin):
self.static_context_extra['current_layers'] = self.project_layers
self.queryset = prj.get_all_compatible_recipes()
- self.queryset = self.queryset.order_by(self.default_orderby)
def setup_columns(self, *args, **kwargs):
@@ -402,7 +428,7 @@ class RecipesTable(ToasterTable, ProjectFiltersMixin):
orderable=True,
field_name="license")
- self.add_column(title="Revision",
+ self.add_column(title="Git revision",
hidden=True,
field_name="layer_version__get_vcs_reference")
@@ -412,6 +438,7 @@ class LayerRecipesTable(RecipesTable):
def __init__(self, *args, **kwargs):
super(LayerRecipesTable, self).__init__(*args, **kwargs)
+ self.default_orderby = "name"
def get_context_data(self, **kwargs):
context = super(LayerRecipesTable, self).get_context_data(**kwargs)
@@ -423,6 +450,7 @@ class LayerRecipesTable(RecipesTable):
self.queryset = \
Recipe.objects.filter(layer_version__pk=int(kwargs['layerid']))
+ self.queryset = self.queryset.order_by(self.default_orderby)
self.static_context_extra['in_prj'] = ProjectLayer.objects.filter(Q(project=kwargs['pid']) & Q(layercommit=kwargs['layerid'])).count()
def setup_columns(self, *args, **kwargs):
@@ -449,18 +477,19 @@ class CustomImagesTable(ToasterTable):
def __init__(self, *args, **kwargs):
super(CustomImagesTable, self).__init__(*args, **kwargs)
self.title = "Custom images"
+ self.default_orderby = "name"
def get_context_data(self, **kwargs):
context = super(CustomImagesTable, self).get_context_data(**kwargs)
project = Project.objects.get(pk=kwargs['pid'])
+ # TODO put project into the ToasterTable base class
context['project'] = project
- context['projectlayers'] = map(lambda prjlayer: prjlayer.layercommit.id, ProjectLayer.objects.filter(project=context['project']))
return context
def setup_queryset(self, *args, **kwargs):
prj = Project.objects.get(pk = kwargs['pid'])
self.queryset = CustomImageRecipe.objects.filter(project=prj)
- self.queryset = self.queryset.order_by('name')
+ self.queryset = self.queryset.order_by(self.default_orderby)
def setup_columns(self, *args, **kwargs):
@@ -472,22 +501,37 @@ class CustomImagesTable(ToasterTable):
self.add_column(title="Custom image",
hideable=False,
+ orderable=True,
+ field_name="name",
static_data_name="name",
static_data_template=name_link_template)
+ recipe_file_template = '''
+ <code>{{data.name}}_{{data.version}}.bb</code>
+ <a href="{% url 'customrecipedownload' extra.pid data.pk %}">
+ <i class="icon-download-alt" data-original-title="Download recipe
+ file"></i>
+ </a>'''
+
self.add_column(title="Recipe file",
- static_data_name='recipe_file',
- static_data_template='')
+ static_data_name='recipe_file_download',
+ static_data_template=recipe_file_template)
+
+ approx_packages_template = '''
+ <a href="{% url 'customrecipe' extra.pid data.id %}">
+ {{data.get_all_packages.count}}
+ </a>'''
- approx_packages_template = '<a href="#imagedetails">{{data.packages.all|length}}</a>'
self.add_column(title="Approx packages",
static_data_name='approx_packages',
static_data_template=approx_packages_template)
- build_btn_template = '''<button data-recipe-name="{{data.name}}"
+ build_btn_template = '''
+ <button data-recipe-name="{{data.name}}"
class="btn btn-block build-recipe-btn" style="margin-top: 5px;" >
- Build</button>'''
+ Build
+ </button>'''
self.add_column(title="Build",
hideable=False,
@@ -500,20 +544,32 @@ class ImageRecipesTable(RecipesTable):
def __init__(self, *args, **kwargs):
super(ImageRecipesTable, self).__init__(*args, **kwargs)
self.title = "Compatible image recipes"
+ self.default_orderby = "name"
def setup_queryset(self, *args, **kwargs):
super(ImageRecipesTable, self).setup_queryset(*args, **kwargs)
- self.queryset = self.queryset.filter(is_image=True)
+ custom_image_recipes = CustomImageRecipe.objects.filter(
+ project=kwargs['pid'])
+ self.queryset = self.queryset.filter(
+ Q(is_image=True) & ~Q(pk__in=custom_image_recipes))
+ self.queryset = self.queryset.order_by(self.default_orderby)
def setup_columns(self, *args, **kwargs):
+
+ name_link_template = '''
+ <a href="{% url 'recipedetails' extra.pid data.pk %}">{{data.name}}</a>
+ '''
+
self.add_column(title="Image recipe",
help_text="When you build an image recipe, you get an "
"image: a root file system you can"
"deploy to a machine",
hideable=False,
orderable=True,
+ static_data_name="name",
+ static_data_template=name_link_template,
field_name="name")
super(ImageRecipesTable, self).setup_columns(*args, **kwargs)
@@ -529,17 +585,27 @@ class NewCustomImagesTable(ImageRecipesTable):
def setup_queryset(self, *args, **kwargs):
super(ImageRecipesTable, self).setup_queryset(*args, **kwargs)
+ prj = Project.objects.get(pk = kwargs['pid'])
+ self.static_context_extra['current_layers'] = \
+ prj.get_project_layer_versions(pk=True)
self.queryset = self.queryset.filter(is_image=True)
def setup_columns(self, *args, **kwargs):
+
+ name_link_template = '''
+ <a href="{% url 'recipedetails' extra.pid data.pk %}">{{data.name}}</a>
+ '''
+
self.add_column(title="Image recipe",
help_text="When you build an image recipe, you get an "
"image: a root file system you can"
"deploy to a machine",
hideable=False,
orderable=True,
- field_name="recipe__name")
+ static_data_name="name",
+ static_data_template=name_link_template,
+ field_name="name")
super(ImageRecipesTable, self).setup_columns(*args, **kwargs)
@@ -555,11 +621,13 @@ class SoftwareRecipesTable(RecipesTable):
def __init__(self, *args, **kwargs):
super(SoftwareRecipesTable, self).__init__(*args, **kwargs)
self.title = "Compatible software recipes"
+ self.default_orderby = "name"
def setup_queryset(self, *args, **kwargs):
super(SoftwareRecipesTable, self).setup_queryset(*args, **kwargs)
self.queryset = self.queryset.filter(is_image=False)
+ self.queryset = self.queryset.order_by(self.default_orderby)
def setup_columns(self, *args, **kwargs):
@@ -576,33 +644,60 @@ class SoftwareRecipesTable(RecipesTable):
self.add_column(**RecipesTable.build_col)
-
-class SelectPackagesTable(ToasterTable):
- """ Table to display the packages to add and remove from an image """
+class PackagesTable(ToasterTable):
+ """ Table to display the packages in a recipe from it's last successful
+ build"""
def __init__(self, *args, **kwargs):
- super(SelectPackagesTable, self).__init__(*args, **kwargs)
- self.title = "Add | Remove packages"
+ super(PackagesTable, self).__init__(*args, **kwargs)
+ self.title = "Packages included"
+ self.packages = None
+ self.default_orderby = "name"
- def setup_queryset(self, *args, **kwargs):
- cust_recipe = CustomImageRecipe.objects.get(pk=kwargs['recipeid'])
- prj = Project.objects.get(pk = kwargs['pid'])
+ def create_package_list(self, recipe, project_id):
+ """Creates a list of packages for the specified recipe by looking for
+ the last SUCCEEDED build of ther recipe"""
- current_packages = cust_recipe.packages.all()
+ target = Target.objects.filter(Q(target=recipe.name) &
+ Q(build__project_id=project_id) &
+ Q(build__outcome=Build.SUCCEEDED)
+ ).last()
- # Get all the packages that are in the custom image
- # Get all the packages built by builds in the current project
- # but not those ones that are already in the custom image
- self.queryset = Package.objects.filter(
- Q(pk__in=current_packages) |
- (Q(build__project=prj) &
- ~Q(name__in=current_packages.values_list('name'))))
+ if target:
+ pkgs = target.target_installed_package_set.values_list('package',
+ flat=True)
+ return Package.objects.filter(pk__in=pkgs)
- self.queryset = self.queryset.order_by('name')
+ # Target/recipe never successfully built so empty queryset
+ return Package.objects.none()
- self.static_context_extra['recipe_id'] = kwargs['recipeid']
- self.static_context_extra['current_packages'] = \
- cust_recipe.packages.values_list('pk', flat=True)
+ def get_context_data(self, **kwargs):
+ """Context for rendering the sidebar and other items on the recipe
+ details page """
+ context = super(PackagesTable, self).get_context_data(**kwargs)
+
+ recipe = Recipe.objects.get(pk=kwargs['recipe_id'])
+ project = Project.objects.get(pk=kwargs['pid'])
+
+ in_project = (recipe.layer_version.pk in
+ project.get_project_layer_versions(pk=True))
+
+ packages = self.create_package_list(recipe, project.pk)
+
+ context.update({'project': project,
+ 'recipe' : recipe,
+ 'packages': packages,
+ 'approx_pkg_size' : packages.aggregate(Sum('size')),
+ 'in_project' : in_project,
+ })
+
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ recipe = Recipe.objects.get(pk=kwargs['recipe_id'])
+
+ self.queryset = self.create_package_list(recipe, kwargs['pid'])
+ self.queryset = self.queryset.order_by('name')
def setup_columns(self, *args, **kwargs):
self.add_column(title="Package",
@@ -611,18 +706,798 @@ class SelectPackagesTable(ToasterTable):
field_name="name")
self.add_column(title="Package Version",
- field_name="version")
+ field_name="version",
+ hideable=False)
self.add_column(title="Approx Size",
orderable=True,
static_data_name="size",
static_data_template="{% load projecttags %} \
{{data.size|filtered_filesizeformat}}")
- self.add_column(title="summary",
- field_name="summary")
+
+ self.add_column(title="License",
+ field_name="license",
+ orderable=True)
+
+
+ self.add_column(title="Dependencies",
+ static_data_name="dependencies",
+ static_data_template='\
+ {% include "snippets/pkg_dependencies_popover.html" %}')
+
+ self.add_column(title="Reverse dependencies",
+ static_data_name="reverse_dependencies",
+ static_data_template='\
+ {% include "snippets/pkg_revdependencies_popover.html" %}',
+ hidden=True)
+
+ self.add_column(title="Recipe",
+ field_name="recipe__name",
+ orderable=True,
+ hidden=True)
+
+ self.add_column(title="Recipe version",
+ field_name="recipe__version",
+ hidden=True)
+
+
+class SelectPackagesTable(PackagesTable):
+ """ Table to display the packages to add and remove from an image """
+
+ def __init__(self, *args, **kwargs):
+ super(SelectPackagesTable, self).__init__(*args, **kwargs)
+ self.title = "Add | Remove packages"
+
+ def setup_queryset(self, *args, **kwargs):
+ self.cust_recipe =\
+ CustomImageRecipe.objects.get(pk=kwargs['custrecipeid'])
+ prj = Project.objects.get(pk = kwargs['pid'])
+
+ current_packages = self.cust_recipe.get_all_packages()
+
+ current_recipes = prj.get_available_recipes()
+
+ # only show packages where recipes->layers are in the project
+ self.queryset = CustomImagePackage.objects.filter(
+ ~Q(recipe=None) &
+ Q(recipe__in=current_recipes))
+
+ self.queryset = self.queryset.order_by('name')
+
+ self.static_context_extra['recipe_id'] = kwargs['custrecipeid']
+ self.static_context_extra['current_packages'] = \
+ current_packages.values_list('pk', flat=True)
+
+ def get_context_data(self, **kwargs):
+ # to reuse the Super class map the custrecipeid to the recipe_id
+ kwargs['recipe_id'] = kwargs['custrecipeid']
+ context = super(SelectPackagesTable, self).get_context_data(**kwargs)
+ custom_recipe = \
+ CustomImageRecipe.objects.get(pk=kwargs['custrecipeid'])
+
+ context['recipe'] = custom_recipe
+ context['approx_pkg_size'] = \
+ custom_recipe.get_all_packages().aggregate(Sum('size'))
+ return context
+
+
+ def setup_columns(self, *args, **kwargs):
+ super(SelectPackagesTable, self).setup_columns(*args, **kwargs)
+
+ add_remove_template = '{% include "pkg_add_rm_btn.html" %}'
self.add_column(title="Add | Remove",
+ hideable=False,
help_text="Use the add and remove buttons to modify "
- "the package content of you custom image",
+ "the package content of your custom image",
static_data_name="add_rm_pkg_btn",
- static_data_template='{% include "pkg_add_rm_btn.html" %}')
+ static_data_template=add_remove_template,
+ filter_name='in_current_image_filter')
+
+ def setup_filters(self, *args, **kwargs):
+ in_current_image_filter = TableFilter(
+ 'in_current_image_filter',
+ 'Filter by added packages'
+ )
+
+ in_image_action = TableFilterActionToggle(
+ 'in_image',
+ 'Packages in %s' % self.cust_recipe.name,
+ Q(pk__in=self.static_context_extra['current_packages'])
+ )
+
+ not_in_image_action = TableFilterActionToggle(
+ 'not_in_image',
+ 'Packages not added to %s' % self.cust_recipe.name,
+ ~Q(pk__in=self.static_context_extra['current_packages'])
+ )
+
+ in_current_image_filter.add_action(in_image_action)
+ in_current_image_filter.add_action(not_in_image_action)
+ self.add_filter(in_current_image_filter)
+
+class ProjectsTable(ToasterTable):
+ """Table of projects in Toaster"""
+
+ def __init__(self, *args, **kwargs):
+ super(ProjectsTable, self).__init__(*args, **kwargs)
+ self.default_orderby = '-updated'
+ self.title = 'All projects'
+ self.static_context_extra['Build'] = Build
+
+ def get_context_data(self, **kwargs):
+ return super(ProjectsTable, self).get_context_data(**kwargs)
+
+ def setup_queryset(self, *args, **kwargs):
+ queryset = Project.objects.all()
+
+ # annotate each project with its number of builds
+ queryset = queryset.annotate(num_builds=Count('build'))
+
+ # exclude the command line builds project if it has no builds
+ q_default_with_builds = Q(is_default=True) & Q(num_builds__gt=0)
+ queryset = queryset.filter(Q(is_default=False) |
+ q_default_with_builds)
+
+ # order rows
+ queryset = queryset.order_by(self.default_orderby)
+
+ self.queryset = queryset
+
+ # columns: last activity on (updated) - DEFAULT, project (name), release,
+ # machine, number of builds, last build outcome, recipe (name), errors,
+ # warnings, image files
+ def setup_columns(self, *args, **kwargs):
+ name_template = '''
+ {% load project_url_tag %}
+ <span data-project-field="name">
+ <a href="{% project_url data %}">
+ {{data.name}}
+ </a>
+ </span>
+ '''
+
+ last_activity_on_template = '''
+ {% load project_url_tag %}
+ <span data-project-field="updated">
+ <a href="{% project_url data %}">
+ {{data.updated | date:"d/m/y H:i"}}
+ </a>
+ </span>
+ '''
+
+ release_template = '''
+ <span data-project-field="release">
+ {% if data.release %}
+ <a href="{% url 'project' data.id %}#project-details">
+ {{data.release.name}}
+ </a>
+ {% elif data.is_default %}
+ <span class="muted">Not applicable</span>
+ <i class="icon-question-sign get-help hover-help"
+ data-original-title="This project does not have a release set.
+ It simply collects information about the builds you start from
+ the command line while Toaster is running"
+ style="visibility: hidden;">
+ </i>
+ {% else %}
+ No release available
+ {% endif %}
+ </span>
+ '''
+
+ machine_template = '''
+ <span data-project-field="machine">
+ {% if data.is_default %}
+ <span class="muted">Not applicable</span>
+ <i class="icon-question-sign get-help hover-help"
+ data-original-title="This project does not have a machine
+ set. It simply collects information about the builds you
+ start from the command line while Toaster is running"
+ style="visibility: hidden;"></i>
+ {% else %}
+ <a href="{% url 'project' data.id %}#machine-distro">
+ {{data.get_current_machine_name}}
+ </a>
+ {% endif %}
+ </span>
+ '''
+
+ number_of_builds_template = '''
+ {% if data.get_number_of_builds > 0 %}
+ <a href="{% url 'projectbuilds' data.id %}">
+ {{data.get_number_of_builds}}
+ </a>
+ {% else %}
+ <span class="muted">0</span>
+ {% endif %}
+ '''
+
+ last_build_outcome_template = '''
+ {% if data.get_number_of_builds > 0 %}
+ <a href="{% url 'builddashboard' data.get_last_build_id %}">
+ {% if data.get_last_outcome == extra.Build.SUCCEEDED %}
+ <i class="icon-ok-sign success"></i>
+ {% elif data.get_last_outcome == extra.Build.FAILED %}
+ <i class="icon-minus-sign error"></i>
+ {% endif %}
+ </a>
+ {% endif %}
+ '''
+
+ recipe_template = '''
+ {% if data.get_number_of_builds > 0 %}
+ <a href="{% url "builddashboard" data.get_last_build_id %}">
+ {{data.get_last_target}}
+ </a>
+ {% endif %}
+ '''
+
+ errors_template = '''
+ {% if data.get_number_of_builds > 0 and data.get_last_errors > 0 %}
+ <a class="errors.count error"
+ href="{% url "builddashboard" data.get_last_build_id %}#errors">
+ {{data.get_last_errors}} error{{data.get_last_errors | pluralize}}
+ </a>
+ {% endif %}
+ '''
+
+ warnings_template = '''
+ {% if data.get_number_of_builds > 0 and data.get_last_warnings > 0 %}
+ <a class="warnings.count warning"
+ href="{% url "builddashboard" data.get_last_build_id %}#warnings">
+ {{data.get_last_warnings}} warning{{data.get_last_warnings | pluralize}}
+ </a>
+ {% endif %}
+ '''
+
+ image_files_template = '''
+ {% if data.get_number_of_builds > 0 and data.get_last_outcome == extra.Build.SUCCEEDED %}
+ <a href="{% url "builddashboard" data.get_last_build_id %}#images">
+ {{data.get_last_build_extensions}}
+ </a>
+ {% endif %}
+ '''
+
+ self.add_column(title='Project',
+ hideable=False,
+ orderable=True,
+ static_data_name='name',
+ static_data_template=name_template)
+
+ self.add_column(title='Last activity on',
+ help_text='Starting date and time of the \
+ last project build. If the project has no \
+ builds, this shows the date the project was \
+ created.',
+ hideable=False,
+ orderable=True,
+ static_data_name='updated',
+ static_data_template=last_activity_on_template)
+
+ self.add_column(title='Release',
+ help_text='The version of the build system used by \
+ the project',
+ hideable=False,
+ orderable=True,
+ static_data_name='release',
+ static_data_template=release_template)
+
+ self.add_column(title='Machine',
+ help_text='The hardware currently selected for the \
+ project',
+ hideable=False,
+ orderable=False,
+ static_data_name='machine',
+ static_data_template=machine_template)
+
+ self.add_column(title='Number of builds',
+ help_text='The number of builds which have been run \
+ for the project',
+ hideable=False,
+ orderable=False,
+ static_data_name='number_of_builds',
+ static_data_template=number_of_builds_template)
+
+ self.add_column(title='Last build outcome',
+ help_text='Indicates whether the last project build \
+ completed successfully or failed',
+ hideable=True,
+ orderable=False,
+ static_data_name='last_build_outcome',
+ static_data_template=last_build_outcome_template)
+
+ self.add_column(title='Recipe',
+ help_text='The last recipe which was built in this \
+ project',
+ hideable=True,
+ orderable=False,
+ static_data_name='recipe_name',
+ static_data_template=recipe_template)
+
+ self.add_column(title='Errors',
+ help_text='The number of errors encountered during \
+ the last project build (if any)',
+ hideable=True,
+ orderable=False,
+ static_data_name='errors',
+ static_data_template=errors_template)
+
+ self.add_column(title='Warnings',
+ help_text='The number of warnings encountered during \
+ the last project build (if any)',
+ hideable=True,
+ hidden=True,
+ orderable=False,
+ static_data_name='warnings',
+ static_data_template=warnings_template)
+
+ self.add_column(title='Image files',
+ help_text='The root file system types produced by \
+ the last project build',
+ hideable=True,
+ hidden=True,
+ orderable=False,
+ static_data_name='image_files',
+ static_data_template=image_files_template)
+
+class BuildsTable(ToasterTable):
+ """Table of builds in Toaster"""
+
+ def __init__(self, *args, **kwargs):
+ super(BuildsTable, self).__init__(*args, **kwargs)
+ self.default_orderby = '-completed_on'
+ self.static_context_extra['Build'] = Build
+ self.static_context_extra['Task'] = Task
+
+ # attributes that are overridden in subclasses
+
+ # title for the page
+ self.title = ''
+
+ # 'project' or 'all'; determines how the mrb (most recent builds)
+ # section is displayed
+ self.mrb_type = ''
+
+ def get_builds(self):
+ """
+ overridden in ProjectBuildsTable to return builds for a
+ single project
+ """
+ return Build.objects.all()
+
+ def get_context_data(self, **kwargs):
+ context = super(BuildsTable, self).get_context_data(**kwargs)
+
+ # should be set in subclasses
+ context['mru'] = []
+
+ context['mrb_type'] = self.mrb_type
+
+ return context
+
+ def setup_queryset(self, *args, **kwargs):
+ """
+ The queryset is annotated so that it can be sorted by number of
+ errors and number of warnings; but note that the criteria for
+ finding the log messages to populate these fields should match those
+ used in the Build model (orm/models.py) to populate the errors and
+ warnings properties
+ """
+ queryset = self.get_builds()
+
+ # Don't include in progress builds pr cancelled builds
+ queryset = queryset.exclude(Q(outcome=Build.IN_PROGRESS) |
+ Q(outcome=Build.CANCELLED))
+
+ # sort
+ queryset = queryset.order_by(self.default_orderby)
+
+ # annotate with number of ERROR, EXCEPTION and CRITICAL log messages
+ criteria = (Q(logmessage__level=LogMessage.ERROR) |
+ Q(logmessage__level=LogMessage.EXCEPTION) |
+ Q(logmessage__level=LogMessage.CRITICAL))
+
+ queryset = queryset.annotate(
+ errors_no=Count(
+ Case(
+ When(criteria, then=Value(1)),
+ output_field=IntegerField()
+ )
+ )
+ )
+
+ # annotate with number of WARNING log messages
+ queryset = queryset.annotate(
+ warnings_no=Count(
+ Case(
+ When(logmessage__level=LogMessage.WARNING, then=Value(1)),
+ output_field=IntegerField()
+ )
+ )
+ )
+
+ self.queryset = queryset
+
+ def setup_columns(self, *args, **kwargs):
+ outcome_template = '''
+ <a href="{% url "builddashboard" data.id %}">
+ {% if data.outcome == data.SUCCEEDED %}
+ <i class="icon-ok-sign success"></i>
+ {% elif data.outcome == data.FAILED %}
+ <i class="icon-minus-sign error"></i>
+ {% endif %}
+ </a>
+
+ {% if data.cooker_log_path %}
+ &nbsp;
+ <a href="{% url "build_artifact" data.id "cookerlog" data.id %}">
+ <i class="icon-download-alt get-help"
+ data-original-title="Download build log"></i>
+ </a>
+ {% endif %}
+ '''
+
+ recipe_template = '''
+ {% for target_label in data.target_labels %}
+ <a href="{% url "builddashboard" data.id %}">
+ {{target_label}}
+ </a>
+ <br />
+ {% endfor %}
+ '''
+
+ machine_template = '''
+ <a href="{% url "builddashboard" data.id %}">
+ {{data.machine}}
+ </a>
+ '''
+
+ started_on_template = '''
+ <a href="{% url "builddashboard" data.id %}">
+ {{data.started_on | date:"d/m/y H:i"}}
+ </a>
+ '''
+
+ completed_on_template = '''
+ <a href="{% url "builddashboard" data.id %}">
+ {{data.completed_on | date:"d/m/y H:i"}}
+ </a>
+ '''
+
+ failed_tasks_template = '''
+ {% if data.failed_tasks.count == 1 %}
+ <a href="{% url "task" data.id data.failed_tasks.0.id %}">
+ <span class="error">
+ {{data.failed_tasks.0.recipe.name}}.{{data.failed_tasks.0.task_name}}
+ </span>
+ </a>
+ <a href="{% url "build_artifact" data.id "tasklogfile" data.failed_tasks.0.id %}">
+ <i class="icon-download-alt"
+ data-original-title="Download task log file">
+ </i>
+ </a>
+ {% elif data.failed_tasks.count > 1 %}
+ <a href="{% url "tasks" data.id %}?filter=outcome%3A{{extra.Task.OUTCOME_FAILED}}">
+ <span class="error">{{data.failed_tasks.count}} tasks</span>
+ </a>
+ {% endif %}
+ '''
+
+ errors_template = '''
+ {% if data.errors_no %}
+ <a class="errors.count error" href="{% url "builddashboard" data.id %}#errors">
+ {{data.errors_no}} error{{data.errors_no|pluralize}}
+ </a>
+ {% endif %}
+ '''
+
+ warnings_template = '''
+ {% if data.warnings_no %}
+ <a class="warnings.count warning" href="{% url "builddashboard" data.id %}#warnings">
+ {{data.warnings_no}} warning{{data.warnings_no|pluralize}}
+ </a>
+ {% endif %}
+ '''
+
+ time_template = '''
+ {% load projecttags %}
+ <a href="{% url "buildtime" data.id %}">
+ {{data.timespent_seconds | sectohms}}
+ </a>
+ '''
+
+ image_files_template = '''
+ {% if data.outcome == extra.Build.SUCCEEDED %}
+ <a href="{% url "builddashboard" data.id %}#images">
+ {{data.get_image_file_extensions}}
+ </a>
+ {% endif %}
+ '''
+
+ self.add_column(title='Outcome',
+ help_text='Final state of the build (successful \
+ or failed)',
+ hideable=False,
+ orderable=True,
+ filter_name='outcome_filter',
+ static_data_name='outcome',
+ static_data_template=outcome_template)
+
+ self.add_column(title='Recipe',
+ help_text='What was built (i.e. one or more recipes \
+ or image recipes)',
+ hideable=False,
+ orderable=False,
+ static_data_name='target',
+ static_data_template=recipe_template)
+
+ self.add_column(title='Machine',
+ help_text='Hardware for which you are building a \
+ recipe or image recipe',
+ hideable=False,
+ orderable=True,
+ static_data_name='machine',
+ static_data_template=machine_template)
+
+ self.add_column(title='Started on',
+ help_text='The date and time when the build started',
+ hideable=True,
+ hidden=True,
+ orderable=True,
+ filter_name='started_on_filter',
+ static_data_name='started_on',
+ static_data_template=started_on_template)
+
+ self.add_column(title='Completed on',
+ help_text='The date and time when the build finished',
+ hideable=False,
+ orderable=True,
+ filter_name='completed_on_filter',
+ static_data_name='completed_on',
+ static_data_template=completed_on_template)
+
+ self.add_column(title='Failed tasks',
+ help_text='The number of tasks which failed during \
+ the build',
+ hideable=True,
+ orderable=False,
+ filter_name='failed_tasks_filter',
+ static_data_name='failed_tasks',
+ static_data_template=failed_tasks_template)
+
+ self.add_column(title='Errors',
+ help_text='The number of errors encountered during \
+ the build (if any)',
+ hideable=True,
+ orderable=True,
+ static_data_name='errors_no',
+ static_data_template=errors_template)
+
+ self.add_column(title='Warnings',
+ help_text='The number of warnings encountered during \
+ the build (if any)',
+ hideable=True,
+ orderable=True,
+ static_data_name='warnings_no',
+ static_data_template=warnings_template)
+
+ self.add_column(title='Time',
+ help_text='How long the build took to finish',
+ hideable=True,
+ hidden=True,
+ orderable=False,
+ static_data_name='time',
+ static_data_template=time_template)
+
+ self.add_column(title='Image files',
+ help_text='The root file system types produced by \
+ the build',
+ hideable=True,
+ orderable=False,
+ static_data_name='image_files',
+ static_data_template=image_files_template)
+
+ def setup_filters(self, *args, **kwargs):
+ # outcomes
+ outcome_filter = TableFilter(
+ 'outcome_filter',
+ 'Filter builds by outcome'
+ )
+
+ successful_builds_action = TableFilterActionToggle(
+ 'successful_builds',
+ 'Successful builds',
+ Q(outcome=Build.SUCCEEDED)
+ )
+
+ failed_builds_action = TableFilterActionToggle(
+ 'failed_builds',
+ 'Failed builds',
+ Q(outcome=Build.FAILED)
+ )
+
+ outcome_filter.add_action(successful_builds_action)
+ outcome_filter.add_action(failed_builds_action)
+ self.add_filter(outcome_filter)
+
+ # started on
+ started_on_filter = TableFilter(
+ 'started_on_filter',
+ 'Filter by date when build was started'
+ )
+
+ started_today_action = TableFilterActionDay(
+ 'today',
+ 'Today\'s builds',
+ 'started_on',
+ 'today'
+ )
+
+ started_yesterday_action = TableFilterActionDay(
+ 'yesterday',
+ 'Yesterday\'s builds',
+ 'started_on',
+ 'yesterday'
+ )
+
+ by_started_date_range_action = TableFilterActionDateRange(
+ 'date_range',
+ 'Build date range',
+ 'started_on'
+ )
+
+ started_on_filter.add_action(started_today_action)
+ started_on_filter.add_action(started_yesterday_action)
+ started_on_filter.add_action(by_started_date_range_action)
+ self.add_filter(started_on_filter)
+
+ # completed on
+ completed_on_filter = TableFilter(
+ 'completed_on_filter',
+ 'Filter by date when build was completed'
+ )
+
+ completed_today_action = TableFilterActionDay(
+ 'today',
+ 'Today\'s builds',
+ 'completed_on',
+ 'today'
+ )
+
+ completed_yesterday_action = TableFilterActionDay(
+ 'yesterday',
+ 'Yesterday\'s builds',
+ 'completed_on',
+ 'yesterday'
+ )
+
+ by_completed_date_range_action = TableFilterActionDateRange(
+ 'date_range',
+ 'Build date range',
+ 'completed_on'
+ )
+
+ completed_on_filter.add_action(completed_today_action)
+ completed_on_filter.add_action(completed_yesterday_action)
+ completed_on_filter.add_action(by_completed_date_range_action)
+ self.add_filter(completed_on_filter)
+
+ # failed tasks
+ failed_tasks_filter = TableFilter(
+ 'failed_tasks_filter',
+ 'Filter builds by failed tasks'
+ )
+
+ criteria = Q(task_build__outcome=Task.OUTCOME_FAILED)
+
+ with_failed_tasks_action = TableFilterActionToggle(
+ 'with_failed_tasks',
+ 'Builds with failed tasks',
+ criteria
+ )
+
+ without_failed_tasks_action = TableFilterActionToggle(
+ 'without_failed_tasks',
+ 'Builds without failed tasks',
+ ~criteria
+ )
+
+ failed_tasks_filter.add_action(with_failed_tasks_action)
+ failed_tasks_filter.add_action(without_failed_tasks_action)
+ self.add_filter(failed_tasks_filter)
+
+
+class AllBuildsTable(BuildsTable):
+ """ Builds page for all builds """
+
+ def __init__(self, *args, **kwargs):
+ super(AllBuildsTable, self).__init__(*args, **kwargs)
+ self.title = 'All builds'
+ self.mrb_type = 'all'
+
+ def setup_columns(self, *args, **kwargs):
+ """
+ All builds page shows a column for the project
+ """
+
+ super(AllBuildsTable, self).setup_columns(*args, **kwargs)
+
+ project_template = '''
+ {% load project_url_tag %}
+ <a href="{% project_url data.project %}">
+ {{data.project.name}}
+ </a>
+ {% if data.project.is_default %}
+ <i class="icon-question-sign get-help hover-help" title=""
+ data-original-title="This project shows information about
+ the builds you start from the command line while Toaster is
+ running" style="visibility: hidden;"></i>
+ {% endif %}
+ '''
+
+ self.add_column(title='Project',
+ hideable=True,
+ orderable=True,
+ static_data_name='project',
+ static_data_template=project_template)
+
+ def get_context_data(self, **kwargs):
+ """ Get all builds for the recent builds area """
+ context = super(AllBuildsTable, self).get_context_data(**kwargs)
+ context['mru'] = Build.get_recent()
+ return context
+
+class ProjectBuildsTable(BuildsTable):
+ """
+ Builds page for a single project; a BuildsTable, with the queryset
+ filtered by project
+ """
+
+ def __init__(self, *args, **kwargs):
+ super(ProjectBuildsTable, self).__init__(*args, **kwargs)
+ self.title = 'All project builds'
+ self.mrb_type = 'project'
+
+ # set from the querystring
+ self.project_id = None
+
+ def setup_columns(self, *args, **kwargs):
+ """
+ Project builds table doesn't show the machines column by default
+ """
+
+ super(ProjectBuildsTable, self).setup_columns(*args, **kwargs)
+
+ # hide the machine column
+ self.set_column_hidden('Machine', True)
+
+ # allow the machine column to be hidden by the user
+ self.set_column_hideable('Machine', True)
+
+ def setup_queryset(self, *args, **kwargs):
+ """
+ NOTE: self.project_id must be set before calling super(),
+ as it's used in setup_queryset()
+ """
+ self.project_id = kwargs['pid']
+ super(ProjectBuildsTable, self).setup_queryset(*args, **kwargs)
+
+ project = Project.objects.get(pk=self.project_id)
+ self.queryset = self.queryset.filter(project=project)
+
+ def get_context_data(self, **kwargs):
+ """
+ Get recent builds for this project, and the project itself
+
+ NOTE: self.project_id must be set before calling super(),
+ as it's used in get_context_data()
+ """
+ self.project_id = kwargs['pid']
+ context = super(ProjectBuildsTable, self).get_context_data(**kwargs)
+
+ project = Project.objects.get(pk=self.project_id)
+ context['mru'] = Build.get_recent(project)
+ context['project'] = project
+
+ return context
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/base.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/base.html
index 11ac2a035..210cf3360 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/base.html
@@ -3,15 +3,15 @@
{% load projecttags %}
{% load project_url_tag %}
<html lang="en">
- <head>
- <title>
- {% block title %} Toaster {% endblock %}
- </title>
-<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css"/>
-<link rel="stylesheet" href="{% static 'css/bootstrap-responsive.min.css' %}" type='text/css'/>
-<link rel="stylesheet" href="{% static 'css/font-awesome.min.css' %}" type='text/css'/>
-<link rel="stylesheet" href="{% static 'css/prettify.css' %}" type='text/css'/>
-<link rel="stylesheet" href="{% static 'css/default.css' %}" type='text/css'/>
+ <head>
+ <title>
+ {% block title %} Toaster {% endblock %}
+ </title>
+ <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css"/>
+ <link rel="stylesheet" href="{% static 'css/bootstrap-responsive.min.css' %}" type='text/css'/>
+ <link rel="stylesheet" href="{% static 'css/font-awesome.min.css' %}" type='text/css'/>
+ <link rel="stylesheet" href="{% static 'css/prettify.css' %}" type='text/css'/>
+ <link rel="stylesheet" href="{% static 'css/default.css' %}" type='text/css'/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
@@ -40,48 +40,35 @@
projectId : {{project.id}},
projectPageUrl : {% url 'project' project.id as purl %}{{purl|json}},
projectName : {{project.name|json}},
- projectIsDefault: {% if project.is_default %}true{% else %}false{% endif %},
recipesTypeAheadUrl: {% url 'xhr_recipestypeahead' project.id as paturl%}{{paturl|json}},
layersTypeAheadUrl: {% url 'xhr_layerstypeahead' project.id as paturl%}{{paturl|json}},
machinesTypeAheadUrl: {% url 'xhr_machinestypeahead' project.id as paturl%}{{paturl|json}},
-
projectBuildsUrl: {% url 'projectbuilds' project.id as pburl %}{{pburl|json}},
+ xhrCustomRecipeUrl : "{% url 'xhr_customrecipe' %}",
projectId : {{project.id}},
+ xhrBuildRequestUrl: "{% url 'xhr_buildrequest' project.id %}",
{% else %}
projectId : undefined,
projectPageUrl : undefined,
projectName : undefined,
- projectIsDefault: false,
{% endif %}
};
</script>
- <script src="{% static 'js/base.js' %}"></script>
- <script>
- $(document).ready(function () {
- /* Vars needed for base.js */
- var ctx = {};
- ctx.numProjects = {{projects|length}};
- ctx.currentUrl = "{{request.path|escapejs}}";
-
- basePageInit(ctx);
- });
- </script>
+ {% block extraheadcontent %}
+ {% endblock %}
+ </head>
-{% block extraheadcontent %}
-{% endblock %}
- </head>
+ <body style="height: 100%">
-<body style="height: 100%">
-
- {% csrf_token %}
- <div id="loading-notification" class="alert lead text-center" style="display:none">
- Loading <i class="fa-pulse icon-spinner"></i>
- </div>
+ {% csrf_token %}
+ <div id="loading-notification" class="alert lead text-center" style="display:none">
+ Loading <i class="fa-pulse icon-spinner"></i>
+ </div>
- <div id="change-notification" class="alert lead alert-info" style="display:none">
- <button type="button" class="close" id="hide-alert">&times;</button>
- <span id="change-notification-msg"></span>
- </div>
+ <div id="change-notification" class="alert lead alert-info" style="display:none">
+ <button type="button" class="close" id="hide-alert">&times;</button>
+ <span id="change-notification-msg"></span>
+ </div>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
@@ -90,10 +77,10 @@
<span class="brand">
<a href="/">Toaster</a>
{% if DEBUG %}
- <i class="icon-info-sign" title="<strong>Toaster version information</strong>" data-content="<dl><dt>Branch</dt><dd>{{TOASTER_BRANCH}}</dd><dt>Revision</dt><dd>{{TOASTER_REVISION}}</dd></dl>"></i>
+ <i class="icon-info-sign" title="<strong>Toaster version information</strong>" data-content="<dl><dt>Git branch</dt><dd>{{TOASTER_BRANCH}}</dd><dt>Git revision</dt><dd>{{TOASTER_REVISION}}</dd></dl>"></i>
{% endif %}
</span>
- {% if BUILD_MODE and request.resolver_match.url_name != 'landing' and request.resolver_match.url_name != 'newproject' %}
+ {% if request.resolver_match.url_name != 'landing' and request.resolver_match.url_name != 'newproject' %}
<ul class="nav">
<li {% if request.resolver_match.url_name == 'all-builds' %}
class="active"
@@ -122,75 +109,18 @@
</li>
</ul>
<span class="pull-right divider-vertical"></span>
-
- <!-- new project button; only show in build mode -->
- {% if BUILD_MODE %}
- <div class="btn-group pull-right">
- <a class="btn" id="new-project-button" href="{% url 'newproject' %}">New project</a>
- </div>
- {% endif %}
-
- <!--
- New build popover; only shown if there is at least one user-created project
- and we're in build mode
- -->
- {% if BUILD_MODE and non_cli_projects.count > 0 %}
- <div class="btn-group pull-right" id="new-build-button" style="display:none">
- <button class="btn dropdown-toggle" data-toggle="dropdown">
- New build
- <i class="icon-caret-down"></i>
- </button>
- <ul class="dropdown-menu new-build multi-select">
- <li>
- <h3>New build</h3>
- <h6>
- Project:
- <span id="project">
- {% if project.id and not project.is_default %}
- <a class="lead" href="{% project_url project %}">{{project.name}}</a>
- {% else %}
- <a class="lead" href="#"></a>
- {% endif %}
- <i class="icon-pencil"></i>
- </span>
- </h6>
- <form id="change-project-form" style="display:none;">
- <div class="input-append">
- <input type="text" class="input-medium" id="project-name-input" placeholder="Type a project name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead"/>
- <button id="save-project-button" class="btn" type="button">Save</button>
- <a href="#" id="cancel-change-project" class="btn btn-link" style="display: none">Cancel</a>
- </div>
- <p><a id="view-all-projects" href="{% url 'all-projects' %}">View all projects</a></p>
- </form>
- </li>
- <li>
- <div class="alert" style="display:none;">
- <p>This project configuration is incomplete, so you cannot run builds.</p>
- <p><a href="{% if project.id %}{% url 'project' project.id %}{% endif %}">View project configuration</a></p>
- </div>
- </li>
- <li id="targets-form">
- <h6>Recipe(s):</h6>
- <form>
- <input type="text" class="input-xlarge build-target-input" placeholder="Type a recipe name" autocomplete="off" data-minLength="1" data-autocomplete="off" data-provide="typeahead" disabled/>
- <div class="row-fluid">
- <button class="btn btn-primary build-button" disabled>Build</button>
- </div>
- </form>
- </li>
- </ul>
- </div>
- {% endif %}
+ <div class="btn-group pull-right">
+ <a class="btn" id="new-project-button" href="{% url 'newproject' %}">New project</a>
+ </div>
+ </div>
+ </div>
</div>
- </div>
-</div>
-<div class="container-fluid top-padded">
-<div class="row-fluid">
-{% block pagecontent %}
-{% endblock %}
-</div>
-</div>
-</body>
+ <div class="container-fluid top-padded">
+ <div class="row-fluid">
+ {% block pagecontent %}
+ {% endblock %}
+ </div>
+ </div>
+ </body>
</html>
-
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuilddetailpage.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuilddetailpage.html
index 22ca50c0c..a62e0b1cb 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuilddetailpage.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuilddetailpage.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+{% load project_url_tag %}
{% load humanize %}
{% block pagecontent %}
@@ -6,16 +7,18 @@
<!-- Breadcrumbs -->
<div class="section">
<ul class="breadcrumb" id="breadcrumb">
- <li class="muted">{{build.project.name}}:</li>
- <li><a href="{% url 'projectbuilds' build.project.id %}">Builds</a></li>
- <li><a href="{%url 'builddashboard' build.pk%}">{{build.target_set.all.0.target}} {%if build.target_set.all.count > 1%}(+ {{build.target_set.all.count|add:"-1"}}){%endif%} ({{build.completed_on|date:"d/m/y H:i"}})</a></li>
+ <li><a href="{% project_url build.project %}">{{build.project.name}}</a></li>
+ {% if not build.project.is_default %}
+ <li><a href="{% url 'projectbuilds' build.project.id %}">Builds</a></li>
+ {% endif %}
+ <li><a href="{%url 'builddashboard' build.pk%}">{{build.get_sorted_target_list.0.target}} {%if build.target_set.all.count > 1%}(+{{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}})</a></li>
{% block localbreadcrumb %}{% endblock %}
</ul>
<script>
$( function () {
$('#breadcrumb > li').append('<span class="divider">&rarr;</span>');
$('#breadcrumb > li:last').addClass("active");
- $('#breadcrumb > li:last > span, #breadcrumb > li:first > span').remove();
+ $('#breadcrumb > li:last > span').remove();
});
</script>
</div> <!--section-->
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuildpage.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
index d441df84e..0d8c8820d 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
@@ -1,88 +1,157 @@
{% extends "base.html" %}
{% load projecttags %}
+{% load project_url_tag %}
+{% load objects_to_dictionaries_filter %}
{% load humanize %}
{% block pagecontent %}
+ <!-- breadcrumbs -->
+ <div class="section">
+ <ul class="breadcrumb" id="breadcrumb">
+ <li><a href="{% project_url build.project %}">{{build.project.name}}</a></li>
+ {% if not build.project.is_default %}
+ <li><a href="{% url 'projectbuilds' build.project.id %}">Builds</a></li>
+ {% endif %}
+ <li>
+ {% block parentbreadcrumb %}
+ <a href="{%url 'builddashboard' build.pk%}">
+ {{build.get_sorted_target_list.0.target}} {% if build.target_set.all.count > 1 %}(+{{build.target_set.all.count|add:"-1"}}){% endif %} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}})
+ </a>
+ {% endblock %}
+ </li>
+ {% block localbreadcrumb %}{% endblock %}
+ </ul>
+ <script>
+ $( function () {
+ $('#breadcrumb > li').append('<span class="divider">&rarr;</span>');
+ $('#breadcrumb > li:last').addClass("active");
+ $('#breadcrumb > li:last > span').remove();
+ });
+ </script>
+ </div>
+ <div class="row-fluid">
+ <!-- begin left sidebar container -->
+ <div id="nav" class="span2">
+ <ul class="nav nav-list well">
+ <li
+ {% if request.resolver_match.url_name == 'builddashboard' %}
+ class="active"
+ {% endif %} >
+ <a class="nav-parent" href="{% url 'builddashboard' build.pk %}">Build summary</a>
+ </li>
+ {% if build.target_set.all.0.is_image and build.outcome == 0 %}
+ <li class="nav-header">Images</li>
+ {% block nav-target %}
+ {% for t in build.get_sorted_target_list %}
+ <li><a href="{% url 'target' build.pk t.pk %}">{{t.target}}</a><li>
+ {% endfor %}
+ {% endblock %}
+ {% endif %}
+ <li class="nav-header">Build</li>
+ {% block nav-configuration %}
+ <li><a href="{% url 'configuration' build.pk %}">Configuration</a></li>
+ {% endblock %}
+ {% block nav-tasks %}
+ <li><a href="{% url 'tasks' build.pk %}">Tasks</a></li>
+ {% endblock %}
+ {% block nav-recipes %}
+ <li><a href="{% url 'recipes' build.pk %}">Recipes</a></li>
+ {% endblock %}
+ {% block nav-packages %}
+ <li><a href="{% url 'packages' build.pk %}">Packages</a></li>
+ {% endblock %}
+ <li class="nav-header">Performance</li>
+ {% block nav-buildtime %}
+ <li><a href="{% url 'buildtime' build.pk %}">Time</a></li>
+ {% endblock %}
+ {% block nav-cputime %}
+ <li><a href="{% url 'cputime' build.pk %}">CPU usage</a></li>
+ {% endblock %}
+ {% block nav-diskio %}
+ <li><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li>
+ {% endblock %}
- <div class="">
-<!-- Breadcrumbs -->
- <div class="section">
- <ul class="breadcrumb" id="breadcrumb">
- <li class="muted">{{build.project.name}}:</li>
- <li><a href="{% url 'projectbuilds' build.project.id %}">Builds</a></li>
- <li>
- {% block parentbreadcrumb %}
- <a href="{%url 'builddashboard' build.pk%}">
- {{build.get_sorted_target_list.0.target}} {%if build.target_set.all.count > 1%}(+ {{build.target_set.all.count|add:"-1"}}){%endif%} ({{build.completed_on|date:"d/m/y H:i"}})
+ <li class="divider"></li>
+
+ <li>
+ <p class="navbar-btn">
+ <a class="btn btn-block" href="{% url 'build_artifact' build.id 'cookerlog' build.id %}">
+ Download build log
</a>
- {% endblock %}
+ </p>
+ </li>
+
+ {% with build.get_custom_image_recipes as custom_image_recipes %}
+ {% if custom_image_recipes.count > 0 %}
+ <!-- edit custom image built during this build -->
+ <li>
+ <p class="navbar-btn" data-role="edit-custom-image-trigger">
+ <button class="btn btn-block">Edit custom image</button>
+ {% include 'editcustomimage_modal.html' %}
+ <script>
+ var editableCustomImageRecipes = {{ custom_image_recipes | objects_to_dictionaries:"id,name" | json }};
+
+ $(document).ready(function () {
+ var editCustomImageTrigger = $('[data-role="edit-custom-image-trigger"]');
+ var editCustomImageModal = $('#edit-custom-image-modal');
+
+ // edit custom image which was built during this build
+ editCustomImageTrigger.click(function () {
+ // single editable custom image: redirect to the edit page
+ // for that image
+ if (editableCustomImageRecipes.length === 1) {
+ var url = '{% url "customrecipe" build.project.id custom_image_recipes.first.id %}';
+ document.location.href = url;
+ }
+ // multiple editable custom images: show modal to select
+ // one of them for editing
+ else {
+ editCustomImageModal.modal('show');
+ }
+ });
+ });
+ </script>
+ </p>
</li>
- {% block localbreadcrumb %}{% endblock %}
- </ul>
- <script>
- $( function () {
- $('#breadcrumb > li').append('<span class="divider">&rarr;</span>');
- $('#breadcrumb > li:last').addClass("active");
- $('#breadcrumb > li:last > span, #breadcrumb > li:first > span').remove();
- console.log("done");
- });
- </script>
- </div>
+ {% endif %}
+ {% endwith %}
- <div class="row-fluid">
+ <li>
+ <!-- new custom image from image recipe in this build -->
+ <p class="navbar-btn" data-role="new-custom-image-trigger">
+ <button class="btn btn-block">New custom image</button>
+ </p>
+ {% include 'newcustomimage_modal.html' %}
+ <script>
+ // imageRecipes includes both custom image recipes and built-in
+ // image recipes, any of which can be used as the basis for a
+ // new custom image
+ var imageRecipes = {{ build.get_image_recipes | objects_to_dictionaries:"id,name" | json }};
- <!-- begin left sidebar container -->
- <div id="nav" class="span2">
- <ul class="nav nav-list well">
- <li
- {% if request.resolver_match.url_name == 'builddashboard' %}
- class="active"
- {% endif %} >
- <a class="nav-parent" href="{% url 'builddashboard' build.pk %}">Build summary</a>
- </li>
- {% if build.target_set.all.0.is_image and build.outcome == 0 %}
- <li class="nav-header">Images</li>
- {% block nav-target %}
- {% for t in build.get_sorted_target_list %}
- <li><a href="{% url 'target' build.pk t.pk %}">{{t.target}}</a><li>
- {% endfor %}
- {% endblock %}
- {% endif %}
- <li class="nav-header">Build</li>
- {% block nav-configuration %}
- <li><a href="{% url 'configuration' build.pk %}">Configuration</a></li>
- {% endblock %}
- {% block nav-tasks %}
- <li><a href="{% url 'tasks' build.pk %}">Tasks</a></li>
- {% endblock %}
- {% block nav-recipes %}
- <li><a href="{% url 'recipes' build.pk %}">Recipes</a></li>
- {% endblock %}
- {% block nav-packages %}
- <li><a href="{% url 'packages' build.pk %}">Packages</a></li>
- {% endblock %}
- <li class="nav-header">Performance</li>
- {% block nav-buildtime %}
- <li><a href="{% url 'buildtime' build.pk %}">Time</a></li>
- {% endblock %}
- {% block nav-cpuusage %}
- <li><a href="{% url 'cpuusage' build.pk %}">CPU usage</a></li>
- {% endblock %}
- {% block nav-diskio %}
- <li><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li>
- {% endblock %}
- </ul>
- </div>
- <!-- end left sidebar container -->
+ $(document).ready(function () {
+ var newCustomImageModal = $('#new-custom-image-modal');
+ var newCustomImageTrigger = $('[data-role="new-custom-image-trigger"]');
- <!-- Begin right container -->
- {% block buildinfomain %}{% endblock %}
- <!-- End right container -->
+ // show create new custom image modal to select an image built
+ // during this build as the basis for the custom recipe
+ newCustomImageTrigger.click(function () {
+ if (!imageRecipes.length) {
+ return;
+ }
+ newCustomImageModalSetRecipes(imageRecipes);
+ newCustomImageModal.modal('show');
+ });
+ });
+ </script>
+ </li>
+ </ul>
</div>
- </div>
-
+ <!-- end left sidebar container -->
+ <!-- begin right container -->
+ {% block buildinfomain %}{% endblock %}
+ <!-- end right container -->
+ </div>
{% endblock %}
-
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html
index 1f45be462..8778305f3 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/baseprojectpage.html
@@ -1,4 +1,5 @@
{% extends "base.html" %}
+
{% load projecttags %}
{% load humanize %}
@@ -26,9 +27,7 @@
<ul class="nav nav-list well">
<li><a class="nav-parent" href="{% url 'project' project.id %}">Configuration</a></li>
<li class="nav-header">Compatible metadata</li>
- {% if CUSTOM_IMAGE %}
<li><a href="{% url 'projectcustomimages' project.id %}">Custom images</a></li>
- {% endif %}
<li><a href="{% url 'projectimagerecipes' project.id %}">Image recipes</a></li>
<li><a href="{% url 'projectsoftwarerecipes' project.id %}">Software recipes</a></li>
<li><a href="{% url 'projectmachines' project.id %}">Machines</a></li>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/basetable_top.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/basetable_top.html
index 33ede6687..0ddd74904 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/basetable_top.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/basetable_top.html
@@ -161,8 +161,8 @@
<!-- control header -->
<div class="navbar">
<div class="navbar-inner">
- <form class="navbar-search input-append pull-left" id="searchform">
- <input class="input-xxlarge" id="search" name="search" type="text" placeholder="Search {%if object_search_display %}{{object_search_display}}{%else%}{{objectname}}{%endif%}" value="{%if request.GET.search %}{{request.GET.search}}{% endif %}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{%endif%}
+ <form class="navbar-search input-append pull-left span6" id="searchform">
+ <input id="search" name="search" type="text" placeholder="Search {%if object_search_display %}{{object_search_display}}{%else%}{{objectname}}{%endif%}" value="{%if request.GET.search %}{{request.GET.search}}{% endif %}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{%endif%}
<input type="hidden" name="orderby" value="{{request.GET.orderby}}">
<input type="hidden" name="page" value="1">
<button class="btn" id="search-button" type="submit" value="Search">Search</button>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/builddashboard.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/builddashboard.html
index 323bbbb6e..a0da71ea4 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/builddashboard.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/builddashboard.html
@@ -6,10 +6,9 @@
{% block parentbreadcrumb %}
{% if build.get_sorted_target_list.count > 0 %}
{{build.get_sorted_target_list.0.target}}
- &nbsp;
{% endif %}
-{%if build.target_set.all.count > 1%}(+ {{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}})
+{%if build.target_set.all.count > 1%}(+{{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}})
{% endblock %}
{% block buildinfomain %}
@@ -111,7 +110,7 @@
</p>
</div>
</div>
- {% else %}
+ {% else %}
<dt>
<i class="icon-question-sign get-help" title="The location in disk of the license manifest, a document listing all packages installed in your image and their licenses"></i>
@@ -126,18 +125,18 @@
</dt>
<dd>
<ul>
- {% for i in target.imageFiles %}
- {% if build.project %}
- <li><a href="{% url 'build_artifact' build.pk 'imagefile' i.id %}">{{i.path}}</a>
- {% else %}
- <li>{{i.path}}
- {% endif %}
- ({{i.size|filtered_filesizeformat}})</li>
- {% endfor %}
+ {% for i in target.imageFiles %}
+ <li>
+ <a href="{% url 'build_artifact' build.pk 'imagefile' i.id %}">
+ {{i.suffix}}
+ </a>
+ &nbsp;({{i.size|filtered_filesizeformat}})
+ </li>
+ {% endfor %}
</ul>
</dd>
</dl>
- {% endif %}
+ {% endif %}
</div>
{% endif %}
{% endfor %}
@@ -161,7 +160,7 @@
<dd><div>
{% for ba in build.buildartifact_set.all|dictsort:"file_name" %}
<a href="{%url 'build_artifact' build.id 'buildartifact' ba.id %}">
- {{ba.get_local_file_name}}
+ {{ba.get_basename}}
</a>
({{ba.file_size|filtered_filesizeformat}}) <br/>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/builds-toastertable.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/builds-toastertable.html
new file mode 100644
index 000000000..bf13a66bd
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/builds-toastertable.html
@@ -0,0 +1,48 @@
+{% extends 'base.html' %}
+{% load static %}
+
+{% block extraheadcontent %}
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.structure.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.theme.min.css' %}" type='text/css'>
+ <script src="{% static 'js/jquery-ui.min.js' %}">
+ </script>
+{% endblock %}
+
+{% block title %} All builds - Toaster {% endblock %}
+
+{% block pagecontent %}
+
+ <div class="row-fluid">
+ {% with mru=mru mrb_type=mrb_type %}
+ {% include 'mrb_section.html' %}
+ {% endwith %}
+
+ <h1 class="page-header top-air" data-role="page-title"></h1>
+
+ {% url 'builds' as xhr_table_url %}
+ {% include 'toastertable.html' %}
+ </div>
+
+ <script>
+ $(document).ready(function () {
+ var tableElt = $("#{{table_name}}");
+ var titleElt = $("[data-role='page-title']");
+
+ tableElt.on("table-done", function (e, total, tableParams) {
+ var title = "All builds";
+
+ if (tableParams.search || tableParams.filter) {
+ if (total === 0) {
+ title = "No builds found";
+ }
+ else if (total > 0) {
+ title = total + " build" + (total > 1 ? 's' : '') + " found";
+ }
+ }
+
+ titleElt.text(title);
+ });
+ });
+ </script>
+{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/builds.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/builds.html
deleted file mode 100644
index a27a12191..000000000
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/builds.html
+++ /dev/null
@@ -1,119 +0,0 @@
-{% extends "base.html" %}
-
-{% load static %}
-{% load projecttags %}
-{% load project_url_tag %}
-{% load humanize %}
-
-{% block title %} All builds - Toaster {% endblock %}
-{% block extraheadcontent %}
-<link rel="stylesheet" href="/static/css/jquery-ui.min.css" type='text/css'>
-<link rel="stylesheet" href="/static/css/jquery-ui.structure.min.css" type='text/css'>
-<link rel="stylesheet" href="/static/css/jquery-ui.theme.min.css" type='text/css'>
-<script src="/static/js/jquery-ui.min.js"></script>
-<script src="/static/js/filtersnippet.js"></script>
-{% endblock %}
-
-{% block pagecontent %}
-
-{% if last_date_from and last_date_to %}
-<script>
- // initialize the date range controls
- $(document).ready(function () {
- date_init('started_on','{{last_date_from}}','{{last_date_to}}','{{dateMin_started_on}}','{{dateMax_started_on}}','{{daterange_selected}}');
- date_init('completed_on','{{last_date_from}}','{{last_date_to}}','{{dateMin_completed_on}}','{{dateMax_completed_on}}','{{daterange_selected}}');
- });
-</script>
-{%endif%} {# last_date_from and last_date_to #}
-
-<div class="row-fluid">
-
- {% include "mrb_section.html" %}
-
- <div class="page-header top-air">
- <h1>
- {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
- {{objects.paginator.count}} build{{objects.paginator.count|pluralize}} found
- {%elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
- No builds found
- {%else%}
- All builds
- {%endif%}
- </h1>
- </div>
-
- {% if objects.paginator.count == 0 %}
- <div class="row-fluid">
- <div class="alert">
- <form class="no-results input-append" id="searchform">
- <input id="search" name="search" class="input-xxlarge" type="text" value="
- {% if request.GET.search %}
- {{request.GET.search}}
- {% endif %}"/>
- {% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{% endif %}
- <button class="btn" type="submit" value="Search">Search</button>
- <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all builds</button>
- </form>
- </div>
- </div>
- {% else %}
- {% include "basetable_top.html" %}
- <!-- Table data rows; the order needs to match the order of "tablecols" definitions; and the <td class value needs to match the tablecols clclass value for show/hide buttons to work -->
- {% for build in objects %}
- <tr class="data" data-table-build-result="{{ build.id }}">
- <td class="outcome">
- <a href="{% url "builddashboard" build.id %}">{%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%}</a> &nbsp;
- </td>
- <td class="target">
- {% for t in build.target_set.all %}
- <a href="{% url "builddashboard" build.id %}">
- {% if t.task %}
- {{t.target}}:{{t.task}}
- {% else %}
- {{t.target}}
- {% endif %}
- </a> <br />
- {% endfor %}
- </td>
- <td class="machine"><a href="{% url "builddashboard" build.id %}">{{build.machine}}</a></td>
- <td class="started_on"><a href="{% url "builddashboard" build.id %}">{{build.started_on|date:"d/m/y H:i"}}</a></td>
- <td class="completed_on"><a href="{% url "builddashboard" build.id %}">{{build.completed_on|date:"d/m/y H:i"}}</a></td>
- <td class="failed_tasks error">
- {% query build.task_build outcome=4 order__gt=0 as exectask%}
- {% if exectask.count == 1 %}
- <a href="{% url "task" build.id exectask.0.id %}">{{exectask.0.recipe.name}}.{{exectask.0.task_name}}</a>
- <a href="{% url 'build_artifact' build.id "tasklogfile" exectask.0.id %}">
- <i class="icon-download-alt" title="" data-original-title="Download task log file"></i>
- </a>
- {% elif exectask.count > 1%}
- <a href="{% url "tasks" build.id %}?filter=outcome%3A4">{{exectask.count}} task{{exectask.count|pluralize}}</a>
- {%endif%}
- </td>
- <td class="errors.count errors_no">
- {% if build.errors.count %}
- <a class="errors.count error" href="{% url "builddashboard" build.id %}#errors">{{build.errors.count}} error{{build.errors.count|pluralize}}</a>
- {%endif%}
- </td>
- <td class="warnings.count warnings_no">{% if build.warnings.count %}<a class="warnings.count warning" href="{% url "builddashboard" build.id %}#warnings">{{build.warnings.count}} warning{{build.warnings.count|pluralize}}</a>{%endif%}</td>
- <td class="time"><a href="{% url "buildtime" build.id %}">{{build.timespent_seconds|sectohms}}</a></td>
- <td class="output">
- {% if build.outcome == build.SUCCEEDED %}
- <a href="{%url "builddashboard" build.id%}#images">{{fstypes|get_dict_value:build.id}}</a>
- {% endif %}
- </td>
- <td class="project-name">
- <a href="{% project_url build.project %}">{{build.project.name}}</a>
- {% if build.project.is_default %}
- <i class="icon-question-sign get-help hover-help" title="" data-original-title="This project shows information about the builds you start from the command line while Toaster is running" style="visibility: hidden;"></i>
- {% endif %}
- </td>
- </tr>
-
- {% endfor %}
-
-
- {% include "basetable_bottom.html" %}
- {% endif %} {# objects.paginator.count #}
-</div><!-- end row-fluid-->
-
-{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/customise_btn.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/customise_btn.html
index 54d05f9ea..2e54a9d90 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/customise_btn.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/customise_btn.html
@@ -1,9 +1,15 @@
-<button class="btn btn-block layer-exists-{{data.layer_version.id}} customise-btn" style="display:none;" data-recipe="{{data.id}}">
+<button class="btn btn-block layer-exists-{{data.layer_version.pk}} customise-btn" data-recipe="{{data.pk}}"
+ {% if data.layer_version.pk not in extra.current_layers %}
+ style="display:none;"
+ {% endif %}
+ >
Customise
</button>
-
-<button class="btn btn-block layer-add-{{data.layer_version.id}} layerbtn" data-layer='{ "id": {{data.layer_version.id}}, "name": "{{data.layer_version.layer.name}}", "layerdetailurl": "{% url 'layerdetails' extra.pid data.layer_version.id %}"}' data-directive="add">
+<button class="btn btn-block layer-add-{{data.layer_version.pk}} layerbtn" data-layer='{ "id": {{data.layer_version.pk}}, "name": "{{data.layer_version.layer.name}}", "layerdetailurl": "{%url 'layerdetails' extra.pid data.layer_version.pk%}"}' data-directive="add"
+ {% if data.layer_version.pk in extra.current_layers %}
+ style="display:none;"
+ {% endif %}
+ >
<i class="icon-plus"></i>
Add layer
</button>
-
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/customrecipe.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/customrecipe.html
index 823bbd8a1..ea3c9c732 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/customrecipe.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/customrecipe.html
@@ -4,13 +4,32 @@
{% load static %}
{% block pagecontent %}
-{% include "projecttopbar.html" %}
+<div class="section">
+ <ul class="breadcrumb">
+ <li>
+ <a href="{% url 'project' project.id %}">{{project.name}}</a>
+ <span class="divider">&rarr;</span>
+ </li>
+ <li><a href="{% url 'projectcustomimages' project.id %}">Custom images</a>
+ <span class="divider">&rarr;</span>
+ </li>
+ <li class="active">
+ {{recipe.name}} ({{recipe.layer_version.layer.name}})
+ </li>
+ </ul>
+</div>
<script src="{% static 'js/customrecipe.js' %}"></script>
<script>
$(document).ready(function (){
var ctx = {
- tableApiUrl: "{% url 'recipeselectpackages' project.id recipe.pk %}?format=json"
+ recipe : {
+ id: {{recipe.pk}},
+ name: "{{recipe.name}}",
+ includedPackagesCount: {{recipe.includes_set.count}},
+ baseRecipeId: {{recipe.base_recipe.pk}},
+ xhrPackageListUrl: "{% url 'xhr_customrecipe_packages' recipe.pk %}",
+ }
};
try {
@@ -21,6 +40,45 @@
}
});
</script>
+<!-- package dependencies modal -->
+<div style="display:none" id="package-deps-modal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
+ <h3><span class="package-to-add-name"></span> dependencies</h3>
+ </div>
+ <div class="modal-body">
+ <p>Based on information from a previous build it is likely that adding <strong class="package-to-add-name"></strong> will also add the following packages to your custom image:</p>
+ <ul id="package-add-dep-list">
+ </ul>
+ </div>
+ <div class="modal-footer">
+ <p class="help-block text-left">Total package size: <strong id="package-deps-total-size"></strong></p>
+ <button id="add-package-deps-modal-btn" type="submit" class="btn btn-primary" data-dismiss="modal">Add package</button>
+ <button class="btn" data-dismiss="modal">Cancel</button>
+ </div>
+</div>
+<!-- end package dependencies modal -->
+
+<!-- package reverse dependencies modal -->
+<div style="display:none" id="package-reverse-deps-modal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
+ <h3><span class="package-to-rm-name"></span> reverse dependencies</h3>
+ </div>
+ <div class="modal-body">
+ <p> <strong class="reverse-deps-count"></strong> <span class="reverse-deps-package"></span> in your image <span class="reverse-deps-depends"></span> on <strong class="package-to-rm-name"></strong>:</p>
+ <ul id="package-reverse-dep-list">
+ </ul>
+ <p>In order to remove <strong class="package-to-rm-name"></strong>, you must remove <span class="reverse-deps-this"></span> <strong class="reverse-deps-count"></strong> <span class="reverse-deps-package"></span> as well.</p>
+ </div>
+ <div class="modal-footer">
+ <p class="help-block text-left">Total package size: <strong id="package-reverse-deps-total-size"></strong></p>
+ <button id="rm-package-reverse-deps-modal-btn" type="submit" class="btn btn-primary" data-dismiss="modal">Remove all <span class="reverse-deps-count-plus1"></button>
+ <button class="btn" data-dismiss="modal">Cancel</button>
+ </div>
+</div>
+<!-- end package dependencies modal -->
+
<div class="row-fluid span11">
<div class="alert alert-success lead" id="image-created-notification" style="margin-top: 15px; display: none">
@@ -30,7 +88,7 @@
<div class="page-header air">
<h1>
{{recipe.name}}
- <small>({{recipe.base_recipe.name}})</small>
+ <small>({{recipe.layer_version.layer.name}})</small>
</h1>
</div>
</div>
@@ -38,44 +96,49 @@
<div class="row-fluid span11">
<div class="span8">
<div class="button-place btn-group" style="width: 100%">
- <a class="btn btn-large span6" href="#" id="build-custom-image" style="width: 50%">
+ <a class="btn btn-large span6 build-custom-image" href="#" style="width: 50%">
Build {{recipe.name}}
</a>
- <button class="btn btn-large span6" data-toggle="modal" data-target="#download-file" id="download" style="width: 50%">
- Download recipe file
- </button>
- </div>
- <div id="no-package-results" class="air" style="display:none;">
- <div class="alert">
- <h3>No packages found</h3>
- <p>You might consider <a href="all-software-recipes.html">searching the list of recipes</a> instead. If you find a recipe that matches the name of the package you want:</p>
- <ol>
- <li>Add the layer providing the recipe to your project</li>
- <li>Build the recipe</li>
- <li>Once the build completes, come back to this page and search for the package</li>
- </ol>
- <form class="input-append no-results">
- <input type="text" class="input-xlarge" value="search query">
- <a href="#" class="add-on btn">
+ <a href="{% url 'customrecipedownload' project.id recipe.id %}" class="btn btn-large span6" style="width: 50%">
+ Download recipe file
+ </a>
+ </div>
+ <div id="no-results-special-{{table_name}}" class="air" style="display:none;">
+ <div class="alert">
+ <h3>No packages found</h3>
+ <p>You might consider <a href={% url 'projectsoftwarerecipes' project.id %}>searching the list of recipes</a> instead. If you find a recipe that matches the name of the package you want:</p>
+ <ol>
+ <li>Add the layer providing the recipe to your project</li>
+ <li>Build the recipe</li>
+ <li>Once the build completes, come back to this page and search for the package</li>
+ </ol>
+ <form class="input-append no-results">
+ <input type="text" class="input-xlarge no-results-search-input" id="no-results-search-input-{{table_name}}" name="search" placeholder="Search {{title|lower}}" />
+ <a href="#" class="add-on btn" id="no-results-remove-search-btn" tabindex="-1">
<i class="icon-remove"></i>
</a>
- <button class="btn">Search</button>
- <button class="btn btn-link" id="show-all">Show all packages</button>
+ <button class="btn search-submit-{{table_name}}">Search</button>
+ <button class="btn btn-link" id="no-results-show-all-packages">Show all packages</button>
</form>
</div>
+ </div>
+ <div id="results-found-{{table_name}}">
+ <div id="packages-table">
+ {% if recipe.get_all_packages.count == 0 and last_build == None %}
+ <h2> Add | Remove packages </h2>
+ <div class="alert alert-info air">
+ <p class="lead">Toaster has no package information for {{recipe.name}}. To generate package information, build {{recipe.name}}</p>
+ <button class="btn btn-info btn-large build-custom-image" style="margin:20px 0 10px 0;">Build {{recipe.name}}</button>
+ </div>
+ {% else %}
+ {# ToasterTable for Adding remove packages #}
+ {% url 'recipeselectpackages' project.id recipe.id as xhr_table_url %}
+ <h2>{{title}} (<span class="table-count-{{table_name}}">0</span>) </h2>
+ {% include "toastertable.html" %}
+ {% endif %}
+ </div>
+ </div>
</div>
- <div id="packages-table">
- {% url 'recipeselectpackages' project.id recipe.id as xhr_table_url %}
- {% with 'recipeselection' as table_name %}
- {% with 'Add | Remove packages' as title %}
-
- <h2>{{title}} (<span class="table-count-{{table_name}}"></span>) </h2>
-
- {% include "toastertable.html" %}
- {% endwith %}
- {% endwith %}
- </div>
- </div>
<div class="span4 well">
<h2 style="margin-bottom:20px;">About {{recipe.name}}</h2>
@@ -84,59 +147,77 @@
Approx. packages included
<i class="icon-question-sign get-help" title="" data-original-title="The number of packages included is based on information from previous builds and from parsing layers, so we can never be sure it is 100% accurate"></i>
</dt>
- <dd class="no-packages">{{recipe.packages.count}}</dd>
- <!-- <dt>
+ <dd id="total-num-packages">{{recipe.get_all_packages.count}}</dd>
+ <dt>
Approx. package size
<i class="icon-question-sign get-help" title="" data-original-title="Package size is based on information from previous builds, so we can never be sure it is 100% accurate"></i>
</dt>
- <dd>244.3 MB</dd>
+ <dd id="total-size-packages">{{approx_pkg_size.size__sum|filtered_filesizeformat}}</dd>
+ {% if last_build %}
<dt>Last build</dt>
<dd>
<i class="icon-ok-sign success"></i>
- <a href="build-dashboard.html">11/06/15 15:22</a>
+ <a href="{% url 'projectbuilds' project.id%}">{{last_build.completed_on|date:"d/m/y H:i"}}</a>
</dd>
+ {% endif %}
+ <dt>Layer</dt>
+ <dd><a href="{% url 'layerdetails' project.id recipe.layer_version.pk %}">{{recipe.layer_version.layer.name}}</a></dd>
+ <dt>Based on</dt>
+ <dd><a href="{% url 'recipedetails' project.id recipe.base_recipe.pk %}">{{recipe.base_recipe.name}}</a></dd>
+ {% if recipe.get_last_successful_built_target %}
+ {% with recipe.get_last_successful_built_target as last_build_target %}
+ <dt>Last build</dt>
+ <dd>
+ <i class="icon-ok-sign success"></i>
+ <a href="{% url 'builddashboard' last_build_target.build.pk %}">
+ {{last_build_target.build.completed_on|date:"d/m/y H:i"}}</a>
+ </dd>
+ {% endwith %}
+ {% endif %}
<dt>Recipe file</dt>
<dd>
- <code>custom-image-name.bb</code>
- <a href="#download-file" data-toggle="modal"><i class="icon-download-alt" title="" data-original-title="Download recipe file"></i></a>
- </dd> -->
+ <code>{{recipe.name}}_{{recipe.version}}.bb</code>
+ <a href="{% url 'customrecipedownload' project.pk recipe.pk %}"><i class="icon-share" title="" data-original-title="View recipe file"></i></a>
+ </dd>
<dt>Layer</dt>
- <!-- TODO recipe details page -->
- <dd><a href="{% url 'layerdetails' project.id recipe.base_recipe.layer_version.pk %}">{{recipe.base_recipe.layer_version.layer.name}}</a></dd>
- <!--<dt>
+ <dd><a href="{% url 'layerdetails' project.id recipe.layer_version.pk %}">{{recipe.layer_version.layer.name}}</a></dd>
+ {% if recipe.summary %}
+ <dt>
Summary
</dt>
<dd>
- <span class="muted">Not set</span>
- <i class="icon-pencil" data-original-title="" title=""></i>
+ {{recipe.summary}}
</dd>
+ {% endif %}
+ {% if recipe.description %}
<dt>
Description
</dt>
<dd>
- <span class="muted">Not set</span>
- <i class="icon-pencil" data-original-title="" title=""></i>
+ {{recipe.description}}
</dd>
+ {% endif %}
<dt>Version</dt>
<dd>
- 1.0
- <i class="icon-pencil" data-original-title="" title=""></i>
+ {{recipe.version}}
</dd>
+ {% if recipe.section %}
<dt>Section</dt>
<dd>
- base
- <i class="icon-pencil" data-original-title="" title=""></i>
- <i class="icon-trash" data-original-title="" title=""></i>
+ {{recipe.section}}
</dd>
+ {% endif %}
<dt>License</dt>
<dd>
- MIT
+ {{recipe.license}}
<i class="icon-question-sign get-help" title="" data-original-title="All custom images have their license set to MIT. This is because the license applies only to the recipe (.bb) file, and not to the image itself. To see which licenses apply to the image you must check the license manifest generated with each build"></i>
- </dd> -->
+ </dd>
</dl>
+ <!--
<i class="icon-trash no-tooltip"></i>
<a href="#" class="error" id="delete">Delete custom image</a>
+ -->
</div>
-</div>
+ </div>
{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/editcustomimage_modal.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/editcustomimage_modal.html
new file mode 100644
index 000000000..8046c08fb
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/editcustomimage_modal.html
@@ -0,0 +1,71 @@
+<!--
+modal dialog shown on the build dashboard, for editing an existing custom image;
+only shown if more than one custom image was built, so the user needs to
+choose which one to edit
+
+required context:
+ build - a Build object
+-->
+<div class="modal hide fade in" aria-hidden="false" id="edit-custom-image-modal">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">Ă—</button>
+ <h3>Which image do you want to edit?</h3>
+ </div>
+
+ <div class="modal-body">
+ <div class="row-fluid">
+ {% for recipe in build.get_custom_image_recipes %}
+ <label class="radio">
+ {{recipe.name}}
+ <input type="radio" class="form-control" name="select-custom-image"
+ data-url="{% url 'customrecipe' build.project.id recipe.id %}">
+ </label>
+ {% endfor %}
+ </div>
+ <span class="help-block error" id="invalid-custom-image-help" style="display:none">
+ Please select a custom image to edit.
+ </span>
+ </div>
+
+ <div class="modal-footer">
+ <button class="btn btn-primary btn-large" data-url="#"
+ data-action="edit-custom-image" disabled>
+ Edit custom image
+ </button>
+ </div>
+</div>
+
+<script>
+$(document).ready(function () {
+ var editCustomImageButton = $('[data-action="edit-custom-image"]');
+ var error = $('#invalid-custom-image-help');
+ var radios = $('[name="select-custom-image"]');
+
+ // return custom image radio buttons which are selected
+ var getSelectedRadios = function () {
+ return $('[name="select-custom-image"]:checked');
+ };
+
+ radios.change(function () {
+ if (getSelectedRadios().length === 1) {
+ editCustomImageButton.removeAttr('disabled');
+ error.hide();
+ }
+ else {
+ editCustomImageButton.attr('disabled', 'disabled');
+ error.show();
+ }
+ });
+
+ editCustomImageButton.click(function () {
+ var selectedRadios = getSelectedRadios();
+
+ if (selectedRadios.length === 1) {
+ document.location.href = selectedRadios.first().attr('data-url');
+ }
+ else {
+ error.show();
+ }
+ });
+});
+</script>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/importlayer.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/importlayer.html
index 033f0aede..1848f410e 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/importlayer.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/importlayer.html
@@ -89,7 +89,7 @@
<input type="text" id="layer-subdir">
<div class="control-group" id="layer-revision-ctrl">
- <label class="control-label project-form" for="layer-git-ref">Revision
+ <label class="control-label project-form" for="layer-git-ref">Git revision
<span class="icon-question-sign get-help" title="You can provide a Git branch, a tag or a commit SHA as the revision"></span>
</label>
<div class="controls">
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/js-unit-tests.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/js-unit-tests.html
index 8d65f33cb..94ad4f8e9 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/js-unit-tests.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/js-unit-tests.html
@@ -4,9 +4,9 @@
{% load static %}
{% block pagecontent %}
-<link rel="stylesheet" href="//code.jquery.com/qunit/qunit-1.18.0.css" />
+<link rel="stylesheet" href="{% static 'css/qunit-1.18.0.css' %}" />
-<script src="//code.jquery.com/qunit/qunit-1.18.0.js"></script>
+<script src="{% static 'js/qunit-1.18.0.js' %}"></script>
<script src="{% static 'js/layerDepsModal.js' %}"></script>
<script src="{% static 'js/projectpage.js' %}"></script>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/landing.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/landing.html
index cafaa1afa..a1b5cdce7 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/landing.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/landing.html
@@ -6,9 +6,6 @@
{% block title %} Welcome to Toaster {% endblock %}
{% block pagecontent %}
-
- {% if BUILD_MODE %}
- <!-- build mode -->
<div class="container-fluid">
<div class="row-fluid">
<div class="hero-unit span12 well-transparent">
@@ -62,11 +59,4 @@
</div>
</div>
</div>
- {% else %}
- <!-- analysis mode -->
- <div class="alert alert-info lead top-air">
- Toaster has not recorded any builds yet. Run a build from the command line to see it here.
- </div>
- {% endif %}
-
{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/layer_btn.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/layer_btn.html
index 314eec7cf..10de37d4b 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/layer_btn.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/layer_btn.html
@@ -4,7 +4,7 @@
{% endif %}
>
<i class="icon-trash"></i>
- Delete layer
+ Remove layer
</button>
<button class="btn btn-block layer-add-{{data.pk}} layerbtn" data-layer='{ "id": {{data.pk}}, "name": "{{data.layer.name}}", "layerdetailurl": "{%url 'layerdetails' extra.pid data.pk%}"}' data-directive="add"
{% if data.pk in extra.current_layers %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/layerdetails.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/layerdetails.html
index 7fe365da3..82be3703b 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/layerdetails.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/layerdetails.html
@@ -8,9 +8,8 @@
<div class="section">
<ul class="breadcrumb">
- <li class="muted">{{project.name}}:</li>
<li>
- <a href="{% url 'project' project.id %}">Configuration</a>
+ <a href="{% url 'project' project.id %}">{{project.name}}</a>
<span class="divider">&rarr;</span>
</li>
<li><a href="{% url 'projectlayers' project.id %}">Compatible layers</a>
@@ -46,7 +45,6 @@
$(document).ready(function (){
var ctx = {
- projectBuildsUrl : "{% url 'projectbuilds' project.id %}",
xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}",
layerVersion : {
name : "{{layerversion.layer.name}}",
@@ -108,7 +106,7 @@
{% else %}
<button id="add-remove-layer-btn" data-directive="remove" class="btn btn-block btn-large btn-danger">
<span class="icon-trash"></span>
- Delete the {{layerversion.layer.name}} layer from your project
+ Remove the {{layerversion.layer.name}} layer from your project
</button>
{% endif %}
</span>
@@ -156,7 +154,7 @@
</dd>
<dt>
<i class="icon-question-sign get-help" title="The Git branch, tag or commit"></i>
- Revision
+ Git revision
</dt>
<dd>
<span class="current-value">{{layerversion.get_vcs_reference}}</span>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/machine_btn.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/machine_btn.html
index d2cb55bab..7b08f6a9a 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/machine_btn.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/machine_btn.html
@@ -1,6 +1,14 @@
-<a href="{% url 'project' extra.pid %}?setMachine={{data.name}}" class="btn btn-block layer-exists-{{data.layer_version.id}}" style="margin-top: 5px; display:none">
+<a href="{% url 'project' extra.pid %}?setMachine={{data.name}}" class="btn btn-block layer-exists-{{data.layer_version.id}}"
+ {% if data.layer_version.pk not in extra.current_layers %}
+ style="display:none;"
+ {% endif %}
+>
Select machine</a>
-<button class="btn btn-block layerbtn layer-add-{{data.layer_version.id}}" data-layer='{ "id": {{data.layer_version.id}}, "name": "{{data.layer_version.layer.name}}", "layerdetailurl": "{%url 'layerdetails' extra.pid data.layer_version.id %}"}' data-directive="add">
+<button class="btn btn-block layerbtn layer-add-{{data.layer_version.id}}" data-layer='{ "id": {{data.layer_version.id}}, "name": "{{data.layer_version.layer.name}}", "layerdetailurl": "{%url 'layerdetails' extra.pid data.layer_version.id %}"}' data-directive="add"
+ {% if data.layer_version.pk in extra.current_layers %}
+ style="display:none;"
+ {% endif %}
+>
<i class="icon-plus"></i>
Add layer
<i title="" class="icon-question-sign get-help" data-original-title="To enable this machine, you must first add the {{data.layer_version.layer.name}} layer to your project"></i>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/mrb_section.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/mrb_section.html
index bd8f99178..b5e798d7c 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/mrb_section.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/mrb_section.html
@@ -2,11 +2,26 @@
{% load projecttags %}
{% load project_url_tag %}
{% load humanize %}
+<script src="{% static 'js/mrbsection.js' %}"></script>
+<script>
+ $(document).ready(function () {
+ var ctx = {
+ mrbType : "{{mrb_type}}",
+ }
+
+ try {
+ mrbSectionInit(ctx);
+ } catch (e) {
+ document.write("Sorry, An error has occurred loading this page");
+ console.warn(e);
+ }
+ });
+</script>
{%if mru and mru.count > 0%}
{%if mrb_type == 'project' %}
- <h2>
+ <h2 class="page-header">
Latest project builds
{% if project.is_default %}
@@ -14,7 +29,7 @@
{% endif %}
</h2>
{% else %}
- <div class="page-header">
+ <div class="page-header top-air">
<h1>
Latest builds
</h1>
@@ -38,8 +53,9 @@
{% if build.target_set.all.count > 0 %}
<span data-toggle="tooltip"
{% if build.target_set.all.count > 1 %}
- title="Targets:
- {% for target in build.target_set.all %}
+ {{build.get_sorted_target_list.0.target}}
+ title="Recipes:
+ {% for target in build.get_sorted_target_list %}
{% if target.task %}
{{target.target}}:{{target.task}}
{% else %}
@@ -49,12 +65,12 @@
{% endif %}
>
{% if build.target_set.all.0.task %}
- {{build.target_set.all.0.target}}:{{build.target_set.all.0.task}}
+ {{build.get_sorted_target_list.0.target}}:{{build.target_set.all.0.task}}
{% else %}
- {{build.target_set.all.0.target}}
+ {{build.get_sorted_target_list.0.target}}
{% endif %}
{% if build.target_set.all.count > 1 %}
- (+ {{build.target_set.all.count|add:"-1"}})
+ (+{{build.target_set.all.count|add:"-1"}})
{% endif %}
</span>
{% endif %}
@@ -98,7 +114,7 @@
" title="Builds in this project cannot be started from Toaster: they are started from the command line">
</i>
{% else %}
- <button class="btn
+ <button class="run-again-btn btn
{% if build.outcome == build.SUCCEEDED %}
btn-success
{% elif build.outcome == build.FAILED %}
@@ -107,54 +123,56 @@
btn-info
{%endif%}
pull-right"
- onclick='scheduleBuild({% url 'projectbuilds' build.project.id as bpi %}{{bpi|json}},
- {{build.project.name|json}},
- {% url 'project' build.project.id as purl %}{{purl|json}},
- {{build.target_set.all|get_tasks|json}})'>
+ data-request-url="{% url 'xhr_buildrequest' build.project.pk %}"
+ data-target='{{build.target_set.all|get_tasks|json}}'>
+
- Run again
+ Rebuild
</button>
{% endif %}
</div>
{%endif%}
{%if build.outcome == build.IN_PROGRESS %}
- <div class="span4 offset1">
- <div class="progress" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete">
- <div style="width: {{build.completeper}}%;" class="bar"></div>
- </div>
- </div>
- <div class="lead pull-right">{{build.completeper}}% of tasks complete</div>
- {%endif%}
- </div>
+ <div class="span4" style="display:none" id="cancelling-msg-{{build.buildrequest.pk}}">
+ <p class="lead">Cancelling the build ...</p>
</div>
+ <div class="span4 offset1 progress-info">
+ <div class="progress" id="build-pc-done-title-{{build.pk}}" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete">
+ <div id="build-pc-done-bar-{{build.pk}}" style="width: {{build.completeper}}%;" class="bar"></div>
+ </div>
+ </div>
+ <div class="lead span3 progress-info"><span id="build-pc-done-{{build.pk}}">{{build.completeper}}</span>% of tasks complete</div>
+ {# No build cancel for command line builds project #}
+ {% if build.project.is_default %}
+ <i class="icon-question-sign get-help get-help-blue pull-right" title="" data-original-title="Builds in this project cannot be cancelled from Toaster: they can only be cancalled from the command line"></i>
+ {% else %}
+ <div class="lead pull-right progress-info">
+ <button class="cancel-build-btn btn btn-info pull-right"
+ data-buildrequest-id={{build.buildrequest.pk}}
+ data-request-url="{% url 'xhr_buildrequest' build.project.pk %}" >
+ Cancel
+ </button>
+ </div>
+ {% endif %}
- {% endfor %}
- </div>
-
-<script>
-
-function scheduleBuild(url, projectName, projectUrl, buildlist) {
- console.log("scheduleBuild");
- libtoaster.startABuild(url, null, buildlist.join(" "), function(){
- console.log("reloading page");
- window.location.reload();
- }, null);
-}
-
-$(document).ready(function(){
+ {%endif%} {# end if in progress #}
- $(".cancel-build-btn").click(function (){
- var url = $(this).data('request-url');
- var buildIds = $(this).data('build-id');
- var btn = $(this);
+ {% if build.outcome == build.CANCELLED %}
+ <div class="span4">
+ <p class="lead">Build cancelled</p>
+ </div>
+ <button class="btn btn-info pull-right run-again-btn"
+ data-request-url="{% url 'xhr_buildrequest' build.project.pk %}"
+ data-target='{{build.target_set.all|get_tasks|json}}'>
+ Rebuild
- libtoaster.cancelABuild(url, buildIds, function(){
- btn.parents(".alert").fadeOut();
- }, null);
- });
-});
+ </button>
+ {% endif %}
+ </div>
+</div>
-</script>
+ {% endfor %}
+ </div>
{%endif%}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage.html
index 4487b3ea0..46aed901f 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage.html
@@ -4,51 +4,11 @@
{% load static %}
{% block pagecontent %}
-<script src="{% static 'js/newcustomimage.js' %}"></script>
-<script>
- $(document).ready(function (){
- var ctx = {
- xhrCustomRecipeUrl : "{% url 'xhr_customrecipe' %}",
- };
-
- try {
- newCustomImagePageInit(ctx);
- } catch (e) {
- document.write("Sorry, An error has occurred loading this page");
- console.warn(e);
- }
- });
-</script>
-
-</script>
-<div class="modal hide fade in" id="new-custom-image-modal" aria-hidden="false">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">Ă—</button>
- <h3>Name your custom image</h3>
- </div>
- <div class="modal-body">
- <div class="row-fluid">
- <span class="help-block span8">Image names must be unique. They should not contain spaces or capital letters, and the only allowed special character is dash (-).<p></p>
- </span></div>
- <div class="control-group controls">
- <input type="text" class="huge span5" placeholder="Type the name, something like 'core-image-myimage'">
- <span class="help-block" style="display:none">Image names cannot contain spaces or capital letters. The only allowed special character is dash (-)</span>
- <span class="help-block" style="display: none">An image with this name already exists. Image names must be unique: try a different one.</span>
- </div>
- </div>
- <div class="modal-footer">
- <a href="#" id="create-new-custom-image-btn" class="btn btn-primary btn-large" data-original-title="" title="">Create custom image</a>
- </div>
-</div>
-
+{% include "newcustomimage_modal.html" %}
{% include "projecttopbar.html" %}
-
{% url table_name project.id as xhr_table_url %}
+<h2>{{title}} (<span class="table-count-{{table_name}}">0</span>)</h2>
{% include "toastertable.html" %}
-
-
{% endblock %}
-
-
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage_modal.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage_modal.html
new file mode 100644
index 000000000..caeb30235
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/newcustomimage_modal.html
@@ -0,0 +1,48 @@
+{% load static %}
+
+<script src="{% static 'js/newcustomimage_modal.js' %}"></script>
+<script>
+ $(document).ready(function (){
+ try {
+ newCustomImageModalInit();
+ } catch (e) {
+ document.write("Sorry, An error has occurred loading this page");
+ console.warn(e);
+ }
+ });
+</script>
+
+<div class="modal hide fade in" id="new-custom-image-modal" aria-hidden="false">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-hidden="true">Ă—</button>
+ <h3>New custom image</h3>
+ </div>
+
+ <div class="modal-body">
+ <!--
+ this container is visible if there are multiple image recipes which could
+ be used as a basis for the new custom image; radio buttons are added to it
+ via newCustomImageModalSetRecipes() as required
+ -->
+ <div data-role="image-selector" style="display:none;">
+ <h4>Which image do you want to customise?</h4>
+ <div data-role="image-selector-radios"></div>
+ <span class="help-block error" id="invalid-recipe-help" style="display:none"></span>
+ <div class="air"></div>
+ </div>
+
+ <h4>Name your custom image</h4>
+
+ <div class="row-fluid">
+ <span class="help-block span8">Image names must be unique. They should not contain spaces or capital letters, and the only allowed special character is dash (-).<p></p>
+ </span></div>
+ <div class="control-group controls">
+ <input type="text" class="huge" placeholder="Type the custom image name" required>
+ <span class="help-block error" id="invalid-name-help" style="display:none"></span>
+ </div>
+ </div>
+
+ <div class="modal-footer">
+ <button id="create-new-custom-image-btn" class="btn btn-primary btn-large" data-original-title="" title="" disabled>Create custom image</button>
+ </div>
+</div>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/pkg_add_rm_btn.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/pkg_add_rm_btn.html
index b766aeac9..0aefc5625 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/pkg_add_rm_btn.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/pkg_add_rm_btn.html
@@ -1,16 +1,34 @@
-<button class="btn btn-block btn-danger add-rm-package-btn" id="package-rm-btn-{{data.pk}}" data-directive="remove" data-package="{{data.pk}}" data-package-url="{% url 'xhr_customrecipe_packages' extra.recipe_id data.pk %}" style="
- {% if data.pk not in extra.current_packages %}
- display:none
- {% endif %}
- ">
- <i class="icon-trash no-tooltip"></i>
- Remove package
-</a>
-<button class="btn btn-block add-rm-package-btn" data-directive="add" id="package-add-btn-{{data.pk}}" data-package="{{data.pk}}" data-package-url="{% url 'xhr_customrecipe_packages' extra.recipe_id data.pk %}" style="
- {% if data.pk in extra.current_packages %}
- display:none
- {% endif %}
- ">
-<i class="icon-plus"></i>
- Add package
-</button>
+{# TODO move to snippets dir #}
+{% if data.is_locale_package %}
+<p class="text-center">
+ <span class="muted">Locale package</span>
+ <i class="icon-question-sign get-help hover-help" title=""
+ data-original-title="This package is included in your image
+ based on the locale specified in the IMAGE_LINGUAS variable"
+ style="visibility: hidden;">
+ </i>
+</p>
+
+{% else %}
+
+<div id="package-btn-cell-{{data.pk}}">
+ <div style="display: none; font-size: 11px; line-height: 1.3;" class="tooltip-inner inline-notification"></div>
+ <button class="btn btn-block btn-danger add-rm-package-btn" data-directive="remove" data-id="{{data.pk}}" data-package-url="{% url 'xhr_customrecipe_packages' extra.recipe_id data.pk %}" data-name="{{data.name}}" style="
+ {% if data.pk not in extra.current_packages %}
+ display:none
+ {% endif %}
+ ">
+ <i class="icon-trash no-tooltip"></i>
+ Remove package
+ </button>
+ <button class="btn btn-block add-rm-package-btn" data-directive="add" data-id="{{data.pk}}" data-package-url="{% url 'xhr_customrecipe_packages' extra.recipe_id data.pk %}" data-name="{{data.name}}" style="
+ {% if data.pk in extra.current_packages %}
+ display:none
+ {% endif %}
+ ">
+ <i class="icon-plus"></i>
+ Add package
+ </button>
+</div>
+
+{% endif %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/project.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/project.html
index 4e83981f8..125676881 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/project.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/project.html
@@ -24,7 +24,9 @@
});
</script>
-<div id="change-release-modal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="change-release-modal" aria-hidden="false">
+<!-- Comment out the ability to change the project release, until we decide what to do this functionality -->
+
+<!--div id="change-release-modal" class="modal hide fade in" tabindex="-1" role="dialog" aria-labelledby="change-release-modal" aria-hidden="false">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
<h3>Changing Yocto Project release to <span class="proposed-release-change-name"></span></h3>
@@ -39,7 +41,7 @@
<button id="change-release-and-rm-layers" data-dismiss="modal" type="submit" class="btn btn-primary">Change release and delete layers</button>
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
</div>
-</div>
+</div-->
<div class="row-fluid" id="project-page" style="display:none">
@@ -68,7 +70,7 @@
<div class="alert alert-info" style="display:none" id="no-most-built">
<span class="lead">You haven't built any recipes yet</span>
- <p style="margin-top: 10px;"><a href="{% url 'projectsoftwarerecipes' project.id %}">Choose a recipe to build</a></p>
+ <p style="margin-top: 10px;"><a href="{% url 'projectimagerecipes' project.id %}">Choose a recipe to build</a></p>
</div>
<ul class="unstyled configuration-list" id="freq-build-list">
@@ -79,12 +81,19 @@
<div class="well well-transparent">
<h3>Project release</h3>
- <p class="lead"><span id="project-release-title"></span> <i title="" data-original-title="" id="release-change-toggle" class="icon-pencil"></i></p>
+ <p class="lead"><span id="project-release-title"></span>
+
+ <!-- Comment out the ability to change the project release, until we decide what to do with this functionality -->
- <form class="form-inline" id="change-release-form" style="display:none;">
+ <!--i title="" data-original-title="" id="release-change-toggle" class="icon-pencil"></i-->
+ </p>
+
+ <!-- Comment out the ability to change the project release, until we decide what to do with this functionality -->
+
+ <!--form class="form-inline" id="change-release-form" style="display:none;">
<select></select>
<button class="btn" style="margin-left:5px;" id="change-release-btn">Change</button> <a href="#" id="cancel-release-change" class="btn btn-link">Cancel</a>
- </form>
+ </form-->
</div>
</div>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html
new file mode 100644
index 000000000..6d7e10bac
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds-toastertable.html
@@ -0,0 +1,56 @@
+{% extends 'base.html' %}
+
+{% load static %}
+
+{% block extraheadcontent %}
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.structure.min.css' %}" type='text/css'>
+ <link rel="stylesheet" href="{% static 'css/jquery-ui.theme.min.css' %}" type='text/css'>
+ <script src="{% static 'js/jquery-ui.min.js' %}">
+ </script>
+{% endblock %}
+
+{% block title %} {{title}} - {{project.name}} - Toaster {% endblock %}
+
+{% block pagecontent %}
+
+ {% include "projecttopbar.html" %}
+
+ <div class="row-fluid">
+ {% with mru=mru mrb_type=mrb_type %}
+ {% include 'mrb_section.html' %}
+ {% endwith %}
+
+ <h2 class="page-header top-air" data-role="page-title"></h2>
+
+ {% url 'projectbuilds' project.id as xhr_table_url %}
+ {% include 'toastertable.html' %}
+ </div>
+
+ <script>
+ $(document).ready(function () {
+ // title
+ var tableElt = $("#{{table_name}}");
+ var titleElt = $("[data-role='page-title']");
+
+ tableElt.on("table-done", function (e, total, tableParams) {
+ var title = "All project builds";
+
+ if (tableParams.search || tableParams.filter) {
+ if (total === 0) {
+ title = "No project builds found";
+ }
+ else if (total > 0) {
+ title = total + " project build" + (total > 1 ? 's' : '') + " found";
+ }
+ }
+
+ titleElt.text(title);
+ });
+
+ // highlight builds tab
+ $("#topbar-builds-tab").addClass("active")
+ });
+ </script>
+
+{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds.html
index bb38284aa..3402fc4fe 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectbuilds.html
@@ -63,11 +63,12 @@
{% for build in objects %} {# if we have a build, just display it #}
<tr class="data">
<td class="outcome"><a href="{% url "builddashboard" build.id %}">{%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%}</a>
- {% if build.project %}
- &nbsp; <a href="{% url 'build_artifact' build.id "cookerlog" build.id %}">
- <i class="icon-download-alt" title="" data-original-title="Download build log"></i>
- </a>
- {% endif %}
+ {% if build.cooker_log_path %}
+ &nbsp;
+ <a href="{% url 'build_artifact' build.id "cookerlog" build.id %}">
+ <i class="icon-download-alt" title="Download build log"></i>
+ </a>
+ {% endif %}
</td>
<td class="target">
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectconf.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectconf.html
index 30fd03e32..27a898b65 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectconf.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projectconf.html
@@ -31,6 +31,28 @@
</dd>
{% endif %}
+ {% if dl_dir_defined %}
+ <dt>
+ <span class="js-config-var-name js-config-var-managed-name">DL_DIR</span>
+ <i class="icon-question-sign get-help" title="Absolute path to the directory used to store downloads required for your builds. By default, Toaster projects share the same downloads directory.<br /><a href='http://www.yoctoproject.org/docs/2.1/ref-manual/ref-manual.html#var-DL_DIR' target='_blank'>Read more in the manual</a>"></i>
+ </dt>
+ <dd class="lead">
+ <span id="dl_dir"{% if dl_dir %}{%else%} class="muted"{%endif%}>{% if dl_dir %}{{dl_dir}}{%else%}Not set{%endif%}</span>
+ <i class="icon-pencil" id="change-dl_dir-icon"></i>
+ <form id="change-dl_dir-form" style="display:none;">
+ <div class="row-fluid">
+ <span class="help-block span4">To set DL_DIR type the absolute path of the download folder.</span>
+ </div>
+ <div class="input-append" id="validate-dl_dir">
+ <input type="text" class="input-xlarge" id="new-dl_dir" placeholder="Type absolute path of the DL_DIR folder">
+ <button id="apply-change-dl_dir" class="btn" type="button">Save</button>
+ <button id="cancel-change-dl_dir" type="button" class="btn btn-link">Cancel</button>
+ </br><span class="help-block error" id="hintError-dl_dir">A valid directory cannot include spaces or any of these characters: . \ ? % * : | " " < ></span>
+ </div>
+ </form>
+ </dd>
+ {% endif %}
+
{% if fstypes_defined %}
<dt>
<span class="js-config-var-name js-config-var-managed-name">IMAGE_FSTYPES</span>
@@ -108,31 +130,28 @@
</dd>
{% endif %}
- {% if sdk_machine_defined %}
+ {% if sstate_dir_defined %}
<dt>
- <span class="js-config-var-name js-config-var-managed-name">SDKMACHINE</span>
- <i class="icon-question-sign get-help" title="Specifies the architecture (i.e. i686 or x86_64) for which to build SDK and ADT items <br /><a href='http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-SDKMACHINE' target='_blank'>Read more in the manual</a>"></i>
+ <span class="js-config-var-name js-config-var-managed-name">SSTATE_DIR</span>
+ <i class="icon-question-sign get-help" title="Absolute path to the directory used to store shared state cache files. These files are reused across the builds, which makes the builds faster. By default, Toaster projects share the same cache directory.<br /><a href='http://www.yoctoproject.org/docs/2.1/ref-manual/ref-manual.html#var-SSTATE_DIR' target='_blank'>Read more in the manual</a>"></i>
</dt>
<dd class="lead">
- <span id="sdkmachine">{{sdk_machine}}</span>
- <i id="change-sdkmachine-icon" class="icon-pencil"></i>
- <form id="change-sdkmachine-form" style="display:none;">
- <label class="radio">
- <input type="radio" name="sdkmachine" value="i686">
- i686
- </label>
- <label class="radio">
- <input type="radio" name="sdkmachine" value="x86_64">
- x86_64
- </label>
- <div style="padding-top:10px;">
- <button id="apply-change-sdkmachine" type="button" class="btn">Save</button>
- <button id="cancel-change-sdkmachine" type="button" class="btn btn-link">Cancel</button>
+ <span id="sstate_dir"{% if sstate_dir %}{%else%} class="muted"{%endif%}>{% if sstate_dir %}{{sstate_dir}}{%else%}Not set{%endif%}</span>
+ <i class="icon-pencil" id="change-sstate_dir-icon"></i>
+ <form id="change-sstate_dir-form" style="display:none;">
+ <div class="row-fluid">
+ <span class="help-block span4">To set SSTATE_DIR type the absolute path of the download folder.</span>
+ </div>
+ <div class="input-append" id="validate-sstate_dir">
+ <input type="text" class="input-xlarge" id="new-sstate_dir" placeholder="Type absolute path of the SSTATE_DIR folder">
+ <span class="error">A valid directory name required</span>
+ <button id="apply-change-sstate_dir" class="btn" type="button">Save</button>
+ <button id="cancel-change-sstate_dir" type="button" class="btn btn-link">Cancel</button>
+ </br><p class="help-block error" id="hintError-sstate_dir">A valid directory cannot include spaces or any of these characters: . \ ? % * : | " " < ></span>
</div>
</form>
</dd>
{% endif %}
-
</dl>
<!-- <ul class="unstyled configuration-list" id="configvar-list"> -->
@@ -182,9 +201,7 @@
<code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-BB_NUMBER_THREADS" target="_blank">BB_NUMBER_THREADS</a></code>
<code>CVS_PROXY_HOST</code>
<code>CVS_PROXY_PORT</code>
- <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-DL_DIR" target="_blank">DL_DIR</a></code>
<code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-PARALLEL_MAKE" target="_blank">PARALLEL_MAKE</a></code>
- <code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-SSTATE_DIR" target="_blank">SSTATE_DIR</a></code>
<code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-SSTATE_MIRRORS" target="_blank">SSTATE_MIRRORS</a></code>
<code><a href="http://www.yoctoproject.org/docs/1.6.1/ref-manual/ref-manual.html#var-TMPDIR" target="_blank">TMPDIR</a></code></p>
<p>Plus the following standard shell environment variables:</p>
@@ -527,6 +544,61 @@
});
{% endif %}
+ {% if dl_dir_defined %}
+
+ // change DL_DIR variable
+ $('#change-dl_dir-icon').click(function() {
+ $('#hintError-dl_dir').hide();
+ // preset the edit value
+ var current_val = $("span#dl_dir").text().trim();
+ if (current_val == "Not set") {
+ current_val="";
+ $("#apply-change-dl_dir").attr("disabled","disabled");
+ }
+ $("input#new-dl_dir").val(current_val);
+
+ $('#change-dl_dir-icon, #dl_dir').hide();
+ $("#change-dl_dir-form").slideDown();
+ });
+
+ $('#cancel-change-dl_dir').click(function(){
+ $("#change-dl_dir-form").slideUp(function() {
+ $('#dl_dir, #change-dl_dir-icon').show();
+ });
+ });
+
+ $("#new-dl_dir").on('input', function(){
+ if ($(this).val().trim().length == 0) {
+ $("#apply-change-dl_dir").attr("disabled","disabled");
+ }
+ else {
+ var input = $(this);
+ var re = /^\/([^ <>\\|":\.%\?\*]+)$/;
+ var invalidDir = re.test(input.val());
+ console.log(invalidDir);
+ if ( invalidDir ) {
+ $('#validate-dl_dir').removeClass('control-group error');
+ $("#apply-change-dl_dir").removeAttr("disabled");
+ $('#hintError-dl_dir').hide();
+ } else {
+ $('#validate-dl_dir').addClass('control-group error');
+ $("#apply-change-dl_dir").attr("disabled","disabled");
+ $('#hintError-dl_dir').show();
+ }
+ }
+ });
+
+ $('#apply-change-dl_dir').click(function(){
+ var value = $('#new-dl_dir').val().trim();
+ postEditAjaxRequest({"configvarChange" : 'DL_DIR:'+value});
+ $('#dl_dir').text(value);
+ $('#dl_dir').removeClass('muted');
+ $("#change-dl_dir-form").slideUp(function () {
+ $('#dl_dir, #change-dl_dir-icon').show();
+ });
+ });
+
+ {% endif %}
{% if fstypes_defined %}
// change IMAGE_FSTYPES variable
@@ -774,47 +846,61 @@
});
{% endif %}
+ {% if sstate_dir_defined %}
- {% if sdk_machine_defined %}
- // change SDKMACHINE variable
- $('#change-sdkmachine-icon').click(function() {
- var current_value = document.getElementById("sdkmachine").innerHTML;
- var radios = document.getElementsByName('sdkmachine');
- for (var i = 0, length = radios.length; i < length; i++) {
- radios[i].checked = false;
- if (radios[i].value == current_value) {
- radios[i].checked = true;
- }
+ // change SSTATE_DIR variable
+ $('#change-sstate_dir-icon').click(function() {
+ $('#hintError-sstate_dir').hide();
+ // preset the edit value
+ var current_val = $("span#sstate_dir").text().trim();
+ if (current_val == "Not set") {
+ current_val="";
+ $("#apply-change-sstate_dir").attr("disabled","disabled");
}
- $('#change-sdkmachine-icon, #sdkmachine').hide();
- $("#change-sdkmachine-form").slideDown();
+ $("input#new-sstate_dir").val(current_val);
+
+ $('#change-sstate_dir-icon, #sstate_dir').hide();
+ $("#change-sstate_dir-form").slideDown();
});
- $('#cancel-change-sdkmachine').click(function(){
- $("#change-sdkmachine-form").slideUp(function() {
- $('#sdkmachine, #change-sdkmachine-icon').show();
+ $('#cancel-change-sstate_dir').click(function(){
+ $("#change-sstate_dir-form").slideUp(function() {
+ $('#sstate_dir, #change-sstate_dir-icon').show();
});
});
- $('#apply-change-sdkmachine').click(function(){
- var value="";
- var radios = document.getElementsByName('sdkmachine');
- for (var i = 0, length = radios.length; i < length; i++) {
- if (radios[i].checked) {
- // do whatever you want with the checked radio
- value=radios[i].value;
- break;
+ $("#new-sstate_dir").on('input', function(){
+ if ($(this).val().trim().length == 0) {
+ $("#apply-change-sstate_dir").attr("disabled","disabled");
+ }
+ else {
+ var input = $(this);
+ var re = /^\/([^ <>\\|":\.%\?\*]+)$/;
+ var invalidDir = re.test(input.val());
+ console.log(invalidDir);
+ if ( invalidDir ) {
+ $('#validate-sstate_dir').removeClass('control-group error');
+ $("#apply-change-sstate_dir").removeAttr("disabled");
+ $('#hintError-sstate_dir').hide();
+ } else {
+ $('#validate-sstate_dir').addClass('control-group error');
+ $("#apply-change-sstate_dir").attr("disabled","disabled");
+ $('#hintError-sstate_dir').show();
}
}
- postEditAjaxRequest({"configvarChange" : 'SDKMACHINE:'+value});
- $('#sdkmachine').text(value);
- $("#change-sdkmachine-form").slideUp(function() {
- $('#sdkmachine, #change-sdkmachine-icon').show();
- });
+ });
+ $('#apply-change-sstate_dir').click(function(){
+ var value = $('#new-sstate_dir').val().trim();
+ postEditAjaxRequest({"configvarChange" : 'SSTATE_DIR:'+value});
+ $('#sstate_dir').text(value);
+ $('#sstate_dir').removeClass('muted');
+ $("#change-sstate_dir-form").slideUp(function () {
+ $('#sstate_dir, #change-sstate_dir-icon').show();
+ });
});
- {% endif %}
+ {% endif %}
// add new variable
$("button#add-configvar-button").click( function (evt) {
@@ -830,7 +916,7 @@
$(".save").attr("disabled","disabled");
// Reload page if admin-removed core managed value is manually added back in
- if (0 <= " DISTRO IMAGE_FSTYPES IMAGE_INSTALL_append PACKAGE_CLASSES SDKMACHINE ".indexOf( " "+variable+" " )) {
+ if (0 <= " DISTRO DL_DIR IMAGE_FSTYPES IMAGE_INSTALL_append PACKAGE_CLASSES SSTATE_DIR ".indexOf( " "+variable+" " )) {
// delayed reload to avoid race condition with postEditAjaxRequest
do_reload=true;
}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html
new file mode 100644
index 000000000..5814f32d0
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projects-toastertable.html
@@ -0,0 +1,36 @@
+{% extends 'base.html' %}
+
+{% block title %} All projects - Toaster {% endblock %}
+
+{% block pagecontent %}
+
+ <div class="page-header top-air">
+ <h1 data-role="page-title"></h1>
+ </div>
+
+ {% url 'projects' as xhr_table_url %}
+ {% include 'toastertable.html' %}
+
+ <script>
+ $(document).ready(function () {
+ var tableElt = $("#{{table_name}}");
+ var titleElt = $("[data-role='page-title']");
+
+ tableElt.on("table-done", function (e, total, tableParams) {
+ var title = "All projects";
+
+ if (tableParams.search || tableParams.filter) {
+ if (total === 0) {
+ title = "No projects found";
+ }
+ else if (total > 0) {
+ title = total + " project" + (total > 1 ? 's' : '') + " found";
+ }
+ }
+
+ titleElt.text(title);
+ });
+ });
+ </script>
+
+{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projects.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projects.html
deleted file mode 100644
index 678a7963b..000000000
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projects.html
+++ /dev/null
@@ -1,92 +0,0 @@
-{% extends "base.html" %}
-
-{% load static %}
-{% load projecttags %}
-{% load project_url_tag %}
-{% load humanize %}
-
-{% block title %} All projects - Toaster {% endblock %}
-
-{% block pagecontent %}
-
-
- <div class="page-header top-air">
- <h1>
- {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
- {{objects.paginator.count}} project{{objects.paginator.count|pluralize}} found
- {%elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
- No projects found
- {%else%}
- All projects
- {%endif%}
- </h1>
- </div>
-
- {% if objects.paginator.count == 0 %}
- <div class="row-fluid">
- <div class="alert">
- <form class="no-results input-append" id="searchform">
- <input id="search" name="search" class="input-xxlarge" type="text" value="
- {% if request.GET.search %}
- {{request.GET.search}}
- {% endif %}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="add-on btn" tabindex="-1"><i class="icon-remove"></i></a>{% endif %}
- <button class="btn" type="submit" value="Search">Search</button>
- <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all projects</button>
- </form>
- </div>
- </div>
-
- {% else %} {# We have builds to display #}
- {% include "basetable_top.html" %}
- {% for o in objects %}
- <tr class="data" data-project="{{ o.id }}">
- <td data-project-field="name">
- <a href="{% project_url o %}">{{o.name}}</a>
- </td>
- <td class="updated"><a href="{% project_url o %}">{{o.updated|date:"d/m/y H:i"}}</a></td>
- <td data-project-field="release">
- {% if o.release %}
- <a href="{% url 'project' o.id %}#project-details">{{o.release.name}}</a>
- {% elif o.is_default %}
- <span class="muted">Not applicable</span>
- <i class="icon-question-sign get-help hover-help" title="" data-original-title="This project does not have a release set. It simply collects information about the builds you start from the command line while Toaster is running" style="visibility: hidden;"></i>
- {% else %}
- No release available
- {% endif %}
- </td>
- <td data-project-field="machine">
- {% if o.is_default %}
- <span class="muted">Not applicable</span>
- <i class="icon-question-sign get-help hover-help" title="" data-original-title="This project does not have a machine set. It simply collects information about the builds you start from the command line while Toaster is running" style="visibility: hidden;"></i>
- {% else %}
- <a href="{% url 'project' o.id %}#machine-distro">{{o.get_current_machine_name}}</a>
- {% endif %}
- </td>
- {% if o.get_number_of_builds == 0 %}
- <td class="muted">{{o.get_number_of_builds}}</td>
- <td class="loutcome"></td>
- <td class="ltarget"></td>
- <td class="lerrors"></td>
- <td class="lwarnings"></td>
- <td class="limagefiles"></td>
- {% else %}
- <td><a href="{% url 'projectbuilds' o.id %}">{{o.get_number_of_builds}}</a></td>
- <td class="loutcome"><a href="{% url "builddashboard" o.get_last_build_id %}">{%if o.get_last_outcome == build_SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif o.get_last_outcome == build_FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%}</a></td>
- <td class="ltarget"><a href="{% url "builddashboard" o.get_last_build_id %}">{{o.get_last_target}} </a></td>
- <td class="lerrors">{% if o.get_last_errors %}<a class="errors.count error" href="{% url "builddashboard" o.get_last_build_id %}#errors">{{o.get_last_errors}} error{{o.get_last_errors|pluralize}}</a>{%endif%}</td>
- <td class="lwarnings">{% if o.get_last_warnings %}<a class="warnings.count warning" href="{% url "builddashboard" o.get_last_build_id %}#warnings">{{o.get_last_warnings}} warning{{o.get_last_warnings|pluralize}}</a>{%endif%}</td>
- <td class="limagefiles">
- {% if o.get_last_outcome == build_SUCCEEDED %}
- <a href="{%url "builddashboard" o.get_last_build_id %}#images">{{fstypes|get_dict_value:o.id}}</a>
- {% endif %}
- </td>
-
- {% endif %}
- </tr>
- {% endfor %}
- {% include "basetable_bottom.html" %}
- {% endif %} {# empty #}
-
-{% endblock %}
-
-
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projecttopbar.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projecttopbar.html
index ee86b5481..007de06ff 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/projecttopbar.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/projecttopbar.html
@@ -1,6 +1,24 @@
+{% load static %}
+<script src="{% static 'js/projecttopbar.js' %}"></script>
+<script>
+ $(document).ready(function () {
+ var ctx = {
+ numProjectLayers : {{project.get_project_layer_versions.count}},
+ machine : "{{project.get_current_machine_name|default_if_none:""}}",
+ }
+
+ try {
+ projectTopBarInit(ctx);
+ } catch (e) {
+ document.write("Sorry, An error has occurred loading this page");
+ console.warn(e);
+ }
+ });
+</script>
+
<div class="alert alert-success lead" id="project-created-notification" style="margin-top:15px; display:none">
<button type="button" class="close" data-dismiss="alert">Ă—</button>
- Your project <strong>{{project.name}}</strong> has been created. You can now <a href="{% url 'projectmachines' project.id %}">select your target machine</a> and <a href="{% url 'projectsoftwarerecipes' project.id %}">choose image recipes</a> to build.
+ Your project <strong>{{project.name}}</strong> has been created. You can now <a href="{% url 'projectmachines' project.id %}">select your target machine</a> and <a href="{% url 'projectimagerecipes' project.id %}">choose image recipes</a> to build.
</div>
<!-- project name -->
@@ -26,31 +44,29 @@
{% if not project.is_default %}
<div id="project-topbar">
<ul class="nav nav-pills">
- <li>
- <a href="{% url 'projectbuilds' project.id %}">
- Builds (<span class="total-builds">0</span>)
- </a>
- </li>
<li id="topbar-configuration-tab">
<a href="{% url 'project' project.id %}">
Configuration
</a>
</li>
<li>
+ <a href="{% url 'projectbuilds' project.id %}">
+ Builds ({{project.get_number_of_builds}})
+ </a>
+ </li>
+ <li>
<a href="{% url 'importlayer' project.id %}">
Import layer
</a>
</li>
- {% if CUSTOM_IMAGE %}
<li>
<a href="{% url 'newcustomimage' project.id %}">
New custom image
</a>
</li>
- {% endif %}
<li class="pull-right">
<form class="form-inline" style="margin-bottom:0px;">
- <i class="icon-question-sign get-help heading-help" data-placement="left" title="" data-original-title="Type the name of one or more recipes you want to build, separated by a space. You can also specify a task by appending a semicolon and a task name to the recipe name, like so: <code>busybox:clean</code>"></i>
+ <i class="icon-question-sign get-help heading-help" data-placement="left" title="" data-original-title="Type the name of one or more recipes you want to build, separated by a space. You can also specify a task by appending a colon and a task name to the recipe name, like so: <code>busybox:clean</code>"></i>
<div class="input-append">
<input id="build-input" type="text" class="input-xlarge input-lg build-target-input" placeholder="Type the recipe you want to build" autocomplete="off" disabled>
<button id="build-button" class="btn btn-primary btn-large build-button" data-project-id="{{project.id}}" disabled>Build</button>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipe.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipe.html
index c6ae2f380..1d6d64e3c 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipe.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipe.html
@@ -71,6 +71,16 @@
Layer commit
</dt>
<dd class="iscommit">{{layer_version.commit}}</dd>
+ {% if object.provides_set.all %}
+ <dt>
+ <i class="icon-question-sign get-help"
+ title="A list of aliases by which a particular recipe can be known. The additional aliases are
+ synonyms for the recipe and can be useful satisfying dependencies of other recipes during
+ the build"></i>
+ PROVIDES
+ </dt>
+ <dd><code>{% for provider in object.provides_set.all %}{{ provider.name }}&nbsp;{% endfor %}</code></dd>
+ {% endif %}
</dl>
<h2 class="details">Tasks</h2>
@@ -162,7 +172,14 @@
{% for rr in object.r_dependencies_recipe.all|dictsort:"depends_on.name" %}
<tr>
- <td><a href="{% url "recipe" build.pk rr.depends_on.pk %}">{{rr.depends_on.name}}</a></td>
+ <td><a href="{% url "recipe" build.pk rr.depends_on.pk %}">{{rr.depends_on.name}}</a>
+ {% if rr.via %}
+ <span class="muted">satisfied via {{rr.via.name}}</span>
+ <i class="icon-question-sign get-help hover-help"
+ title="This dependency is satisfied by the PROVIDES value
+ {{rr.via.name}} in the {{rr.depends_on.name}} recipe"></i>
+ {% endif %}
+ </td>
<td><a href="{% url "recipe" build.pk rr.depends_on.pk %}">{{rr.depends_on.version}}</a></td>
</tr>
{% endfor %}
@@ -194,7 +211,14 @@
{% for rr in object.r_dependencies_depends.all|dictsort:"recipe.name" %}
<tr>
- <td><a href="{% url "recipe" build.pk rr.recipe.pk %}">{{rr.recipe.name}}</a></td>
+ <td><a href="{% url "recipe" build.pk rr.recipe.pk %}">{{rr.recipe.name}}</a>
+ {% if rr.via %}
+ <span class="muted"> satisfied via {{rr.via.name}}</span>
+ <i class="icon-question-sign get-help hover-help"
+ title="This dependency is satisfied by the PROVIDES value
+ {{rr.via.name}} in the {{rr.depends_on.name}} recipe"></i>
+ {% endif %}
+ </td>
<td><a href="{% url "recipe" build.pk rr.recipe.pk %}">{{rr.recipe.version}}</a></td>
</tr>
{% endfor %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipedetails.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipedetails.html
new file mode 100644
index 000000000..23aa171ce
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/recipedetails.html
@@ -0,0 +1,177 @@
+{% extends "base.html" %}
+{% load projecttags %}
+{% load humanize %}
+{% load static %}
+{% block pagecontent %}
+
+<div class="section">
+ <ul class="breadcrumb">
+ <li>
+ <a href="{% url 'project' project.id %}">{{project.name}}</a>
+ <span class="divider">&rarr;</span>
+ </li>
+ <li>
+ {% if recipe.is_image %}
+ <a href="{% url 'projectimagerecipes' project.id %}">Image recipes</a>
+ {% else %}
+ <a href="{% url 'projectsoftwarerecipes' project.id %}">Software recipes</a>
+ {% endif %}
+ <span class="divider">&rarr;</span>
+ </li>
+ <li class="active">
+ {{recipe.name}} ({{recipe.layer_version.layer.name}})
+ </li>
+ </ul>
+</div>
+
+<script src="{% static 'js/recipedetails.js' %}"></script>
+<script>
+ $(document).ready(function (){
+ var ctx = {
+ recipe : {
+ id: {{recipe.pk}},
+ name: "{{recipe.name}}",
+ totalPackages: {{packages.count}},
+ layer_version : {
+ id: {{recipe.layer_version.pk}},
+ name: "{{recipe.layer_version.layer.name}}",
+ layerdetailurl: "{% url 'layerdetails' project.pk recipe.layer_version.pk %}"
+ }
+ }
+ };
+
+ try {
+ recipeDetailsPageInit(ctx);
+ } catch (e) {
+ document.write("Sorry, An error has occurred loading this page");
+ console.warn(e);
+ }
+ });
+</script>
+
+{% include 'newcustomimage_modal.html' %}
+
+<div class="row-fluid span11">
+ <div class="alert alert-success lead" id="image-created-notification" style="margin-top: 15px; display: none">
+ <button type="button" data-dismiss="alert" class="close">x</button>
+ Your custom image <strong>{{recipe.name}}</strong> has been created. You can now add or remove packages as needed.
+ </div>
+ <div class="page-header air">
+ <h1>
+ {{recipe.name}}
+ <small>({{recipe.layer_version.layer.name}})</small>
+ </h1>
+ </div>
+</div>
+
+<div class="row-fluid span11">
+ <div class="span8">
+ <div class="button-place btn-group" id="customise-build-btns"
+ style="width: 100%;
+ {% if not in_project %}
+ display:none;
+ {% endif %}">
+ <button class="btn btn-large span6 build-recipe-btn" style="width: 50%">
+ Build {{recipe.name}}
+ </button>
+ {% if recipe.is_image %}
+ <button class="btn btn-large span6 customise-btn" data-recipe="{{recipe.pk}}" style="width: 50%">
+ Customise {{recipe.name}}
+ </button>
+ {% endif %}
+ </div>
+ <div class="button-place">
+ <button class="btn btn-block btn-large" id="add-layer-btn"
+ style="width:100%;
+ {% if in_project %}
+ display:none;
+ {% endif %}">
+ <i class="icon-plus"></i>
+ Add the {{recipe.layer_version.layer.name}} layer to your project to build or customise this image recipe
+ </button>
+ </div>
+
+ <div id="packages-table">
+ {% if packages.count %}
+ {% url 'recipepackages' project.id recipe.id as xhr_table_url %}
+ <h2>{{title}} (<span class="table-count-{{table_name}}">0</span>) </h2>
+ {% include "toastertable.html" %}
+ {% else %}
+ <h2>{{title}}</h2>
+ {% endif %}
+
+ <div class="alert alert-info air" id="build-to-get-packages-msg"
+ {# if there are packages and it's in the project don't show this msg #}
+ {% if packages.count or not packages.count and not in_project %}
+ style="display:none"
+ {% endif %} >
+ <p class="lead">Toaster has no package information for {{recipe.name}}. To generate package information, build {{recipe.name}}</p>
+ <button class="btn btn-info btn-large build-recipe-btn" style="margin:20px 0 10px 0;">Build {{recipe.name}}</button>
+ </div>
+
+ <div class="alert alert-info air" id="packages-alert"
+ {% if packages.count or in_project %}
+ style="display:none"
+ {% endif %}
+ >
+ <p class="lead">Toaster has no package information for {{recipe.name}}
+ </p>
+ </div>
+ </div>
+ </div>
+ <div class="span4 well">
+ <h2 style="margin-bottom:20px;">About {{recipe.name}}</h2>
+ <dl>
+ <dt>
+ Approx. packages included
+ <i class="icon-question-sign get-help" title="" data-original-title="The number of packages included is based on information from previous builds and from parsing layers, so we can never be sure it is 100% accurate"></i>
+ </dt>
+ <dd class="no-packages">{{packages.count}}</dd>
+ <dt>
+ Approx. package size
+ <i class="icon-question-sign get-help" title="" data-original-title="Package size is based on information from previous builds, so we can never be sure it is 100% accurate"></i>
+ </dt>
+ <dd>{{approx_pkg_size.size__sum|filtered_filesizeformat}}</dd>
+ {% if last_build %}
+ <dt>Last build</dt>
+ <dd>
+ <i class="icon-ok-sign success"></i>
+ <a href="{% url 'projectbuilds' project.id%}">{{last_build.completed_on|date:"d/m/y H:i"}}</a>
+ </dd>
+ {% endif %}
+ <dt>Recipe file</dt>
+ <dd>
+ <code>{{recipe.file_path|cut_path_prefix:recipe.layer_version.local_path}}</code>
+ <a href="{{recipe.get_vcs_recipe_file_link_url}}"><i class="icon-share" title="" data-original-title="View recipe file"></i></a>
+ </dd>
+ <dt>Layer</dt>
+ <dd><a href="{% url 'layerdetails' project.id recipe.layer_version.pk %}">{{recipe.layer_version.layer.name}}</a></dd>
+ <dt>
+ Summary
+ </dt>
+ <dd>
+ {{recipe.summary}}
+ </dd>
+ <dt>
+ Description
+ </dt>
+ <dd>
+ {{recipe.description}}
+ </dd>
+ <dt>Version</dt>
+ <dd>
+ {{recipe.version}}
+ </dd>
+ <dt>Section</dt>
+ <dd>
+ {{recipe.section}}
+ </dd>
+ <dt>License</dt>
+ <dd>
+ {{recipe.license}}
+ </dd>
+ </dl>
+ </div>
+</div>
+
+{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
new file mode 100644
index 000000000..a3fcdb09e
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_dependencies_popover.html
@@ -0,0 +1,14 @@
+{# Popover that displays the dependences and sizes of a package 'data' used in the Packages table #}
+{% with data.package_dependencies_source.all_depends.count as dep_count %}
+{% load projecttags %}
+{% if dep_count %}
+ <a data-content="<ul class='unstyled'>
+ {% for dep in data.package_dependencies_source.all_depends %}
+ <li>{{dep.depends_on.name}} {% if dep.depends_on.size > 0 %}({{dep.depends_on.size|filtered_filesizeformat}}){% endif %}</li>
+ {% endfor %}
+ </ul>" title="" class="btn" data-original-title="
+ <strong>{{data.name}}</strong> dependencies - <strong>{{data.package_dependencies_source.get_total_source_deps_size.depends_on__size__sum|filtered_filesizeformat}}</strong>">
+ {{dep_count}}
+</a>
+{% endif %}
+{% endwith %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
new file mode 100644
index 000000000..453a9d013
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/snippets/pkg_revdependencies_popover.html
@@ -0,0 +1,14 @@
+{# Popover that displays the reverse dependencies and sizes of a package 'data' used in the Packages table #}
+{% with data.package_dependencies_target.all_depends.count as dep_count %}
+{% load projecttags %}
+{% if dep_count %}
+ <a data-content="<ul class='unstyled'>
+ {% for dep in data.package_dependencies_target.all_depends|dictsort:'package.name' %}
+ <li>{{dep.package.name}} {% if dep.package.size > 0 %}({{dep.package.size|filtered_filesizeformat}}){% endif %}</li>
+ {% endfor %}
+ </ul>" title="" class="btn" data-original-title="
+ <strong>{{data.name}}</strong> reverse dependencies - <strong>{{data.package_dependencies_target.get_total_revdeps_size.package_id__size__sum|filtered_filesizeformat}}</strong>">
+ {{dep_count}}
+</a>
+{% endif %}
+{% endwith %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/task.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/task.html
index ef628d9f9..576826243 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/task.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/task.html
@@ -238,7 +238,7 @@
</dl>
{# Performance section - shown only for executed tasks #}
-{%if task.elapsed_time or task.cpu_usage or task.disk_io %}
+{%if task.elapsed_time or task.cpu_time_user or task.cpu_time_system or task.disk_io %}
<h2 class="details">Performance</h2>
{% endif %}
<dl class="dl-horizontal">
@@ -249,19 +249,26 @@
</dt>
<dd>{{task.elapsed_time|format_none_and_zero|floatformat:2}}</dd>
{% endif %}
- {% if task.cpu_usage > 0 %}
+ {% if task.cpu_time_user > 0 %}
<dt>
- <i class="icon-question-sign get-help" title="The percentage of task CPU utilization"></i>
- CPU usage
+ <i class="icon-question-sign get-help" title="Total amount of time spent executing in user mode, in seconds. Note that this time can be greater than the task time due to parallel execution."></i>
+ User CPU time (secs)
</dt>
- <dd>{{task.cpu_usage|format_none_and_zero|floatformat:2}}%</dd>
+ <dd>{{task.cpu_time_user|format_none_and_zero|floatformat:2}}</dd>
+ {% endif %}
+ {% if task.cpu_time_system > 0 %}
+ <dt>
+ <i class="icon-question-sign get-help" title="Total amount of time spent executing in kernel mode, in seconds. Note that this time can be greater than the task time due to parallel execution."></i>
+ System CPU time (secs)
+ </dt>
+ <dd>{{task.cpu_time_system|format_none_and_zero|floatformat:2}}</dd>
{% endif %}
{% if task.disk_io > 0 %}
<dt>
- <i class="icon-question-sign get-help" title="Number of miliseconds the task spent doing disk input and output"></i>
- Disk I/O (ms)
+ <i class="icon-question-sign get-help" title="Number of bytes written to and read from the disk during the task"></i>
+ Disk I/O (bytes)
</dt>
- <dd>{{task.disk_io|format_none_and_zero}}</dd>
+ <dd>{{task.disk_io|format_none_and_zero|intcomma}}</dd>
{% endif %}
</dl>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/tasks.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/tasks.html
index 353410f92..84bc10386 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/tasks.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/tasks.html
@@ -1,4 +1,5 @@
{% extends "basebuildpage.html" %}
+{% load humanize %}
{% load projecttags %}
{% block title %} {{mainheading}} - {{build.target_set.all|dictsort:"target"|join:", "}} {{build.machine}} - {{build.project.name}} - Toaster{% endblock %}
@@ -20,13 +21,15 @@
<li><a href="{% url 'buildtime' build.pk %}">Time</a></li>
{% endif %}
{% endblock %}
-{% block nav-cpuusage %}
- {% if 'CPU usage' == mainheading %}
- <li class="active"><a href="{% url 'cpuusage' build.pk %}">CPU usage</a></li>
+
+{% block nav-cputime %}
+ {% if 'CPU time' == mainheading %}
+ <li class="active"><a href="{% url 'cputime' build.pk %}">CPU time</a></li>
{% else %}
- <li><a href="{% url 'cpuusage' build.pk %}">CPU usage</a></li>
+ <li><a href="{% url 'cputime' build.pk %}">CPU time</a></li>
{% endif %}
{% endblock %}
+
{% block nav-diskio %}
{% if 'Disk I/O' == mainheading %}
<li class="active"><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li>
@@ -107,11 +110,14 @@
<td class="time_taken">
{{task.elapsed_time|format_none_and_zero|floatformat:2}}
</td>
- <td class="cpu_used">
- {{task.cpu_usage|format_none_and_zero|floatformat:2}}{% if task.cpu_usage %}%{% endif %}
+ <td class="cpu_time_system">
+ {{task.cpu_time_system|format_none_and_zero|floatformat:2}}
+ </td>
+ <td class="cpu_time_user">
+ {{task.cpu_time_user|format_none_and_zero|floatformat:2}}
</td>
<td class="disk_io">
- {{task.disk_io|format_none_and_zero}}
+ {{task.disk_io|format_none_and_zero|intcomma}}
</td>
</tr>
@@ -125,7 +131,7 @@
<script type="text/javascript">
$(document).ready(function() {
- // enable blue hightlight animation for the order link
+ // highlight heading on the column for the field used for ordering
if (location.href.search('#') > -1) {
var task_order = location.href.split('#')[1];
$("#" + task_order).addClass("highlight");
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html
index 7c8dc49b3..4d28793bf 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable-filter.html
@@ -10,7 +10,9 @@
<span id="filter-actions-{{table_name}}"></span>
</div>
<div class="modal-footer">
- <button class="btn btn-primary" type="submit">Apply</button>
+ <button class="btn btn-primary" type="submit" data-role="filter-apply">
+ Apply
+ </button>
</div>
</form>
</div>
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable.html
index 98a715f27..21c3d36c7 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/toastertable.html
@@ -32,8 +32,11 @@
<a href="#" class="add-on btn remove-search-btn-{{table_name}}" tabindex="-1">
<i class="icon-remove"></i>
</a>
- <button class="btn search-submit-{{table_name}}" >Search</button>
- <button class="btn btn-link remove-search-btn-{{table_name}}">Show {{title|lower}}
+ <button class="btn search-submit-{{table_name}}">
+ Search
+ </button>
+ <button class="btn btn-link show-all-{{table_name}} remove-search-btn-{{table_name}}">
+ Show all
</button>
</form>
</div>
@@ -43,9 +46,9 @@
<!-- control header -->
<div class="navbar" id="table-chrome-{{table_name}}">
<div class="navbar-inner">
- <div class="navbar-search input-append pull-left">
+ <div class="navbar-search input-append pull-left span6">
- <input class="input-xxlarge" id="search-input-{{table_name}}" name="search" type="text" placeholder="Search {{title|lower}}" value="{%if request.GET.search%}{{request.GET.search}}{%endif%}"/>
+ <input id="search-input-{{table_name}}" name="search" type="text" placeholder="Search {{title|lower}}" value="{%if request.GET.search%}{{request.GET.search}}{%endif%}"/>
<a href="#" style="display:none" class="add-on btn remove-search-btn-{{table_name}}" tabindex="-1">
<i class="icon-remove"></i>
</a>
@@ -54,7 +57,7 @@
<div class="pull-right">
<div class="btn-group">
- <button class="btn dropdown-toggle" data-toggle="dropdown">Edit columns
+ <button id="edit-columns-button" class="btn dropdown-toggle" data-toggle="dropdown">Edit columns
<span class="caret"></span>
</button>
<ul class="dropdown-menu editcol">
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templates/unavailable_artifact.html b/yocto-poky/bitbake/lib/toaster/toastergui/templates/unavailable_artifact.html
index 0301a6c60..2d3d02c2e 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/templates/unavailable_artifact.html
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templates/unavailable_artifact.html
@@ -3,15 +3,14 @@
{% load humanize %}
{% load static %}
-{% block title %} Build artifact no longer exists - Toaster {% endblock %}
+{% block title %} Build artifact does not exist - Toaster {% endblock %}
{% block pagecontent %}
-
-<div class="row-fluid air">
- <div class="alert alert-info span8 lead">
- <p"> The build artifact you are trying to download no longer exists.</p>
- <p><a href="javascript:window.history.back()">Back to previous page</a></p>
+ <div class="row-fluid air">
+ <div class="alert alert-info span8 lead">
+ <p>The build artifact you are trying to download does not exist.</p>
+ <p><a href="javascript:window.history.back()">Back to previous page</a></p>
+ </div>
</div>
-</div>
{% endblock %}
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/templatetags/objects_to_dictionaries_filter.py b/yocto-poky/bitbake/lib/toaster/toastergui/templatetags/objects_to_dictionaries_filter.py
new file mode 100644
index 000000000..0dcc7d271
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/templatetags/objects_to_dictionaries_filter.py
@@ -0,0 +1,35 @@
+from django import template
+import json
+
+register = template.Library()
+
+def objects_to_dictionaries(iterable, fields):
+ """
+ Convert an iterable into a list of dictionaries; fields should be set
+ to a comma-separated string of properties for each item included in the
+ resulting list; e.g. for a queryset:
+
+ {{ queryset | objects_to_dictionaries:"id,name" }}
+
+ will return a list like
+
+ [{'id': 1, 'name': 'foo'}, ...]
+
+ providing queryset has id and name fields
+
+ This is mostly to support serialising querysets or lists of model objects
+ to JSON
+ """
+ objects = []
+
+ if fields:
+ fields_list = [field.strip() for field in fields.split(',')]
+ for item in iterable:
+ out = {}
+ for field in fields_list:
+ out[field] = getattr(item, field)
+ objects.append(out)
+
+ return objects
+
+register.filter('objects_to_dictionaries', objects_to_dictionaries)
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/tests.py b/yocto-poky/bitbake/lib/toaster/toastergui/tests.py
index 9e6c46a25..a4cab5848 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/tests.py
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/tests.py
@@ -30,90 +30,45 @@ from orm.models import Project, Release, BitbakeVersion, Package, LogMessage
from orm.models import ReleaseLayerSourcePriority, LayerSource, Layer, Build
from orm.models import Layer_Version, Recipe, Machine, ProjectLayer, Target
from orm.models import CustomImageRecipe, ProjectVariable
-from orm.models import Branch
+from orm.models import Branch, CustomImagePackage
import toastermain
+import inspect
+import toastergui
from toastergui.tables import SoftwareRecipesTable
import json
+from datetime import timedelta
from bs4 import BeautifulSoup
import re
+import string
+import json
PROJECT_NAME = "test project"
+PROJECT_NAME2 = "test project 2"
CLI_BUILDS_PROJECT_NAME = 'Command line builds'
-# by default, tests are run in build mode; to run in analysis mode,
-# set this to False in individual test cases
-toastermain.settings.BUILD_MODE = True
-
class ViewTests(TestCase):
"""Tests to verify view APIs."""
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name="test bbv", giturl="/tmp/",
- branch="master", dirpath="")
- release = Release.objects.create(name="test release",
- branch_name="master",
- bitbake_version=bbv)
- self.project = Project.objects.create_project(name=PROJECT_NAME,
- release=release)
- now = timezone.now()
-
- build = Build.objects.create(project=self.project,
- started_on=now,
- completed_on=now)
-
- layersrc = LayerSource.objects.create(sourcetype=LayerSource.TYPE_IMPORTED)
- self.priority = ReleaseLayerSourcePriority.objects.create(release=release,
- layer_source=layersrc)
- layer = Layer.objects.create(name="base-layer", layer_source=layersrc,
- vcs_url="/tmp/")
-
- branch = Branch.objects.create(name="master", layer_source=layersrc)
-
- lver = Layer_Version.objects.create(layer=layer, project=self.project,
- layer_source=layersrc, commit="master",
- up_branch=branch)
-
- self.recipe1 = Recipe.objects.create(layer_source=layersrc,
- name="base-recipe",
- version="1.2",
- summary="one recipe",
- description="recipe",
- layer_version=lver)
-
- Machine.objects.create(layer_version=lver, name="wisk",
- description="wisking machine")
-
- ProjectLayer.objects.create(project=self.project, layercommit=lver)
-
-
- self.customr = CustomImageRecipe.objects.create(\
- name="custom recipe", project=self.project,
- base_recipe=self.recipe1)
-
- self.package = Package.objects.create(name='pkg1', recipe=self.recipe1,
- build=build)
+ fixtures = ['toastergui-unittest-data']
+ def setUp(self):
- # recipe with project for testing AvailableRecipe table
- self.recipe2 = Recipe.objects.create(layer_source=layersrc,
- name="fancy-recipe",
- version="1.4",
- summary="a fancy recipe",
- description="fancy recipe",
- layer_version=lver,
- file_path='/home/foo')
-
- self.assertTrue(lver in self.project.compatible_layerversions())
+ self.project = Project.objects.first()
+ self.recipe1 = Recipe.objects.get(pk=2)
+ self.recipe2 = Recipe.objects.last()
+ self.customr = CustomImageRecipe.objects.first()
+ self.cust_package = CustomImagePackage.objects.first()
+ self.package = Package.objects.first()
+ self.lver = Layer_Version.objects.first()
def test_get_base_call_returns_html(self):
"""Basic test for all-projects view"""
response = self.client.get(reverse('all-projects'), follow=True)
self.assertEqual(response.status_code, 200)
self.assertTrue(response['Content-Type'].startswith('text/html'))
- self.assertTemplateUsed(response, "projects.html")
- self.assertTrue(PROJECT_NAME in response.content)
+ self.assertTemplateUsed(response, "projects-toastertable.html")
def test_get_json_call_returns_json(self):
"""Test for all projects output in json format"""
@@ -128,16 +83,9 @@ class ViewTests(TestCase):
self.assertEqual(data["error"], "ok")
self.assertTrue("rows" in data)
- self.assertTrue(PROJECT_NAME in [x["name"] for x in data["rows"]])
+ self.assertTrue(self.project.name in [x["name"] for x in data["rows"]])
self.assertTrue("id" in data["rows"][0])
- self.assertEqual(sorted(data["rows"][0]),
- ['bitbake_version_id', 'created', 'id',
- 'is_default', 'layersTypeAheadUrl', 'name',
- 'num_builds', 'projectBuildsUrl', 'projectPageUrl',
- 'recipesTypeAheadUrl', 'release_id',
- 'short_description', 'updated', 'user_id'])
-
def test_typeaheads(self):
"""Test typeahead ReST API"""
layers_url = reverse('xhr_layerstypeahead', args=(self.project.id,))
@@ -181,7 +129,6 @@ class ViewTests(TestCase):
return False
- import string
for url in urls:
results = False
@@ -198,15 +145,17 @@ class ViewTests(TestCase):
def test_xhr_import_layer(self):
"""Test xhr_importlayer API"""
+ LayerSource.objects.create(sourcetype=LayerSource.TYPE_IMPORTED)
#Test for importing an already existing layer
args = {'vcs_url' : "git://git.example.com/test",
'name' : "base-layer",
'git_ref': "c12b9596afd236116b25ce26dbe0d793de9dc7ce",
- 'project_id': 1, 'dir_path' : "/path/in/repository"}
+ 'project_id': self.project.id,
+ 'dir_path' : "/path/in/repository"}
response = self.client.post(reverse('xhr_importlayer'), args)
data = json.loads(response.content)
self.assertEqual(response.status_code, 200)
- self.assertNotEqual(data["error"], "ok")
+ self.assertEqual(data["error"], "ok")
#Test to verify import of a layer successful
args['name'] = "meta-oe"
@@ -272,13 +221,12 @@ class ViewTests(TestCase):
def test_xhr_custom_details(self):
"""Test getting custom recipe details"""
- name = "custom recipe"
url = reverse('xhr_customrecipe_id', args=(self.customr.id,))
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
expected = {"error": "ok",
"info": {'id': self.customr.id,
- 'name': name,
+ 'name': self.customr.name,
'base_recipe_id': self.recipe1.id,
'project_id': self.project.id,
}
@@ -290,7 +238,9 @@ class ViewTests(TestCase):
name = "to be deleted"
recipe = CustomImageRecipe.objects.create(\
name=name, project=self.project,
- base_recipe=self.recipe1)
+ base_recipe=self.recipe1,
+ file_path="/tmp/testing",
+ layer_version=self.customr.layer_version)
url = reverse('xhr_customrecipe_id', args=(recipe.id,))
response = self.client.delete(url)
self.assertEqual(response.status_code, 200)
@@ -303,20 +253,34 @@ class ViewTests(TestCase):
def test_xhr_custom_packages(self):
"""Test adding and deleting package to a custom recipe"""
- url = reverse('xhr_customrecipe_packages',
- args=(self.customr.id, self.package.id))
- # add self.package1 to recipe
- response = self.client.put(url)
+ # add self.package to recipe
+ response = self.client.put(reverse('xhr_customrecipe_packages',
+ args=(self.customr.id,
+ self.cust_package.id)))
+
self.assertEqual(response.status_code, 200)
- self.assertEqual(json.loads(response.content), {"error": "ok"})
- self.assertEqual(self.customr.packages.all()[0].id, self.package.id)
+ self.assertEqual(json.loads(response.content),
+ {"error": "ok"})
+ self.assertEqual(self.customr.appends_set.first().name,
+ self.cust_package.name)
# delete it
- response = self.client.delete(url)
+ to_delete = self.customr.appends_set.first().pk
+ del_url = reverse('xhr_customrecipe_packages',
+ args=(self.customr.id, to_delete))
+
+ response = self.client.delete(del_url)
self.assertEqual(response.status_code, 200)
self.assertEqual(json.loads(response.content), {"error": "ok"})
- self.assertFalse(self.customr.packages.all())
- # delete it again to test error condition
- response = self.client.delete(url)
+ all_packages = self.customr.get_all_packages().values_list('pk',
+ flat=True)
+
+ self.assertFalse(to_delete in all_packages)
+ # delete invalid package to test error condition
+ del_url = reverse('xhr_customrecipe_packages',
+ args=(self.customr.id,
+ 99999))
+
+ response = self.client.delete(del_url)
self.assertEqual(response.status_code, 200)
self.assertNotEqual(json.loads(response.content)["error"], "ok")
@@ -332,6 +296,18 @@ class ViewTests(TestCase):
self.assertNotEqual(json.loads(response.content),
{"error": "ok"})
+ def test_download_custom_recipe(self):
+ """Download the recipe file generated for the custom image"""
+
+ # Create a dummy recipe file for the custom image generation to read
+ open("/tmp/a_recipe.bb", 'wa').close()
+ response = self.client.get(reverse('customrecipedownload',
+ args=(self.project.id,
+ self.customr.id)))
+
+ self.assertEqual(response.status_code, 200)
+
+
def test_software_recipes_table(self):
"""Test structure returned for Software RecipesTable"""
table = SoftwareRecipesTable()
@@ -344,7 +320,6 @@ class ViewTests(TestCase):
row2 = next(x for x in rows if x['name'] == self.recipe2.name)
self.assertEqual(response.status_code, 200, 'should be 200 OK status')
- self.assertEqual(len(rows), 2, 'should be 2 recipes')
# check other columns have been populated correctly
self.assertEqual(row1['name'], self.recipe1.name)
@@ -360,568 +335,160 @@ class ViewTests(TestCase):
self.assertEqual(row2['layer_version__layer__name'],
self.recipe2.layer_version.layer.name)
-class LandingPageTests(TestCase):
- """ Tests for redirects on the landing page """
- # disable bogus pylint message error:
- # "Instance of 'WSGIRequest' has no 'url' member (no-member)"
- # (see https://github.com/landscapeio/pylint-django/issues/42)
- # pylint: disable=E1103
-
- LANDING_PAGE_TITLE = 'This is Toaster'
-
- def setUp(self):
- """ Add default project manually """
- self.project = Project.objects.create_project('foo', None)
- self.project.is_default = True
- self.project.save()
-
- def test_only_default_project(self):
- """
- No projects except default
- => get the landing page
- """
- response = self.client.get(reverse('landing'))
- self.assertTrue(self.LANDING_PAGE_TITLE in response.content)
-
- def test_default_project_has_build(self):
- """
- Default project has a build, no other projects
- => get the builds page
- """
- now = timezone.now()
- build = Build.objects.create(project=self.project,
- started_on=now,
- completed_on=now)
- build.save()
-
- response = self.client.get(reverse('landing'))
- self.assertEqual(response.status_code, 302,
- 'response should be a redirect')
- self.assertTrue('/builds' in response.url,
- 'should redirect to builds')
-
- def test_user_project_exists(self):
- """
- User has added a project (without builds)
- => get the projects page
- """
- user_project = Project.objects.create_project('foo', None)
- user_project.save()
-
- response = self.client.get(reverse('landing'))
- self.assertEqual(response.status_code, 302,
- 'response should be a redirect')
- self.assertTrue('/projects' in response.url,
- 'should redirect to projects')
-
- def test_user_project_has_build(self):
- """
- User has added a project (with builds)
- => get the builds page
- """
- user_project = Project.objects.create_project('foo', None)
- user_project.save()
-
- now = timezone.now()
- build = Build.objects.create(project=user_project,
- started_on=now,
- completed_on=now)
- build.save()
-
- response = self.client.get(reverse('landing'))
- self.assertEqual(response.status_code, 302,
- 'response should be a redirect')
- self.assertTrue('/builds' in response.url,
- 'should redirect to builds')
-
-class AllProjectsPageTests(TestCase):
- """ Tests for projects page /projects/ """
-
- MACHINE_NAME = 'delorean'
-
- def setUp(self):
- """ Add default project manually """
- project = Project.objects.create_project(CLI_BUILDS_PROJECT_NAME, None)
- self.default_project = project
- self.default_project.is_default = True
- self.default_project.save()
-
- # this project is only set for some of the tests
- self.project = None
-
- self.release = None
-
- def _add_build_to_default_project(self):
- """ Add a build to the default project (not used in all tests) """
- now = timezone.now()
- build = Build.objects.create(project=self.default_project,
- started_on=now,
- completed_on=now)
- build.save()
-
- def _add_non_default_project(self):
- """ Add another project """
- bbv = BitbakeVersion.objects.create(name="test bbv", giturl="/tmp/",
- branch="master", dirpath="")
- self.release = Release.objects.create(name="test release",
- branch_name="master",
- bitbake_version=bbv)
- self.project = Project.objects.create_project(PROJECT_NAME, self.release)
- self.project.is_default = False
- self.project.save()
-
- # fake the MACHINE variable
- project_var = ProjectVariable.objects.create(project=self.project,
- name='MACHINE',
- value=self.MACHINE_NAME)
- project_var.save()
-
- def test_default_project_hidden(self):
- """ The default project should be hidden if it has no builds """
- params = {"count": 10, "orderby": "updated:-", "page": 1}
- response = self.client.get(reverse('all-projects'), params)
-
- self.assertTrue(not('tr class="data"' in response.content),
- 'should be no project rows in the page')
- self.assertTrue(not(CLI_BUILDS_PROJECT_NAME in response.content),
- 'default project "cli builds" should not be in page')
-
- def test_default_project_has_build(self):
- """ The default project should be shown if it has builds """
- self._add_build_to_default_project()
-
- params = {"count": 10, "orderby": "updated:-", "page": 1}
- response = self.client.get(reverse('all-projects'), params)
-
- self.assertTrue('tr class="data"' in response.content,
- 'should be a project row in the page')
- self.assertTrue(CLI_BUILDS_PROJECT_NAME in response.content,
- 'default project "cli builds" should be in page')
-
- def test_default_project_release(self):
- """
- The release for the default project should display as
- 'Not applicable'
- """
- # need a build, otherwise project doesn't display at all
- self._add_build_to_default_project()
-
- # another project to test, which should show release
- self._add_non_default_project()
-
- response = self.client.get(reverse('all-projects'), follow=True)
- soup = BeautifulSoup(response.content)
-
- # check the release cell for the default project
- attrs = {'data-project': str(self.default_project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- self.assertEqual(len(rows), 1, 'should be one row for default project')
- cells = rows[0].find_all('td', attrs={'data-project-field': 'release'})
- self.assertEqual(len(cells), 1, 'should be one release cell')
- text = cells[0].select('span.muted')[0].text
- self.assertEqual(text, 'Not applicable',
- 'release should be not applicable for default project')
-
- # check the link in the release cell for the other project
- attrs = {'data-project': str(self.project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- cells = rows[0].find_all('td', attrs={'data-project-field': 'release'})
- text = cells[0].select('a')[0].text
- self.assertEqual(text, self.release.name,
- 'release name should be shown for non-default project')
-
- def test_default_project_machine(self):
- """
- The machine for the default project should display as
- 'Not applicable'
- """
- # need a build, otherwise project doesn't display at all
- self._add_build_to_default_project()
-
- # another project to test, which should show machine
- self._add_non_default_project()
-
- response = self.client.get(reverse('all-projects'), follow=True)
- soup = BeautifulSoup(response.content)
-
- # check the machine cell for the default project
- attrs = {'data-project': str(self.default_project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- self.assertEqual(len(rows), 1, 'should be one row for default project')
- cells = rows[0].find_all('td', attrs={'data-project-field': 'machine'})
- self.assertEqual(len(cells), 1, 'should be one machine cell')
- text = cells[0].select('span.muted')[0].text
- self.assertEqual(text, 'Not applicable',
- 'machine should be not applicable for default project')
-
- # check the link in the machine cell for the other project
- attrs = {'data-project': str(self.project.id)}
- rows = soup.find_all('tr', attrs=attrs)
- cells = rows[0].find_all('td', attrs={'data-project-field': 'machine'})
- text = cells[0].select('a')[0].text
- self.assertEqual(text, self.MACHINE_NAME,
- 'machine name should be shown for non-default project')
-
- def test_project_page_links(self):
- """
- Test that links for the default project point to the builds
- page /projects/X/builds for that project, and that links for
- other projects point to their configuration pages /projects/X/
- """
-
- # need a build, otherwise project doesn't display at all
- self._add_build_to_default_project()
-
- # another project to test, which should show machine
- self._add_non_default_project()
-
- response = self.client.get(reverse('all-projects'), follow=True)
- soup = BeautifulSoup(response.content)
-
- # link for default project
- row = soup.find('tr', attrs={'data-project': self.default_project.id})
- cell = row.find('td', attrs={'data-project-field': 'name'})
- expected_url = reverse('projectbuilds', args=(self.default_project.id,))
- self.assertEqual(cell.find('a')['href'], expected_url,
- 'link on default project name should point to builds')
-
- # link for other project
- row = soup.find('tr', attrs={'data-project': self.project.id})
- cell = row.find('td', attrs={'data-project-field': 'name'})
- expected_url = reverse('project', args=(self.project.id,))
- self.assertEqual(cell.find('a')['href'], expected_url,
- 'link on project name should point to configuration')
+ def test_toaster_tables(self):
+ """Test all ToasterTables instances"""
+ current_recipes = self.project.get_available_recipes()
+
+ def get_data(table, options={}):
+ """Send a request and parse the json response"""
+ options['format'] = "json"
+ options['nocache'] = "true"
+ request = RequestFactory().get('/', options)
+
+ # This is the image recipe needed for a package list for
+ # PackagesTable do this here to throw a non exist exception
+ image_recipe = Recipe.objects.get(pk=4)
+
+ # Add any kwargs that are needed by any of the possible tables
+ args = {'pid': self.project.id,
+ 'layerid': self.lver.pk,
+ 'recipeid': self.recipe1.pk,
+ 'recipe_id': image_recipe.pk,
+ 'custrecipeid': self.customr.pk
+ }
-class ProjectBuildsPageTests(TestCase):
- """ Test data at /project/X/builds is displayed correctly """
+ response = table.get(request, **args)
+ return json.loads(response.content)
+
+ # Get a list of classes in tables module
+ tables = inspect.getmembers(toastergui.tables, inspect.isclass)
+
+ for name, table_cls in tables:
+ # Filter out the non ToasterTables from the tables module
+ if not issubclass(table_cls, toastergui.widgets.ToasterTable) or \
+ table_cls == toastergui.widgets.ToasterTable:
+ continue
+
+ # Get the table data without any options, this also does the
+ # initialisation of the table i.e. setup_columns,
+ # setup_filters and setup_queryset that we can use later
+ table = table_cls()
+ all_data = get_data(table)
+
+ self.assertTrue(len(all_data['rows']) > 1,
+ "Cannot test on a %s table with < 1 row" % name)
+
+ if table.default_orderby:
+ row_one = all_data['rows'][0][table.default_orderby.strip("-")]
+ row_two = all_data['rows'][1][table.default_orderby.strip("-")]
+
+ if '-' in table.default_orderby:
+ self.assertTrue(row_one >= row_two,
+ "Default ordering not working on %s"
+ " '%s' should be >= '%s'" %
+ (name, row_one, row_two))
+ else:
+ self.assertTrue(row_one <= row_two,
+ "Default ordering not working on %s"
+ " '%s' should be <= '%s'" %
+ (name, row_one, row_two))
+
+ # Test the column ordering and filtering functionality
+ for column in table.columns:
+ if column['orderable']:
+ # If a column is orderable test it in both order
+ # directions ordering on the columns field_name
+ ascending = get_data(table_cls(),
+ {"orderby" : column['field_name']})
+
+ row_one = ascending['rows'][0][column['field_name']]
+ row_two = ascending['rows'][1][column['field_name']]
+
+ self.assertTrue(row_one <= row_two,
+ "Ascending sort applied but row 0 is less "
+ "than row 1 %s %s " %
+ (column['field_name'], name))
+
+
+ descending = get_data(table_cls(),
+ {"orderby" :
+ '-'+column['field_name']})
+
+ row_one = descending['rows'][0][column['field_name']]
+ row_two = descending['rows'][1][column['field_name']]
+
+ self.assertTrue(row_one >= row_two,
+ "Descending sort applied but row 0 is "
+ "greater than row 1 %s %s" %
+ (column['field_name'], name))
+
+ # If the two start rows are the same we haven't actually
+ # changed the order
+ self.assertNotEqual(ascending['rows'][0],
+ descending['rows'][0],
+ "An orderby %s has not changed the "
+ "order of the data in table %s" %
+ (column['field_name'], name))
+
+ if column['filter_name']:
+ # If a filter is available for the column get the filter
+ # info. This contains what filter actions are defined.
+ filter_info = get_data(table_cls(),
+ {"cmd": "filterinfo",
+ "name": column['filter_name']})
+ self.assertTrue(len(filter_info['filter_actions']) > 0,
+ "Filter %s was defined but no actions "
+ "added to it" % column['filter_name'])
+
+ for filter_action in filter_info['filter_actions']:
+ # filter string to pass as the option
+ # This is the name of the filter:action
+ # e.g. project_filter:not_in_project
+ filter_string = "%s:%s" % (column['filter_name'],
+ filter_action['action_name'])
+ # Now get the data with the filter applied
+ filtered_data = get_data(table_cls(),
+ {"filter" : filter_string})
+
+ # date range filter actions can't specify the
+ # number of results they return, so their count is 0
+ if filter_action['count'] != None:
+ self.assertEqual(len(filtered_data['rows']),
+ int(filter_action['count']),
+ "We added a table filter for %s but "
+ "the number of rows returned was not "
+ "what the filter info said there "
+ "would be" % name)
+
+
+ # Test search functionality on the table
+ something_found = False
+ for search in list(string.ascii_letters):
+ search_data = get_data(table_cls(), {'search' : search})
+
+ if len(search_data['rows']) > 0:
+ something_found = True
+ break
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name="bbv1", giturl="/tmp/",
- branch="master", dirpath="")
- release = Release.objects.create(name="release1",
- bitbake_version=bbv)
- self.project1 = Project.objects.create_project(name=PROJECT_NAME,
- release=release)
- self.project1.save()
-
- self.project2 = Project.objects.create_project(name=PROJECT_NAME,
- release=release)
- self.project2.save()
-
- self.default_project = Project.objects.create_project(
- name=CLI_BUILDS_PROJECT_NAME,
- release=release
- )
- self.default_project.is_default = True
- self.default_project.save()
-
- # parameters for builds to associate with the projects
- now = timezone.now()
-
- self.project1_build_success = {
- "project": self.project1,
- "started_on": now,
- "completed_on": now,
- "outcome": Build.SUCCEEDED
- }
-
- self.project1_build_in_progress = {
- "project": self.project1,
- "started_on": now,
- "completed_on": now,
- "outcome": Build.IN_PROGRESS
- }
-
- self.project2_build_success = {
- "project": self.project2,
- "started_on": now,
- "completed_on": now,
- "outcome": Build.SUCCEEDED
- }
-
- self.project2_build_in_progress = {
- "project": self.project2,
- "started_on": now,
- "completed_on": now,
- "outcome": Build.IN_PROGRESS
- }
-
- def _get_rows_for_project(self, project_id):
- """ Helper to retrieve HTML rows for a project """
- url = reverse("projectbuilds", args=(project_id,))
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
- return soup.select('tr[class="data"]')
-
- def test_show_builds_for_project(self):
- """ Builds for a project should be displayed """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
- build_rows = self._get_rows_for_project(self.project1.id)
- self.assertEqual(len(build_rows), 2)
-
- def test_show_builds_project_only(self):
- """ Builds for other projects should be excluded """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
-
- # shouldn't see these two
- Build.objects.create(**self.project2_build_success)
- Build.objects.create(**self.project2_build_in_progress)
-
- build_rows = self._get_rows_for_project(self.project1.id)
- self.assertEqual(len(build_rows), 3)
-
- def test_builds_exclude_in_progress(self):
- """ "in progress" builds should not be shown """
- Build.objects.create(**self.project1_build_success)
- Build.objects.create(**self.project1_build_success)
-
- # shouldn't see this one
- Build.objects.create(**self.project1_build_in_progress)
-
- # shouldn't see these two either, as they belong to a different project
- Build.objects.create(**self.project2_build_success)
- Build.objects.create(**self.project2_build_in_progress)
-
- build_rows = self._get_rows_for_project(self.project1.id)
- self.assertEqual(len(build_rows), 2)
-
- def test_tasks_in_projectbuilds(self):
- """ Task should be shown as suffix on build name """
- build = Build.objects.create(**self.project1_build_success)
- Target.objects.create(build=build, target='bash', task='clean')
- url = reverse("projectbuilds", args=(self.project1.id,))
- response = self.client.get(url, follow=True)
- result = re.findall('^ +bash:clean$', response.content, re.MULTILINE)
- self.assertEqual(len(result), 2)
-
- def test_cli_builds_hides_tabs(self):
- """
- Display for command line builds should hide tabs;
- note that the latest builds section is already tested in
- AllBuildsPageTests, as the template is the same
- """
- url = reverse("projectbuilds", args=(self.default_project.id,))
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
- tabs = soup.select('#project-topbar')
- self.assertEqual(len(tabs), 0,
- 'should be no top bar shown for command line builds')
-
- def test_non_cli_builds_has_tabs(self):
- """
- Non-command-line builds projects should show the tabs
- """
- url = reverse("projectbuilds", args=(self.project1.id,))
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
- tabs = soup.select('#project-topbar')
- self.assertEqual(len(tabs), 1,
- 'should be a top bar shown for non-command-line builds')
-
-class AllBuildsPageTests(TestCase):
- """ Tests for all builds page /builds/ """
+ self.assertTrue(something_found,
+ "We went through the whole alphabet and nothing"
+ " was found for the search of table %s" % name)
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name="bbv1", giturl="/tmp/",
- branch="master", dirpath="")
- release = Release.objects.create(name="release1",
- bitbake_version=bbv)
- self.project1 = Project.objects.create_project(name=PROJECT_NAME,
- release=release)
- self.default_project = Project.objects.create_project(
- name=CLI_BUILDS_PROJECT_NAME,
- release=release
- )
- self.default_project.is_default = True
- self.default_project.save()
-
- # parameters for builds to associate with the projects
- now = timezone.now()
-
- self.project1_build_success = {
- "project": self.project1,
- "started_on": now,
- "completed_on": now,
- "outcome": Build.SUCCEEDED
- }
-
- self.default_project_build_success = {
- "project": self.default_project,
- "started_on": now,
- "completed_on": now,
- "outcome": Build.SUCCEEDED
- }
-
- def test_show_tasks_in_allbuilds(self):
- """ Task should be shown as suffix on build name """
- build = Build.objects.create(**self.project1_build_success)
- Target.objects.create(build=build, target='bash', task='clean')
- url = reverse('all-builds')
- response = self.client.get(url, follow=True)
- result = re.findall('bash:clean', response.content, re.MULTILINE)
- self.assertEqual(len(result), 3)
-
- def test_no_run_again_for_cli_build(self):
- """ "Run again" button should not be shown for command-line builds """
- build = Build.objects.create(**self.default_project_build_success)
- url = reverse('all-builds')
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
-
- attrs = {'data-latest-build-result': build.id}
- result = soup.find('div', attrs=attrs)
-
- # shouldn't see a run again button for command-line builds
- run_again_button = result.select('button')
- self.assertEqual(len(run_again_button), 0)
-
- # should see a help icon for command-line builds
- help_icon = result.select('i.get-help-green')
- self.assertEqual(len(help_icon), 1)
-
- def test_tooltips_on_project_name(self):
- """
- A tooltip should be present next to the command line
- builds project name in the all builds page, but not for
- other projects
- """
- build1 = Build.objects.create(**self.project1_build_success)
- default_build = Build.objects.create(**self.default_project_build_success)
-
- url = reverse('all-builds')
- response = self.client.get(url, follow=True)
- soup = BeautifulSoup(response.content)
-
- # no help icon on non-default project name
- result = soup.find('tr', attrs={'data-table-build-result': build1.id})
- name = result.select('td.project-name')[0]
- icons = name.select('i.get-help')
- self.assertEqual(len(icons), 0,
- 'should not be a help icon for non-cli builds name')
-
- # help icon on default project name
- result = soup.find('tr', attrs={'data-table-build-result': default_build.id})
- name = result.select('td.project-name')[0]
- icons = name.select('i.get-help')
- self.assertEqual(len(icons), 1,
- 'should be a help icon for cli builds name')
-
-class ProjectPageTests(TestCase):
- """ Test project data at /project/X/ is displayed correctly """
- CLI_BUILDS_PROJECT_NAME = 'Command line builds'
-
- def test_command_line_builds_in_progress(self):
- """
- In progress builds should not cause an error to be thrown
- when navigating to "command line builds" project page;
- see https://bugzilla.yoctoproject.org/show_bug.cgi?id=8277
- """
-
- # add the "command line builds" default project; this mirrors what
- # we do in migration 0026_set_default_project.py
- default_project = Project.objects.create_project(self.CLI_BUILDS_PROJECT_NAME, None)
- default_project.is_default = True
- default_project.save()
-
- # add an "in progress" build for the default project
- now = timezone.now()
- build = Build.objects.create(project=default_project,
- started_on=now,
- completed_on=now,
- outcome=Build.IN_PROGRESS)
-
- # navigate to the project page for the default project
- url = reverse("project", args=(default_project.id,))
- response = self.client.get(url, follow=True)
+ # Test the limit functionality on the table
+ limited_data = get_data(table_cls(), {'limit' : "1"})
+ self.assertEqual(len(limited_data['rows']),
+ 1,
+ "Limit 1 set on table %s but not 1 row returned"
+ % name)
- self.assertEqual(response.status_code, 200)
+ # Test the pagination functionality on the table
+ page_one_data = get_data(table_cls(), {'limit' : "1",
+ "page": "1"})['rows'][0]
-class BuildDashboardTests(TestCase):
- """ Tests for the build dashboard /build/X """
+ page_two_data = get_data(table_cls(), {'limit' : "1",
+ "page": "2"})['rows'][0]
- def setUp(self):
- bbv = BitbakeVersion.objects.create(name="bbv1", giturl="/tmp/",
- branch="master", dirpath="")
- release = Release.objects.create(name="release1",
- bitbake_version=bbv)
- project = Project.objects.create_project(name=PROJECT_NAME,
- release=release)
-
- now = timezone.now()
-
- self.build1 = Build.objects.create(project=project,
- started_on=now,
- completed_on=now)
-
- # exception
- msg1 = 'an exception was thrown'
- self.exception_message = LogMessage.objects.create(
- build=self.build1,
- level=LogMessage.EXCEPTION,
- message=msg1
- )
-
- # critical
- msg2 = 'a critical error occurred'
- self.critical_message = LogMessage.objects.create(
- build=self.build1,
- level=LogMessage.CRITICAL,
- message=msg2
- )
-
- def _get_build_dashboard_errors(self):
- """
- Get a list of HTML fragments representing the errors on the
- build dashboard
- """
- url = reverse('builddashboard', args=(self.build1.id,))
- response = self.client.get(url)
- soup = BeautifulSoup(response.content)
- return soup.select('#errors div.alert-error')
-
- def _check_for_log_message(self, log_message):
- """
- Check whether the LogMessage instance <log_message> is
- represented as an HTML error in the build dashboard page
- """
- errors = self._get_build_dashboard_errors()
- self.assertEqual(len(errors), 2)
-
- expected_text = log_message.message
- expected_id = str(log_message.id)
-
- found = False
- for error in errors:
- error_text = error.find('pre').text
- text_matches = (error_text == expected_text)
-
- error_id = error['data-error']
- id_matches = (error_id == expected_id)
-
- if text_matches and id_matches:
- found = True
- break
-
- template_vars = (expected_text, error_text,
- expected_id, error_id)
- assertion_error_msg = 'exception not found as error: ' \
- 'expected text "%s" and got "%s"; ' \
- 'expected ID %s and got %s' % template_vars
- self.assertTrue(found, assertion_error_msg)
-
- def test_exceptions_show_as_errors(self):
- """
- LogMessages with level EXCEPTION should display in the errors
- section of the page
- """
- self._check_for_log_message(self.exception_message)
-
- def test_criticals_show_as_errors(self):
- """
- LogMessages with level CRITICAL should display in the errors
- section of the page
- """
- self._check_for_log_message(self.critical_message)
+ self.assertNotEqual(page_one_data,
+ page_two_data,
+ "Changed page on table %s but first row is the "
+ "same as the previous page" % name)
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/urls.py b/yocto-poky/bitbake/lib/toaster/toastergui/urls.py
index a1adbb7be..27b0baabf 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/urls.py
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/urls.py
@@ -22,12 +22,16 @@ from django.views.generic import RedirectView, TemplateView
from django.http import HttpResponseBadRequest
from toastergui import tables
from toastergui import typeaheads
+from toastergui import api
urlpatterns = patterns('toastergui.views',
# landing page
url(r'^landing/$', 'landing', name='landing'),
- url(r'^builds/$', 'builds', name='all-builds'),
+ url(r'^builds/$',
+ tables.AllBuildsTable.as_view(template_name="builds-toastertable.html"),
+ name='all-builds'),
+
# build info navigation
url(r'^build/(?P<build_id>\d+)$', 'builddashboard', name="builddashboard"),
@@ -61,7 +65,7 @@ urlpatterns = patterns('toastergui.views',
url(r'^build/(?P<build_id>\d+)/configuration$', 'configuration', name='configuration'),
url(r'^build/(?P<build_id>\d+)/configvars$', 'configvars', name='configvars'),
url(r'^build/(?P<build_id>\d+)/buildtime$', 'buildtime', name='buildtime'),
- url(r'^build/(?P<build_id>\d+)/cpuusage$', 'cpuusage', name='cpuusage'),
+ url(r'^build/(?P<build_id>\d+)/cputime$', 'cputime', name='cputime'),
url(r'^build/(?P<build_id>\d+)/diskio$', 'diskio', name='diskio'),
# image information dir
@@ -74,12 +78,15 @@ urlpatterns = patterns('toastergui.views',
# project URLs
url(r'^newproject/$', 'newproject', name='newproject'),
-
- url(r'^projects/$', 'projects', name='all-projects'),
+ url(r'^projects/$',
+ tables.ProjectsTable.as_view(template_name="projects-toastertable.html"),
+ name='all-projects'),
url(r'^project/(?P<pid>\d+)/$', 'project', name='project'),
url(r'^project/(?P<pid>\d+)/configuration$', 'projectconf', name='projectconf'),
- url(r'^project/(?P<pid>\d+)/builds/$', 'projectbuilds', name='projectbuilds'),
+ url(r'^project/(?P<pid>\d+)/builds/$',
+ tables.ProjectBuildsTable.as_view(template_name="projectbuilds-toastertable.html"),
+ name='projectbuilds'),
# the import layer is a project-specific functionality;
url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'),
@@ -103,13 +110,10 @@ urlpatterns = patterns('toastergui.views',
tables.NewCustomImagesTable.as_view(template_name="newcustomimage.html"),
name="newcustomimage"),
-
url(r'^project/(?P<pid>\d+)/layers/$',
tables.LayersTable.as_view(template_name="generic-toastertable-page.html"),
name="projectlayers"),
-
-
url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$',
'layerdetails', name='layerdetails'),
@@ -126,15 +130,21 @@ urlpatterns = patterns('toastergui.views',
name=tables.LayerMachinesTable.__name__.lower()),
- url(r'^project/(?P<pid>\d+)/customrecipe/(?P<recipeid>\d+)/selectpackages/$',
- tables.SelectPackagesTable.as_view(template_name="generic-toastertable-page.html"), name="recipeselectpackages"),
+ url(r'^project/(?P<pid>\d+)/customrecipe/(?P<custrecipeid>\d+)/selectpackages/$',
+ tables.SelectPackagesTable.as_view(), name="recipeselectpackages"),
- url(r'^project/(?P<pid>\d+)/customrecipe/(?P<recipe_id>\d+)$',
- 'customrecipe',
+ url(r'^project/(?P<pid>\d+)/customrecipe/(?P<custrecipeid>\d+)$',
+ tables.SelectPackagesTable.as_view(template_name="customrecipe.html"),
name="customrecipe"),
+ url(r'^project/(?P<pid>\d+)/customrecipe/(?P<recipe_id>\d+)/download$',
+ 'customrecipe_download',
+ name="customrecipedownload"),
+ url(r'^project/(?P<pid>\d+)/recipe/(?P<recipe_id>\d+)$',
+ tables.PackagesTable.as_view(template_name="recipedetails.html"),
+ name="recipedetails"),
# typeahead api end points
url(r'^xhr_typeahead/(?P<pid>\d+)/layers$',
@@ -162,11 +172,19 @@ urlpatterns = patterns('toastergui.views',
# image customisation functionality
url(r'^xhr_customrecipe/(?P<recipe_id>\d+)/packages/(?P<package_id>\d+|)$',
'xhr_customrecipe_packages', name='xhr_customrecipe_packages'),
+
+ url(r'^xhr_customrecipe/(?P<recipe_id>\d+)/packages/$',
+ 'xhr_customrecipe_packages', name='xhr_customrecipe_packages'),
+
url(r'^xhr_customrecipe/(?P<recipe_id>\d+)$', 'xhr_customrecipe_id',
name='xhr_customrecipe_id'),
url(r'^xhr_customrecipe/', 'xhr_customrecipe',
name='xhr_customrecipe'),
+ url(r'^xhr_buildrequest/project/(?P<pid>\d+)$',
+ api.XhrBuildRequest.as_view(),
+ name='xhr_buildrequest'),
+
# default redirection
- url(r'^$', RedirectView.as_view( url= 'landing')),
+ url(r'^$', RedirectView.as_view(url='landing', permanent=True)),
)
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/views.py b/yocto-poky/bitbake/lib/toaster/toastergui/views.py
index 0e255f1b8..bd5bf6334 100755
--- a/yocto-poky/bitbake/lib/toaster/toastergui/views.py
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/views.py
@@ -27,15 +27,15 @@ import operator,re
from django.db.models import F, Q, Sum, Count, Max
from django.db import IntegrityError, Error
-from django.shortcuts import render, redirect
+from django.shortcuts import render, redirect, get_object_or_404
from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
-from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact
+from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact, CustomImagePackage
from orm.models import BitbakeVersion, CustomImageRecipe
from bldcontrol import bbcontroller
from django.views.decorators.cache import cache_control
from django.core.urlresolvers import reverse, resolve
-from django.core.exceptions import MultipleObjectsReturned
+from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.http import HttpResponseBadRequest, HttpResponseNotFound
from django.utils import timezone
@@ -43,7 +43,9 @@ from django.utils.html import escape
from datetime import timedelta, datetime
from django.utils import formats
from toastergui.templatetags.projecttags import json as jsonfilter
+from decimal import Decimal
import json
+import os
from os.path import dirname
from functools import wraps
import itertools
@@ -73,13 +75,9 @@ class MimeTypeFinder(object):
def landing(request):
# in build mode, we redirect to the command-line builds page
# if there are any builds for the default (cli builds) project
- default_project = Project.objects.get_default_project()
+ default_project = Project.objects.get_or_create_default_project()
default_project_builds = Build.objects.filter(project = default_project)
- if (not toastermain.settings.BUILD_MODE) and default_project_builds.count() > 0:
- args = (default_project.id,)
- return redirect(reverse('projectbuilds', args = args), permanent = False)
-
# we only redirect to projects page if there is a user-generated project
num_builds = Build.objects.all().count()
user_projects = Project.objects.filter(is_default = False)
@@ -95,52 +93,6 @@ def landing(request):
return render(request, 'landing.html', context)
-# returns a list for most recent builds;
-def _get_latest_builds(prj=None):
- queryset = Build.objects.all()
-
- if prj is not None:
- queryset = queryset.filter(project = prj)
-
- if not toastermain.settings.BUILD_MODE:
- queryset = queryset.exclude(project__is_default=False)
-
- return list(itertools.chain(
- queryset.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"),
- queryset.filter(outcome__lt=Build.IN_PROGRESS).order_by("-started_on")[:3] ))
-
-
-# a JSON-able dict of recent builds; for use in the Project page, xhr_ updates, and other places, as needed
-def _project_recent_build_list(prj):
- data = []
- # take the most recent 3 completed builds, plus any builds in progress
- for x in _get_latest_builds(prj):
- d = {
- "id": x.pk,
- "targets" : map(lambda y: {"target": y.target, "task": y.task }, x.target_set.all()), # TODO: create the task entry in the Target table
- "status": x.get_current_status(),
- "errors": map(lambda y: {"type": y.lineno, "msg": y.message, "tb": y.pathname}, (x.logmessage_set.filter(level__gte=LogMessage.WARNING)|x.logmessage_set.filter(level=LogMessage.EXCEPTION))),
- "updated": x.completed_on.strftime('%s')+"000",
- "command_time": (x.completed_on - x.started_on).total_seconds(),
- "br_page_url": reverse('builddashboard', args=(x.pk,) ),
- "build" : map( lambda y: {"id": y.pk,
- "status": y.get_outcome_display(),
- "completed_on" : y.completed_on.strftime('%s')+"000",
- "build_time" : (y.completed_on - y.started_on).total_seconds(),
- "build_page_url" : reverse('builddashboard', args=(y.pk,)),
- 'build_time_page_url': reverse('buildtime', args=(y.pk,)),
- "errors": y.errors.count(),
- "warnings": y.warnings.count(),
- "completeper": y.completeper() if y.outcome == Build.IN_PROGRESS else "0",
- "eta": y.eta().strftime('%s')+"000" if y.outcome == Build.IN_PROGRESS else "0",
- }, [x]),
- }
- data.append(d)
-
- return data
-
-
-
def objtojson(obj):
from django.db.models.query import QuerySet
from django.db.models import Model
@@ -151,6 +103,8 @@ def objtojson(obj):
return obj.total_seconds()
elif isinstance(obj, QuerySet) or isinstance(obj, set):
return list(obj)
+ elif isinstance(obj, Decimal):
+ return str(obj)
elif type(obj).__name__ == "RelatedManager":
return [x.pk for x in obj.all()]
elif hasattr( obj, '__dict__') and isinstance(obj, Model):
@@ -509,7 +463,7 @@ def builddashboard( request, build_id ):
for t in tgts:
elem = { }
elem[ 'target' ] = t
- if ( t.is_image ):
+ if t.is_image:
hasImages = True
npkg = 0
pkgsz = 0
@@ -527,9 +481,13 @@ def builddashboard( request, build_id ):
if ( ndx < 0 ):
ndx = 0;
f = i.file_name[ ndx + 1: ]
- imageFiles.append({ 'id': i.id, 'path': f, 'size' : i.file_size })
- if ( t.is_image and
- (( len( imageFiles ) <= 0 ) or ( len( t.license_manifest_path ) <= 0 ))):
+ imageFiles.append({
+ 'id': i.id,
+ 'path': f,
+ 'size': i.file_size,
+ 'suffix': i.suffix
+ })
+ if t.is_image and (len(imageFiles) <= 0 or len(t.license_manifest_path) <= 0):
targetHasNoImages = True
elem[ 'imageFiles' ] = imageFiles
elem[ 'targetHasNoImages' ] = targetHasNoImages
@@ -549,6 +507,7 @@ def builddashboard( request, build_id ):
context = {
'build' : build,
+ 'project' : build.project,
'hasImages' : hasImages,
'ntargets' : ntargets,
'targets' : targets,
@@ -705,7 +664,9 @@ def recipe_packages(request, build_id, recipe_id):
def target_common( request, build_id, target_id, variant ):
template = "target.html"
- (pagesize, orderby) = _get_parameters_values(request, 25, 'name:+')
+ default_orderby = 'name:+'
+
+ (pagesize, orderby) = _get_parameters_values(request, 25, default_orderby)
mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby': orderby }
retval = _verify_parameters( request.GET, mandatory_parameters )
if retval:
@@ -725,8 +686,6 @@ def target_common( request, build_id, target_id, variant ):
queryset = queryset.select_related("recipe", "recipe__layer_version", "recipe__layer_version__layer")
packages = _build_page_range( Paginator(queryset, pagesize), request.GET.get( 'page', 1 ))
-
-
build = Build.objects.get( pk = build_id )
# bring in package dependencies
@@ -839,11 +798,12 @@ eans multiple licenses exist that cover different parts of the source',
context = {
'objectname': variant,
'build' : build,
+ 'project' : build.project,
'target' : Target.objects.filter( pk = target_id )[ 0 ],
'objects' : packages,
'packages_sum' : packages_sum[ 'installed_size__sum' ],
'object_search_display': "packages included",
- 'default_orderby' : orderby,
+ 'default_orderby' : default_orderby,
'tablecols' : [
tc_package,
tc_packageVersion,
@@ -979,7 +939,10 @@ def dirinfo(request, build_id, target_id, file_path=None):
if head != sep:
dir_list.insert(0, head)
- context = { 'build': Build.objects.get(pk=build_id),
+ build = Build.objects.get(pk=build_id)
+
+ context = { 'build': build,
+ 'project': build.project,
'target': Target.objects.get(pk=target_id),
'packages_sum': packages_sum['installed_size__sum'],
'objects': objects,
@@ -1038,29 +1001,29 @@ def tasks_common(request, build_id, variant, task_anchor):
anchor=task_anchor
# default ordering depends on variant
- if 'buildtime' == variant:
- title_variant='Time'
- object_search_display="time data"
- filter_search_display="tasks"
- (pagesize, orderby) = _get_parameters_values(request, 25, 'elapsed_time:-')
- elif 'diskio' == variant:
- title_variant='Disk I/O'
- object_search_display="disk I/O data"
- filter_search_display="tasks"
- (pagesize, orderby) = _get_parameters_values(request, 25, 'disk_io:-')
- elif 'cpuusage' == variant:
- title_variant='CPU usage'
- object_search_display="CPU usage data"
- filter_search_display="tasks"
- (pagesize, orderby) = _get_parameters_values(request, 25, 'cpu_usage:-')
- else :
- title_variant='Tasks'
- object_search_display="tasks"
- filter_search_display="tasks"
- (pagesize, orderby) = _get_parameters_values(request, 25, 'order:+')
+ default_orderby = None
+ filter_search_display = 'tasks'
+
+ if 'buildtime' == variant:
+ default_orderby = 'elapsed_time:-'
+ title_variant = 'Time'
+ object_search_display = 'time data'
+ elif 'diskio' == variant:
+ default_orderby = 'disk_io:-'
+ title_variant = 'Disk I/O'
+ object_search_display = 'disk I/O data'
+ elif 'cputime' == variant:
+ default_orderby = 'cpu_time_system:-'
+ title_variant='CPU time'
+ object_search_display = 'CPU time data'
+ else:
+ default_orderby = 'order:+'
+ title_variant = 'Tasks'
+ object_search_display = 'tasks'
+ (pagesize, orderby) = _get_parameters_values(request, 25, default_orderby)
- mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby': orderby }
+ mandatory_parameters = {'count': pagesize, 'page' : 1, 'orderby': orderby}
template = 'tasks.html'
retval = _verify_parameters( request.GET, mandatory_parameters )
@@ -1204,23 +1167,38 @@ def tasks_common(request, build_id, variant, task_anchor):
del tc_time['clclass']
tc_cache['hidden']='1'
- tc_cpu={
- 'name':'CPU usage',
- 'qhelp':'The percentage of task CPU utilization',
- 'orderfield': _get_toggle_order(request, "cpu_usage", True),
- 'ordericon':_get_toggle_order_icon(request, "cpu_usage"),
- 'orderkey' : 'cpu_usage',
- 'clclass': 'cpu_used', 'hidden' : 1,
+ tc_cpu_time_system={
+ 'name':'System CPU time (secs)',
+ 'qhelp':'Total amount of time spent executing in kernel mode, in ' +
+ 'seconds. Note that this time can be greater than the task ' +
+ 'time due to parallel execution.',
+ 'orderfield': _get_toggle_order(request, "cpu_time_system", True),
+ 'ordericon':_get_toggle_order_icon(request, "cpu_time_system"),
+ 'orderkey' : 'cpu_time_system',
+ 'clclass': 'cpu_time_system', 'hidden' : 1,
}
- if 'cpuusage' == variant:
- tc_cpu['hidden']='0'
- del tc_cpu['clclass']
+ tc_cpu_time_user={
+ 'name':'User CPU time (secs)',
+ 'qhelp':'Total amount of time spent executing in user mode, in seconds. ' +
+ 'Note that this time can be greater than the task time due to ' +
+ 'parallel execution.',
+ 'orderfield': _get_toggle_order(request, "cpu_time_user", True),
+ 'ordericon':_get_toggle_order_icon(request, "cpu_time_user"),
+ 'orderkey' : 'cpu_time_user',
+ 'clclass': 'cpu_time_user', 'hidden' : 1,
+ }
+
+ if 'cputime' == variant:
+ tc_cpu_time_system['hidden']='0'
+ tc_cpu_time_user['hidden']='0'
+ del tc_cpu_time_system['clclass']
+ del tc_cpu_time_user['clclass']
tc_cache['hidden']='1'
tc_diskio={
- 'name':'Disk I/O (ms)',
- 'qhelp':'Number of miliseconds the task spent doing disk input and output',
+ 'name':'Disk I/O (bytes)',
+ 'qhelp':'Number of bytes written to and read from the disk during the task',
'orderfield': _get_toggle_order(request, "disk_io", True),
'ordericon':_get_toggle_order_icon(request, "disk_io"),
'orderkey' : 'disk_io',
@@ -1238,8 +1216,9 @@ def tasks_common(request, build_id, variant, task_anchor):
'filter_search_display': filter_search_display,
'mainheading': title_variant,
'build': build,
+ 'project': build.project,
'objects': task_objects,
- 'default_orderby' : orderby,
+ 'default_orderby' : default_orderby,
'search_term': search_term,
'total_count': queryset_with_search.count(),
'tablecols':[
@@ -1251,7 +1230,8 @@ def tasks_common(request, build_id, variant, task_anchor):
tc_outcome,
tc_cache,
tc_time,
- tc_cpu,
+ tc_cpu_time_system,
+ tc_cpu_time_user,
tc_diskio,
]}
@@ -1272,9 +1252,8 @@ def buildtime(request, build_id):
def diskio(request, build_id):
return tasks_common(request, build_id, 'diskio', '')
-def cpuusage(request, build_id):
- return tasks_common(request, build_id, 'cpuusage', '')
-
+def cputime(request, build_id):
+ return tasks_common(request, build_id, 'cputime', '')
def recipes(request, build_id):
template = 'recipes.html'
@@ -1284,7 +1263,10 @@ def recipes(request, build_id):
if retval:
return _redirect_parameters( 'recipes', request.GET, mandatory_parameters, build_id = build_id)
(filter_string, search_term, ordering_string) = _search_tuple(request, Recipe)
- queryset = Recipe.objects.filter(layer_version__id__in=Layer_Version.objects.filter(build=build_id)).select_related("layer_version", "layer_version__layer")
+
+ build = Build.objects.get(pk=build_id)
+
+ queryset = build.get_recipes()
queryset = _get_queryset(Recipe, queryset, filter_string, search_term, ordering_string, 'name')
recipes = _build_page_range(Paginator(queryset, pagesize),request.GET.get('page', 1))
@@ -1303,11 +1285,10 @@ def recipes(request, build_id):
revlist.append(recipe_dep)
revs[recipe.id] = revlist
- build = Build.objects.get(pk=build_id)
-
context = {
'objectname': 'recipes',
'build': build,
+ 'project': build.project,
'objects': recipes,
'default_orderby' : 'name:+',
'recipe_deps' : deps,
@@ -1392,10 +1373,12 @@ def configuration(request, build_id):
'MACHINE', 'DISTRO', 'DISTRO_VERSION', 'TUNE_FEATURES', 'TARGET_FPU')
context = dict(Variable.objects.filter(build=build_id, variable_name__in=var_names)\
.values_list('variable_name', 'variable_value'))
+ build = Build.objects.get(pk=build_id)
context.update({'objectname': 'configuration',
'object_search_display':'variables',
'filter_search_display':'variables',
- 'build': Build.objects.get(pk=build_id),
+ 'build': build,
+ 'project': build.project,
'targets': Target.objects.filter(build=build_id)})
return render(request, template, context)
@@ -1432,12 +1415,15 @@ def configvars(request, build_id):
file_filter += '/bitbake.conf'
build_dir=re.sub("/tmp/log/.*","",Build.objects.get(pk=build_id).cooker_log_path)
+ build = Build.objects.get(pk=build_id)
+
context = {
'objectname': 'configvars',
'object_search_display':'BitBake variables',
'filter_search_display':'variables',
'file_filter': file_filter,
- 'build': Build.objects.get(pk=build_id),
+ 'build': build,
+ 'project': build.project,
'objects' : variables,
'total_count':queryset_with_search.count(),
'default_orderby' : 'variable_name:+',
@@ -1506,6 +1492,7 @@ def bpackage(request, build_id):
context = {
'objectname': 'packages built',
'build': build,
+ 'project': build.project,
'objects' : packages,
'default_orderby' : 'name:+',
'tablecols':[
@@ -1580,7 +1567,12 @@ def bpackage(request, build_id):
def bfile(request, build_id, package_id):
template = 'bfile.html'
files = Package_File.objects.filter(package = package_id)
- context = {'build': Build.objects.get(pk=build_id), 'objects' : files}
+ build = Build.objects.get(pk=build_id)
+ context = {
+ 'build': build,
+ 'project': build.project,
+ 'objects' : files
+ }
return render(request, template, context)
@@ -1893,11 +1885,6 @@ def managedcontextprocessor(request):
"projects": projects,
"non_cli_projects": projects.exclude(is_default=True),
"DEBUG" : toastermain.settings.DEBUG,
-
- # True if Toaster is in build mode, False otherwise
- "BUILD_MODE": toastermain.settings.BUILD_MODE,
-
- "CUSTOM_IMAGE" : toastermain.settings.CUSTOM_IMAGE,
"TOASTER_BRANCH": toastermain.settings.TOASTER_BRANCH,
"TOASTER_REVISION" : toastermain.settings.TOASTER_REVISION,
}
@@ -1908,6 +1895,7 @@ def managedcontextprocessor(request):
import toastermain.settings
from orm.models import Project, ProjectLayer, ProjectTarget, ProjectVariable
+from bldcontrol.models import BuildEnvironment
# we have a set of functions if we're in managed mode, or
# a default "page not available" simple functions for interactive mode
@@ -1926,263 +1914,6 @@ if True:
''' The exception raised on invalid POST requests '''
pass
- # shows the "all builds" page for managed mode; it displays build requests (at least started!) instead of actual builds
- # WARNING _build_list_helper() may raise a RedirectException, which
- # will set the GET parameters and redirect back to the
- # all-builds or projectbuilds page as appropriate;
- # TODO don't use exceptions to control program flow
- @_template_renderer("builds.html")
- def builds(request):
- # define here what parameters the view needs in the GET portion in order to
- # be able to display something. 'count' and 'page' are mandatory for all views
- # that use paginators.
-
- queryset = Build.objects.all()
-
- # if in analysis mode, exclude builds for all projects except
- # command line builds
- if not toastermain.settings.BUILD_MODE:
- queryset = queryset.exclude(project__is_default=False)
-
- redirect_page = resolve(request.path_info).url_name
-
- context, pagesize, orderby = _build_list_helper(request,
- queryset,
- redirect_page)
- # all builds page as a Project column
- context['tablecols'].append({
- 'name': 'Project',
- 'clclass': 'project_column'
- })
-
- _set_parameters_values(pagesize, orderby, request)
- return context
-
-
- # helper function, to be used on "all builds" and "project builds" pages
- def _build_list_helper(request, queryset_all, redirect_page, pid=None):
- default_orderby = 'completed_on:-'
- (pagesize, orderby) = _get_parameters_values(request, 10, default_orderby)
- mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby }
- retval = _verify_parameters( request.GET, mandatory_parameters )
- if retval:
- params = {}
- if pid:
- params = {'pid': pid}
- raise RedirectException(redirect_page,
- request.GET,
- mandatory_parameters,
- **params)
-
- # boilerplate code that takes a request for an object type and returns a queryset
- # for that object type. copypasta for all needed table searches
- (filter_string, search_term, ordering_string) = _search_tuple(request, Build)
-
- # post-process any date range filters
- filter_string, daterange_selected = _modify_date_range_filter(filter_string)
-
- # don't show "in progress" builds in "all builds" or "project builds"
- queryset_all = queryset_all.exclude(outcome = Build.IN_PROGRESS)
-
- # append project info
- queryset_all = queryset_all.select_related("project")
-
- # annotate with number of ERROR and EXCEPTION log messages
- queryset_all = queryset_all.annotate(
- errors_no = Count(
- 'logmessage',
- only=Q(logmessage__level=LogMessage.ERROR) |
- Q(logmessage__level=LogMessage.EXCEPTION)
- )
- )
-
- # annotate with number of warnings
- q_warnings = Q(logmessage__level=LogMessage.WARNING)
- queryset_all = queryset_all.annotate(
- warnings_no = Count('logmessage', only=q_warnings)
- )
-
- # add timespent field
- timespent = 'completed_on - started_on'
- queryset_all = queryset_all.extra(select={'timespent': timespent})
-
- queryset_with_search = _get_queryset(Build, queryset_all,
- None, search_term,
- ordering_string, '-completed_on')
-
- queryset = _get_queryset(Build, queryset_all,
- filter_string, search_term,
- ordering_string, '-completed_on')
-
- # retrieve the objects that will be displayed in the table; builds a paginator and gets a page range to display
- build_info = _build_page_range(Paginator(queryset, pagesize), request.GET.get('page', 1))
-
- # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds)
- build_mru = _get_latest_builds()[:3]
-
- # calculate the exact begining of local today and yesterday, append context
- context_date,today_begin,yesterday_begin = _add_daterange_context(queryset_all, request, {'started_on','completed_on'})
-
- # set up list of fstypes for each build
- fstypes_map = {};
- for build in build_info:
- targets = Target.objects.filter( build_id = build.id )
- comma = "";
- extensions = "";
- for t in targets:
- if ( not t.is_image ):
- continue
- tif = Target_Image_File.objects.filter( target_id = t.id )
- for i in tif:
- s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name)
- if s == i.file_name:
- s=re.sub('.*\.', '', i.file_name)
- if None == re.search(s,extensions):
- extensions += comma + s
- comma = ", "
- fstypes_map[build.id]=extensions
-
- # send the data to the template
- context = {
- # specific info for
- 'mru' : build_mru,
- # TODO: common objects for all table views, adapt as needed
- 'objects' : build_info,
- 'objectname' : "builds",
- 'default_orderby' : default_orderby,
- 'fstypes' : fstypes_map,
- 'search_term' : search_term,
- 'total_count' : queryset_with_search.count(),
- 'daterange_selected' : daterange_selected,
- # Specifies the display of columns for the table, appearance in "Edit columns" box, toggling default show/hide, and specifying filters for columns
- 'tablecols' : [
- {'name': 'Outcome', # column with a single filter
- 'qhelp' : "The outcome tells you if a build successfully completed or failed", # the help button content
- 'dclass' : "span2", # indication about column width; comes from the design
- 'orderfield': _get_toggle_order(request, "outcome"), # adds ordering by the field value; default ascending unless clicked from ascending into descending
- 'ordericon':_get_toggle_order_icon(request, "outcome"),
- # filter field will set a filter on that column with the specs in the filter description
- # the class field in the filter has no relation with clclass; the control different aspects of the UI
- # still, it is recommended for the values to be identical for easy tracking in the generated HTML
- 'filter' : {'class' : 'outcome',
- 'label': 'Show:',
- 'options' : [
- ('Successful builds', 'outcome:' + str(Build.SUCCEEDED), queryset_with_search.filter(outcome=str(Build.SUCCEEDED)).count()), # this is the field search expression
- ('Failed builds', 'outcome:'+ str(Build.FAILED), queryset_with_search.filter(outcome=str(Build.FAILED)).count()),
- ]
- }
- },
- {'name': 'Recipe', # default column, disabled box, with just the name in the list
- 'qhelp': "What you built (i.e. one or more recipes or image recipes)",
- 'orderfield': _get_toggle_order(request, "target__target"),
- 'ordericon':_get_toggle_order_icon(request, "target__target"),
- },
- {'name': 'Machine',
- 'qhelp': "The machine is the hardware for which you are building a recipe or image recipe",
- 'orderfield': _get_toggle_order(request, "machine"),
- 'ordericon':_get_toggle_order_icon(request, "machine"),
- 'dclass': 'span3'
- }, # a slightly wider column
- {'name': 'Started on', 'clclass': 'started_on', 'hidden' : 1, # this is an unchecked box, which hides the column
- 'qhelp': "The date and time you started the build",
- 'orderfield': _get_toggle_order(request, "started_on", True),
- 'ordericon':_get_toggle_order_icon(request, "started_on"),
- 'orderkey' : "started_on",
- 'filter' : {'class' : 'started_on',
- 'label': 'Show:',
- 'options' : [
- ("Today's builds" , 'started_on__gte:'+today_begin.strftime("%Y-%m-%d"), queryset_all.filter(started_on__gte=today_begin).count()),
- ("Yesterday's builds",
- 'started_on__gte!started_on__lt:'
- +yesterday_begin.strftime("%Y-%m-%d")+'!'
- +today_begin.strftime("%Y-%m-%d"),
- queryset_all.filter(
- started_on__gte=yesterday_begin,
- started_on__lt=today_begin
- ).count()),
- ("Build date range", 'daterange', 1, '', 'started_on'),
- ]
- }
- },
- {'name': 'Completed on',
- 'qhelp': "The date and time the build finished",
- 'orderfield': _get_toggle_order(request, "completed_on", True),
- 'ordericon':_get_toggle_order_icon(request, "completed_on"),
- 'orderkey' : 'completed_on',
- 'filter' : {'class' : 'completed_on',
- 'label': 'Show:',
- 'options' : [
- ("Today's builds" , 'completed_on__gte:'+today_begin.strftime("%Y-%m-%d"), queryset_all.filter(completed_on__gte=today_begin).count()),
- ("Yesterday's builds",
- 'completed_on__gte!completed_on__lt:'
- +yesterday_begin.strftime("%Y-%m-%d")+'!'
- +today_begin.strftime("%Y-%m-%d"),
- queryset_all.filter(
- completed_on__gte=yesterday_begin,
- completed_on__lt=today_begin
- ).count()),
- ("Build date range", 'daterange', 1, '', 'completed_on'),
- ]
- }
- },
- {'name': 'Failed tasks', 'clclass': 'failed_tasks', # specifing a clclass will enable the checkbox
- 'qhelp': "How many tasks failed during the build",
- 'filter' : {'class' : 'failed_tasks',
- 'label': 'Show:',
- 'options' : [
- ('Builds with failed tasks', 'task_build__outcome:4', queryset_with_search.filter(task_build__outcome=4).count()),
- ('Builds without failed tasks', 'task_build__outcome:NOT4', queryset_with_search.filter(~Q(task_build__outcome=4)).count()),
- ]
- }
- },
- {'name': 'Errors', 'clclass': 'errors_no',
- 'qhelp': "How many errors were encountered during the build (if any)",
- # Comment out sorting and filter until YOCTO #8131 is fixed
- #'orderfield': _get_toggle_order(request, "errors_no", True),
- #'ordericon':_get_toggle_order_icon(request, "errors_no"),
- #'orderkey' : 'errors_no',
- #'filter' : {'class' : 'errors_no',
- # 'label': 'Show:',
- # 'options' : [
- # ('Builds with errors', 'errors_no__gte:1', queryset_with_search.filter(errors_no__gte=1).count()),
- # ('Builds without errors', 'errors_no:0', queryset_with_search.filter(errors_no=0).count()),
- # ]
- # }
- },
- {'name': 'Warnings', 'clclass': 'warnings_no',
- 'qhelp': "How many warnings were encountered during the build (if any)",
- # Comment out sorting and filter until YOCTO #8131 is fixed
- #'orderfield': _get_toggle_order(request, "warnings_no", True),
- #'ordericon':_get_toggle_order_icon(request, "warnings_no"),
- #'orderkey' : 'warnings_no',
- #'filter' : {'class' : 'warnings_no',
- # 'label': 'Show:',
- # 'options' : [
- # ('Builds with warnings','warnings_no__gte:1', queryset_with_search.filter(warnings_no__gte=1).count()),
- # ('Builds without warnings','warnings_no:0', queryset_with_search.filter(warnings_no=0).count()),
- # ]
- # }
- },
- {'name': 'Time', 'clclass': 'time', 'hidden' : 1,
- 'qhelp': "How long it took the build to finish",
- # Comment out sorting until YOCTO #8131 is fixed
- #'orderfield': _get_toggle_order(request, "timespent", True),
- #'ordericon':_get_toggle_order_icon(request, "timespent"),
- #'orderkey' : 'timespent',
- },
- {'name': 'Image files', 'clclass': 'output',
- 'qhelp': "The root file system types produced by the build. You can find them in your <code>/build/tmp/deploy/images/</code> directory",
- # TODO: compute image fstypes from Target_Image_File
- }
- ]
- }
-
- # merge daterange values
- context.update(context_date)
- return context, pagesize, orderby
-
-
-
# new project
def newproject(request):
template = "newproject.html"
@@ -2280,16 +2011,17 @@ if True:
prj.bitbake_version = prj.release.bitbake_version
prj.save()
# we need to change the layers
- for i in prj.projectlayer_set.all():
+ for project in prj.projectlayer_set.all():
# find and add a similarly-named layer on the new branch
try:
- lv = prj.compatible_layerversions(layer_name = i.layercommit.layer.name)[0]
- ProjectLayer.objects.get_or_create(project = prj, layercommit = lv)
+ layer_versions = prj.get_all_compatible_layer_versions()
+ layer_versions = layer_versions.filter(layer__name = project.layercommit.layer.name)
+ ProjectLayer.objects.get_or_create(project = prj, layercommit = layer_versions.first())
except IndexError:
pass
finally:
# get rid of the old entry
- i.delete()
+ project.delete()
if 'machineName' in request.POST:
machinevar = prj.projectvariable_set.get(name="MACHINE")
@@ -2316,7 +2048,7 @@ if True:
"completedbuilds": Build.objects.exclude(outcome = Build.IN_PROGRESS).filter(project_id = pid),
"prj" : {"name": prj.name, },
"buildrequests" : prj.build_set.filter(outcome=Build.IN_PROGRESS),
- "builds" : _project_recent_build_list(prj),
+ "builds" : Build.get_recent(prj),
"layers" : map(lambda x: {
"id": x.layercommit.pk,
"orderid": x.pk,
@@ -2371,13 +2103,23 @@ if True:
name = "_js_unit_test_prj_"
- # If there is an existing project by this name delete it. We don't want
- # Lots of duplicates cluttering up the projects.
+ # If there is an existing project by this name delete it.
+ # We don't want Lots of duplicates cluttering up the projects.
Project.objects.filter(name=name).delete()
- new_project = Project.objects.create_project(name=name, release=release)
+ new_project = Project.objects.create_project(name=name,
+ release=release)
+ # Add a layer
+ layer = new_project.get_all_compatible_layer_versions().first()
+
+ ProjectLayer.objects.get_or_create(layercommit=layer,
+ project=new_project)
- context = { 'project' : new_project }
+ # make sure we have a machine set for this project
+ ProjectVariable.objects.get_or_create(project=new_project,
+ name="MACHINE",
+ value="qemux86")
+ context = {'project': new_project}
return render(request, "js-unit-tests.html", context)
from django.views.decorators.csrf import csrf_exempt
@@ -2399,12 +2141,17 @@ if True:
retval = []
- for i in prj.projectlayer_set.all():
- lv = prj.compatible_layerversions(release = Release.objects.get(pk=new_release_id)).filter(layer__name = i.layercommit.layer.name)
+ for project in prj.projectlayer_set.all():
+ release = Release.objects.get(pk = new_release_id)
+
+ layer_versions = prj.get_all_compatible_layer_versions()
+ layer_versions = layer_versions.filter(release = release)
+ layer_versions = layer_versions.filter(layer__name = project.layercommit.layer.name)
+
# there is no layer_version with the new release id,
# and the same name
- if lv.count() < 1:
- retval.append(i)
+ if layer_versions.count() < 1:
+ retval.append(project)
return response({"error":"ok",
"rows" : map( _lv_to_dict(prj),
@@ -2461,6 +2208,10 @@ if True:
except ProjectVariable.DoesNotExist:
pass
try:
+ return_data['dl_dir'] = ProjectVariable.objects.get(project = prj, name = "DL_DIR").value,
+ except ProjectVariable.DoesNotExist:
+ pass
+ try:
return_data['fstypes'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_FSTYPES").value,
except ProjectVariable.DoesNotExist:
pass
@@ -2473,7 +2224,7 @@ if True:
except ProjectVariable.DoesNotExist:
pass
try:
- return_data['sdk_machine'] = ProjectVariable.objects.get(project = prj, name = "SDKMACHINE").value,
+ return_data['sstate_dir'] = ProjectVariable.objects.get(project = prj, name = "SSTATE_DIR").value,
except ProjectVariable.DoesNotExist:
pass
@@ -2493,8 +2244,11 @@ if True:
layers_added = [];
# Rudimentary check for any possible html tags
- if "<" in request.POST:
- return HttpResponse(jsonfilter({"error": "Invalid character <"}), content_type = "application/json")
+ for val in request.POST.values():
+ if "<" in val:
+ return HttpResponse(jsonfilter(
+ {"error": "Invalid character <"}),
+ content_type="application/json")
prj = Project.objects.get(pk=request.POST['project_id'])
@@ -2669,33 +2423,106 @@ if True:
# create custom recipe
try:
- recipe = CustomImageRecipe.objects.create(
- name=request.POST["name"],
- base_recipe=params["base"],
- project=params["project"])
+
+ # Only allowed chars in name are a-z, 0-9 and -
+ if re.search(r'[^a-z|0-9|-]', request.POST["name"]):
+ return {"error": "invalid-name"}
+
+ custom_images = CustomImageRecipe.objects.all()
+
+ # Are there any recipes with this name already in our project?
+ existing_image_recipes_in_project = custom_images.filter(
+ name=request.POST["name"], project=params["project"])
+
+ if existing_image_recipes_in_project.count() > 0:
+ return {"error": "image-already-exists"}
+
+ # Are there any recipes with this name which aren't custom
+ # image recipes?
+ custom_image_ids = custom_images.values_list('id', flat=True)
+ existing_non_image_recipes = Recipe.objects.filter(
+ Q(name=request.POST["name"]) & ~Q(pk__in=custom_image_ids)
+ )
+
+ if existing_non_image_recipes.count() > 0:
+ return {"error": "recipe-already-exists"}
+
+ # create layer 'Custom layer' and verion if needed
+ layer = Layer.objects.get_or_create(
+ name=CustomImageRecipe.LAYER_NAME,
+ summary="Layer for custom recipes",
+ vcs_url="file:///toaster_created_layer")[0]
+
+ # Check if we have a layer version already
+ # We don't use get_or_create here because the dirpath will change
+ # and is a required field
+ lver = Layer_Version.objects.filter(Q(project=params['project']) &
+ Q(layer=layer) &
+ Q(build=None)).last()
+ if lver == None:
+ lver, created = Layer_Version.objects.get_or_create(
+ project=params['project'],
+ layer=layer,
+ dirpath="toaster_created_layer")
+
+ # Add a dependency on our layer to the base recipe's layer
+ LayerVersionDependency.objects.get_or_create(
+ layer_version=lver,
+ depends_on=params["base"].layer_version)
+
+ # Add it to our current project if needed
+ ProjectLayer.objects.get_or_create(project=params['project'],
+ layercommit=lver,
+ optional=False)
+
+ # Create the actual recipe
+ recipe, created = CustomImageRecipe.objects.get_or_create(
+ name=request.POST["name"],
+ base_recipe=params["base"],
+ project=params["project"],
+ layer_version=lver,
+ is_image=True)
+
+ # If we created the object then setup these fields. They may get
+ # overwritten later on and cause the get_or_create to create a
+ # duplicate if they've changed.
+ if created:
+ recipe.file_path = request.POST["name"]
+ recipe.license = "MIT"
+ recipe.version = "0.1"
+ recipe.save()
+
except Error as err:
return {"error": "Can't create custom recipe: %s" % err}
# Find the package list from the last build of this recipe/target
- build = Build.objects.filter(target__target=params['base'].name,
- project=params['project']).last()
-
- if build:
+ target = Target.objects.filter(Q(build__outcome=Build.SUCCEEDED) &
+ Q(build__project=params['project']) &
+ (Q(target=params['base'].name) |
+ Q(target=recipe.name))).last()
+ if target:
# Copy in every package
# We don't want these packages to be linked to anything because
# that underlying data may change e.g. delete a build
- for package in build.package_set.all():
- # Create the duplicate
- package.pk = None
- package.save()
- # Disassociate the package from the build
- package.build = None
- package.save()
- recipe.packages.add(package)
- else:
- logger.warn("No packages found for this base recipe")
+ for tpackage in target.target_installed_package_set.all():
+ try:
+ built_package = tpackage.package
+ # The package had no recipe information so is a ghost
+ # package skip it
+ if built_package.recipe == None:
+ continue;
+
+ config_package = CustomImagePackage.objects.get(
+ name=built_package.name)
+
+ recipe.includes_set.add(config_package)
+ except Exception as e:
+ logger.warning("Error adding package %s %s" %
+ (tpackage.package.name, e))
+ pass
return {"error": "ok",
+ "packages" : recipe.get_all_packages().count(),
"url": reverse('customrecipe', args=(params['project'].pk,
recipe.id))}
@@ -2720,34 +2547,105 @@ if True:
or
{"error": <error message>}
"""
- objects = CustomImageRecipe.objects.filter(id=recipe_id)
- if not objects:
+ try:
+ custom_recipe = CustomImageRecipe.objects.get(id=recipe_id)
+ except CustomImageRecipe.DoesNotExist:
return {"error": "Custom recipe with id=%s "
"not found" % recipe_id}
+
if request.method == 'GET':
- values = CustomImageRecipe.objects.filter(id=recipe_id).values()
- if values:
- return {"error": "ok", "info": values[0]}
- else:
- return {"error": "Custom recipe with id=%s "
- "not found" % recipe_id}
- return {"error": "ok", "info": objects.values()[0]}
+ info = {"id" : custom_recipe.id,
+ "name" : custom_recipe.name,
+ "base_recipe_id": custom_recipe.base_recipe.id,
+ "project_id": custom_recipe.project.id,
+ }
+
+ return {"error": "ok", "info": info}
+
elif request.method == 'DELETE':
- objects.delete()
+ custom_recipe.delete()
return {"error": "ok"}
else:
return {"error": "Method %s is not supported" % request.method}
+ def customrecipe_download(request, pid, recipe_id):
+ recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id)
+
+ file_data = recipe.generate_recipe_file_contents()
+
+ response = HttpResponse(file_data, content_type='text/plain')
+ response['Content-Disposition'] = \
+ 'attachment; filename="%s_%s.bb"' % (recipe.name,
+ recipe.version)
+
+ return response
+
+ def _traverse_dependents(next_package_id, rev_deps, all_current_packages, tree_level=0):
+ """
+ Recurse through reverse dependency tree for next_package_id.
+ Limit the reverse dependency search to packages not already scanned,
+ that is, not already in rev_deps.
+ Limit the scan to a depth (tree_level) not exceeding the count of
+ all packages in the custom image, and if that depth is exceeded
+ return False, pop out of the recursion, and write a warning
+ to the log, but this is unlikely, suggesting a dependency loop
+ not caught by bitbake.
+ On return, the input/output arg rev_deps is appended with queryset
+ dictionary elements, annotated for use in the customimage template.
+ The list has unsorted, but unique elements.
+ """
+ max_dependency_tree_depth = all_current_packages.count()
+ if tree_level >= max_dependency_tree_depth:
+ logger.warning(
+ "The number of reverse dependencies "
+ "for this package exceeds " + max_dependency_tree_depth +
+ " and the remaining reverse dependencies will not be removed")
+ return True
+
+ package = CustomImagePackage.objects.get(id=next_package_id)
+ dependents = \
+ package.package_dependencies_target.annotate(
+ name=F('package__name'),
+ pk=F('package__pk'),
+ size=F('package__size'),
+ ).values("name", "pk", "size").exclude(
+ ~Q(pk__in=all_current_packages)
+ )
+
+ for pkg in dependents:
+ if pkg in rev_deps:
+ # already seen, skip dependent search
+ continue
+
+ rev_deps.append(pkg)
+ if (_traverse_dependents(
+ pkg["pk"], rev_deps, all_current_packages, tree_level+1)):
+ return True
+
+ return False
+
+ def _get_all_dependents(package_id, all_current_packages):
+ """
+ Returns sorted list of recursive reverse dependencies for package_id,
+ as a list of dictionary items, by recursing through dependency
+ relationships.
+ """
+ rev_deps = []
+ _traverse_dependents(package_id, rev_deps, all_current_packages)
+ rev_deps = sorted(rev_deps, key=lambda x: x["name"])
+ return rev_deps
+
@xhr_response
def xhr_customrecipe_packages(request, recipe_id, package_id):
"""
ReST API to add/remove packages to/from custom recipe.
- Entry point: /xhr_customrecipe/<recipe_id>/packages/
+ Entry point: /xhr_customrecipe/<recipe_id>/packages/<package_id>
Methods:
PUT - Add package to the recipe
DELETE - Delete package from the recipe
+ GET - Get package information
Returns:
{"error": "ok"}
@@ -2760,26 +2658,149 @@ if True:
return {"error": "Custom recipe with id=%s "
"not found" % recipe_id}
- if request.method == 'GET' and not package_id:
- return {"error": "ok",
- "packages": list(recipe.packages.values_list('id'))}
+ if package_id:
+ try:
+ package = CustomImagePackage.objects.get(id=package_id)
+ except Package.DoesNotExist:
+ return {"error": "Package with id=%s "
+ "not found" % package_id}
- try:
- package = Package.objects.get(id=package_id)
- except Package.DoesNotExist:
- return {"error": "Package with id=%s "
- "not found" % package_id}
+ if request.method == 'GET':
+ # If no package_id then list the current packages
+ if not package_id:
+ total_size = 0
+ packages = recipe.get_all_packages().values("id",
+ "name",
+ "version",
+ "size")
+ for package in packages:
+ package['size_formatted'] = \
+ filtered_filesizeformat(package['size'])
+ total_size += package['size']
+
+ return {"error": "ok",
+ "packages" : list(packages),
+ "total" : len(packages),
+ "total_size" : total_size,
+ "total_size_formatted" :
+ filtered_filesizeformat(total_size)
+ }
+ else:
+ all_current_packages = recipe.get_all_packages()
+
+ # Dependencies for package which aren't satisfied by the
+ # current packages in the custom image recipe
+ deps = package.package_dependencies_source.annotate(
+ name=F('depends_on__name'),
+ pk=F('depends_on__pk'),
+ size=F('depends_on__size'),
+ ).values("name", "pk", "size").filter(
+ # There are two depends types we don't know why
+ (Q(dep_type=Package_Dependency.TYPE_TRDEPENDS) |
+ Q(dep_type=Package_Dependency.TYPE_RDEPENDS)) &
+ ~Q(pk__in=all_current_packages)
+ )
+
+ # Reverse dependencies which are needed by packages that are
+ # in the image. Recursive search providing all dependents,
+ # not just immediate dependents.
+ reverse_deps = _get_all_dependents(package_id, all_current_packages)
+ total_size_deps = 0
+ total_size_reverse_deps = 0
+
+ for dep in deps:
+ dep['size_formatted'] = \
+ filtered_filesizeformat(dep['size'])
+ total_size_deps += dep['size']
+
+ for dep in reverse_deps:
+ dep['size_formatted'] = \
+ filtered_filesizeformat(dep['size'])
+ total_size_reverse_deps += dep['size']
+
+
+ return {"error": "ok",
+ "id": package.pk,
+ "name": package.name,
+ "version": package.version,
+ "unsatisfied_dependencies": list(deps),
+ "unsatisfied_dependencies_size": total_size_deps,
+ "unsatisfied_dependencies_size_formatted":
+ filtered_filesizeformat(total_size_deps),
+ "reverse_dependencies": list(reverse_deps),
+ "reverse_dependencies_size": total_size_reverse_deps,
+ "reverse_dependencies_size_formatted":
+ filtered_filesizeformat(total_size_reverse_deps)}
+
+ included_packages = recipe.includes_set.values_list('pk', flat=True)
if request.method == 'PUT':
- recipe.packages.add(package)
+ # If we're adding back a package which used to be included in this
+ # image all we need to do is remove it from the excludes
+ if package.pk in included_packages:
+ try:
+ recipe.excludes_set.remove(package)
+ return {"error": "ok"}
+ except Package.DoesNotExist:
+ return {"error":
+ "Package %s not found in excludes but was in "
+ "included list" % package.name}
+
+ else:
+ recipe.appends_set.add(package)
+ # Make sure that package is not in the excludes set
+ try:
+ recipe.excludes_set.remove(package)
+ except:
+ pass
+ # Add the dependencies we think will be added to the recipe
+ # as a result of appending this package.
+ # TODO this should recurse down the entire deps tree
+ for dep in package.package_dependencies_source.all_depends():
+ try:
+ cust_package = CustomImagePackage.objects.get(
+ name=dep.depends_on.name)
+
+ recipe.includes_set.add(cust_package)
+ try:
+ # When adding the pre-requisite package, make
+ # sure it's not in the excluded list from a
+ # prior removal.
+ recipe.excludes_set.remove(cust_package)
+ except Package.DoesNotExist:
+ # Don't care if the package had never been excluded
+ pass
+ except:
+ logger.warning("Could not add package's suggested"
+ "dependencies to the list")
+
return {"error": "ok"}
+
elif request.method == 'DELETE':
- if package in recipe.packages.all():
- recipe.packages.remove(package)
+ try:
+ # If we're deleting a package which is included we need to
+ # Add it to the excludes list.
+ if package.pk in included_packages:
+ recipe.excludes_set.add(package)
+ else:
+ recipe.appends_set.remove(package)
+ all_current_packages = recipe.get_all_packages()
+ reverse_deps_dictlist = _get_all_dependents(package.pk, all_current_packages)
+ ids = [entry['pk'] for entry in reverse_deps_dictlist]
+ reverse_deps = CustomImagePackage.objects.filter(id__in=ids)
+ for r in reverse_deps:
+ try:
+ if r.id in included_packages:
+ recipe.excludes_set.add(r)
+ else:
+ recipe.appends_set.remove(r)
+ except:
+ pass
+
return {"error": "ok"}
- else:
- return {"error": "Package '%s' is not in the recipe '%s'" % \
- (package.name, recipe.name)}
+ except CustomImageRecipe.DoesNotExist:
+ return {"error": "Tried to remove package that wasn't present"}
+
else:
return {"error": "Method %s is not supported" % request.method}
@@ -2816,30 +2837,16 @@ if True:
}
vars_blacklist = {
- 'DL_DR','PARALLEL_MAKE','BB_NUMBER_THREADS','SSTATE_DIR',
+ 'PARALLEL_MAKE','BB_NUMBER_THREADS',
'BB_DISKMON_DIRS','BB_NUMBER_THREADS','CVS_PROXY_HOST','CVS_PROXY_PORT',
- 'DL_DIR','PARALLEL_MAKE','SSTATE_DIR','SSTATE_DIR','SSTATE_MIRRORS','TMPDIR',
+ 'PARALLEL_MAKE','SSTATE_MIRRORS','TMPDIR',
'all_proxy','ftp_proxy','http_proxy ','https_proxy'
}
- vars_fstypes = {
- 'btrfs','cpio','cpio.gz','cpio.lz4','cpio.lzma','cpio.xz','cramfs',
- 'elf','ext2','ext2.bz2','ext2.gz','ext2.lzma', 'ext4', 'ext4.gz', 'ext3','ext3.gz','hddimg',
- 'iso','jffs2','jffs2.sum','squashfs','squashfs-lzo','squashfs-xz','tar.bz2',
- 'tar.lz4','tar.xz','tartar.gz','ubi','ubifs','vmdk'
- }
+ vars_fstypes = Target_Image_File.SUFFIXES
return(vars_managed,sorted(vars_fstypes),vars_blacklist)
- def customrecipe(request, pid, recipe_id):
- project = Project.objects.get(pk=pid)
- context = {'project' : project,
- 'projectlayers': [],
- 'recipe' : CustomImageRecipe.objects.get(pk=recipe_id)
- }
-
- return render(request, "customrecipe.html", context)
-
@_template_renderer("projectconf.html")
def projectconf(request, pid):
@@ -2870,6 +2877,19 @@ if True:
except ProjectVariable.DoesNotExist:
pass
try:
+ if ProjectVariable.objects.get(project = prj, name = "DL_DIR").value == "${TOPDIR}/../downloads":
+ be = BuildEnvironment.objects.get(pk = str(1))
+ dl_dir = os.path.join(dirname(be.builddir), "downloads")
+ context['dl_dir'] = dl_dir
+ pv, created = ProjectVariable.objects.get_or_create(project = prj, name = "DL_DIR")
+ pv.value = dl_dir
+ pv.save()
+ else:
+ context['dl_dir'] = ProjectVariable.objects.get(project = prj, name = "DL_DIR").value
+ context['dl_dir_defined'] = "1"
+ except ProjectVariable.DoesNotExist,BuildEnvironment.DoesNotExist:
+ pass
+ try:
context['fstypes'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_FSTYPES").value
context['fstypes_defined'] = "1"
except ProjectVariable.DoesNotExist:
@@ -2885,268 +2905,78 @@ if True:
except ProjectVariable.DoesNotExist:
pass
try:
- context['sdk_machine'] = ProjectVariable.objects.get(project = prj, name = "SDKMACHINE").value
- context['sdk_machine_defined'] = "1"
- except ProjectVariable.DoesNotExist:
+ if ProjectVariable.objects.get(project = prj, name = "SSTATE_DIR").value == "${TOPDIR}/../sstate-cache":
+ be = BuildEnvironment.objects.get(pk = str(1))
+ sstate_dir = os.path.join(dirname(be.builddir), "sstate-cache")
+ context['sstate_dir'] = sstate_dir
+ pv, created = ProjectVariable.objects.get_or_create(project = prj, name = "SSTATE_DIR")
+ pv.value = sstate_dir
+ pv.save()
+ else:
+ context['sstate_dir'] = ProjectVariable.objects.get(project = prj, name = "SSTATE_DIR").value
+ context['sstate_dir_defined'] = "1"
+ except ProjectVariable.DoesNotExist, BuildEnvironment.DoesNotExist:
pass
return context
- # WARNING _build_list_helper() may raise a RedirectException, which
- # will set the GET parameters and redirect back to the
- # all-builds or projectbuilds page as appropriate;
- # TODO don't use exceptions to control program flow
- @_template_renderer('projectbuilds.html')
- def projectbuilds(request, pid):
- prj = Project.objects.get(id = pid)
-
- if request.method == "POST":
- # process any build request
-
- if 'buildCancel' in request.POST:
- for i in request.POST['buildCancel'].strip().split(" "):
- try:
- br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED)
- br.state = BuildRequest.REQ_DELETED
- br.save()
- except BuildRequest.DoesNotExist:
- pass
-
- if 'buildDelete' in request.POST:
- for i in request.POST['buildDelete'].strip().split(" "):
- try:
- BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
- except BuildRequest.DoesNotExist:
- pass
-
- if 'targets' in request.POST:
- ProjectTarget.objects.filter(project = prj).delete()
- s = str(request.POST['targets'])
- for t in s.translate(None, ";%|\"").split(" "):
- if ":" in t:
- target, task = t.split(":")
- else:
- target = t
- task = ""
- ProjectTarget.objects.create(project = prj,
- target = target,
- task = task)
- prj.schedule_build()
-
- queryset = Build.objects.filter(project_id = pid)
-
- redirect_page = resolve(request.path_info).url_name
-
- context, pagesize, orderby = _build_list_helper(request,
- queryset,
- redirect_page,
- pid)
-
- context['project'] = prj
- _set_parameters_values(pagesize, orderby, request)
-
- # add the most recent builds for this project
- context['mru'] = _get_latest_builds(prj)
-
- return context
+ def _file_names_for_artifact(build, artifact_type, artifact_id):
+ """
+ Return a tuple (file path, file name for the download response) for an
+ artifact of type artifact_type with ID artifact_id for build; if
+ artifact type is not supported, returns (None, None)
+ """
+ file_name = None
+ response_file_name = None
+ if artifact_type == "cookerlog":
+ file_name = build.cooker_log_path
+ response_file_name = "cooker.log"
- def _file_name_for_artifact(b, artifact_type, artifact_id):
- file_name = None
- # Target_Image_File file_name
- if artifact_type == "imagefile":
- file_name = Target_Image_File.objects.get(target__build = b, pk = artifact_id).file_name
+ elif artifact_type == "imagefile":
+ file_name = Target_Image_File.objects.get(target__build = build, pk = artifact_id).file_name
elif artifact_type == "buildartifact":
- file_name = BuildArtifact.objects.get(build = b, pk = artifact_id).file_name
+ file_name = BuildArtifact.objects.get(build = build, pk = artifact_id).file_name
- elif artifact_type == "licensemanifest":
- file_name = Target.objects.get(build = b, pk = artifact_id).license_manifest_path
+ elif artifact_type == "licensemanifest":
+ file_name = Target.objects.get(build = build, pk = artifact_id).license_manifest_path
elif artifact_type == "tasklogfile":
- file_name = Task.objects.get(build = b, pk = artifact_id).logfile
+ file_name = Task.objects.get(build = build, pk = artifact_id).logfile
elif artifact_type == "logmessagefile":
- file_name = LogMessage.objects.get(build = b, pk = artifact_id).pathname
- else:
- raise Exception("FIXME: artifact type %s not implemented" % (artifact_type))
+ file_name = LogMessage.objects.get(build = build, pk = artifact_id).pathname
- return file_name
+ if file_name and not response_file_name:
+ response_file_name = os.path.basename(file_name)
+ return (file_name, response_file_name)
def build_artifact(request, build_id, artifact_type, artifact_id):
- if artifact_type in ["cookerlog"]:
- try:
- build = Build.objects.get(pk = build_id)
- file_name = build.cooker_log_path
+ """
+ View which returns a build artifact file as a response
+ """
+ file_name = None
+ response_file_name = None
+
+ try:
+ build = Build.objects.get(pk = build_id)
+ file_name, response_file_name = _file_names_for_artifact(
+ build, artifact_type, artifact_id
+ )
+
+ if file_name and response_file_name:
fsock = open(file_name, "r")
content_type = MimeTypeFinder.get_mimetype(file_name)
response = HttpResponse(fsock, content_type = content_type)
- disposition = 'attachment; filename=cooker.log'
- response['Content-Disposition'] = disposition
+ disposition = "attachment; filename=" + response_file_name
+ response["Content-Disposition"] = disposition
return response
- except IOError:
- context = {
- 'build' : Build.objects.get(pk = build_id),
- }
- return render(request, "unavailable_artifact.html", context)
-
- else:
- # retrieve the artifact directly from the build environment
- return _get_be_artifact(request, build_id, artifact_type, artifact_id)
-
-
- def _get_be_artifact(request, build_id, artifact_type, artifact_id):
- try:
- b = Build.objects.get(pk=build_id)
- if b.buildrequest is None or b.buildrequest.environment is None:
- raise Exception("Artifact not available for download (missing build request or build environment)")
-
- file_name = _file_name_for_artifact(b, artifact_type, artifact_id)
- fsock = None
- content_type='application/force-download'
-
- if file_name is None:
- raise Exception("Could not handle artifact %s id %s" % (artifact_type, artifact_id))
else:
- content_type = MimeTypeFinder.get_mimetype(file_name)
- fsock = b.buildrequest.environment.get_artifact(file_name)
- file_name = os.path.basename(file_name) # we assume that the build environment system has the same path conventions as host
-
- response = HttpResponse(fsock, content_type = content_type)
-
- # returns a file from the environment
- response['Content-Disposition'] = 'attachment; filename=' + file_name
- return response
- except IOError:
- context = {
- 'build' : Build.objects.get(pk = build_id),
- }
- return render(request, "unavailable_artifact.html", context)
-
-
-
-
- @_template_renderer("projects.html")
- def projects(request):
- (pagesize, orderby) = _get_parameters_values(request, 10, 'updated:-')
- mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby }
- retval = _verify_parameters( request.GET, mandatory_parameters )
- if retval:
- raise RedirectException( 'all-projects', request.GET, mandatory_parameters )
-
- queryset_all = Project.objects.all()
-
- # annotate each project with its number of builds
- queryset_all = queryset_all.annotate(num_builds=Count('build'))
-
- # exclude the command line builds project if it has no builds
- q_default_with_builds = Q(is_default=True) & Q(num_builds__gt=0)
- queryset_all = queryset_all.filter(Q(is_default=False) |
- q_default_with_builds)
-
- # if in BUILD_MODE, exclude everything but the command line builds project
- if not toastermain.settings.BUILD_MODE:
- queryset_all = queryset_all.exclude(is_default=False)
-
- # boilerplate code that takes a request for an object type and returns a queryset
- # for that object type. copypasta for all needed table searches
- (filter_string, search_term, ordering_string) = _search_tuple(request, Project)
- queryset_with_search = _get_queryset(Project, queryset_all, None, search_term, ordering_string, '-updated')
- queryset = _get_queryset(Project, queryset_all, filter_string, search_term, ordering_string, '-updated')
-
- # retrieve the objects that will be displayed in the table; projects a paginator and gets a page range to display
- project_info = _build_page_range(Paginator(queryset, pagesize), request.GET.get('page', 1))
-
- # add fields needed in JSON dumps for API call support
- for p in project_info.object_list:
- p.id = p.pk
- p.projectPageUrl = reverse('project', args=(p.id,))
- p.layersTypeAheadUrl = reverse('xhr_layerstypeahead', args=(p.id,))
- p.recipesTypeAheadUrl = reverse('xhr_recipestypeahead', args=(p.id,))
- p.projectBuildsUrl = reverse('projectbuilds', args=(p.id,))
-
- # build view-specific information; this is rendered specifically in the builds page, at the top of the page (i.e. Recent builds)
- build_mru = _get_latest_builds()
-
- # translate the project's build target strings
- fstypes_map = {};
- for project in project_info:
- try:
- targets = Target.objects.filter( build_id = project.get_last_build_id() )
- comma = "";
- extensions = "";
- for t in targets:
- if ( not t.is_image ):
- continue
- tif = Target_Image_File.objects.filter( target_id = t.id )
- for i in tif:
- s=re.sub('.*tar.bz2', 'tar.bz2', i.file_name)
- if s == i.file_name:
- s=re.sub('.*\.', '', i.file_name)
- if None == re.search(s,extensions):
- extensions += comma + s
- comma = ", "
- fstypes_map[project.id]=extensions
- except (Target.DoesNotExist,IndexError):
- fstypes_map[project.id]=project.get_last_imgfiles
-
- context = {
- 'mru' : build_mru,
-
- 'objects' : project_info,
- 'objectname' : "projects",
- 'default_orderby' : 'id:-',
- 'search_term' : search_term,
- 'total_count' : queryset_with_search.count(),
- 'fstypes' : fstypes_map,
- 'build_FAILED' : Build.FAILED,
- 'build_SUCCEEDED' : Build.SUCCEEDED,
- 'tablecols': [
- {'name': 'Project',
- 'orderfield': _get_toggle_order(request, "name"),
- 'ordericon':_get_toggle_order_icon(request, "name"),
- 'orderkey' : 'name',
- },
- {'name': 'Last activity on',
- 'clclass': 'updated',
- 'qhelp': "Shows the starting date and time of the last project build. If the project has no builds, it shows the date the project was created",
- 'orderfield': _get_toggle_order(request, "updated", True),
- 'ordericon':_get_toggle_order_icon(request, "updated"),
- 'orderkey' : 'updated',
- },
- {'name': 'Release',
- 'qhelp' : "The version of the build system used by the project",
- 'orderfield': _get_toggle_order(request, "release__name"),
- 'ordericon':_get_toggle_order_icon(request, "release__name"),
- 'orderkey' : 'release__name',
- },
- {'name': 'Machine',
- 'qhelp': "The hardware currently selected for the project",
- },
- {'name': 'Number of builds',
- 'qhelp': "How many builds have been run for the project",
- },
- {'name': 'Last build outcome', 'clclass': 'loutcome',
- 'qhelp': "Tells you if the last project build completed successfully or failed",
- },
- {'name': 'Recipe', 'clclass': 'ltarget',
- 'qhelp': "The last recipe that was built in this project",
- },
- {'name': 'Errors', 'clclass': 'lerrors',
- 'qhelp': "How many errors were encountered during the last project build (if any)",
- },
- {'name': 'Warnings', 'clclass': 'lwarnings',
- 'qhelp': "How many warnigns were encountered during the last project build (if any)",
- },
- {'name': 'Image files', 'clclass': 'limagefiles', 'hidden': 1,
- 'qhelp': "The root file system types produced by the last project build",
- },
- ]
- }
-
- _set_parameters_values(pagesize, orderby, request)
- return context
+ return render(request, "unavailable_artifact.html")
+ except ObjectDoesNotExist, IOError:
+ return render(request, "unavailable_artifact.html")
diff --git a/yocto-poky/bitbake/lib/toaster/toastergui/widgets.py b/yocto-poky/bitbake/lib/toaster/toastergui/widgets.py
index 6bb388936..d2ef5d3db 100644
--- a/yocto-poky/bitbake/lib/toaster/toastergui/widgets.py
+++ b/yocto-poky/bitbake/lib/toaster/toastergui/widgets.py
@@ -38,11 +38,13 @@ import json
import collections
import operator
import re
+import urllib
import logging
logger = logging.getLogger("toaster")
from toastergui.views import objtojson
+from toastergui.tablefilter import TableFilterMap
class ToasterTable(TemplateView):
def __init__(self, *args, **kwargs):
@@ -52,10 +54,12 @@ class ToasterTable(TemplateView):
self.title = "Table"
self.queryset = None
self.columns = []
- self.filters = {}
+
+ # map from field names to Filter instances
+ self.filter_map = TableFilterMap()
+
self.total_count = 0
self.static_context_extra = {}
- self.filter_actions = {}
self.empty_state = "Sorry - no data found"
self.default_orderby = ""
@@ -65,7 +69,7 @@ class ToasterTable(TemplateView):
orderable=True,
field_name="id")
- # prevent HTTP caching of table data
+ # prevent HTTP caching of table data
@cache_control(must_revalidate=True, max_age=0, no_store=True, no_cache=True)
def dispatch(self, *args, **kwargs):
return super(ToasterTable, self).dispatch(*args, **kwargs)
@@ -107,26 +111,10 @@ class ToasterTable(TemplateView):
self.apply_search(search)
name = request.GET.get("name", None)
- if name is None:
- data = json.dumps(self.filters,
- indent=2,
- cls=DjangoJSONEncoder)
- else:
- for actions in self.filters[name]['filter_actions']:
- actions['count'] = self.filter_actions[actions['name']](count_only=True)
-
- # Add the "All" items filter action
- self.filters[name]['filter_actions'].insert(0, {
- 'name' : 'all',
- 'title' : 'All',
- 'count' : self.queryset.count(),
- })
-
- data = json.dumps(self.filters[name],
- indent=2,
- cls=DjangoJSONEncoder)
-
- return data
+ table_filter = self.filter_map.get_filter(name)
+ return json.dumps(table_filter.to_json(self.queryset),
+ indent=2,
+ cls=DjangoJSONEncoder)
def setup_columns(self, *args, **kwargs):
""" function to implement in the subclass which sets up the columns """
@@ -138,30 +126,13 @@ class ToasterTable(TemplateView):
""" function to implement in the subclass which sets up the queryset"""
pass
- def add_filter(self, name, title, filter_actions):
+ def add_filter(self, table_filter):
"""Add a filter to the table.
Args:
- name (str): Unique identifier of the filter.
- title (str): Title of the filter.
- filter_actions: Actions for all the filters.
+ table_filter: Filter instance
"""
- self.filters[name] = {
- 'title' : title,
- 'filter_actions' : filter_actions,
- }
-
- def make_filter_action(self, name, title, action_function):
- """ Utility to make a filter_action """
-
- action = {
- 'title' : title,
- 'name' : name,
- }
-
- self.filter_actions[name] = action_function
-
- return action
+ self.filter_map.add_filter(table_filter.name, table_filter)
def add_column(self, title="", help_text="",
orderable=False, hideable=True, hidden=False,
@@ -197,6 +168,24 @@ class ToasterTable(TemplateView):
'computation': computation,
})
+ def set_column_hidden(self, title, hidden):
+ """
+ Set the hidden state of the column to the value of hidden
+ """
+ for col in self.columns:
+ if col['title'] == title:
+ col['hidden'] = hidden
+ break
+
+ def set_column_hideable(self, title, hideable):
+ """
+ Set the hideable state of the column to the value of hideable
+ """
+ for col in self.columns:
+ if col['title'] == title:
+ col['hideable'] = hideable
+ break
+
def render_static_data(self, template, row):
"""Utility function to render the static data template"""
@@ -210,19 +199,35 @@ class ToasterTable(TemplateView):
return template.render(context)
- def apply_filter(self, filters, **kwargs):
+ def apply_filter(self, filters, filter_value, **kwargs):
+ """
+ Apply a filter submitted in the querystring to the ToasterTable
+
+ filters: (str) in the format:
+ '<filter name>:<action name>'
+ filter_value: (str) parameters to pass to the named filter
+
+ <filter name> and <action name> are used to look up the correct filter
+ in the ToasterTable's filter map; the <action params> are set on
+ TableFilterAction* before its filter is applied and may modify the
+ queryset returned by the filter
+ """
self.setup_filters(**kwargs)
try:
- filter_name, filter_action = filters.split(':')
+ filter_name, action_name = filters.split(':')
+ action_params = urllib.unquote_plus(filter_value)
except ValueError:
return
- if "all" in filter_action:
+ if "all" in action_name:
return
try:
- self.filter_actions[filter_action]()
+ table_filter = self.filter_map.get_filter(filter_name)
+ action = table_filter.get_action(action_name)
+ action.set_filter_params(action_params)
+ self.queryset = action.filter(self.queryset)
except KeyError:
# pass it to the user - programming error here
raise
@@ -251,13 +256,20 @@ class ToasterTable(TemplateView):
def get_data(self, request, **kwargs):
- """Returns the data for the page requested with the specified
- parameters applied"""
+ """
+ Returns the data for the page requested with the specified
+ parameters applied
+
+ filters: filter and action name, e.g. "outcome:build_succeeded"
+ filter_value: value to pass to the named filter+action, e.g. "on"
+ (for a toggle filter) or "2015-12-11,2015-12-12" (for a date range filter)
+ """
page_num = request.GET.get("page", 1)
limit = request.GET.get("limit", 10)
search = request.GET.get("search", None)
filters = request.GET.get("filter", None)
+ filter_value = request.GET.get("filter_value", "on")
orderby = request.GET.get("orderby", None)
nocache = request.GET.get("nocache", None)
@@ -289,7 +301,7 @@ class ToasterTable(TemplateView):
if search:
self.apply_search(search)
if filters:
- self.apply_filter(filters, **kwargs)
+ self.apply_filter(filters, filter_value, **kwargs)
if orderby:
self.apply_orderby(orderby)
diff --git a/yocto-poky/bitbake/lib/toaster/toastermain/management/commands/checksocket.py b/yocto-poky/bitbake/lib/toaster/toastermain/management/commands/checksocket.py
new file mode 100644
index 000000000..0399b8659
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastermain/management/commands/checksocket.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# ex:ts=4:sw=4:sts=4:et
+# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2015 Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""Custom management command checksocket."""
+
+import errno
+import socket
+
+from django.core.management.base import BaseCommand, CommandError
+from django.utils.encoding import force_text
+
+DEFAULT_ADDRPORT = "0.0.0.0:8000"
+
+class Command(BaseCommand):
+ """Custom management command."""
+
+ help = 'Check if Toaster can listen on address:port'
+
+ def add_arguments(self, parser):
+ parser.add_argument('addrport', nargs='?', default=DEFAULT_ADDRPORT,
+ help='ipaddr:port to check, %s by default' % \
+ DEFAULT_ADDRPORT)
+
+ def handle(self, *args, **options):
+ addrport = options['addrport']
+ if ':' not in addrport:
+ raise CommandError('Invalid addr:port specified: %s' % addrport)
+ splitted = addrport.split(':')
+ try:
+ splitted[1] = int(splitted[1])
+ except ValueError:
+ raise CommandError('Invalid port specified: %s' % splitted[1])
+ self.stdout.write('Check if toaster can listen on %s' % addrport)
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ sock.bind(tuple(splitted))
+ except (socket.error, OverflowError) as err:
+ errors = {
+ errno.EACCES: 'You don\'t have permission to access port %s' \
+ % splitted[1],
+ errno.EADDRINUSE: 'Port %s is already in use' % splitted[1],
+ errno.EADDRNOTAVAIL: 'IP address can\'t be assigned to',
+ }
+ if hasattr(err, 'errno') and err.errno in errors:
+ errtext = errors[err.errno]
+ else:
+ errtext = force_text(err)
+ raise CommandError(errtext)
+
+ self.stdout.write("OK")
diff --git a/yocto-poky/bitbake/lib/toaster/toastermain/management/commands/get-dburl.py b/yocto-poky/bitbake/lib/toaster/toastermain/management/commands/get-dburl.py
new file mode 100644
index 000000000..22b3eb79e
--- /dev/null
+++ b/yocto-poky/bitbake/lib/toaster/toastermain/management/commands/get-dburl.py
@@ -0,0 +1,9 @@
+from toastermain.settings import getDATABASE_URL
+from django.core.management.base import NoArgsCommand
+
+class Command(NoArgsCommand):
+ args = ""
+ help = "get database url"
+
+ def handle_noargs(self,**options):
+ print getDATABASE_URL()
diff --git a/yocto-poky/bitbake/lib/toaster/toastermain/settings.py b/yocto-poky/bitbake/lib/toaster/toastermain/settings.py
index b28ddb2b0..74ab60462 100644
--- a/yocto-poky/bitbake/lib/toaster/toastermain/settings.py
+++ b/yocto-poky/bitbake/lib/toaster/toastermain/settings.py
@@ -23,11 +23,6 @@
import os, re
-# Temporary toggle for Image customisation
-CUSTOM_IMAGE = False
-if os.environ.get("CUSTOM_IMAGE", None) is not None:
- CUSTOM_IMAGE = True
-
DEBUG = True
TEMPLATE_DEBUG = DEBUG
@@ -64,6 +59,7 @@ if 'sqlite' in DATABASES['default']['ENGINE']:
if 'DATABASE_URL' in os.environ:
dburl = os.environ['DATABASE_URL']
+
if dburl.startswith('sqlite3://'):
result = re.match('sqlite3://(.*)', dburl)
if result is None:
@@ -78,7 +74,7 @@ if 'DATABASE_URL' in os.environ:
}
elif dburl.startswith('mysql://'):
# URL must be in this form: mysql://user:pass@host:port/name
- result = re.match(r"mysql://([^:]*):([^@]*)@([^:]*):(\d+)/([^/]*)", dburl)
+ result = re.match(r"mysql://([^:]*):([^@]*)@([^:]*):(\d*)/([^/]*)", dburl)
if result is None:
raise Exception("ERROR: Could not read mysql database url: %s" % dburl)
DATABASES['default'] = {
@@ -92,9 +88,6 @@ if 'DATABASE_URL' in os.environ:
else:
raise Exception("FIXME: Please implement missing database url schema for url: %s" % dburl)
-BUILD_MODE = False
-if 'TOASTER_MANAGED' in os.environ and os.environ['TOASTER_MANAGED'] == "1":
- BUILD_MODE = True
# Allows current database settings to be exported as a DATABASE_URL environment variable value
@@ -231,7 +224,7 @@ CACHES = {
# },
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
- 'LOCATION': '/tmp/django-default-cache',
+ 'LOCATION': '/tmp/toaster_cache_%d' % os.getuid(),
'TIMEOUT': 1,
}
}
@@ -279,7 +272,6 @@ INSTALLED_APPS = (
'django.contrib.humanize',
'bldcollector',
'toastermain',
- 'south',
)
@@ -402,12 +394,3 @@ class InvalidString(str):
"Undefined variable or unknown value for: \"%s\"" % other)
TEMPLATE_STRING_IF_INVALID = InvalidString("%s")
-
-import sys
-sys.path.append(
- os.path.join(
- os.path.join(
- os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
- "contrib"),
- "django-aggregate-if-master")
- )
diff --git a/yocto-poky/bitbake/lib/toaster/toastermain/urls.py b/yocto-poky/bitbake/lib/toaster/toastermain/urls.py
index 6c4a953b4..534679dc5 100644
--- a/yocto-poky/bitbake/lib/toaster/toastermain/urls.py
+++ b/yocto-poky/bitbake/lib/toaster/toastermain/urls.py
@@ -45,7 +45,7 @@ urlpatterns = patterns('',
url(r'^orm/eventfile$', 'bldcollector.views.eventfile'),
# if no application is selected, we have the magic toastergui app here
- url(r'^$', never_cache(RedirectView.as_view(url='/toastergui/'))),
+ url(r'^$', never_cache(RedirectView.as_view(url='/toastergui/', permanent=True))),
)
import toastermain.settings
@@ -59,12 +59,11 @@ if toastermain.settings.DEBUG_PANEL_ENABLED:
urlpatterns.insert(1, url(r'', include(debug_toolbar.urls)))
#logger.info("Enabled django_toolbar extension")
+urlpatterns = [
+ # Uncomment the next line to enable the admin:
+ url(r'^admin/', include(admin.site.urls)),
+] + urlpatterns
-if toastermain.settings.BUILD_MODE:
- urlpatterns = [
- # Uncomment the next line to enable the admin:
- url(r'^admin/', include(admin.site.urls)),
- ] + urlpatterns
# Automatically discover urls.py in various apps, beside our own
# and map module directories to the patterns
diff --git a/yocto-poky/bitbake/toaster-requirements.txt b/yocto-poky/bitbake/toaster-requirements.txt
index 1d7d21b33..0e8c742cb 100644
--- a/yocto-poky/bitbake/toaster-requirements.txt
+++ b/yocto-poky/bitbake/toaster-requirements.txt
@@ -1,5 +1,4 @@
-Django==1.6
-South==0.8.4
+Django>1.8,<1.9
argparse==1.2.1
wsgiref==0.1.2
beautifulsoup4>=4.4.0
OpenPOWER on IntegriCloud