* [PATCH 01/11] toaster: clear up toaster shutdown for mac osx
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 02/11] toastergui: decrease load time for configuration page Alex DAMIAN
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel; +Cc: Alexander Kanevskiy
From: Alexander Kanevskiy <alexander.kanevskiy@intel.com>
This patch properly shuts down toaster in interactive mode
under Mac OSx.
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
bin/toaster | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/toaster b/bin/toaster
index 7907b57..792fb72 100755
--- a/bin/toaster
+++ b/bin/toaster
@@ -37,7 +37,7 @@ function webserverKillAll()
kill -SIGTERM -$(< ${pidfile}) 2>/dev/null
sleep 1;
# Kill processes if they are still running - may happen in interactive shells
- ps fux | grep "python.*manage.py runserver" | awk '{print $2}' | xargs kill
+ pkill -U $UID -f "python.*manage.py runserver"
done;
rm ${pidfile}
fi
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/11] toastergui: decrease load time for configuration page
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
2015-05-11 10:58 ` [PATCH 01/11] toaster: clear up toaster shutdown for mac osx Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 03/11] toaster: Make toaster script working in zsh Alex DAMIAN
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Ed Bartosh <ed.bartosh@linux.intel.com>
Used __in field lookup for QuerySet to get build variables faster.
[YOCTO #6691]
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
---
lib/toaster/toastergui/views.py | 46 ++++++++---------------------------------
1 file changed, 9 insertions(+), 37 deletions(-)
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 7e90926..e296cf6 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -1266,43 +1266,15 @@ def recipes(request, build_id):
def configuration(request, build_id):
template = 'configuration.html'
- variables = Variable.objects.filter(build=build_id)
-
- def _get_variable_or_empty(variable_name):
- from django.core.exceptions import ObjectDoesNotExist
- try:
- return variables.get(variable_name=variable_name).variable_value
- except ObjectDoesNotExist:
- return ''
-
- BB_VERSION=_get_variable_or_empty(variable_name='BB_VERSION')
- BUILD_SYS=_get_variable_or_empty(variable_name='BUILD_SYS')
- NATIVELSBSTRING=_get_variable_or_empty(variable_name='NATIVELSBSTRING')
- TARGET_SYS=_get_variable_or_empty(variable_name='TARGET_SYS')
- MACHINE=_get_variable_or_empty(variable_name='MACHINE')
- DISTRO=_get_variable_or_empty(variable_name='DISTRO')
- DISTRO_VERSION=_get_variable_or_empty(variable_name='DISTRO_VERSION')
- TUNE_FEATURES=_get_variable_or_empty(variable_name='TUNE_FEATURES')
- TARGET_FPU=_get_variable_or_empty(variable_name='TARGET_FPU')
-
- targets = Target.objects.filter(build=build_id)
-
- context = {
- 'objectname': 'configuration',
- 'object_search_display':'variables',
- 'filter_search_display':'variables',
- 'build': Build.objects.get(pk=build_id),
- 'BB_VERSION':BB_VERSION,
- 'BUILD_SYS':BUILD_SYS,
- 'NATIVELSBSTRING':NATIVELSBSTRING,
- 'TARGET_SYS':TARGET_SYS,
- 'MACHINE':MACHINE,
- 'DISTRO':DISTRO,
- 'DISTRO_VERSION':DISTRO_VERSION,
- 'TUNE_FEATURES':TUNE_FEATURES,
- 'TARGET_FPU':TARGET_FPU,
- 'targets':targets,
- }
+ var_names = ('BB_VERSION', 'BUILD_SYS', 'NATIVELSBSTRING', 'TARGET_SYS',
+ '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'))
+ context.update({'objectname': 'configuration',
+ 'object_search_display':'variables',
+ 'filter_search_display':'variables',
+ 'build': Build.objects.get(pk=build_id),
+ 'targets': Target.objects.filter(build=build_id)})
return render(request, template, context)
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/11] toaster: Make toaster script working in zsh
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
2015-05-11 10:58 ` [PATCH 01/11] toaster: clear up toaster shutdown for mac osx Alex DAMIAN
2015-05-11 10:58 ` [PATCH 02/11] toastergui: decrease load time for configuration page Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 04/11] toaster: Code cleanup: indent Alex DAMIAN
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Ed Bartosh <ed.bartosh@linux.intel.com>
Fixed shell syntax not understood by zsh. Made toaster
script to work for both shells in both modes: sourced and
directly called.
[YOCTO #6964]
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
---
bin/toaster | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/bin/toaster b/bin/toaster
index 792fb72..8568c13 100755
--- a/bin/toaster
+++ b/bin/toaster
@@ -63,7 +63,7 @@ function webserverStartAll()
retval=0
python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=1
fi
- if [ "x$TOASTER_MANAGED" == "x1" ]; then
+ if [ "$TOASTER_MANAGED" '==' '1' ]; then
python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol || retval=1
python $BBBASEDIR/lib/toaster/manage.py checksettings --traceback || retval=1
fi
@@ -97,7 +97,7 @@ INSTOPSYSTEM=0
function stop_system()
{
# prevent reentry
- if [ $INSTOPSYSTEM == 1 ]; then return; fi
+ if [ $INSTOPSYSTEM -eq 1 ]; then return; fi
INSTOPSYSTEM=1
if [ -f ${BUILDDIR}/.toasterui.pid ]; then
kill $(< ${BUILDDIR}/.toasterui.pid ) 2>/dev/null
@@ -119,7 +119,7 @@ function check_pidbyfile() {
function notify_chldexit() {
- if [ $NOTOASTERUI == 0 ]; then
+ if [ $NOTOASTERUI -eq 0 ]; then
check_pidbyfile ${BUILDDIR}/.toasterui.pid && return
stop_system
fi
@@ -143,8 +143,7 @@ function verify_prereq() {
# read command line parameters
-
-BBBASEDIR=`dirname ${BASH_SOURCE}`/..
+BBBASEDIR=`dirname ${BASH_SOURCE:-${(%):-%x}}`/..
RUNNING=0
NOTOASTERUI=0
@@ -168,8 +167,9 @@ for param in $*; do
esac
done
+[ -z "$ZSH_NAME" ] && SRCFILE=${BASH_SOURCE} || SRCFILE=$_
-if [ -z "$ZSH_NAME" ] && [ `basename \"$0\"` = `basename \"$BASH_SOURCE\"` ]; then
+if [ `basename \"$0\"` = `basename \"${SRCFILE}\"` ]; 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.
@@ -183,7 +183,7 @@ if [ -z "$ZSH_NAME" ] && [ `basename \"$0\"` = `basename \"$BASH_SOURCE\"` ]; th
exit 1;
fi
- if [ "x`which daemon`" == "x" ]; then
+ if ! which daemon >/dev/null 2>&1; then
echo -e "Failed dependency; toaster needs the 'daemon' program in order to be able to start builds'. Please install the 'daemon' program from your distribution repositories or http://www.libslack.org/daemon/" 1>&2;
exit 1;
fi
@@ -251,14 +251,14 @@ fi
# We make sure we're running in the current shell and in a good environment
-if [ -z "$BUILDDIR" ] || [ -z `which bitbake` ]; then
+if [ -z "$BUILDDIR" ] || ! which bitbake >/dev/null 2>&1 ; then
echo "Error: Build environment is not setup or bitbake is not in path." 1>&2;
return 2
fi
# Determine the action. If specified by arguments, fine, if not, toggle it
-if [ "x$1" == "xstart" ] || [ "x$1" == "xstop" ]; then
+if [ "$1" '==' 'start' ] || [ "$1" '==' 'stop' ]; then
CMD="$1"
else
if [ -z "$BBSERVER" ]; then
@@ -274,16 +274,16 @@ echo "The system will $CMD."
lock=1
if [ -e $BUILDDIR/bitbake.lock ]; then
- (flock -n 200 ) 200<$BUILDDIR/bitbake.lock || lock=0
+ 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
+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
+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
@@ -311,7 +311,7 @@ case $CMD in
echo "Bitbake server start failed"
else
export BBSERVER=0.0.0.0:-1
- if [ $NOTOASTERUI == 0 ]; then # we start the TOASTERUI only if not inhibited
+ 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
fi
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/11] toaster: Code cleanup: indent
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (2 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 03/11] toaster: Make toaster script working in zsh Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 05/11] toaster: fix typo in format string Alex DAMIAN
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Ed Bartosh <ed.bartosh@linux.intel.com>
Replaced tabs with 4 spaces.
Removed useless semicolons at the end of lines.
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
---
bin/toaster | 125 ++++++++++++++++++++++++++++++------------------------------
1 file changed, 62 insertions(+), 63 deletions(-)
diff --git a/bin/toaster b/bin/toaster
index 8568c13..f5ee68c 100755
--- a/bin/toaster
+++ b/bin/toaster
@@ -30,65 +30,65 @@
function webserverKillAll()
{
- local pidfile
- for pidfile in ${BUILDDIR}/.toastermain.pid; do
- if [ -f ${pidfile} ]; then
- while kill -0 $(< ${pidfile}) 2>/dev/null; do
- kill -SIGTERM -$(< ${pidfile}) 2>/dev/null
- sleep 1;
- # Kill processes if they are still running - may happen in interactive shells
- pkill -U $UID -f "python.*manage.py runserver"
- done;
- rm ${pidfile}
- fi
- done
+ local pidfile
+ for pidfile in ${BUILDDIR}/.toastermain.pid; do
+ if [ -f ${pidfile} ]; then
+ while kill -0 $(< ${pidfile}) 2>/dev/null; do
+ kill -SIGTERM -$(< ${pidfile}) 2>/dev/null
+ sleep 1
+ # Kill processes if they are still running - may happen in interactive shells
+ pkill -U $UID -f "python.*manage.py runserver"
+ done;
+ rm ${pidfile}
+ fi
+ done
}
function webserverStartAll()
{
- # do not start if toastermain points to a valid process
- if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then
- retval=1
- rm "${BUILDDIR}/.toastermain.pid"
- fi
+ # do not start if toastermain points to a valid process
+ if ! cat "${BUILDDIR}/.toastermain.pid" 2>/dev/null | xargs -I{} kill -0 {} ; then
+ retval=1
+ rm "${BUILDDIR}/.toastermain.pid"
+ fi
+ retval=0
+ python $BBBASEDIR/lib/toaster/manage.py syncdb || retval=1
+ python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=2
+ if [ $retval -eq 1 ]; then
+ echo "Failed db sync, stopping system start" 1>&2
+ elif [ $retval -eq 2 ]; then
+ echo -e "\nError on migration, trying to recover... \n"
+ python $BBBASEDIR/lib/toaster/manage.py migrate orm 0001_initial --fake
retval=0
- python $BBBASEDIR/lib/toaster/manage.py syncdb || retval=1
- python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=2
- if [ $retval -eq 1 ]; then
- echo "Failed db sync, stopping system start" 1>&2
- elif [ $retval -eq 2 ]; then
- echo -e "\nError on migration, trying to recover... \n"
- python $BBBASEDIR/lib/toaster/manage.py migrate orm 0001_initial --fake
- retval=0
- python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=1
- fi
- if [ "$TOASTER_MANAGED" '==' '1' ]; then
- python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol || retval=1
- python $BBBASEDIR/lib/toaster/manage.py checksettings --traceback || retval=1
- fi
- if [ $retval -eq 0 ]; then
- 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
- sleep 1
- if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then
- retval=1
- rm "${BUILDDIR}/.toastermain.pid"
- else
- echo "Webserver address: http://0.0.0.0:$WEB_PORT/"
- fi
+ python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=1
+ fi
+ if [ "$TOASTER_MANAGED" '==' '1' ]; then
+ python $BBBASEDIR/lib/toaster/manage.py migrate bldcontrol || retval=1
+ python $BBBASEDIR/lib/toaster/manage.py checksettings --traceback || retval=1
+ fi
+ if [ $retval -eq 0 ]; then
+ 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
+ sleep 1
+ if ! cat "${BUILDDIR}/.toastermain.pid" | xargs -I{} kill -0 {} ; then
+ retval=1
+ rm "${BUILDDIR}/.toastermain.pid"
+ else
+ echo "Webserver address: http://0.0.0.0:$WEB_PORT/"
fi
- return $retval
+ fi
+ return $retval
}
# Helper functions to add a special configuration file
function addtoConfiguration()
{
- file=$1
- shift
- echo "#Created by toaster start script" > ${BUILDDIR}/conf/$file
- for var in "$@"; do echo $var >> ${BUILDDIR}/conf/$file; done
+ file=$1
+ shift
+ echo "#Created by toaster start script" > ${BUILDDIR}/conf/$file
+ for var in "$@"; do echo $var >> ${BUILDDIR}/conf/$file; done
}
INSTOPSYSTEM=0
@@ -127,7 +127,7 @@ function notify_chldexit() {
function verify_prereq() {
- # Verify prerequisites
+ # 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
echo -e "This program needs Django 1.6. Please install with\n\npip install django==1.6\n"
@@ -174,25 +174,25 @@ if [ `basename \"$0\"` = `basename \"${SRCFILE}\"` ]; then
# Start just the web server, point the web browser to the interface, and start any Django services.
if ! verify_prereq; then
- echo -e "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;
+ echo -e "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
- echo -e "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." 1>&2;
- exit 1;
+ echo -e "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." 1>&2
+ exit 1
fi
if ! which daemon >/dev/null 2>&1; then
- echo -e "Failed dependency; toaster needs the 'daemon' program in order to be able to start builds'. Please install the 'daemon' program from your distribution repositories or http://www.libslack.org/daemon/" 1>&2;
- exit 1;
+ echo -e "Failed dependency; toaster needs the 'daemon' program in order to be able to start builds'. Please install the 'daemon' program from your distribution repositories or http://www.libslack.org/daemon/" 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 -e "Previous toaster run directory $BUILDDIR found, cowardly refusing to start. Please remove the directory when that toaster instance is over" 2>&1
- exit 1;
+ exit 1
fi
mkdir -p "$BUILDDIR"
@@ -219,14 +219,14 @@ if [ `basename \"$0\"` = `basename \"${SRCFILE}\"` ]; then
else
echo "No errors found, removing the run directory '$BUILDDIR'"
do_cleanup
- fi;
+ fi
}
TOASTER_MANAGED=1
export TOASTER_MANAGED=1
if [ $WEBSERVER -gt 0 ] && ! webserverStartAll; then
- echo "Failed to start the web server, stopping" 1>&2;
+ echo "Failed to start the web server, stopping" 1>&2
cleanup
- exit 1;
+ exit 1
fi
if [ $WEBSERVER -gt 0 ]; then
echo "Starting browser..."
@@ -245,14 +245,14 @@ fi
if ! verify_prereq; then
- echo -e "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;
- return 1;
+ echo -e "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
+ return 1
fi
# 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
- echo "Error: Build environment is not setup or bitbake is not in path." 1>&2;
+ echo "Error: Build environment is not setup or bitbake is not in path." 1>&2
return 2
fi
@@ -265,7 +265,7 @@ else
CMD="start"
else
CMD="stop"
- fi;
+ fi
fi
echo "The system will $CMD."
@@ -303,7 +303,7 @@ case $CMD in
unset BBSERVER
PREREAD=""
if [ -e ${BUILDDIR}/conf/toaster-pre.conf ]; then
- rm ${BUILDDIR}/conf/toaster-pre.conf
+ rm ${BUILDDIR}/conf/toaster-pre.conf
fi
bitbake $PREREAD --postread conf/toaster.conf --server-only -t xmlrpc -B 0.0.0.0:0
if [ $? -ne 0 ]; then
@@ -337,4 +337,3 @@ case $CMD in
;;
esac
-
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/11] toaster: fix typo in format string
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (3 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 04/11] toaster: Code cleanup: indent Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 06/11] toaster: <Add class id to a few columns> Alex DAMIAN
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Ed Bartosh <ed.bartosh@linux.intel.com>
Fixed TypeError: not all arguments converted during string formatting
[YOCTO #7618]
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
---
lib/toaster/orm/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index b9bb896..c00c352 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -52,7 +52,7 @@ class ToasterSetting(models.Model):
value = models.CharField(max_length=255)
def __unicode__(self):
- return "Setting %s = " % (self.name, self.value)
+ return "Setting %s = %s" % (self.name, self.value)
class ProjectManager(models.Manager):
def create_project(self, name, release):
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 00/11] Toaster patchset
@ 2015-05-11 10:58 Alex DAMIAN
2015-05-11 10:58 ` [PATCH 01/11] toaster: clear up toaster shutdown for mac osx Alex DAMIAN
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
Hello,
This a bug fixing patchset that cleans up the code and fixes some legacy issues,
partially refactors the URL structure for a cleaner appliance of REST principles,
and enables the code to passes tests under TTS.
Can you please pull at your convenience ?
Thank you,
Alex
The following changes since commit 3e12f4e8e3ec66d1df772a64be04b90ec72462ae:
prserv: serv.py: remove unused and duplicate imports (2015-05-08 17:46:25 +0100)
are available in the git repository at:
git://git.yoctoproject.org/poky-contrib adamian/20150511-submission-bb
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=adamian/20150511-submission-bb
Alexander Kanevskiy (1):
toaster: clear up toaster shutdown for mac osx
Alexandru DAMIAN (4):
toasterui: URL refactoring
toaster: adding art missing from Bootstrap
toastergui: fix whitespace after URL
toastergui: removing unused views
Ed Bartosh (5):
toastergui: decrease load time for configuration page
toaster: Make toaster script working in zsh
toaster: Code cleanup: indent
toaster: fix typo in format string
toastergui: Consider task name when restarting a build
Mihail Stanciu (1):
toaster: <Add class id to a few columns>
bin/toaster | 149 +++++++++---------
lib/toaster/orm/models.py | 2 +-
.../static/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes
.../toastergui/static/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes
lib/toaster/toastergui/static/js/projectapp.js | 2 +-
.../toastergui/templates/basetable_top_layers.html | 2 +-
lib/toaster/toastergui/templates/bpackage.html | 4 +-
lib/toaster/toastergui/templates/importlayer.html | 2 +-
lib/toaster/toastergui/templates/layer.html | 34 -----
lib/toaster/toastergui/templates/layerdetails.html | 8 +-
lib/toaster/toastergui/templates/layers.html | 14 +-
lib/toaster/toastergui/templates/machines.html | 4 +-
lib/toaster/toastergui/templates/package.html | 36 -----
lib/toaster/toastergui/templates/project.html | 24 +--
lib/toaster/toastergui/templates/recipes.html | 8 +-
lib/toaster/toastergui/templates/targets.html | 6 +-
lib/toaster/toastergui/templates/tasks.html | 8 +-
lib/toaster/toastergui/urls.py | 26 ++--
lib/toaster/toastergui/views.py | 169 ++++++---------------
19 files changed, 177 insertions(+), 321 deletions(-)
create mode 100644 lib/toaster/toastergui/static/img/glyphicons-halflings-white.png
create mode 100644 lib/toaster/toastergui/static/img/glyphicons-halflings.png
delete mode 100644 lib/toaster/toastergui/templates/layer.html
delete mode 100644 lib/toaster/toastergui/templates/package.html
--
1.9.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 06/11] toaster: <Add class id to a few columns>
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (4 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 05/11] toaster: fix typo in format string Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 07/11] toastergui: Consider task name when restarting a build Alex DAMIAN
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel; +Cc: Mihail Stanciu
From: Mihail Stanciu <stanciux.mihail@intel.com>
Added class ids to columns that were missing them in the Packages and Recipes pages. This is required for Toaster UI automation efforts.
[YOCTO #7377]
---
lib/toaster/toastergui/templates/bpackage.html | 4 ++--
lib/toaster/toastergui/templates/recipes.html | 8 ++++++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/lib/toaster/toastergui/templates/bpackage.html b/lib/toaster/toastergui/templates/bpackage.html
index 80229f9..6fbdc7b 100644
--- a/lib/toaster/toastergui/templates/bpackage.html
+++ b/lib/toaster/toastergui/templates/bpackage.html
@@ -60,9 +60,9 @@
<tr class="data">
<!-- Package -->
- <td><a href="{% url "package_built_detail" build.pk package.pk %}">{{package.name}}</a></td>
+ <td class="package_name"><a href="{% url "package_built_detail" build.pk package.pk %}">{{package.name}}</a></td>
<!-- Package Version -->
- <td>{%if package.version%}<a href="{% url "package_built_detail" build.pk package.pk %}">{{package.version}}-{{package.revision}}</a>{%endif%}</td>
+ <td class="package_version">{%if package.version%}<a href="{% url "package_built_detail" build.pk package.pk %}">{{package.version}}-{{package.revision}}</a>{%endif%}</td>
<!-- Package Size -->
<td class="size sizecol">{{package.size|filtered_filesizeformat}}</td>
<!-- License -->
diff --git a/lib/toaster/toastergui/templates/recipes.html b/lib/toaster/toastergui/templates/recipes.html
index 458d724..dc2d9e8 100644
--- a/lib/toaster/toastergui/templates/recipes.html
+++ b/lib/toaster/toastergui/templates/recipes.html
@@ -41,8 +41,12 @@
{% for recipe in objects %}
<tr class="data">
- <td><a href="{% url "recipe" build.pk recipe.pk %}">{{recipe.name}}</a></td>
- <td><a href="{% url "recipe" build.pk recipe.pk %}">{{recipe.version}}</a></td>
+ <td class="recipe__name">
+ <a href="{% url "recipe" build.pk recipe.pk %}">{{recipe.name}}</a>
+ </td>
+ <td class="recipe__version">
+ <a href="{% url "recipe" build.pk recipe.pk %}">{{recipe.version}}</a>
+ </td>
<!-- Depends -->
<td class="depends_on">
{% with deps=recipe_deps|get_dict_value:recipe.pk %}
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/11] toastergui: Consider task name when restarting a build
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (5 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 06/11] toaster: <Add class id to a few columns> Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 08/11] toasterui: URL refactoring Alex DAMIAN
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Ed Bartosh <ed.bartosh@linux.intel.com>
'Run again' button now restarts the build using target:task if task
was specified for the build.
[YOCTO #7442]
Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com>
---
lib/toaster/toastergui/static/js/projectapp.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/toaster/toastergui/static/js/projectapp.js b/lib/toaster/toastergui/static/js/projectapp.js
index 43436c5..a3309c7 100644
--- a/lib/toaster/toastergui/static/js/projectapp.js
+++ b/lib/toaster/toastergui/static/js/projectapp.js
@@ -357,7 +357,7 @@ projectApp.controller('prjCtrl', function($scope, $modal, $http, $interval, $loc
};
$scope.buildExistingTarget = function(targets) {
- $scope.buildTargetList(targets.map(function(v){return v.target;}));
+ $scope.buildTargetList(targets.map(function(v){return ((v.task) ? v.target + ":" + v.task : v.target);}));
};
$scope.buildTargetList = function(targetlist) {
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/11] toasterui: URL refactoring
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (6 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 07/11] toastergui: Consider task name when restarting a build Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 09/11] toaster: adding art missing from Bootstrap Alex DAMIAN
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
This is a URL refactoring needed to remove the inadvertent
usage of server-side user session in a REST-style API.
We move the parameters that were stored in the user session
to the URL, making navigation more robust.
This refactoring allows a clean (no 500 HTTP return codes) crawl
of the website following inside links.
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
.../toastergui/templates/basetable_top_layers.html | 2 +-
lib/toaster/toastergui/templates/importlayer.html | 2 +-
lib/toaster/toastergui/templates/layerdetails.html | 8 +-
lib/toaster/toastergui/templates/layers.html | 14 ++--
lib/toaster/toastergui/templates/machines.html | 4 +-
lib/toaster/toastergui/templates/project.html | 24 +++---
lib/toaster/toastergui/templates/targets.html | 6 +-
lib/toaster/toastergui/urls.py | 21 +++--
lib/toaster/toastergui/views.py | 94 +++++++++-------------
9 files changed, 80 insertions(+), 95 deletions(-)
diff --git a/lib/toaster/toastergui/templates/basetable_top_layers.html b/lib/toaster/toastergui/templates/basetable_top_layers.html
index bd6e7dd..722091b 100644
--- a/lib/toaster/toastergui/templates/basetable_top_layers.html
+++ b/lib/toaster/toastergui/templates/basetable_top_layers.html
@@ -1,5 +1,5 @@
{% extends "basetable_top.html" %}
{%block custombuttons %}
- <a class="btn" href="{% url 'importlayer' %}" style="margin-right:5px;">Import layer</a>
+ <a class="btn" href="{% url 'importlayer' project.id %}" style="margin-right:5px;">Import layer</a>
{%endblock%}
diff --git a/lib/toaster/toastergui/templates/importlayer.html b/lib/toaster/toastergui/templates/importlayer.html
index ed03b2e..d73c319 100644
--- a/lib/toaster/toastergui/templates/importlayer.html
+++ b/lib/toaster/toastergui/templates/importlayer.html
@@ -14,7 +14,7 @@
<script>
$(document).ready(function (){
var ctx = {
- layerDetailsUrl : "{% url 'base_layerdetails' %}",
+ layerDetailsUrl : "{% url 'base_layerdetails' project.id %}",
xhrImportLayerUrl : "{% url 'xhr_importlayer' %}",
};
diff --git a/lib/toaster/toastergui/templates/layerdetails.html b/lib/toaster/toastergui/templates/layerdetails.html
index 4b27d05..4d892d5 100644
--- a/lib/toaster/toastergui/templates/layerdetails.html
+++ b/lib/toaster/toastergui/templates/layerdetails.html
@@ -3,7 +3,7 @@
{% load humanize %}
{% load static %}
{% block localbreadcrumb %}
-<li><a href="{% url 'layers' %}">All compatible layers</a></li>
+<li><a href="{% url 'all-layers' project.id %}">All compatible layers</a></li>
<li>
{{layerversion.layer.name}} ({{layerversion.get_vcs_reference|truncatechars:13}})
</li>
@@ -17,7 +17,7 @@
$(document).ready(function (){
var ctx = {
projectBuildUrl : "{% url 'xhr_build' %}",
- layerDetailsUrl : "{% url 'base_layerdetails' %}",
+ layerDetailsUrl : "{% url 'base_layerdetails' project.id %}",
xhrUpdateLayerUrl : "{% url 'xhr_updatelayer' %}",
numTargets : {{total_targets}},
numMachines: {{machines|length}},
@@ -26,7 +26,7 @@
id : {{layerversion.id}},
commit: "{{layerversion.get_vcs_reference}}",
inCurrentPrj : {{layer_in_project}},
- url : "{% url 'layerdetails' layerversion.id %}",
+ url : "{% url 'layerdetails' project.id layerversion.id %}",
sourceId: {{layerversion.layer_source_id}},
}
};
@@ -164,7 +164,7 @@
{% for ld in layerversion.dependencies.all %}
<span class="current-value">
<li data-layer-id="{{ld.depends_on.id}}">
- <a data-toggle="tooltip" title="{{ld.depends_on.layer.vcs_url}} | {{ld.depends_on.get_vcs_reference}}" href="{% url 'layerdetails' ld.depends_on.id %}">{{ld.depends_on.layer.name}}</a>
+ <a data-toggle="tooltip" title="{{ld.depends_on.layer.vcs_url}} | {{ld.depends_on.get_vcs_reference}}" href="{% url 'layerdetails' project.id ld.depends_on.id %}">{{ld.depends_on.layer.name}}</a>
<span class="icon-trash " data-toggle="tooltip" title="Delete"></span>
</li>
</span>
diff --git a/lib/toaster/toastergui/templates/layers.html b/lib/toaster/toastergui/templates/layers.html
index 2367e7c..abad007 100644
--- a/lib/toaster/toastergui/templates/layers.html
+++ b/lib/toaster/toastergui/templates/layers.html
@@ -73,14 +73,14 @@
{% include "basetable_top_layers.html" %}
{% for o in objects %}
<tr class="data">
- <td class="layer"><a href="{% url 'layerdetails' o.id %}">{{o.layer.name}}</a></td>
+ <td class="layer"><a href="{% url 'layerdetails' project.id o.id %}">{{o.layer.name}}</a></td>
<td class="description">{% if o.layer.summary %}{{o.layer.summary}}{%endif%}</td>
- <td class="git-repo"><a href="{% url 'layerdetails' o.pk %}"><code>{{o.layer.vcs_url}}</code></a>
+ <td class="git-repo"><a href="{% url 'layerdetails' project.id o.pk %}"><code>{{o.layer.vcs_url}}</code></a>
{% if o.get_vcs_link_url %}
<a target="_blank" href="{{ o.get_vcs_link_url }}"><i class="icon-share get-info"></i></a>
{% endif %}
</td>
- <td class="git-subdir" style="display: table-cell;"><a href="{% url 'layerdetails' o.pk %}"><code>{{o.dirpath}}</code></a>
+ <td class="git-subdir" style="display: table-cell;"><a href="{% url 'layerdetails' project.id o.pk %}"><code>{{o.dirpath}}</code></a>
{% if o.dirpath and o.get_vcs_dirpath_link_url %}
<a target="_blank" href="{{ o.get_vcs_dirpath_link_url }}"><i class="icon-share get-info"></i></a>
{% endif %}
@@ -100,10 +100,10 @@
{% with ods=o.dependencies.all%}
{% if ods.count %}
<a class="btn"
- title="<a href='{% url "layerdetails" o.pk %}'>{{o.layer.name}}</a> dependencies"
+ title="<a href='{% url "layerdetails" project.id o.pk %}'>{{o.layer.name}}</a> dependencies"
data-content="<ul class='unstyled'>
{% for i in ods%}
- <li><a href='{% url "layerdetails" i.depends_on.pk %}'>{{i.depends_on.layer.name}}</a></li>
+ <li><a href='{% url "layerdetails" project.id i.depends_on.pk %}'>{{i.depends_on.layer.name}}</a></li>
{% endfor %}
</ul>">
{{ods.count}}
@@ -113,11 +113,11 @@
</td>
{% if project %}
<td class="add-del-layers" value="{{o.pk}}">
- <button class="btn btn-danger btn-block layer-exists-{{o.pk}} layerbtn" style="display:none;" data-layer='{ "id": {{o.pk}}, "name": "{{o.layer.name}}", "url": "{%url 'layerdetails' o.pk%}"}' data-directive="remove" >
+ <button class="btn btn-danger btn-block layer-exists-{{o.pk}} layerbtn" style="display:none;" data-layer='{ "id": {{o.pk}}, "name": "{{o.layer.name}}", "url": "{%url 'layerdetails' project.id o.pk%}"}' data-directive="remove" >
<i class="icon-trash"></i>
Delete layer
</button>
- <button class="btn btn-block layer-add-{{o.pk}} layerbtn" data-layer='{ "id": {{o.pk}}, "name": "{{o.layer.name}}", "url": "{%url 'layerdetails' o.pk%}"}' data-directive="add">
+ <button class="btn btn-block layer-add-{{o.pk}} layerbtn" data-layer='{ "id": {{o.pk}}, "name": "{{o.layer.name}}", "url": "{%url 'layerdetails' project.id o.pk%}"}' data-directive="add">
<i class="icon-plus"></i>
Add layer
</button>
diff --git a/lib/toaster/toastergui/templates/machines.html b/lib/toaster/toastergui/templates/machines.html
index d116a45..4a09862 100644
--- a/lib/toaster/toastergui/templates/machines.html
+++ b/lib/toaster/toastergui/templates/machines.html
@@ -69,12 +69,12 @@
<tr class="data">
<td class="machine">{{o.name}}</td>
<td class="description">{{o.description}}</td>
- <td class="layer"><a href="{%url "layerdetails" o.layer_version.id %}">{{o.layer_version.layer.name}}</a></td>
+ <td class="layer"><a href="{%url "layerdetails" project.id o.layer_version.id %}">{{o.layer_version.layer.name}}</a></td>
<td class="branch">{{o.layer_version.get_vcs_reference}}</td>
<td class="machinefile"><code>/machine/conf/{{o.name}}.conf</code><a href="{{o.get_vcs_machine_file_link_url}}" target="_blank"><i class="icon-share get-info"></i></a></td>
<td class="select-or-add" style="height: 32px;">
<a href="{% url 'project' project.id %}#/machineselect={{o.name}}" class="btn btn-block layer-exists-{{o.layer_version.id}}" style="margin-top: 5px; display:none">Select machine</a>
- <button class="btn btn-block layerbtn layer-add-{{o.layer_version.id}}" data-layer='{ "id": {{o.layer_version.id}}, "name": "{{o.layer_version.layer.name}}", "url": "{%url 'layerdetails' o.layer_version.id %}"}' data-directive="add">
+ <button class="btn btn-block layerbtn layer-add-{{o.layer_version.id}}" data-layer='{ "id": {{o.layer_version.id}}, "name": "{{o.layer_version.layer.name}}", "url": "{%url 'layerdetails' project.id o.layer_version.id %}"}' data-directive="add">
<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 {{o.layer_version.layer.name}} layer to your project"></i></i>
diff --git a/lib/toaster/toastergui/templates/project.html b/lib/toaster/toastergui/templates/project.html
index 5f8f4d1..85a1b16 100644
--- a/lib/toaster/toastergui/templates/project.html
+++ b/lib/toaster/toastergui/templates/project.html
@@ -24,7 +24,7 @@ vim: expandtab tabstop=2
<p>Toaster has no layer information. Without layer information, you cannot run builds. To generate layer information you can:</p>
<ul>
<li> <a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">Configure a layer source</a></li>
- <li> <a href="{% url 'importlayer' %}">Import a layer</a></li>
+ <li> <a href="{% url 'importlayer' project.id %}">Import a layer</a></li>
</ul>
</div>
@@ -111,7 +111,7 @@ vim: expandtab tabstop=2
</div>
<i class="icon-question-sign get-help get-help-blue" 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 a recipe name, like so: <code>core-image-minimal:do_build</code>"></i>
<p>
- <a href="{% url 'all-targets' %}">View all compatible recipes</a>
+ <a href="{% url 'all-targets' project.id %}">View all compatible recipes</a>
<i class="icon-question-sign get-help get-help-blue heading-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i>
{% if completedbuilds.count %}
| <a href="{% url 'projectbuilds' project.id %}">View all project builds ({{completedbuilds.count}})</a>
@@ -278,8 +278,8 @@ vim: expandtab tabstop=2
<p>
You can:
<ul>
- <li> <a href="{% url 'layers'%}">View all compatible layers available in Toaster</a>
- <li> <a href="{% url 'importlayer' %}">Import a layer</a>
+ <li> <a href="{% url 'all-layers' project.id %}">View all compatible layers available in Toaster</a>
+ <li> <a href="{% url 'importlayer' project.id %}">Import a layer</a>
<li> <a href="https://www.yoctoproject.org/docs/1.6.1/dev-manual/dev-manual.html#understanding-and-creating-layers" target="_blank">Read about layers in the manual</a>
</ul>
Or type a layer name below.
@@ -293,10 +293,10 @@ vim: expandtab tabstop=2
{% csrf_token %}
</form>
<p>
- <a href="{% url 'layers' %}">View all compatible layers</a>
+ <a href="{% url 'all-layers' project.id %}">View all compatible layers</a>
<i class="icon-question-sign get-help" title="View all the layers you can build with the release selected for this project, which is {[project.release.desc]}"></i>
|
- <a href="{% url 'importlayer' %}">Import layer</a></p>
+ <a href="{% url 'importlayer' project.id %}">Import layer</a></p>
<ul class="unstyled configuration-list">
<li ng-repeat="l in layers track by l.id" class="animate-repeat">
<a href="{[l.layerdetailurl]}" class="layer-info" data-toggle="tooltip" tooltip-placement="right" tooltip="{[l.giturl]} | {[l.branch.name]}">{[l.name]}</a>
@@ -321,7 +321,7 @@ vim: expandtab tabstop=2
{% csrf_token %}
</form>
<p>
- <a href="{% url 'all-targets' %}">View all compatible recipes</a>
+ <a href="{% url 'all-targets' project.id %}">View all compatible recipes</a>
<i class="icon-question-sign get-help" title="View all the recipes you can build with the release selected for this project, which is {[project.release.desc]}"></i>
</p>
<div ng-if="frequenttargets.length">
@@ -361,7 +361,7 @@ vim: expandtab tabstop=2
{% csrf_token %}
</form>
<p>
- <a href="{% url 'machines' %}" class="link">View all compatible machines</a>
+ <a href="{% url 'all-machines' project.id %}" class="link">View all compatible machines</a>
<i class="icon-question-sign get-help" title="View all the machines you can set with the release selected for this project, which is {[project.release.desc]}"></i>
</p>
</div>
@@ -432,10 +432,10 @@ angular.element(document).ready(function() {
scope.urls.xhr_build = "{% url 'xhr_projectbuild' project.id %}";
scope.urls.xhr_edit = "{% url 'xhr_projectedit' project.id %}";
scope.urls.xhr_datatypeahead = "{% url 'xhr_datatypeahead' %}";
- scope.urls.layers = "{% url 'layers' %}";
- scope.urls.targets = "{% url 'all-targets' %}";
- scope.urls.importlayer = "{% url 'importlayer'%}";
- scope.urls.layer = "{% url 'base_layerdetails' %}";
+ scope.urls.layers = "{% url 'all-layers' project.id %}";
+ scope.urls.targets = "{% url 'all-targets' project.id %}";
+ scope.urls.importlayer = "{% url 'importlayer' project.id %}";
+ scope.urls.layer = "{% url 'base_layerdetails' project.id %}";
scope.project = {{prj|json}};
scope.builds = {{builds|json}};
scope.layers = {{layers|json}};
diff --git a/lib/toaster/toastergui/templates/targets.html b/lib/toaster/toastergui/templates/targets.html
index 903e841..dc2cef6 100644
--- a/lib/toaster/toastergui/templates/targets.html
+++ b/lib/toaster/toastergui/templates/targets.html
@@ -62,7 +62,7 @@
<p>Toaster has no recipe information. To generate recipe information you can:</p>
<ul>
<li><a href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html#layer-source">Configure a layer source</a></li>
- <li><a href="{% url 'importlayer' %}">Import a layer</a>, then run a build</li>
+ <li><a href="{% url 'importlayer' project.id %}">Import a layer</a>, then run a build</li>
</ul>
</div>
{% endif %}
@@ -84,7 +84,7 @@
</td>
<td class="target-section">{{o.section}}</td>
<td class="license">{{o.license}}</td>
- <td class="layer"><a href="{% url 'layerdetails' o.preffered_layerversion.id%}">{{o.preffered_layerversion.layer.name}}</a></td>
+ <td class="layer"><a href="{% url 'layerdetails' project.id o.preffered_layerversion.id%}">{{o.preffered_layerversion.layer.name}}</a></td>
<td class="branch">
{% if o.preffered_layerversion.up_branch %}
{{o.preffered_layerversion.up_branch.name}}
@@ -101,7 +101,7 @@
<a href="{% url 'project' project.id %}#/targetbuild={{o.name}}" class="btn btn-block layer-exists-{{o.preffered_layerversion.pk}}" style="display:none; margin-top: 5px;" >
Build recipe
</a>
- <button class="btn btn-block layerbtn layer-add-{{o.preffered_layerversion.pk}}" data-layer='{ "id": {{o.preffered_layerversion.pk}}, "name": "{{o.preffered_layerversion.layer.name}}", "url": "{%url 'layerdetails' o.preffered_layerversion.pk%}"}' data-directive="add">
+ <button class="btn btn-block layerbtn layer-add-{{o.preffered_layerversion.pk}}" data-layer='{ "id": {{o.preffered_layerversion.pk}}, "name": "{{o.preffered_layerversion.layer.name}}", "url": "{%url 'layerdetails' project.id o.preffered_layerversion.pk%}"}' data-directive="add">
<i class="icon-plus"></i>
Add layer
<i title="" class="icon-question-sign get-help" data-original-title="To build this target, you must first add the {{o.preffered_layerversion.layer.name}} layer to your project"></i></i>
diff --git a/lib/toaster/toastergui/urls.py b/lib/toaster/toastergui/urls.py
index 76357e3..52fc0cc 100644
--- a/lib/toaster/toastergui/urls.py
+++ b/lib/toaster/toastergui/urls.py
@@ -76,20 +76,25 @@ urlpatterns = patterns('toastergui.views',
# project URLs
url(r'^newproject/$', 'newproject', name='newproject'),
- url(r'^importlayer/$', 'importlayer', name='importlayer'),
- url(r'^layers/$', 'layers', name='layers'),
- url(r'^layer/(?P<layerid>\d+)/$', 'layerdetails', name='layerdetails'),
- url(r'^layer/$', lambda x: HttpResponseBadRequest(), name='base_layerdetails'),
- url(r'^targets/$', 'targets', name='all-targets'),
- url(r'^machines/$', 'machines', name='machines'),
url(r'^projects/$', 'projects', name='all-projects'),
url(r'^project/$', lambda x: HttpResponseBadRequest(), name='base_project'),
- url(r'^project/(?P<pid>\d+)/$', 'project', name='project'),
+
+ 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/$', 'projectbuilds', name='projectbuilds'),
+
+ url(r'^project/(?P<pid>\d+)/layers/$', 'layers', name='all-layers'),
+ url(r'^project/(?P<pid>\d+)/layer/(?P<layerid>\d+)$', 'layerdetails', name='layerdetails'),
+ url(r'^project/(?P<pid>\d+)/layer/$', lambda x: HttpResponseBadRequest(), name='base_layerdetails'),
+
+ # the import layer is a project-specific functionality;
+ url(r'^project/(?P<pid>\d+)/importlayer$', 'importlayer', name='importlayer'),
+
+ url(r'^project/(?P<pid>\d+)/targets/$', 'targets', name='all-targets'),
+ url(r'^project/(?P<pid>\d+)/machines/$', 'machines', name='all-machines'),
url(r'^xhr_build/$', 'xhr_build', name='xhr_build'),
url(r'^xhr_projectbuild/(?P<pid>\d+)/$', 'xhr_projectbuild', name='xhr_projectbuild'),
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index e296cf6..23025a2 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -1806,6 +1806,20 @@ def package_included_reverse_dependencies(request, build_id, target_id, package_
def image_information_dir(request, build_id, target_id, packagefile_id):
# stubbed for now
return redirect(builds)
+ # the context processor that supplies data used across all the pages
+
+
+def managedcontextprocessor(request):
+ import subprocess
+ ret = {
+ "projects": Project.objects.all(),
+ "MANAGED" : toastermain.settings.MANAGED,
+ "DEBUG" : toastermain.settings.DEBUG,
+ "TOASTER_BRANCH": toastermain.settings.TOASTER_BRANCH,
+ "TOASTER_REVISION" : toastermain.settings.TOASTER_REVISION,
+ }
+ return ret
+
import toastermain.settings
@@ -1827,23 +1841,6 @@ if toastermain.settings.MANAGED:
class BadParameterException(Exception): pass # error thrown on invalid POST requests
- # the context processor that supplies data used across all the pages
- def managedcontextprocessor(request):
- import subprocess
- ret = {
- "projects": Project.objects.all(),
- "MANAGED" : toastermain.settings.MANAGED,
- "DEBUG" : toastermain.settings.DEBUG,
- "TOASTER_BRANCH": toastermain.settings.TOASTER_BRANCH,
- "TOASTER_REVISION" : toastermain.settings.TOASTER_REVISION,
- }
- if 'project_id' in request.session:
- try:
- ret['project'] = Project.objects.get(pk = request.session['project_id'])
- except Project.DoesNotExist:
- del request.session['project_id']
- return ret
-
class InvalidRequestException(Exception):
def __init__(self, response):
@@ -2176,7 +2173,7 @@ if toastermain.settings.MANAGED:
puser = None
# we use implicit knowledge of the current user's project to filter layer information, e.g.
- request.session['project_id'] = prj.id
+ pid = prj.id
from collections import Counter
freqtargets = []
@@ -2201,7 +2198,7 @@ if toastermain.settings.MANAGED:
"name" : x.layercommit.layer.name,
"giturl": x.layercommit.layer.vcs_url,
"url": x.layercommit.layer.layer_index_url,
- "layerdetailurl": reverse("layerdetails", args=(x.layercommit.pk,)),
+ "layerdetailurl": reverse("layerdetails", args=(prj.id, x.layercommit.pk,)),
# This branch name is actually the release
"branch" : { "name" : x.layercommit.get_vcs_reference(), "layersource" : x.layercommit.up_branch.layer_source.name if x.layercommit.up_branch != None else None}},
prj.projectlayer_set.all().order_by("id")),
@@ -2237,7 +2234,7 @@ if toastermain.settings.MANAGED:
try:
if request.method != "POST":
raise BadParameterException("invalid method")
- request.session['project_id'] = pid
+ pid = pid
prj = Project.objects.get(id = pid)
@@ -2326,7 +2323,7 @@ if toastermain.settings.MANAGED:
# return all project settings
return HttpResponse(jsonfilter( {
"error": "ok",
- "layers" : map(lambda x: {"id": x.layercommit.pk, "orderid" : x.pk, "name" : x.layercommit.layer.name, "giturl" : x.layercommit.layer.vcs_url, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(x.layercommit.pk,)), "branch" : { "name" : x.layercommit.get_vcs_reference(), "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all().select_related("layer").order_by("id")),
+ "layers" : map(lambda x: {"id": x.layercommit.pk, "orderid" : x.pk, "name" : x.layercommit.layer.name, "giturl" : x.layercommit.layer.vcs_url, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(prj.id, x.layercommit.pk,)), "branch" : { "name" : x.layercommit.get_vcs_reference(), "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all().select_related("layer").order_by("id")),
"builds" : _project_recent_build_list(prj),
"variables": map(lambda x: (x.name, x.value), prj.projectvariable_set.all()),
"machine": {"name": prj.projectvariable_set.get(name="MACHINE").value},
@@ -2344,8 +2341,6 @@ if toastermain.settings.MANAGED:
prj = None
if request.GET.has_key('project_id'):
prj = Project.objects.get(pk = request.GET['project_id'])
- elif 'project_id' in request.session:
- prj = Project.objects.get(pk = request.session['project_id'])
else:
raise Exception("No valid project selected")
@@ -2389,8 +2384,6 @@ if toastermain.settings.MANAGED:
# returns layer versions that would be deleted on the new release__pk
if request.GET['type'] == "versionlayers":
- if not 'project_id' in request.session:
- raise Exception("This call cannot makes no sense outside a project context")
retval = []
for i in prj.projectlayer_set.all():
@@ -2689,16 +2682,15 @@ if toastermain.settings.MANAGED:
- def importlayer(request):
+ def importlayer(request, pid):
template = "importlayer.html"
context = {
+ 'project': Project.objects.get(id=pid),
}
return render(request, template, context)
- def layers(request):
- if not 'project_id' in request.session:
- raise Exception("invalid page: cannot show page without a project")
+ def layers(request, pid):
template = "layers.html"
# define here what parameters the view needs in the GET portion in order to
@@ -2708,13 +2700,13 @@ if toastermain.settings.MANAGED:
mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby };
retval = _verify_parameters( request.GET, mandatory_parameters )
if retval:
- return _redirect_parameters( 'layers', request.GET, mandatory_parameters)
+ return _redirect_parameters( 'all-layers', request.GET, mandatory_parameters, pid=pid)
# 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, Layer_Version)
- prj = Project.objects.get(pk = request.session['project_id'])
+ prj = Project.objects.get(pk = pid)
queryset_all = prj.compatible_layerversions()
@@ -2729,6 +2721,7 @@ if toastermain.settings.MANAGED:
context = {
+ 'project' : prj,
'projectlayerset' : jsonfilter(map(lambda x: x.layercommit.id, prj.projectlayer_set.all())),
'objects' : layer_info,
'objectname' : "layers",
@@ -2773,7 +2766,7 @@ if toastermain.settings.MANAGED:
return response
- def layerdetails(request, layerid):
+ def layerdetails(request, pid, layerid):
template = "layerdetails.html"
limit = 10
@@ -2806,8 +2799,9 @@ if toastermain.settings.MANAGED:
machines = _build_page_range(Paginator(machines_query.order_by("name"), limit), request.GET.get('mpage', 1))
context = {
+ 'project' : Project.objects.get(pk=pid),
'layerversion': layer_version,
- 'layer_in_project' : ProjectLayer.objects.filter(project_id=request.session['project_id'],layercommit=layerid).count(),
+ 'layer_in_project' : ProjectLayer.objects.filter(project_id=pid,layercommit=layerid).count(),
'machines': machines,
'targets': targets,
'total_targets': Recipe.objects.filter(layer_version=layer_version).count(),
@@ -2816,19 +2810,16 @@ if toastermain.settings.MANAGED:
}
return render(request, template, context)
- def targets(request):
- if not 'project_id' in request.session:
- raise Exception("invalid page: cannot show page without a project")
-
+ def targets(request, pid):
template = 'targets.html'
(pagesize, orderby) = _get_parameters_values(request, 100, 'name:+')
mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby }
retval = _verify_parameters( request.GET, mandatory_parameters )
if retval:
- return _redirect_parameters( 'all-targets', request.GET, mandatory_parameters)
+ return _redirect_parameters( 'all-targets', request.GET, mandatory_parameters, pid = pid)
(filter_string, search_term, ordering_string) = _search_tuple(request, Recipe)
- prj = Project.objects.get(pk = request.session['project_id'])
+ prj = Project.objects.get(pk = pid)
queryset_all = Recipe.objects.filter(Q(layer_version__up_branch__name= prj.release.name) | Q(layer_version__build__in = prj.build_set.all())).filter(name__regex=r'.{1,}.*')
queryset_with_search = _get_queryset(Recipe, queryset_all, None, search_term, ordering_string, '-name')
@@ -2854,6 +2845,7 @@ if toastermain.settings.MANAGED:
e.vcs_link_url = e.vcs_link_url.replace('%branch%', e.preffered_layerversion.up_branch.name)
context = {
+ 'project' : prj,
'projectlayerset' : jsonfilter(map(lambda x: x.layercommit.id, prj.projectlayer_set.all().select_related("layercommit"))),
'objects' : target_info,
'objectname' : "recipes",
@@ -2916,10 +2908,7 @@ if toastermain.settings.MANAGED:
return response
- def machines(request):
- if not 'project_id' in request.session:
- raise Exception("invalid page: cannot show page without a project")
-
+ def machines(request, pid):
template = "machines.html"
# 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
@@ -2928,13 +2917,13 @@ if toastermain.settings.MANAGED:
mandatory_parameters = { 'count': pagesize, 'page' : 1, 'orderby' : orderby };
retval = _verify_parameters( request.GET, mandatory_parameters )
if retval:
- return _redirect_parameters( 'machines', request.GET, mandatory_parameters)
+ return _redirect_parameters( 'all-machines', request.GET, mandatory_parameters, pid = pid)
# 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, Machine)
- prj = Project.objects.get(pk = request.session['project_id'])
+ prj = Project.objects.get(pk = pid)
compatible_layers = prj.compatible_layerversions()
queryset_all = Machine.objects.filter(layer_version__in=compatible_layers)
@@ -2946,7 +2935,7 @@ if toastermain.settings.MANAGED:
# Make sure we only show machines / layers which are compatible
# with the current project
- project_layers = ProjectLayer.objects.filter(project_id=request.session['project_id']).values_list('layercommit',flat=True)
+ project_layers = ProjectLayer.objects.filter(project_id=pid).values_list('layercommit',flat=True)
# Now we need to weed out the layers which will appear as duplicated
# because they're from a layer source which doesn't need to be used
@@ -2958,6 +2947,7 @@ if toastermain.settings.MANAGED:
machine_info = _build_page_range(Paginator(queryset_all, request.GET.get('count', 100)),request.GET.get('page', 1))
context = {
+ 'project': prj,
'objects' : machine_info,
'projectlayerset' : jsonfilter(map(lambda x: x.layercommit.id, prj.projectlayer_set.all())),
'objectname' : "machines",
@@ -3041,6 +3031,7 @@ if toastermain.settings.MANAGED:
configvars = configvars.exclude(name = var)
context = {
+ 'project': prj,
'configvars': configvars,
'vars_managed': vars_managed,
'vars_fstypes': vars_fstypes,
@@ -3316,17 +3307,6 @@ if toastermain.settings.MANAGED:
else:
- # these are pages that are NOT available in interactive mode
- def managedcontextprocessor(request):
- return {
- "projects": [],
- "MANAGED" : toastermain.settings.MANAGED,
- "DEBUG" : toastermain.settings.DEBUG,
- "TOASTER_BRANCH": toastermain.settings.TOASTER_BRANCH,
- "TOASTER_REVISION" : toastermain.settings.TOASTER_REVISION,
- }
-
-
# shows the "all builds" page for interactive mode; this is the old code, simply moved
def builds(request):
template = 'build.html'
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/11] toaster: adding art missing from Bootstrap
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (7 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 08/11] toasterui: URL refactoring Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 10/11] toastergui: fix whitespace after URL Alex DAMIAN
2015-05-11 10:58 ` [PATCH 11/11] toastergui: removing unused views Alex DAMIAN
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
When Bootstrap 2.3 was imported, we missed a couple of art file.
This patch adds them to complete Bootstrap integrity.
License used is (as previously documented).
GLYPHICONS Halflings released with Bootstrap, CC BY 3.0
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
.../static/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes
.../toastergui/static/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 lib/toaster/toastergui/static/img/glyphicons-halflings-white.png
create mode 100644 lib/toaster/toastergui/static/img/glyphicons-halflings.png
diff --git a/lib/toaster/toastergui/static/img/glyphicons-halflings-white.png b/lib/toaster/toastergui/static/img/glyphicons-halflings-white.png
new file mode 100644
index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae
GIT binary patch
literal 8777
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
B7G?kd
literal 0
HcmV?d00001
diff --git a/lib/toaster/toastergui/static/img/glyphicons-halflings.png b/lib/toaster/toastergui/static/img/glyphicons-halflings.png
new file mode 100644
index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643
GIT binary patch
literal 12799
zcma*OWmH^Ivn@*S;K3nSf_t!#;0f+&pm7Po8`nk}2q8f5;M%x$<L>SdAkd9FAvlc$
zx660V9e3Ox@4WZ^?7jZ%QFGU-T~%||Ug4iK6bbQY@zBuF2$hxOw9wF=A)nUSxR_5@
zEX>HBryGrjyuOFFv$Y4<+|3H@gQfEqD<)+}a~mryD|1U9*I_FOG&F%+Ww{SJ-V2BR
zjt<81Ek$}Yb*95D4RS0HCps|uLyovt;P05hchQb-u2bzLtmog&f2}1VlNhxXV);S9
zM2buBg~!q9PtF)&KGRgf3#z7B(hm5WlNClaCWFs!-P!4-u*u5+=+D|ZE9e`KvhTHT
zJBnLwGM%!u&vlE%1ytJ=!xt~y_YkFLQb6bS!E+s8l7PiPGSt9xrmg?LV&&SL?J~cI
zS(e9TF1?SGyh+M_p@o1dyWu7o7_6p;N6hO!;4~<t3w3SV570<|$VWNPP~TbX3|=X>
z2B`I;y`;$ZdtBpvK5%oQ^p4eR2L)BH>B$FQeC*t)c`L71gXHPUa|vyu`Bnz)H$Z<N
z7UVAHFsR+HLO+(tK~=M@pM7ZMPj5gkz>cXGve(}XvR!+*8a>BLV;+ryG1kt0=)ytl
zNJxFUN{V7P?#|Cp85QTa@(*Q3%K-R(Pkv1N8YU*(d(Y}9?PQ(j<e|z%-Bnrh*J1R%
z%JAF*cdp#Zk#h09fv12$TuGUsX=V-wgNcEGe0hhp%mK8EVPi6@!a;xi$k!wcIO|bJ
zPx8DZ*0Y(ggKhnp2=Ax#f<wKp{=pA29>;NzWoEVWRD-~H$=f>j<LsfOZ;WLF*F0cm
z9PSRSlSFQE>9~PN^BM2okI(gY-&_&BCV6RP&I$FnSEM3d=0fCxbxA6~l>54-upTrw
zYgX@%m>jsSGi`0cQt6b8cX~+02IghVlNblR7eI;0ps}mpWUcxty1yG56C5rh%ep(X
z?)#2d?C<4t-KLc*EAn>>M8%HvC1TyBSoPNg(4id~H8JwO#I)Bf;N*y6ai6K9_bA`4
z_g9(-R;qyH&6I$`b<fg~;S@}+8_8-ItZ!TS<!|pei*+CWiVH?M1CEFM{ij_eP4dL+
zsn%eDn^Kp7vLEn|Dq0`Wt&GpZ?eq^%pqXVR^PA!ZyoGLI7ihDaWiNi$M6h)PNwvHR
zEcA82H5fM6RnpZ!R872>42v|0V3Z8IXN*p*8g$gE98+JpXNY+jXxU0zsR^W$#V=KP
z3AEFp@OL}WqwOfsV<)A^UTF4&HF1vQecz?LWE@p^Z2){=KEC_3Iopx_eS42>DeiDG
zWMXGbYfG~W7C8s@@m<_?#Gqk;!&)_Key@^0xJxrJahv{B&{^!>TV7TEDZlP|$=ZCz
zmX=ZWtt4QZK<Y>x**)lQQoW8y-XLiOQy#T`2t}p6l*S`68ojyH@UXJ-b~@tN`WpjF
z%7%Yzv807gsO!v=!(2uR)16!&U5~VPrPHtGzUU?2w(b1Xchq}(5<TwC<%h0ow%K}h
zTlz}37c^dc?7rEmt7Zy9#q|V+5bE1c06?X{e~%TDZ!@uG_uU!n6VJy=odWKS?p#j?
zn;v){i#`+1X;Ls^(9p!?42vli(fu1D-%nf?-3VKCs1JT^-;{Pg82EGZ&|T}A#wtP(
zR^df|3P4JZ0|weuCV=JopL6MLvYycbd;-Xx_r)Hm1~(2>Ed^G|SD7IG+kvgyVksU)
z(0R)SW1V(>&q2nM%Z!C9=;pTg!(8pPSc%H01urXmQI6Gi^dkYCYfu6b4^tW))b^U+
z$2K&iOgN_OU7n#GC2jgiXU{caO5hZt0(>k+c^(r><#m|#J^s?zA6pi;^#*rp&;aqL
zRcZi0Q4HhVX3$ybclxo4FFJW*`IV`)Bj_L3rQe?5{wLJh168Ve1jZv+f1D}f0S$N=
zm4i|9cEWz&C9~ZI3q*gwWH^<6sBWuphgy@S3Qy?MJiL>gwd|E<2h9-$3;gT9V~S6r
z)cAcmE0KXOwDA5eJ02-75d~f?3;n7a9d_xPBJaO;Z)#@s7gk5$Qn(Fc^w@9c5W0zY
z59is0?Mt^@Rolcn{4%)Ioat(kxQH6}hIykSA)zht=9F_W*D#<}N(k&&;k;&gKkWIL
z0Of*sP=X(Uyu$Pw;?F@?j{}=>{aSHFcii#78FC^6JGrg-)!)MV4AKz>pXnhVgTgx8
z1&5Y=>|8RGA6++FrSy=__k_imx|z-EI@foKi>tK0Hq2LetjUotCgk2QFXaej!BWYL
zJc{fv(&qA7UUJ|AXL<Te#svgLe$GRVt~C0`%AZ+-=S0D^On=i42k@^tJ-LZGdLpRi
zdrV5?>c5z*_NW#yWzKtl(c8mEW{A>5Hj^gfZ^HC9lQNQ?RowXjmuCj4!!54Us1=hY
z0{@-phvC}yls!PmA~_z>Y&n&IW9FQcj}9(OLO-t^NN$c0o}YksCUWt|DV(MJB%%Sr
zdf}8!9ylU2TW!=T{?)g-ojAMKc>3pW;KiZ7f0;&g)k}K^#HBhE5ot)%oxq$*$W@b#
zg4p<<e2}@}ZtI091*fR6EHmhc2JFT&S+9NWaDJ!A80$GFF7R`A%xl6?3MWwFH)kiY
zKkO7P(Y}AIYl!b@wU{Hfoy`qG`h+F#SJJ{&-s<{+@b9bRRm+2<>Ou`ME|Kd1WHK@8
zzLD+0(NHWa`B{em3Ye?@aVsEi>y#0XVZfaFuq#;X5C3{*ikRx7UY4FF{ZtNHNO?A_
z#Q?hwRv~D8fPEc%B5E-ZMI&TAmikl||EERumQCRh7p;)>fdZMxvKq;ky0}7IjhJph
zW*uuu*<F&)uV|73Nr>(Y6)S;Od--8uR^R#sb$cmFCnPcj9PPCWhPN;n`i1Q#Qn>ii
z{WR|0>8F`vf&#E(c2NsoH=I7Cd-FV|%(7a`i}gZw4N~QFFG2WtS^H%@c?%9UZ+kez
z;PwGgg_r6V>Kn5n(nZ40P4qMyrCP3bDkJp@hp6&X3>gzC>=f@Hsen<%I~7W+x@}b>
z0}Et*vx_50-q@PIV=(3&Tbm}}QRo*FP2@)A#XX-8jYspIhah`9ukPBr)$8>Tmtg&R
z?JBoH17?+1@Y@r>anoKPQ}F8o9?vhcG79Cjv^V6ct709VOQwg{c0Q#rBSsSmK3Q;O
zBpNihl3S0_IGVE)^`#94#j~$;<ISbQ+zLM8Q_sWpD4<&Sicl|!a~&A@PH`UFRr4^t
zSjAA>7+u870yWiV$@={|GrBmuz4b)*bCOPkaN0{6$MvazOEBxFdKZDlbVvv{8_*kJ
zfE6C`4&Kkz<5u%dEdStd85-5UHG5IOWbo8i9azgg#zw-(P1AA049hddAB*UdG3Vn0
zX`OgM+EM|<+KhJ<=k?z~WA5waVj?T9eBdfJGebVifBKS1u<$#vl^<Wg*!!OoyJ@GG
z%+_%2Ex-A(=Z(Bs6q~agBwBL+Pcns5yTYUCI_zEv3JOnOB;7f=h8xGf|IQl+Qw37#
z{BhR?wjaFo)FpPNNRkn616I`fE=rl+<Vv=sXw)oTB*nsxZd}^hq|lwuLq2tPYK9Ch
zP~rW|kx{-S+q;ojdznAWu9)x>BvSg)xsnT5Aw_ZY#}v*LXO#htB>f}x3qDdDHoFeb
zAq7;0CW;XJ`d&G*9V)@H&739DpfWYzdQt+Kx_E1K#Cg1EMtFa8eQRk_JuUdHD*2;W
zR~XFnl!L2A?48O;_iqCVr1oxEXvOIiN_9CUVTZs3C~P+11}ebyTRLACiJuMIG#`xP
zKlC|E(S@QvN+%pBc6vPiQS8KgQAUh75C0<L{Rx=;M-*LCs2Bp<jfOoZepIeH1&E9@
zECcRp6~TSaxo9}VYr%Om){SqtW<MPRfw2-K1_c9&KORpSyh3Z*9=_y`d-Pn0_zAw+
z=kYI%Xg`=LN{&qw<HTtk2MKE0r;WoX$l}>a2xcPQDD$}*bM&z~g8+=9ltmkT$;c;s
z5_=8%i0H^fEAOQbHXf0;?D<BP;<HVQI1JZt*v)6RAq&gagO^!F$spXEh)>N5z-5+1
zDxj50yYkz4ox9p$HbZ|H?8ukAbLE^P$@h}L%i6QVcY>)i!w=hkv2zvrduut%!8>6b
zcus3bh1w~L804EZ*s96?GB&<V5y;va8bgv&LhJ<YYLxjoJ6PJ;r2T$n2GZZ+&blBq
zN@;fP%v^kz^?uH{Kpq(Ih{eCW5OnE5%HakzY6sMl!wfw!(lBl{oyDuNM|bEKU#YtR
zTTK?n-{?&5Szx)y^~WKl(fG>F7c5?m?|t$-tp2rKMy>F*=4;w*jW}^;8v`st&8)c;
z2Ct2{)?S(Z;@_mjAEjb8x=qAQvx=}S6l9?~H?PmP`-xu;ME*B8sm|!h@BX4>u(xg_
zIHmQzp4Tgf*J}Y=8STR5_s)GKcmgV!<zLBv<JCu*R*$7_b_L{9GvwPbpvkT@1&MS$
zijYfuLM?Pa-BA2}iX9A(2K)AF@cP6QkvvCLyswdDf?LI~tZ|qKPtWR#^oamFBRcUk
zs5b$Sc+=%VrL*7Ba(pp>$JKTg@LO402{{Wrg>#D4-L%vjmtJ4r?p&$F!o-BOf7ej~
z6)BuK^^g1b#(E>$s`t3i13{6-mmSp7{;QkeG5v}GAN&lM2lQT$@(aQCcFP(%UyZbF
z#$HLTqGT^@F#A29b0HqiJ<ZOKS1P#S0IU6AksffR*wx4ca5r>sRJAlh8kngU`BDI6
zJUE~&!cQ*&f95Ot$#mxU5+*^$qg_DWNdfu+1irglB7yDglzH()2!@#rpu)^3S8weW
z_FE$=j^GTY*|5SH95O8o8W9FluYwB=2PwtbW|JG6kcV^dMVmX(wG+Otj;E$%gfu^K
z!t~<3??8=()WQSycsBKy24>NjRtuZ>zxJIED;YXaU<x|u=Vd7uuZ|>z$@0z4rl+TW
zWxmvM$%4jYIpO>j5k1t1&}1VKM~s!<EQ6q8U;EP6<gFYZ!m%POxUBC$P89e*7OnrM
zdWQA)CjX#LYDI-i*mnQZr;sN<6@SPOXNM}9Rp_hcE;y>eLsCVQ`TTjn3JRXZD~>GM
z$-IT~(Y)flNqDkC%DfbxaV9?QuWCV&-U1yzrV@0jRhE;)ZO0=r-{s@W?HOFbRHDDV
zq;eLo+wOW;nI|#mNf(J?RImB9{YSO2Y`9825Lz#u4(nk3)RGv3X8B(A$TsontJ8L!
z9JP^eWxtKC?G8^xAZa1HECx*rp35s!^%;&@Jyk)NexVc)@U4$^<D$wmm?XpH-Sg4*
z8B^w;<H>X1Dag6`WKs|(HhZ#rzO2KEw3xh~-0<;|zcs0L>OcO#YYX{S<TTw)*(lZC
zIx888OkDY0a@=pFP3fhTGE0#kua@EqJ8hp4VSNt-Xfx&Iq8mr)#UbJIBdW*?_9fdi
z7f!0)Iy{xeM7LDi+*QJ?BdGeD5e0(0aSm&GvjQ!V6CD0we*R)~MbsZ|>N8m6`9pp+
zQG@q$I)T?aoe#AoR@%om_#z=c@ych!bj~lV13Qi-xg$i$hXEAB#l=t7QWENGbma4L
zbBf*X*4oNYZUd_;1{Ln_ZeAwQv4z?n9$eoxJeI?lU9^!AB2Y~AwOSq67dT9ADZ)s@
zCRYS7W$Zpkdx$3T>7$I%3EI2ik~m!f7&$Djpt6kZqDWZJ-G{*_eXs*B8$1R4+I}Kf
zqniwCI64r;>h2Lu{0c(#Atn)%E8&)=0S4BMhq9$`vu|Ct;^ur~gL`bD>J@l)P$q_A
zO7b3HGOUG`vgH{}&&Agr<FnKy|IF(G1iR*`GW247VX<aAlJ2F?Q<={Aib+`}_HyE*
zujP5~Z9@I2PBhiOY}cNA6jXAuIimavj#$XIs@HezE!U24{*GtAdHFvr(O>Fy%K^>?
z>wf**coZ2vdSDcNYSm~dZ(vk6&m6bVKmVgrx-X<>{QzA!)2*L+HLTQz$e8UcB&Djq
zl)-%s$ZtUN-R!4ZiG=L0#_P=BbUyH+YPmFl_ogkkQ$=s@T1v}rNnZ^eMaqJ|quc+6
z*ygceDOrldsL30w`H;rNu+I<VKUrjL=bDy~WtS;;K#ThRGVRMNFq&Gco*pd+ChOJI
zqAbbk-&kSt%3!MCpue~I%|gblH{=P#-)jqQC%xCp|J^jUO>jlS+G~p&0SawXCA1+D
zC%cZtjUkLNq%FadtHE?O(yQTP486A{1x<{krq#rpauNQaeyhM3*i0%tBpQHQo-u)x
z{0{&KS`>}vf2_}b160XZO2$b)cyrHq7ZSeiSbRvaxnKUH{Q`-P(nL&^fcF2){vhN-
zbX&WEjP7?b4A%0y6n_=m%l00uZ+}mCYO(!x?j$+O$*TqoD_Q5EoyDJ?w?^UIa491H
zE}87(bR`X;@u#3Qy~9wWdWQIg1`cXrk$x9=ccR|RY1~%{fAJ@uq@J3e872x0v$hmv
ze_KcL(wM|n0EOp;t{hKoohYyDmYO;!`7^Lx;0k=PWPGZpI>V5qYlzjSL_(%|mud50
z7#{p97s`U|Sn$WYF>-i{i4`kzlrV6a<}=72q2sAT7Zh{>P%*6B;Zl;~0xWymt10Mo
zl5{bmR(wJefJpNGK=fSRP|mpCI-)Nf6?Pv==FcFmpSwF1%CTOucV{yqxSyx4Zws3O
z8hr5Uyd%ezIO7?PnEO0T%af#KOiXD$e?V&OX-B|ZX-YsgSs%sv-6U+sLPuz{D4bq|
zpd&|o5tNCmpT>(uIbRf?8c}d3IpOb3sn6>_dr*26R#ev<_~vi)wleW$P<Wyn_7n0-
zl)LIgF0z;$xTz(0JgW0t|K0{|pl+d7{+{fAW)lB*Qg({z1~qrplnmDSP!2>X|5)$_
z+_|=pi(0D(AB_sjQ;sQQSM&AWqzDO1@NHw;C9cPdXRKRI#@nUW)CgFxzQ1nyd!+h&
zcjU!U=&u|>@}R(9D$%lu2TlV>@I2-n@fCr5Pr<dtPlfA<Z*`%$WS?W!M7-X@Sw}lf
zu7sLkI`BK6gTBwv0nqdk^SqiGBO}U16-Ky}DlzfpVxxnEAc|MG(;#A7b;H&MP*riE
zHr?l)sap(Q`P6U_@Ov18QJwI7yr|=6Y+TbD2PUEPfsh&V{s?8AA2dT>ZNVyKWR7hm
zWjoy^<!R*J%IXEk=E5cj6b=;i9u3uQuMH4{qOT^=OGnt_=n2>p7v8m#$qN0K#8jT-
zq`mSirDZDa1Jxm;Rg3<Jf$!Bj9`<kE;Sz+T_M)m3-f__2l^&CsYnIwV?+%t2FG{Ta
zI-67-X7Fu-xbrdN@cn6z3_k9VZ?2i{<ie%nx)UUiUTLNtHEK)0HD_qUYpV0X30}z?
zM!*@omRu>rAPhC)LcI4@-RvKT+@9&KsR3b0_0zuM!Fg7u>oF>3bzOxZPU&$ab$Z9@
zY)f7<va9`_LvY6!5H@PMYi?(=yM97@*rbrsB=oh`t5ydnN2A;15DysI3n?zsE3{ZX
zq+yK*u5H1rVq8mwv!|dvE&PWazz!0^LY7dozu5qaS3Q5~q}uAQUJN5WW+A&wvpho?
z=!z1Q9;>pKh22I7ZykL{YsdjcqeN++=0a}elQM-4;Q)(`Ep3|VFHqnXOh14`!Bus&
z9w%*EWK6AiAM{s$6~SEQS;A>ey$#`7)khZvamem{P?>k)5&7Sl&&NXKk}o!%vd;-!
zpo2p-_h^b$D<fdz<@`H3n|HeSVR76K@6|_9&-VHAVO=;`v1rN8I|9P)PS7vp83efu
z`yTr9OVLz|?h*IHce7sdT@Ktb#!>NBO>{h4JdGB=D>fvGIYN8v&XsfxU~VaefL?q}
z3ekM?<wNDtI4J<DC6XBgM26Nv#0iut=ZwA#^>iOKkCzQHkBkhg=hD!@&(L}FcHKoa
zbZ7)H1C|lHjwEb@tu=n^OvdHOo7o+W`0-y3KdP#bb~wM=Vr_gyoEq|#B?$&d$tals
ziIs-&7isBpvS|CjC|7C&3I0SE?~`a%g~$PI%;au^cUp@ER3?mn-|vyu!$7MV6(uvt
z+CcGuM(Ku2&G0tcRCo7#D$Dirfqef2qPOE5I)oCGzmR5G!o#Q~(k~)c=LpIfrhHQk
zeAva6MilEifE7rgP1M7AyWmLOXK}i8?=z<j)TsCg#MI>2;N=no)`IGm#y%aGE>-FN
zyXCp0Sln{IsfOBuCdE*#@CQof%jzuU*jkR*Su3?5t}F(#g0BD0Zzu|1MDes8U7f9;
z$JBg|mqTXt`muZ8=Z`3wx$uizZG_7>GI7tcfOHW`C2bKxNOR)XAwRkLOaHS4xwlH4
zDpU29#6wLXI;H?0Se`SRa&I_QmI{zo7p%uveBZ0KZKd9H6@U?YGArbfm)D*^5=&Rp
z`k{35?Z5GbZnv>z@NmJ%+sx=1WanWg)8r}C_>EGR8mk(NR$pW<-l8OTU^_u3M@gwS
z7}GGa1)`z5G|DZirw;FB@VhH7Dq*0qc=|9lLe{w2#`g+_nt<uBB~iQoK%j+BR{KW$
zxUoEE;u<56rl_>>_%o<~9(VZe=zI*SSz4w43-_o>4E4`M@NPKTWZuQJs)?KXbWp1M
zimd5F;?AP(LWcaI-^Sl{`~>tmxsQB9Y$Xi*{Zr#py_+I$vx7@NY`S?HFfS!hUiz$a
z{>!&e1(16T!Om)m)&k1W#*d#GslD^4!TwiF2WjFBvi=Ms!ADT)ArEW6zfVuIXcXVk
z>AHjPADW+mJzY`_Ieq(s?jbk4iD2Rb8*V3t6?I+E06(K8H!!xnDzO%GB;Z$N-{M|B
zeT`jo%9)s%op*XZKDd6*)-^lWO{#RaIGFdBH+;XXjI(8RxpBc~azG1H^2v7c^bkFE
zZ<!d@6;Xr=zrz^$h_Zbcf~Z$lrrBw0nL?BbB`hkkx&01qcs_@(`dj5M$3rI2JKgsr
zS^x~?G~LTF&PL>CVPE+E*Q=FSe8Vm&6|^3ki{9~qafiMAf7i4APZg>b%&5>nT@pHH
z%O*pOv(77<h_P}M1fVl@bA%;8!%G$2v2^1K;a|J|258iaFK<JsY+PvseEryJp$5<!
z9lXGNp5qrv`T=s~_@3Ry-B6o<m;T-lQtjLZ)m`X2mKrN#6`?5SI5G#qCc`>?ZiT{W
zBibx}Q12tRc7Py1NcZTp`Q4ey%T_nj@<r4RLoFiQ1cOG!U!@-f&DrHzjFreg6r@E|
zvE{2Q=kFJS$gwo*FVtl=epg~LzgZ(&E7V*y3ct|~AGvI-3JcYr{%DF#=;?cH6~ge-
zxOld^6>1WKg5Fz_Rjl4wlJQj)rtp8yL3r!S<K<bid;Q+mY&EMZN}!KaieT~EVI>hy
zvZvnmh!tH4T6Js-?vI0<-rzzl{mgT*S0d_7^AU_8gBg^03o-J=p(1o6kww2hx|!%T
z-jqp}m^G*W?$!R#M%Ef?&2jYxmx+lXWZszpI4d$p<r;|3!?@3AW<2Zgi0<hN9ff)N
z(zo6I+-$9Bx*(c$-bk0EGqBsb91nmH7yrN`CVj(QCaD{RJgvV-JPkoBQAwGD;nyzn
z*I;L?L=(3oeAQ<rjW4NvWy!bHdLOHMjezGb#Hb+lSX`#>UN`(S)|*c^CgdwY>Fa>>
zgGBJhwe8y#Xd*q0=@SLEgPF>+Qe4?%E*v{a`||luZ~&dqMBrRfJ{SDMaJ!s_;cSJp
zSqZHXIdc@@XteNySUZs^9SG7xK`8=NBN<V=E)OCgg+S0s%X@m8dOqs;y*2U#C_D)u
z81;Mt5p^uC3PVJP@9PH9!<3b5IE^n;kwm}NvP7!(7^P%;1DOYVJumd1Eg9zSvb@M<
z=8_n~reVNX{Rwy18un@y&;emesWi1XQooSmDu!<kFo)-HRP5pn?;0r-+4i~5mY$28
z(;>M)fRVOjw)D^)w%L2OPkTQ$Tel-J)GD3=YXy+F4in(ILy*A3m@3o73uv?JC}Q>f
zr<Ie&tGbM^0N<roTuDj*?S_O(I}B&He=e8Pl8`tjGg-O~5%TUI<1yQ05r*$Oc2#s#
z8%FWrdDtn79-cwa2pX4M_-JFx9zK7mChDM?zK(~_K9>Y&8SWmesiba0|3X-jmlMT3
z*ST|_U@O=i*sM_*48G)dgXqlwoFp5G6qSM3&%_f_*<qxyINw1$We6It<0I>n!P<uj
z?87vdPOI3mk{cGX^R<>iT>?cNI)fAUkA{qWnqdMi+aNK_yVQ&lx4UZknAc9FIzVk%
zo6JmFH~c{_tK!gt4+o2>)zoP{sR}!!vfRjI=13!z<fc;{t9y2@_q+%poab^!jwREr
z2+#Zf9d~36snX-iZ(5U>5}ijMFQ4a4?QIg-BE4T6!#%?d&L;`j5=a`4is>U;%@Rd~
zXC<xcC%fK=hCSNPW&)8o$8W+KO-SU#5LbV{{RyL+099LpC;6!uxU&{MmE<Y{b<h52
z$81YnCmIWu(0dlOntRk)&>~H7eGQhhYWhMPWf9znDbYIgwud(6$W3e>$W4$~d%qoJ
z+JE`1g$qJ%>b|z*xCKenmpV$0pM=Gl-Y*LT8K+P)2X#;XYEFF4mRb<YTI|Oo*wqC5
z0h9Vcyd1-aYw_k;tVodW95W2hdEX}FLSrp|R+GE56fkm-P)-t$V)|A=l7x|mefFZC
zXMAilrJt8o)%dz@>c~jj?DM@(1e`nL=F4Syv)TKIePQUz)bZ<lVCgA$*!Fmgxl6o%
zjdFR@&JKgonL5u$SS;U)hR2JO%(X!<3`;2ma}g7i__wVr1m~_yKAfNhm3c!NlBG8F
zi*)rX!5cY!j#B&Bh5F)#rbPS@4QDD~@ulB?(x|5|p4JWn*dAG|<;_kq<4J3{W|V%$
zFux+io?Ym>?Bi3@G@HO$Aps1DvDGkYF50O$_welu^cL7;vPiMGho74$;4fDqKbE{U
zd1h{;LfM#Fb|Z&uH~Rm_J)R~Vy4b;1?tW_A)Iz#S_=F|~pISaVkCnQ0&u%Yz%o#|!
zS-TSg87LUfFSs{tTuM3$!06ZzH&MFtG)X-l7>3)V?Txuj2HyG*5u;EY2_5vU0ujA?
zHXh5G%6e3y7v?AjhyX79pnRBVr}RmPmtrxoB7lkxEzChX^(vKd+sLh?SBic=Q)5nA
zdz7Mw3_iA>;T^_Kl~?1|5t%GZ;ki_+i>Q~Q1EVdKZ)$Sh3LM@ea&D~{2HOG++7*wF
zAC6jW4>fa~!Vp5+$Z{<)Qxb|<doy+ePfu6oC(7$`&WuO0q0$+a9a%yz_{5phPWBz7
zW*;>{unMgCv2)@%3j=7)Zc%U<^i|SAF88s!A^+Xs!OASYT%7;Jx?olg_6NFP1475N
z#0s<@E~FI}#LNQ{?B1;t+N$2k*`K$Hxb%#8tRQi*Z#No0J}Pl;HWb){l7{A8(pu#@
zfE<FZzTROa?{|??!(1M&=4t#qdoS<^Na+oYIxC;QnUK0am@X-v$)ut<3yca1@z&t9
zM)d{X_R6>-OTvEreoz1+p`9sUI%<waswQ*s(MUS7r-ADfL?@KW0)mbJ;|S&qT$0vX
z+3A>Y{e5L-oTP_^NkgpYhZjp&ykinnW;(fu1;ttpSsgYM8ABX4dHe_HxU+%M(D=~)
zYM}XUJ5guZ;=_ZcOsC`_{CiU$zN3$+x&5C`vX-V3`8&RjlBs^rf00MNYZW+jCd~7N
z%{jJuUUwY(M`8$`B>K&_48!Li682ZaRknMgQ3~dnlp8C?__!P2z@=Auv;T^$yrsNy
zCARmaA@^Yo2sS%2$`031-+h9K<HTVTe5)EQvp!MW(iadmCJS1wSbK_@ufo=dlOY}z
zCO9zVYKg|I&o<%8Sb*|F!S|!19op-p&g=TZ%N9@L#(UmyHRFj))9t+gQpBfbTesf-
za`2nVU~8Sd4Kd<Xb>MZsIHfB>s@}>Y(z988e!`%4=EDoAQ0kbk>+lCoK60Mx9P!~I
zlq~wf7kcm_NFImt3ZYlE(b3O1K^QWiFb$V^a2Jlwvm(!XYx<`i@ZMS3UwFt{;x+-v
zhx{m=m;4dgvkKp5{*lfSN3o^keSpp9{hlXj%=}e_7Ou{Yiw(J@NXuh*;pL6@$HsfB
zh?v+r^cp@jQ4E<vE>spC#RqpwPY(}_SS$wZ{S959`C25777&sgtNh%XTCo9VHJC-G
z;;wi9{-iv+ETiY;K9qvlEc04f;ZnUP>cUL_T*ms``EtGoP^B#Q>n2dSrbAg8a>*Lg
zd0EJ^=tdW~7fbcLFsqryFEcy*-<UjNQKPSE=_Pn2>8!?;n%;F+8i{eZyCDaiYxghr
z$8k>L|2&-!lhvuVdk!r-kpSFl`5F5d4DJr%M4-qOy3<bq6e{+%w<EWihn1$%KzFfu
z`LKHky~)zdoi4^H8U?2zL}?l1u6MD%jgB7&*;Qf>gdmQb<G$UVN?JmKSKB~L!OR=i
zI@^y#3#{3i>qF1=aBtRM<!CT741&i5jO+s2lsMXtwRPLCm;Sn!-GpQ>7)c_Ae?$b8
zQg4c8*KQ{XJmL)1c7#0Yn0#PTMEs4-IH<W7>Pjkn0!=;JdhMXqzMLeh`yOylXROP-
zl#z3+fwM9l3%VN(6R77ua*uI9%hO7l7{+Hcbr(peh;afUK?B4EC09J{-u{mv)+u#?
zdKVBCPt`eU@IzL)OXA`E<o1(5;mC6=k@-!Ol2~E}J9hOE??)KsP;2EQ2{Z(0gwv}f
z!It<n&*dKHQo4x|g+0u^h~lZ5Ov4IC#Tfq*CptilVN;HXz`iK4{1F;tZh8So5XLY*
zXxgB;G7CZ#<Iv1X4e=NIfHyT;2#ek12;Y}7qA*ja41jVbduyrB$HRMX3i4#!N49oM
z=DRz&*@5P2{)@K+w!!IcW58;P<<)I=(H60m7Iz@T{w1f<%~zS?f9pR^Y*#fpT<Noz
z19vhe>bu`Xp?u0m%h&X41}FNfnJ*g1!1wcbbpo%F4x!-#R9ft!8{5`Ho}04?FI#Kg
zL|k`tF1t_`ywdy8(wnTut>HND(qNnq%Sq=AvvZbXnLx|mJhi!*&lwG2g|edBdVgLy
zjvVTKHAx(+&P;P#2Xobo7_RttUi)Nllc}}hX>|N?-u5g7VJ-NNdwYcaOG?NK=5)}`
zMtOL;o|i0mSKm(UI_7BL_^6HnVOTkuPI6y@ZLR(H?c1cr-_ouSLp{5!bx^DiKd*Yb
z{K78Ci<l%%epWQ$#NR9uIf5|S3KV`ZTJ$&qJ6`ry!VhqBuPs(j#jC&+5r^-xzR6fB
zK27~T)ZekimVRRz-lpCAJu2yR?1~gIvHR5a1NYj$*q3Netl55}ts!oix2<m^q4oKA
zx&s$GFeBD?)7%@b7gCQPQkbzcY-#e<IqbmH&`NOUj{m_7zrJE%0%MGK`P$ftHCCyA
z#QEOkdexcb5q+aRNqFbL{IkS#hFvjjH9v~WbirfMFFJD$DOv0$f8V^PmC)h@B?4Tt
zm|Lni^t};e&92Z{h%k-#j#z#sF&$u2EIp%nX3YhhH9Z@UzRMIVYuCt&$V#l>&Twup
zTKm)ioN|wcYy%Qnwb)Izb<b#d)i{+1p{kvKer6Fm8jK>H>W!;Ah5Zdm_jRY`+VRJ2
zhkspZ9hbK3iQD91A$d!0*-1i#%x81|s+SPRmD}d~<1p6!A13(!vABP<Z{iwC7e4%~
z_Ln8-%lvcLY32-Y@1SO1*q92_(j#+rhCS=CLMntrY3Mry$(OvuZNSYRrU>2kNgqEG
z?AMgl^P+iRoIY(9@_I?n1829lGvAsRnHwS~|5vD2+Zi53j<5N4wNn0{q>>jF9*bI)
zL$kMXM-awNOElF>{?Jr^tOz1glbwaD-<Z?hQEA3Pbch{-zrz(GmD@~J*ag^+fZsaw
zY>M0OKOlTeW3C!1ZyxRbB>8JDof(O&R1bh%3x#>y2~<>OXO#IIedH0Q`(&&?eo-c~
z>*Ah#3~09unym~UC-UFqqI>{dmUD$Y4@evG#ORLI*{ZM)J<p{vwhmRDEF0r$s4y_e
z=sJVWn|ZM-lg`hKmi%p5C*Kde*o`ZFJEf1Ej+^5AxXqpoV)MlQbue7)^k_qkb+e;`
zWde0R#5(=H5cM$dK9LAsdS=Yk0oGNTPVR(|j6Ls{ih2+`6_F=VxMEkqB<u_yrMn-7
zem-jG!zg{VfBK=QGIg$ZuYze9uWx?aDxho7OdK|L{6b`Vwt6C>l=e1it!XzY($S3V
zLG!Y6fCjE>x6r@5FG1n|8ompSZaJ>9)q6jqU;XxCQk9zV(?C9<V#w?Lf%1Im<}?28
z%fv0sO4GSZ%zfKH*&?O&xk<I#mt_{KWN@l7yB^%JPt=7^LfPgcr~mEkBmfFP7Db0M
zd#E!M<3epZs@^{m3?RG}!71NRBMkEamf~hxD%`6taJAN-7_P+KIU~cqcmswNPF@u0
zBEd?J2tVMNdm+C_OO1xnDaP<CvO06_?;7EsCcbdr{cefhRUYuKyPaC&4Q})>+i*>w
z21+KYt1gXX&0`x3E)hS7I5}snbBzox9C@Xzcr|{B8Hw;SY1$}&BoYKXH^hpjW-RgJ
z-Fb}tannKCv>y~^`r|(1Q9;+sZlYf3XPSX|^gR01UFtu$B*R;$sPZdIZShRr>|b@J
z;#G{EdoY+O;REEjQ}X7_YzWL<b@Mth=4xckE^wJmIQPsUfw>O+Ey3>a_KDe1CjSe|
z6arqcEZ)CX!8r(si`dqbF$uu&pnf^Np{1f*TdJ<q2__L6D@tfPK*~rzVm(OhYZi{~
zO7D1Cy0z3WdT1AOu^h7D1_(%nFOYSW(8K@CEF1cpVqIf7{ZixjH(=6Z%>`r2;@SaZ
z#hb4xlaCA@Pwqj#LlUEe5L{I$k(Zj$d3(~)u(F%&xb8={N9hKxlZIO1ABsM{Mt|)2
zJ^t9Id;?%4PfR4&Ph9B9cFK~@tG3wlFW-0<w~5R`uK#F{bA6_apO|PKuT2G1V=wh!
zZWPJWbbu)nGiWn?;_;mE<K|T11{jR4I#*v{H=AUuEc3+UXA@7uIuDpTy`jcYhUz%o
zBA}z0OR6}0Iqx8Rc?*~((>fXZS_L4U*EiAA%+`h%q2^6BCC;t0iO<j7`ENmUd8a;m
zq?b}^r<Irhn?t82<3YNwQO;C@tCYRR<pR}s5&giTT+nc?H}mtH3ZX|EFpV#H_g4in
z8Tbrg7JdfQvFh#<ovHft;`1YsxU2!leoc~Y)qNFc1mAL8P2+9584$1X7q1nBToy)y
z$s4}XIl~zQ7=m5m-cT@n8wijJJ$|#uxO(nL+IWs9qk?i9%s#W2ZxqfW`jt6{wIS^q
z*iUq6jHCeqca?Re1w*!C)k-nH(eV#(PnPU`?~ov%Y+nj9)j3~WBrKHnC<W0QlTNC*
z<u_q0O?_PoEKdE%)ty@V5F=^-=y+E`(D|T`;&Jjf?_7CST84~oRyM!RwLEZ{ZM@iY
zIB{U~Ge+IK^?H|Bpj8js3(0P2EU%fWNhAH!9B5rA(2TXL071s~i2t!VlQfp=S*6A2
zkt-CN_z|1uc9QB1_^Gpz5);n_@pEbj*T#DvuqJuuKb_PutQhcu6?7{m7g7o;mzZA9
zf{W$DK$@&k565^Y7M*vmK#vF0i(Zb4TM%~5g7C?du<oAbjjU>4V=s4Qug{M|iDV@s
zC7|ef-dxiR7T&Mpre!%hiUhHM%3Qxi$Lzw6&(Tvlx9QA_7LhYq<(o~=Y>3ka-zrQa
zhGpfFK@)#)rtfz61w35^sN1=IFw&Oc!Nah+8@qhJ0UEGr;JplaxOGI82OVqZHsqfX
ze1}r{jy;G?&}Da}a7>S<aX|!tNbjGLu?E#M_FQ+tx7QwU!f|T#|0pGw8beze%W}X8
zTh%o9Dbrk*KF8LN?^<3buL7%?KbkRMr_jMII=xY`U$vl5f0r@#H-|^ToExGU<wfLd
zXr+GANZ(jz6qI7<1HwuGyQ7H^naJ1E$XxZfl>CDsFDuzusee<BvkaOnN;I1*%q9kj
z^#m2ll1tq&oMv5g`}?0u!-DOva7&B0@Z!bH=K`f(k?GfNkG{%)>CKof|Dz2BPsP8?
zY;a)Tkr2P~0^2BeO?wnzF_<l4Nvqf<W`7QjWtJDSw)B?FOMa{8DG?kxHAQnVhPF5z
zxnU_-^up4Prel^ed-PkB1+y((Pnm`A;p#0KHiAU@r9|EKB!f~*!CI?=fpguhu1lxJ
zNfwd#_vJ<v;}^GGOcxE|6OXh~-#_DXMEuzGXcF>Ul-ekY=-w26VnU%U3f19Z-pj&2
z4J_a|o4Dci+MO)mPQIM>kdPG1<w<ic`+WErB>xydiR9@#<n}&^Z@zb@F^w%zU4>8m
zh27D7GF{p|a{8({Q-Pr-;#jV{2zHR><r}G)UYxpAdB=!PS*(C~*1H#i#3#T1$j2)t
z81k%ZC~^7K<oMng7XOD4<}b)aGe_1j<vxx~;=~OWNZThvqsq&|9D#PlGC$L88fM!1
ziqq3RXQ^4C*>lGoFtIfIpoMo?exuQyX_A;;l0AP4!)JEM$EwMInZkj+8*IHP4vKRd
zKx_l-i*>A*C@{u%ct`y~s6MWAfO{@FPIX&sg8H{GMDc{4M3%$@c8&RAlw0-R<4DO3
trJqdc$mBpWeznn?E0M$F`|3v=`3%T2A17h;rxP7$%JLd=6(2u;`(N3pt&so#
literal 0
HcmV?d00001
--
1.9.1
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 10/11] toastergui: fix whitespace after URL
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (8 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 09/11] toaster: adding art missing from Bootstrap Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
2015-05-11 10:58 ` [PATCH 11/11] toastergui: removing unused views Alex DAMIAN
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
This patch fixes whitespace after URLs in the tasks page,
fixing warnings from the linkchecker.
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/toastergui/templates/tasks.html | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/toaster/toastergui/templates/tasks.html b/lib/toaster/toastergui/templates/tasks.html
index 5c1c476..32c0552 100644
--- a/lib/toaster/toastergui/templates/tasks.html
+++ b/lib/toaster/toastergui/templates/tasks.html
@@ -86,13 +86,13 @@
<a href="{% url "recipe" build.pk task.recipe.pk %}">{{task.recipe.version}}</a>
</td>
<td class="task_name">
- <a href="{%url "task" build.pk task.pk%} ">{{task.task_name}}</a> {% if task.get_description %}<i class="icon-question-sign get-help hover-help" title="{{task.get_description}}"></i> {% endif %}
+ <a href="{%url "task" build.pk task.pk%}">{{task.task_name}}</a> {% if task.get_description %}<i class="icon-question-sign get-help hover-help" title="{{task.get_description}}"></i> {% endif %}
</td>
<td class="executed">
- <a href="{%url "task" build.pk task.pk%} ">{{task.get_executed_display}}</a>
+ <a href="{%url "task" build.pk task.pk%}">{{task.get_executed_display}}</a>
</td>
<td class="outcome">
- <a href="{%url "task" build.pk task.pk%} ">{{task.get_outcome_display}} </a>
+ <a href="{%url "task" build.pk task.pk%}">{{task.get_outcome_display}} </a>
{% if MANAGED and build.project and task.outcome = task.OUTCOME_FAILED %}
<a href="{% url 'build_artifact' build.pk "tasklogfile" task.pk %}">
<i class="icon-download-alt" title="Download task log file"></i>
@@ -101,7 +101,7 @@
<i class="icon-question-sign get-help hover-help" title="{{task.get_outcome_help}}"></i>
</td>
<td class="cache_attempt">
- <a href="{%url "task" build.pk task.pk%} ">{{task.get_sstate_result_display|format_none_and_zero}}</a>
+ <a href="{%url "task" build.pk task.pk%}">{{task.get_sstate_result_display|format_none_and_zero}}</a>
</td>
<td class="time_taken">
{{task.elapsed_time|format_none_and_zero|floatformat:2}}
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 11/11] toastergui: removing unused views
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
` (9 preceding siblings ...)
2015-05-11 10:58 ` [PATCH 10/11] toastergui: fix whitespace after URL Alex DAMIAN
@ 2015-05-11 10:58 ` Alex DAMIAN
10 siblings, 0 replies; 12+ messages in thread
From: Alex DAMIAN @ 2015-05-11 10:58 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
We remove url entries, views and templates that are not
used in the interface; these are leftovers from the development
process, and are not linked anywhere in the interface nor
mentioned in documentation.
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/toastergui/templates/layer.html | 34 -------------------------
lib/toaster/toastergui/templates/package.html | 36 ---------------------------
lib/toaster/toastergui/urls.py | 5 ----
lib/toaster/toastergui/views.py | 29 ---------------------
4 files changed, 104 deletions(-)
delete mode 100644 lib/toaster/toastergui/templates/layer.html
delete mode 100644 lib/toaster/toastergui/templates/package.html
diff --git a/lib/toaster/toastergui/templates/layer.html b/lib/toaster/toastergui/templates/layer.html
deleted file mode 100644
index 410d766..0000000
--- a/lib/toaster/toastergui/templates/layer.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% extends "basetable.html" %}
-
-{% block pagename %}
- <h1>Toaster - Layers</h1>
-{% endblock %}
-
-{% block pagetable %}
- {% load projecttags %}
-
- <tr>
- <th>Name</th>
- <th>Local Path</th>
- <th>Layer Index URL</th>
- <th>Known Versions</th>
- </tr>
-
- {% for layer in objects %}
-
- <tr class="data">
- <td>{{layer.name}}</td>
- <td>{{layer.local_path}}</td>
- <td><a href='{{layer.layer_index_url}}'>{{layer.layer_index_url}}</a></td>
- <td><table>
- {% for lv in layer.versions %}
- <tr><td>
- <a href="{% url "layer_versions_recipes" lv.id %}">({{lv.priority}}){{lv.branch}}:{{lv.commit}} ({{lv.count}} recipes)</a>
- </td></tr>
- {% endfor %}
- </table></td>
- </tr>
-
- {% endfor %}
-
-{% endblock %}
diff --git a/lib/toaster/toastergui/templates/package.html b/lib/toaster/toastergui/templates/package.html
deleted file mode 100644
index 1ba3726..0000000
--- a/lib/toaster/toastergui/templates/package.html
+++ /dev/null
@@ -1,36 +0,0 @@
-{% extends "basebuildpage.html" %}
-
-{% block pagetable %}
- {% if not objects %}
- <p>No packages were recorded for this target!</p>
- {% else %}
-
- <tr>
- <th>Name</th>
- <th>Version</th>
- <th>Size (Bytes)</th>
- <th>Recipe</th>
- <th>Depends on</th>
- </tr>
-
- {% for package in objects %}
-
- <tr class="data">
- <td><a name="#{{package.name}}">{{package.name}}</a></td>
- <td>{{package.version}}</td>
- <td>{{package.size}}</td>
- <td>{%if package.recipe %}<a name="{{package.recipe.name}}.{{package.package_name}}">
- <a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
- <td>
- <div style="height: 4em; overflow:auto">
- {% for d in package.package_dependencies_source.all %}
- <a href="#{{d.name}}">{{d.depends_on.name}}</a><br/>
- {% endfor %}
- </div>
- </td>
-
- {% endfor %}
-
- {% endif %}
-
-{% endblock %}
diff --git a/lib/toaster/toastergui/urls.py b/lib/toaster/toastergui/urls.py
index 52fc0cc..de8c62c 100644
--- a/lib/toaster/toastergui/urls.py
+++ b/lib/toaster/toastergui/urls.py
@@ -56,7 +56,6 @@ urlpatterns = patterns('toastergui.views',
url(r'^dentries/build/(?P<build_id>\d+)/target/(?P<target_id>\d+)$', 'dirinfo_ajax', name='dirinfo_ajax'),
url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/dirinfo$', 'dirinfo', name='dirinfo'),
url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/dirinfo_filepath/_(?P<file_path>(?:/[^/\n]+)*)$', 'dirinfo', name='dirinfo_filepath'),
- url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/packages$', 'tpackage', name='targetpackages'),
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'),
@@ -67,13 +66,9 @@ urlpatterns = patterns('toastergui.views',
url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/packagefile/(?P<packagefile_id>\d+)$',
'image_information_dir', name='image_information_dir'),
-
# build download artifact
url(r'^build/(?P<build_id>\d+)/artifact/(?P<artifact_type>\w+)/id/(?P<artifact_id>\w+)', 'build_artifact', name="build_artifact"),
- # urls not linked from the dashboard
- url(r'^layerversions/(?P<layerversion_id>\d+)/recipes/.*$', 'layer_versions_recipes', name='layer_versions_recipes'),
-
# project URLs
url(r'^newproject/$', 'newproject', name='newproject'),
diff --git a/lib/toaster/toastergui/views.py b/lib/toaster/toastergui/views.py
index 23025a2..d938fd8 100755
--- a/lib/toaster/toastergui/views.py
+++ b/lib/toaster/toastergui/views.py
@@ -1479,35 +1479,6 @@ def bfile(request, build_id, package_id):
context = {'build': Build.objects.get(pk=build_id), 'objects' : files}
return render(request, template, context)
-def tpackage(request, build_id, target_id):
- template = 'package.html'
- packages = map(lambda x: x.package, list(Target_Installed_Package.objects.filter(target=target_id)))
- context = {'build': Build.objects.get(pk=build_id), 'objects' : packages}
- return render(request, template, context)
-
-def layer(request):
- template = 'layer.html'
- layer_info = Layer.objects.all()
-
- for li in layer_info:
- li.versions = Layer_Version.objects.filter(layer = li)
- for liv in li.versions:
- liv.count = Recipe.objects.filter(layer_version__id = liv.id).count()
-
- context = {'objects': layer_info}
-
- return render(request, template, context)
-
-
-def layer_versions_recipes(request, layerversion_id):
- template = 'recipe.html'
- recipes = Recipe.objects.filter(layer_version__id = layerversion_id)
-
- context = {'objects': recipes,
- 'layer_version' : Layer_Version.objects.get( id = layerversion_id )
- }
-
- return render(request, template, context)
# A set of dependency types valid for both included and built package views
OTHER_DEPENDS_BASE = [
--
1.9.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-05-11 11:00 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-11 10:58 [PATCH 00/11] Toaster patchset Alex DAMIAN
2015-05-11 10:58 ` [PATCH 01/11] toaster: clear up toaster shutdown for mac osx Alex DAMIAN
2015-05-11 10:58 ` [PATCH 02/11] toastergui: decrease load time for configuration page Alex DAMIAN
2015-05-11 10:58 ` [PATCH 03/11] toaster: Make toaster script working in zsh Alex DAMIAN
2015-05-11 10:58 ` [PATCH 04/11] toaster: Code cleanup: indent Alex DAMIAN
2015-05-11 10:58 ` [PATCH 05/11] toaster: fix typo in format string Alex DAMIAN
2015-05-11 10:58 ` [PATCH 06/11] toaster: <Add class id to a few columns> Alex DAMIAN
2015-05-11 10:58 ` [PATCH 07/11] toastergui: Consider task name when restarting a build Alex DAMIAN
2015-05-11 10:58 ` [PATCH 08/11] toasterui: URL refactoring Alex DAMIAN
2015-05-11 10:58 ` [PATCH 09/11] toaster: adding art missing from Bootstrap Alex DAMIAN
2015-05-11 10:58 ` [PATCH 10/11] toastergui: fix whitespace after URL Alex DAMIAN
2015-05-11 10:58 ` [PATCH 11/11] toastergui: removing unused views Alex DAMIAN
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox