Squashed 'yocto-poky/' changes from 7b86c77..c8a4ed9

b1f23d1 build-appliance-image: Update to jethro head revision
7fe17a2 qemu: Security fix CVE-2016-2198
50700a7 qemu: Security fix CVE-2016-2197
1f0e615 libgcrypt: Security fix CVE-2015-7511
dc5f155 uclibc: Security fix CVE-2016-2225
ef13511 uclibc: Security fix CVE-2016-2224
ae57ea0 libbsd: Security fix CVE-2016-2090
eb9666a glibc: Security fix CVE-2015-7547
5b12268 build-appliance-image: Update to jethro head revision
a3a374a curl: Secuirty fix CVE-2016-0755
f4341a9 curl: Security fix CVE-2016-0754
35f4306 nettle: Security fix CVE-2015-8804
3e8a07b nettle: Security fix CVE-2015-8803 and CVE-2015-8805
5ffc326 socat: Security fix CVE-2016-2217
5cc5f99 libpng: Security fix CVE-2015-8472
21a816c libpng: Security fix CVE-2015-8126
6a0fbfa foomatic-filters: Security fixes CVE-2015-8327
d57aaf7 foomatic-filters: Security fix CVE-2015-8560
941874a build-appliance-image: Update to jethro head revision
d74a3cb cross-localedef-native: add ABI breaking glibc patch
12fae23 build-appliance-image: Update to jethro head revision
67ac9d6 e2fsprogs: Ensure we use the right mke2fs.conf when restoring from sstate
5812fc9 build-appliance-image: Update to jethro head revision
3de2492 ref-manual: Updated host package install requirements CentOS
79de8cf toaster-manual: Updated the "Installation" to have TOASTER_DIR information
a23d262 toaster-manual: Updated instructions for production setup.
b6def81 linux-yocto: Update SRCREV for genericx86* for 4.1, fixes CVE-2016-0728
db0f8ac linux-yocto: Update SRCREV for genericx86* for 3.19, fixes CVE-2016-0728
c8122a0 linux-yocto: Update SRCREV for genericx86* for 3.14, fixes CVE-2016-0728
cdeb241 meta-yocto-bsp: Remove uvesafb (v86d) from generic x86 features
52cd219 yocto-bsp: Set SRCREV meta/machine revisions to AUTOREV
a88d6cb yocto-bsp: Set KTYPE to user selected base branch
4e74b36 yocto-bsp: Avoid duplication of user patches ({{=machine}}-user-patches.scc)
6680773 yocto-bsp: Default kernel version to 4.1 on x86_64
4c075e7 piglit: don't use /tmp to write generated sources to
ee52ac6 gen-lockedsig-cache: fix bad destination path joining
e9f95df linux-yocto: Update SRCREV for qemux86* for 4.1, fixes CVE-2016-0728
e63bab1 linux-yocto: Update SRCREV for qemux86* for 3.19, fixes CVE-2016-0728
64a4920 linux-yocto: Update SRCREV for qemux86* for 3.14, fixes CVE-2016-0728
5b043da libpng12: update URL that no longer exists
655c8a5 libpng: update URL that no longer exists
96fda8c busybox: fix build of last applet
ae037d9 ghostscript: add dependency for pnglibconf.h
26eb877 gcr: Require x11 DISTRO_FEATURE
e632cdb uClibc: enable utmp for shadow compatibility
e8c9613 git: Security fix CVE-2015-7545
108ea6d glibc-locale: fix QA warning
9a88c1d grub: Security fix CVE-2015-8370
443b09a gdk-pixbuf: Security fix CVE-2015-7674
6c91068 librsvg: Security fix CVE-2015-7558
9fd2349 bind: Security fix CVE-2015-8461
5a40d9f bind: Security fix CVE-2015-8000
1bbf183 libxml2: Security fix CVE-2015-8710
2ec6d1d libxml2: Security fix CVE-2015-8241
55aafb5 dpkg: Security fix CVE-2015-0860
029948b tzdata: update to 2016a
2bcf141 tzcode: update to 2016a
cc3a391 kernel-yocto: fix checkout bare-cloned kernel repositories
049be17 libpcre: bug fixes include security
5e94ac7 qemu: Security fix CVE-2015-7295
7ee1828 qemu: Security fix CVE-2016-1568
ca6ec2e qemu: Security fix CVE-2015-8345
b55a677 qemu: Security fix CVE-2015-7512
4922f47 qemu: Security fix CVE-2015-7504
3ec0e95 qemu: Security fix CVE-2015-8504
942ce53 openssl: Security fix CVE-2016-0701
ce8ae1c openssl: Security fix CVE-2015-3197
080e027 tiff: Security fix CVE-2015-8784
c6ae9c1 tiff: Security fix CVE-2015-8781
049b7db bind: CVE-2015-8704 and CVE-2015-8705
d632a92 rpmresolve.c: Fix unfreed pointers that keep DB opened
5b993ed openssh: CVE-2016-1907
27ee5b4 glibc: CVE-2015-8776
a4134af glibc: CVE-2015-9761
e10ec6f glibc: CVE-2015-8779
a5a965d glibc: CVE-2015-8777.patch
2fb7ee2 bitbake: toaster: make runbuilds loop
b9ad87b nativesdk-buildtools-perl-dummy: Bump PR
0a1c63a nativesdk-buildtools-perl-dummy: properly set PACKAGE_ARCH
d4b400e nativesdk-buildtools-perl-dummy: fix rebuilding when SDKMACHINE changes
8c8c4ed Revert "gstreamer1.0-plugins-good.inc: add gudev back to PACKAGECONFIG"
b832202 Revert "gstreamer: Deal with merge conflict which breaks systemd builds"
dd0ba9e build-appliance-image: Update to jethro head revision
325d205 gstreamer: Deal with merge conflict which breaks systemd builds
53b114b build-appliance-image: Update to jethro head revision
02be35d poky.conf: Bump version for 2.0.1 jethro release
f5551f8 ref-manual: Updated the list of supported image types.
aa179ae dev-manual: Added three new wic option descriptions.
20007c8 dev-manual: Added the --overhead-factor wic option description.
2dd7f46 dev-manual: Added the --extra-space wic option description.
81cc737 dev-manual: Added wic --notable option description.
2b1dce5 dev-manual:
a6f5293 kernel/kernel-arch: Explicitly mapping between i386/x86_64 and x86 for kernel ARCH
e79a538 openssh: update to 7.1p2
b171076 devtool: reset: do clean for multiple recipes at once with -a
255115f devtool: sdk-update: fix error checking
3f69105 devtool: sdk-update: fix metadata update step
5ba94af devtool: sdk-update: fix not using updateserver config file option
d03d145 classes/populate_sdk_ext: disable signature warnings
00ff950 classes/populate_sdk_ext: fix cascading from preparation failure
22446c6 scripts/oe-publish-sdk: add missing call to git update-server-info
8597a61 devtool: use cp instead of shutil.copytree
95cc641 buildhistory: fix not recording SDK information
84d48ac recipetool: create: fix error when extracting source to a specified directory
4369329 recipetool: create: detect when specified URL returns a web page
4c3191f recipetool: create: prevent attempting to unpack entire DL_DIR
caca77e recipetool: create: fix do_install handling for makefile-only software
383159e recipetool: create: avoid traceback on fetch error
be40baa recipetool: create: handle https://....git URLs
a897bfd devtool: sdk-update: fix traceback without update server set
9c4b61e classes/populate_sdk_ext: error out of install if buildtools install fails
4c07dd2 gstreamer1.0-plugins-good.inc: add gudev back to PACKAGECONFIG
83b72d8 linux-yocto: Update Genericx86* BSP to 4.1.15 kernel
44639bd libaio: don't disable linking to the system libraries
a0be9bd linux-yocto/4.1: update to v4.1.15
53f0290 libxml2: security fix CVE-2015-5312
f4b0c49 libxml2: security fix CVE-2015-8242
fb409c9 libxml2: security fix CVE-2015-7500
55d097a libxml2: security fix CVE-2015-7499
8e6b2d6 libxml2: security fix CVE-2015-7497
332eb1d libxml2: security fix CVE-2015-7498
cbc4e83 libxml2: security fix CVE-2015-8035
c4b71e1 libxml2: security fix CVE-2015-7942
fdea03d libxml2: security fix CVE-2015-8317
6fc1109 libxml2: security fix CVE-2015-7941
9eb4ce0 openssl: fix for CVE-2015-3195
6880f82 openssl: fix for CVE-2015-3194
7dcaa84 openssl: fix for CVE-2015-3193
435139b logrotate: do not move binary logrotate to /usr/bin
5f49c0a cairo: fix license for cairo-script-interpreter
a29ec81 glibc: Fix ld.so / prelink interface for ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA
b1e980f gcc: Update default Power GCC settings to use secure-plt
ed82690 prelink: Fix various prelink issues on IA32, ARM, and MIPS.
9a620da autotools: Allow recipe-individual configure scripts
f828071 toolchain-scripts.bbclass: unset command_not_found_handle
49858bd devtool: upgrade: fetch remote repository before checking out new revision
d213452 devtool: upgrade: remove erroneous error when not renaming recipe
fec97f6 devtool: upgrade: fix updating PV and SRCREV
3b4f659 devtool: upgrade: fix removing other recipes from workspace on reset
61a7de0 devtool: include do_patch in SRCTREECOVEREDTASKS
82c0072 toolchain-shar-extract.sh: do not allow $ in paths for ext SDK
f181e72 scripts/gen-lockedsig-cache: improve output
4b5d4ca toolchain-shar-extract.sh: proper fix for additional env setup scripts
d2ea8f1 toolchain-shar-relocate: don't assume last state of env_setup_script is good
02ef437 populate_sdk_ext.bbclass: Be more permissive on the name of the buildtools
3653b17 classes/populate_sdk_ext: fail if SDK_ARCH != BUILD_ARCH
8879571 classes/populate_sdk_ext: tweak reporting of workspace exclusion
eeda3c6 classes/populate_sdk_ext: make it clear when SDK installation has failed
dee9fbe classes/populate_sdk_ext: tidy up preparation log file writing
d001d46 classes/license: fix intermittent license collection warning
777451c classes/metadata_scm: fix git errors showing up on non-git repositories
cb0ca72 oeqa/selftest/layerappend: fix test if build directory is not inside COREBASE
8970ad6 oeqa/selftest/devtool: fix test if build directory is not inside COREBASE
4f7fdd0 classes/distrodata: split SRC_URI properly before determining type
3b7df55 uninative.bbclass: Choose the correct loader based on BUILD_ARCH
f3d7c3f openssl: sanity check that the bignum module is present
96b1b5c glibc: Backported a patch to fix glibc's bug(18589)
7aecb57 directfb.inc: force bfd linker for armv7a
75ca2c8 texinfo: don't create dependency on INHERIT variable
02c7b3f package_manager.py: define info_dir and status_file when OPKGLIBDIR isn't the default
003c94f libsdl2: require GLES when building Wayland support
ad6db01 gst-plugins-bad: add PACKAGECONFIGs for voamrwbenc, voaacenc, resindvd
f0d87fe gstreamer1.0-plugins-good: fix PACKAGECONFIG for gudev and add one for v4l2 and libv4l2
35f34a6 gstreamer1.0-plugins-bad: fix dependencies for uvch264 PACKAGECONFIG
3b77e20 gstreamer1.0-plugins-{base,good}: update PACKAGECONFIGs
e2d4412 libunwind: fix build for qemuarm
ef69078 guile, mailx, gcc, opensp, gstreamer1.0-libav, libunwind: disable thumb where it fails for qemuarm
4700e40 icu: force arm mode
743ee04 libxcb: Add a workaround for gcc5 bug on mips
8a3deca bitbake: fetch: use orig localpath when calling orig method
0073b23 yocto-bsp: Typo on the file extension
71dbbcd bsp-guide: Updated the license statement.
41f1026 dev-manual: Correction to the KVM stuff in the runqemu commands.
38e3c6e mega-manual: Added four new figures for GUI example.
b99ec28 poky.ent: Fixed POKYVERSION variable.
c670dc7 yocto-project-qs, ref-manual, poky.ent: CentOS Package updates
b968190 dev-manual: Updated runqemu command options list
1278753 toaster-manual: Removed SDKMACHINE from the json file example.
7b25b70 ref-manual: Updated list of supported distros.
d9423fb ref-manual: Updated the GCC 5 migration section for 2.0
347347a bitbake: lib/bb/utils: improve edit_bblayers_conf() handling of bblayers.conf formatting
5935783 bitbake: lib/bb/utils: fix error in edit_metadata() when deleting first line
7fdad70 rpcbind: Security Advisory - rpcbind - CVE-2015-7236
0cb2fa5 subversion: fix CVE-2015-3187
5b52e9b subversion: fix CVE-2015-3184
59bdde4 linux-firmware: rtl8192cx: Add latest available firmware
8ad2bcc init-install-efi: fix script for gummiboot loader
c3087bd init-install-efi: fix script for eMMC installation
d2bf9fb pulseaudio: Fix HDMI profile selection
0556c58 allarch: Force TARGET_*FLAGS variable values
e683dac libsndfile: fix CVE-2014-9756
092757e libxslt: CVE-2015-7995
dab5555 unzip: rename patch to reflect CVE fix
1753d4a readline: rename patch to contain CVE reference
9dd3422 libarchive: rename patch to reflect CVE
1401976 binutils: Fix octeon3 disassembly patch
a54a0db opkg: add cache filename length fixes
fc45dea build-appliance-image: Update to jethro head revision
e14498b meta-yocto/distro: Updated SANITY_TESTED_DISTROS.
01bba74 meta-yocto/distro: Updated SANITY_TESTED_DISTROS.
e1aa897 build-appliance-image: Update to jethro head revision
96cab33 unzip: CVE-2015-7696, CVE-2015-7697
1b2a942 vte: fix DoS from malicious escape sequence (CVE-2012-2738)
370a291 build-appliance-image: Update to jethro head revision
00911c9 linux-yocto_4.1: Update SRCREV for genericx86*
c86957a glibc: Allow 64 bit atomics for x86
b02c5f6 local.conf.sample: Disable image-prelink by default
1630dbb ref-manual: Applied a correction to the GCC 5 migration 2.0 section.
37677d6 ref-manual: Updated ADT Installer Extras
a79e303 kernel-dev: Added cross-reference to .config information
e03b19b ref-manual: Applied review updates to 2.0 migration section.
a0791c1 bitbake: toasterui: Create per-build logs
290534d bitbake: build/utils: Add BB_TASK_IONICE_LEVEL support
3ebf761 bitbake: cooker: Ensure BB_CONSOLE remains correct over server resets
5b19b71 bitbake: bb/ui: Use getSetVariable command for BB_CONSOLELOG
acc7b4d bitbake: command: Add getSetVariable command
c8051c5 bitbake: bitbake-user-manual: Added new description for BB_TASK_IONICE_LEVEL
183290a bitbake: bitbake-user-manual: Added BBTARGETS variable description.
66d3c35 bitbake: toaster: templates Add meaningful title tags
5724b2a perl: Remove errornous extra path-specs for Module::Build based modules
884cf7a perl: Correct path for vendorlib, vendorarch, sitelib and sitearch
2d0c499 perl: fix Perl5 module builds
24cfcc4 runqemu-export-rootfs: update location of unfsd binary
da386d3 gtk-icon-cache: pass the native libdir to the intercept
63a0311 connman: Move wired-setup to ${datadir}
1c3c76d useradd-staticids.bbclass: Do not require trailing colons
8a0d8ee toaster manual: Updated the set up and use chapter
f19b52c ref-manual: Updates to the 1.8 to 2.0 Migration section.
b73da6b toaster-manual: Added new Toaster functionality descriptions.
947e156 ref-manual: Updated the rootfs*.bbclass description.
62e200e bitbake: toaster: orm Fix restrictive LogMessage message length
78f935d bitbake: toaster: Remove all navigation when not in build mode
c5f147b bitbake: toaster: Run tests in build mode
1d17109 bitbake: toaster: Hide builds for non-cli projects in analysis mode
a580479 bitbake: toaster: Hide top bar buttons in analysis mode
1ec2ec3 bitbake: toaster: Show mode-appropriate landing page
bbac0f0 bitbake: toaster: Add BUILD_MODE flag to context
851f0d8 bitbake: toaster: add get_or_create_targets API
dcd9cd0 bitbake: fetcher: svn: Add support for checkout to a custom path
4ab7202 bitbake: cooker: preserve pre and post configs
fdfdfc8 oeqa/utils/decorators: fix missing keyword arguments on decorators
a2d5b7a classes/gtk-icon-cache: don't pass STAGING_LIBDIR_NATIVE to intercepts
5171329 intercepts/update_icon_cache: use STAGING_DIR_NATIVE from environment
d18d902 lib/oe/rootfs: tell intercepts where the native sysroot is
9336e1f subversion: add explicit dependency on file-replacement-native for native builds
19358d0 rpm: add explicit dependency on file-replacement-native for native builds
698c3de file: don't replace host file when built natively
83a2bde sanity: check that the host has file installed
43c46e9 bitbake: add file-native to ASSUME_PROVIDED
2925cd9 Revert "runqemu-export-rootfs: update location of unfsd binary"
d023d99 populate_sdk_base: Ensure PKGDATA_DIR exists
9b956c4 Perl: Use CC version not $Config(gccversion)
0f75740 wic/utils/oe/misc.py: Preserve PATH when running native tools
273bcb4 mtools_4.0.18.bb: Use create_wrapper() for mcopy
031d464 scripts/oe-pkgdata-util: Fix variable name in error handling
d8d4ce7 Add 850 codepage to uninative-tarball
c1d5e89 e2fsprogs: backport a patch to fix filetype for hardlink
426a9b7 oeqa/selftest: Added testcase decorators.
835525c runqemu-ifup: Check if the tap interface is set up correctly
b13c0be qemurunner: Show the output of runqemu script
9846275 runqemu-internal: Enable support for use virtio devices.
304c956 linux-yocto{, -rt}: Enable support for virtio drivers in qemu machines.
eebcbe1 runqemu: Enable support for kvm without vhost in x86 and x86_64
135d094 prserv.bbclass: remove it since it is null
c509c78 initscripts/sysfs.sh: Mount devtmpfs on /dev/ if needed
022f8cc image-mklibs.bbclass: update i586 TARGET_ARCH test to i*86
d492a70 base.bbclass: considering multilib when setting LICENSE_EXCLUSION
54b7471 gcc-target.inc: Add support for executable thats may have a suffix
0d69a171 cairo: backport fix for compatibility with OpenGL ES 2.0
64b5e3e mesa-demos: fix deadlock in sharedtex_mt
dc8495f bzip2: fix bunzip2 -qt returns 0 for corrupt archives
5bf1430 gnome-desktop: add xkeyboard-config dependency
48443cc gtk+3: Do not try to initialize GL without libgl
59fdbae classes/insane: rename invalid-pkgconfig QA check to invalid-packageconfig
73e1d33 uclibc: Implement syncfs and AT_EMPTY_PATH for all and O_PATH for arm
2e4575d systemd: Fix build with uclibc
40911f4 libtirpc: Fix a bug exposed by uclibc
d90d3e8 libpam: Fix build with uclibc
32c8625 coreutils: Do not use host paths in getloadavg.m4
20b7d87 coreutils-6.9: Add missing dependency on virtual/libiconv
8bb6436 uclibc: Fix build with gcc5
e5e8fce libtirpc: Refresh uclibc patches
fd66dd1 rpcbind: Fix build with uclibc
369c536 scripts/oe-publish-sdk: create directory before making git repo
8a555fe rootfs.py: add more info to the warning message
787253f package signing: automatically export public keys
579e254 package_manager: fail if signed feeds are enabled for ipk or dpkg
835e755 Add new bbclass for package feed signing
822844d sign_rpm.bbclass: make RPM_GPG_NAME a mandatory setting
48d60fc sign_rpm.bbclass: be more verbose in case of error
dbb9af6 package_manager: support GPG_PATH variable
b682fca sign_rpm.bbclass: introduce GPG_PATH variable
8ccbc26 apr: remove conflict with ccache
5e42593 linux-yocto: nf_tables: Add nf_tables feature
1c2fdd9 linux-yocto/3.19: fix ARM boot with gcc5.x
3bab714 linux-yocto: skip kernel meta data branches when finding machine branch
1561d0d kern-tools: avoid duplicate .scc file processing
47dcee2 linux-yocto/4.1: drm/i915: Fix the VBT child device parsing for BSW
380f2c6 linux-yocto: axxia configuration updates
505a826 build-appliance-image: Update to jethro head revision
7d30d67 ref-manual: Updated the allarch class description.
a8674ae ref-manual: Updated the MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS variable
e7c8c79 ref-manual: Added the 1.8 to 2.0 migration section.
cd48ccc dev-manual: Added notes to clarify use of pkg-config
dc9e4cb ref-manual: Added correct class name as part of pkgconfig description
5bc8fa6 ref-manual: Fixed typo in 1.6 migration section for BitBake
2fe3809 ref-manual, dev-manual: Applied feedback to edit several classes
359b7fb ref-manual: Added three PACKAGE_FEED_* variable descriptions
2f4e90c toaster-manual: Updated the json file example bits to be current
66653cb ref-manual: Updated the image-swab.bbclass description
d66cf20 toaster-manual: New section on PREFERRED_VERSION
4b9daa8 ref-manual: Added many new class descriptions.
ae0d508 toaster-manual: Added note for creating virtual environment
98d7d24 toaster-manual: Updates to example toasterconf.json file
b263a3e dev-manual: Added CentOS packages to enable runtime tests on QEMU
9abc72c adt-manual: Fixed PMS typo
2e7d650 ref-manual: Updates to clarify Fetcher URL directory parameters
7facee6 toaster-manual: Updated the section for setting up virtual env.
10970a6 dev-manual: Added package requirements for runtime QEMU testing
acacf6b ref-manual: Added linuxloader.bbclass reference description.
8fc90a7 Makefile: Updated the make file to not create toaster-manual pdf
0889848 dev-manual: Updated devtool build --help example
1944d28 documentation: Updated files to support 2.0 release.
8d2a6f0 toaster-manual: Removed "dizzy" and replaced with "jethro"
3bff581 ref-manual: Added descriptions for 5 new variables and 2 tasks.
a87268e dev-manual: Updated the Marking Packages information.
1c7f462 ref-manual: Added oe-seltest package requirements sections.
3d82046 adt-manual: Updated the build toolchain section with more detail.
54b4aff adt-manual: Updated some hard-coded distro values
196210f dev-manual: Updated the multilib example.
3930f04 ref-manual: Updated the EXCLUDE_FROM_SHLIBS description
0d1c86b ref-manual: Updated EXCLUDE_FROM_SHLIBS description.
eea7521 ref-manual: Updated distrodata.bbclass example
2eaf843 ref-manual: Added new description for PACKAGE_EXCLUDE_COMPLEMENTARY
97298fb dev-manual: Fixed typo in path for wic plugins
05d8101 ref-manual: Added new EXCLUDE_FROM_SHLIB variable
316d432 ref-manual: Added new variable description for SKIP_FILEDEPS
a1b25e6 yocto-project-qs, ref-manual: Replaced "yum" with "dnf"
d284fba ref-manual: Added cross-reference phrase to some variables
5a226f7 dev-manual: Changed multilib example
6ca549f dev-manual: Added note about building out Autotools projects
92b26ad archiver.bbclass: Fixes and improves archiver class for kernel and gcc packages
2d00803 oeqa/selftest: improve config writing and cleanup
1881564 oeqa/selftest/wic: remove numbers from test names
2ac34d2 oeqa/selftest: clean up selftest.inc in teardown
a66ed33 oeqa/selftest/wic: fix cleaning
b67b1a4 oeqa/selftest/wic: corrected testcase decorator for test18_iso_image
e191120 oeqa/selftest: verify that devtool can use plugins in other layers
b8a9728 oeqa/selftest/buildoptions: Use the correct script for cleaning the workdir
94decbc oeqa/selftest/bbtests: Updated bitbake TCs
322c324 oeqa/selftest/bbtests: clean up local DL_DIR/SSTATE_DIR safely
cf311a7 oeqa/utils/ftools: From functions that expect data, check if None
900639c oeqa/utils/ftools: Ignore the exception if file does not exist
2e91cbd oeqa/selftest/manifest.py: Test support for manifests
c9bef34 useradd_base.bbclass: Do not warn without a reason
accb59e qemu: disable Valgrind
ac1bc7d i2c-tools: fix inverted RDEPENDS
35c043b rpm: remove spurious build dependencies
41cbfd7 gcc-5.2: Fix various _FOR_BUILD and related variables
a27da70 sudo: fix file permission for /etc/pam.d/sudo
abeaed9 openssh: fix file permission for /etc/pam.d/sshd
96a5cfd sanity.bbclass: expand warning when chmod fails
409e6e0 populate SDK: prepare calling of bb.utils for exceptions
db55d31 devtool: handle virtual providers
8578bc1 libc-package: Fix localedef multilib dependency issues
0942aff toolchain-shar-extract.sh: print full-length title underline
9630fc1 classes/populate_sdk_ext: detect and warn if running in OE environment
254ff38 classes/populate_sdk_ext: add note to env setup script
9a81ba7 classes/populate_sdk_ext: prevent image construction from executing on install
ec5ec35 classes/populate_sdk_ext: consistent indentation
b8f7042 oeqa/runtime: Fix setUp and tearDown methods
3327401 oetest: Add tearDownLocal class
3b7853a test-empty-image: rename from core-image-empty
5febb1d scripts/gen-lockedsig-cache: fix race with temp file creation
3b5d6ff image-live: make SYSLINUX_ROOT changable in image recipes
5009966 toolchain-shar-extract.sh: provide proper path for env_setup_script
ae7703f classes/base: provide hints on PACKAGECONFIG error
5a02ec2 devtool: extract: fix error handling
3aac110 metadata_scm: rewrite git hash logic
59668f2 linux-yocto-custom: fix typo in Upstream-Status tag
c52dcb0 grub-efi, gummiboot: Emit correct path in startup.nsh
f9d29ab coreutils: fix for native and nativesdk
b1a7405 gcc-4.x: fix wrong warning when using the universal zero initializer {0}
402723e tzdata: reinstate changes reverted in 2014c upgrade
3770461 build-compare: drop PATCHTOOL setting
4846260 common-licenses: use correct GFDL-1.1 license text
a9053ac bitbake: toaster: Add tests for error message display on the build dashboard
2517987 bitbake: toaster: Modify "New build" button behaviour for cli builds project
56d4c84 bitbake: toaster: Clean up template code
d96cedf bitbake: toaster: More linting of tests
7c8877e bitbake: toaster: Show tooltip next to cli builds project name in all builds
7670234 bitbake: toaster: Hide tabs and add info popups for command line builds
da4c614 bitbake: toaster: Make the builds view the project page for "command line builds"
ef6fc2b bitbake: toaster: Replace "Run again" button with help text for cli builds
7467b68 bitbake: toaster: Exclude "command line builds" project from projects typeahead
b5624c7 bitbake: toaster: Show 'not applicable' for default project machine and release
3c4c984 bitbake: toaster: Reorganise and lint tests
3ba43f2 bitbake: fetch2/hg: Include missing errno import
6fa3fec bitbake: cooker: normalize build targets
5effe8f bitbake: toaster: Allow any text input to machine configuration variable
320d05e bitbake: toaster: exit or return depending on the mode
2e2e40c bitbake: toaster: set TOASTER_MANAGED variable
a73895e bitbake: toaster: get rid of SRCFILE
779539c bitbake: toaster: use path to the script to guess config path
eb8b2b9 bitbake: toaster: Guard against builds with no targets
65e8bde bitbake: toaster: Remove Toaster exceptions section of build dashboard
93f0b61 bitbake: toaster: Record critical errors
069a611 bitbake: toaster: Test that exception isn't thrown by project page
026e981 bitbake: toaster: Check whether buildrequest exists before using it
1feeb8e bitbake: toaster: Always run bldcontrol migrations
ae82d77 bitbake: toaster: buildinfohelper Detect command line builds
596c219 bitbake: toaster: Disable add layer button when input is empty
24e5a17 bitbake: toaster: Have 'Version' next to recipe name
c895838 bitbake: toaster: Improve directory structure layout
2f52ef4 bitbake: toaster: importlayer Update property names for importlayer api calls
556c0ea lib/oe/image.py: Fix dependency handling for compressed types
d302c98 bitbake: toaster: Fix missing tooltips from layers on project configuration page
7e5464b bitbake: toaster: Fix broken test case
2e375e6 bitbake: toaster: exclude recipes with empty names
fa3e82d bitbake: toaster: delete recipe if it can't be saved
82675fc bitbake: toaster: Remove project name from latest project builds
6aeaca1 bitbake: toaster: test get_alldeps API
0fb6be0 bitbake: toaster: fix orm tests
dea679a bitbake: toaster: fix NameError
6e0c0fd bitbake: toaster: use get_alldeps in layerdetails renderer
bd2ec77 bitbake: toaster: implement API to get full list of deps
05594f8 bash: Disable custom memory allocator
adbbab7 icu: fix install race
b1d0aab webkitgtk, gcr, libsecret: force ARM mode
67d6500 gtk+3: gtk3-demo needs libgl
f385ed1 lib/oe/distro_check: Remove '_proxy' on dict values used by urllib.open
4bf7b7d cups: fix non-deterministic xinetd behaviour
32dbf71 cronie: clean up bugtracker info
6396d6a irda-utils: clean up bugtracker info
8d5878b screen: fix CVE-2015-6806
acdc2db kbd: provide a workaround for build failures
67959b9 machine/qemu: Fix OpenGL/GLX support with xserver-xorg.
fedff4f busybox.inc: remove redundant @DATADIR@ replacement
78b9d2d insane.bbclass: remove misleading path in warning
8995a30 iptables: only check libnetfilter-conntrack when libnfnetlink is enabled
e35c404 bitbake: toaster: Don't descend into directories for cached_layers
d9528d9 toasterconf: update meta-yocto to jethro and drop dizzy
2d6701f bitbake: toaster: Update JS unit tests
ab896df bitbake: toaster: Fix stale layer state buttons
41a5f82 bitbake: toaster: tables Add the recipe filter back into the Recipe table
2bebcd4 bitbake: toaster: Fix typo in returning pk list of layer versions in current project
d6d680d bitbake: toaster: layerdetails update build recipe button class name
7794b57 bitbake: toaster: Hide "Download build log" button if log doesn't exist
8c69539 bitbake: toaster: fix naming for clone directory
41286f4 bitbake: toaster: buildinfohelper Skip packages we have no build info about
97d0006 bitbake: toaster: buildinfohelper associate build data with built_recipe
0dcc963 bitbake: toaster: remove bashisms so script works in dash as well
8068aa3 bitbake: toaster: get rid of interactivity in bldcontrol
7d7823e bitbake: toaster: check for configuration file and exit if not found
315989c bitbake: toaster: remove layer and build dir interactive questions
489d5ff bitbake: toaster: removed superuser question from startup
c7d1dab bitbake: toaster: orm Machines filter don't pass self in as parameter
dd957fe bitbake: toaster: Rationalise mimetype guessing to fix artifact downloads
ce9011a bitbake: toaster: Use Python's mimetypes module
466bbec bitbake: toaster: display warnings for bad "IMAGE_FSTYPES" values
8b7d846 bitbake: toaster: Set default columns in recipes tables
9daf6ef bitbake: toaster: Comment out broken sorting and filters
b661f53 bitbake: toaster: Don't HTTP cache ToasterTable responses
a3742a0 bitbake: toaster: Don't add new history entries when table data loads
fa68ae0 bitbake: toaster: use meaningful logging levels
bd8b27b bitbake: toaster: ignore ReachableStamps event
ceeb52a linux-yocto: Update SRCREV for genericx86* BSPs
7766265 os-release: fix do_compile() when RPM signing is enabled
9a02df0 readline: actually apply readline63-003 (aka CVE-2014-2524)
a856580 rpm: fix return without value in patch
49bf4b1 Revert "qemu-native: Enable temporary debug info as default."
ad8c021 linux-yocto/4.1: drm/i915 backports
48e5579 oeqa/utils/qemurunner: Add support for Unicode from qemu
1f99452 report-error.bbclass: Support Unicode reports
b25af33 udev: add PROVIDES = "libgudev"
a0d9d2d lib/oe/image.py: Add image generation for companion debug filesystem
8ee9a93 package_manager.py: sort output of OpkgPkgsList().list
37c54af ThunderX: Add initial tune file
a0e7311 tzdata: update to 2015g
931dda4 tzcode: update to 2015g
8cacd22 recipetool: create: fix change in path structure if --extract-to path exists
e961688 devtool: update-recipe: avoid updating patches that have not changed
07fc8c2 oe-selftest: wic: fix LocalSetup
eac61f3 build-appliance-image: Update to jethro head revision
c9bdcf5 oeqa/runexported: Replaced optionparser with argparse.
038ae3f systemd: remove glib-2.0 build dependency
0516cd2 webkitgtk: Add some PACKAGECONFIG options.
dff30d2 fontcache: allow to pass extra parameters and environment to fc-cache
d5ce2f5 webkitgtk: Use ON/OFF for cmake switches.
ebd5035 testimage: Added IO commands to dumps
b73a35e distro-alias.inc: Updated for jethro 2.0 release
b7f9cde build-appliance-image: Update to jethro head revision
cf8ad8d toaster: Special case the openembedded-core layer to avoid duplicates
20b888b build-appliance-image: Update to jethro head revision
8fb5a5a bitbake: bitbake/lib: Update version to 1.28.0
0eca7ff build-appliance-image: Update to jethro head revision
34fede6 poky.conf: Bump version for 2.0 jethro release
a7329e1 Revert "oeqa/runtime: Added one runtime testcase in connman."
c2e78e3 qemu: Drop BROKEN usage
e788961 smart:cache.py: getPackages() matches name + arch
f3e57ba devtool: modify: use correct local files directory name
7cb0765 xuser-account: Take over xuser specific D-Bus policy
cdaa8fd bluez5: Use upstream D-Bus policy
e4a4961 ptest: run-ptest not required to run do_install_ptest
12cd705 distrodata: Take account proxies on distrodata tasks
f047ee8 devtool: update-recipe: enable var history tracking
979de77 lib/oeqa/selftest/yoctobsp: Basic tests for yocto-bsp script
e20d8b8 scripts/lib/bsp/engine: Indent the karch properties when stored into a file
f2933cc yocto-bsp: Update templates to 4.1 kernel
8283a57 scrips/lib/bsp/engine: List properties to stdout when output parameter is omitted
b355a5e scripts/yocto-bsp: Exit successfully when asking for help
ad9ee3d meta-yocto-bsp: bump to linux-yocto 4.1 for the non-x86 BSPs
cdc57f6 bitbake: siggen: Make it clear why nostamp tasks signatures don't match
1630f0a bitbake: runqueue: Add handling of virtual/xxx provider mappings
0b96e6f bitbake: taskdata: Add a function to return the virtual/ mapping data
40fae32 bitbake: cookerdata: Rename BBPKGS -> BBTARGETS
1e467b3 bitbake: bitbake-worker: Guard against multiprocessing corruption of event data
e5b9c2a oeqa/selftest/wic: Use SetupLocal instead of Setup
4266cc9 kernel.bbclass: fix the bug of checking the existing sections in do_strip()
ec1146e linux-yocto_{3.14,3.19,4.1}: qemuarm enable virtio drivers
2ea0e4c runqemu-internal: qemuarm enable usage of virtio devices
a23239a gnome-doc-utils: xslt - don't install Makefiles
f671163 apr-utils: cleanup buildpaths for target stuffs
f68d739 apr: cleanup buildpaths from target stuffs
a7ac905 curl: cleanup buildpaths from curl-config
833bfd3 dropbear: fix key generation when systemd is in use and rootfs is readonly
d592abd image.bbclass: tweak the key location for dropbear when rootfs is readonly
299806d openssh: fix sshd key generation when systemd is in use and rootfs is readonly
006497e image.bbclass: when building a readonly rootfs, tweak ssh settings regardless of init system in use
f1e2515 lttng-tools: Drop KERNELDIR reference
381a7bd meta-ide-support: No need to mark as nostamp anymore
ab9d2bb adt-installer: No need to mark as nostamp
d8ab563 distutils3: Avoid MACHINE specific checksums
a0d6322 gstreamer-omx: Improve variable expansion of ${S}
c71bd57 bitbake.conf: Exclude sstate-outputdirs flag from checksums
f02cbc6 deploy: Mark deploy tasks as MACHINE specific
a0435bf layer.conf: Add SIGGEN exclusion for oprofile kernel dependency
f4a8917 layer.conf: Improve siggen exclusion to handle virtual/libc
6fe4fd2 multilib_global: Add handling of SIGGEN variables for multilib
2c19695 lib/oe/sstate: Add tasks_resolved handler for virtual/xxx mappings
ff17f14 oeqa/selftest/sstatetests: Add test that MACHINE doesn't change target sigs
d822764 meta-selftest: Add qemux86copy machine
6cfc7c0 oeqa/selftest/sstatetests: Add check for same sigs for SDKMACHINE
5dbd061 multilib.conf: Ensure MACHINE doesn't change target sigs
71fdb36 gcc-multilib-config: Ensure SDK_ARCH doesn't change target sigs
c9ea0c6 lib/oe/package_manager: Handle empty package list in opkg case
ec504e0 oeqa/utils/decorators: Append the testname without the full path
8fe5b48 kern-tools: fix multi-layer patch application
b054506 linux-yocto/4.1: braswell bug fixes
c6c093b linux-yocto/4.1: update to 4.1.8 -stable
a502a2d linux-yocto-rt/4.1: integrate axxia BSP
38f0ffa meta: fix build with gettext 0.16.1
56c0fdf hostap-utils: Use C99 stddefs in defining local typedefs
34707c2 linux-yocto-custom: Update for newer kernel
df09a6f oetest: Change logic of a failed test
7a6cb2e cwautomacros: cleanup buildpath in autogen.sh
1222eb1 oeqa/runexported: Fix a problem with ssh_target_log existing in folder.
cb93670 qemurunner: Sanitize output from qemu and qemu pid
ba0f6ca oeqa/testimage: Add ability to run single test from suite.
3e40688 recipes-extended: remove duplicate recipe and .wks
6f2047a runqemu-internal: Make sure two serial ports always exist
385a5e8 cross-canadian.bbclass: big-endian ARM is also gnueabi.
7c96fcf openssl: fix ptest failures
d9ce095 python-async: inherit setuptools
adb6987 util-linux: add runuser PAM config files to fix runuser error
9549f57 oeqa/decorators: Fixed a problem with decorator logs link.
790b6c7 oeqa/selftest/wic: Added testcase decorator to all testcases + fixed minor typos.
ffd4bd6 toolchain-shar-extract: Correct environment-setup script names for multilib
249b810 lsb: add lsbinitscripts and util-linux rdepends
c7548b5 systemd: add PACKAGECONFIG for qrencode
3b04553 opkg: create opkg.lock in /run instead of /var/run
c275627 toolchain-shar-relocate.sh: make it faster
434665d populate_sdk_base: Simplify postprocess commands
5bfcd13 classes/meta: Add DISTRO_FEATURES check for gtk+/gtk3+
5b629a9 devtool: modify: make bitbake use local files from srctree
e9bae50 devtool: better support for local source files
a74fa38 devtool: file mover function that creates target dir
109c09b devtool: update_recipe: refactor patch generation
c976028 devtool: update-recipe: add new patches in correct order
2f8440b oe-selftest: devtool: add method for checking repo status
0a9f59e oe-selftest: devtool: add method for checking srctree repo
afb0142 oe-selftest: devtool: add setup() method
31c3078 oe.patch.GitApplyTree: add paths argument to extractPatches
d5e2dd4 recipeutils: implement get_recipe_local_files()
4bc3f09 bitbake: toaster: move clones into subdirectory
9e1516d bitbake: toaster: make clone directory name unique
552fd83 bitbake: toaster: fix reimporting module
55dc927 bitbake: toaster: fix bug in resetting git repository
6939340 bitbake: toaster: use git reset --hard instead of rebase
3d73dfa bitbake: toaster: don't use --single-branch when cloning
226e7da bitbake: utils: only add layer once in edit_bblayers_conf()
d48b7ef bitbake: toaster: display most recent builds for projects
f902dc6 bitbake: toaster: orm remove the complicated querying on the ORM
fe29297 bitbake: Revert "bitbake: toaster: don't re-create Target objects"
e6d967d bitbake: toaster: buildinfohelper Create a copy of the built layer and recipe
17fe16b bitbake: toaster: tables show all recipes in the layerdetails even duplicates
aed6d2e bitbake: toaster: Prioroitise the layer more generic vcs reference over the sha
922503f bitbake: toaster: Create a relationship between build information and toaster layers
0bc0a44 bitbake: toaster: Special case the openembedded-core layer to avoid duplicates
e68f63a bitbake: toaster: Add test cases for new Image customisation features
d98c771 bitbake: toaster: Add Image customisation frontend feature
37948cc bitbake: toaster: Add ToasterTables for Image customisation feature
a3ff4b2 bitbake: toaster: Add new ReST API for Image Customisation feature
28153ac bitbake: toaster: Fix indentation of jsunittests view
60f3ddb bitbake: toaster: implement decorator for REST responses
a7f43bd bitbake: toaster: add toggle for enabling image customisation feeature
3ff6401 bitbake: toaster: Add CustomImageRecipe model
8948d04 bitbake: toaster: ToasterTable remove unused class definition
c1157cf bitbake: toaster: add nocache option to the ToasterTable widget
1cafc39 bitbake: toaster: widgets ToasterTable Add more info to search field exception
c71bbad bitbake: toaster: widgets ToasterTable add logger to notify when cache hit
934f8d7 bitbake: toaster: create custom layer and recipes for Image customisation
340b398 bitbake: toaster: tables Move the title and name into the widget
e1851fe bitbake: toaster: make a workaround for old style index
f78f902 bitbake: prserv/serv.py: Better messaging when starting/stopping the server with port=0
134b267 bitbake: prserv/serv: Close the DB connection out of class destructor
caf422c multilib: Add TARGET_VENDOR to saved variables list
3af9f06 oeqa/sdk/gcc: Fix makefile test
00f0d2b gdk-pixbuf: Only apply native cleaning in normal task, not setscene
452237b runqemu-export-rootfs: update location of unfsd binary
aa1253f runqemu: don't complain about conflicting machines if they are equal
994915b oeqa/testimage: Remove absolute path to oeqa from json
f8da3b6 iproute2: fix the configure process
218d9f4 gcc-multilib-config: Expand ccargs variable
be13cdb Empty image: core-image-empty recipe
2bbec56 Empty image:rootfs.py:handle empty PACKAGE_INSTALL
4562f3f gstreamer1.0-plugins-bad: change glimagesink rank to marginal
677a463 linux-yocto/4.1: rt update to 4.1.x-rt8
cdd9c4c linux-yocto/4.1: common-pc-drivers: add CONFIG_PATA_SCH
9028d93 ltp: replace 'inline' with 'static inline' for gcc 5.x
5942dfe waffle: Fix build with musl
cfa3ed0 cups: fix pam configuration file's permission
8227d49 busybox: Use CC instead of bare LD to be the Linker
a3c4817 busybox: Use UTMPX instead of legacy UTMP
ea031f0 distrodata: handle recipes with empty or absent SRC_URI in checkpkg()
5cc44fe recipeutils.py: don't hardcode the upstream version as 1.0 when SRC_URI is empty or absent
320500e oeqa/parselogs: Updated log parser whitelist.
adeba9a connman: Don't use a blanket "allow" D-Bus policy
907c8a7 connman: Depend on xuser-account unconditionally
1b146c5 byacc: add missing patch header
5fd3089 sstate: run recipe-provided hooks outside of ${B}
3fb464f oeqa/decorators: Add timestamp to decorator logs.
5f371e5 image types: add hdddirect
ca52ca0 packagegroup-core-standalone-sdk-target: ensure libatomic is in SDK
6d68ba9 glibc/mmc-utils: Rename 'BRANCH' variable to 'SRCBRANCH' for clearness
c5aab3f sanity.bbclass: show warning when chmod fails
5702a19 systemd: apply persistent storage udev rules also for /dev/hd*
cb24cbb rpm: search for gpg if gpg2 is not found
217cccd openssl: Add mapping for nios2
3408d0d qemurunner: Handle qemu start failure correctly
79e3418 gcc-runtime: Add multilib C++ header mapping
09af262 oeqa/oetest: Fix SDK command execution
5d4f39f mulitlib: Ensure SDKTARGETSYSROOT is set correctly
c356961 gtk-icon-cache/pixbufcache: don't set GDK_PIXBUF_MODULEDIR
4a36842 librsvg: tell configure where gdk-pixbuf-query-loaders is
8a12632 gdk-pixbuf: move gdk-pixbuf-query-loaders to $libdir for multilib safety
b070778 gdk-pixbuf: move gdk-pixbuf-pixdata to gdk-pixbuf-dev
7fb583a multilib: Drop populate_sdk variable manipulation
eb7b1a5 package_manager.py: make rpm install mutilib pkgs corectly
5a51fb2 bitbake: prserv/serv: Start/Stop daemon using ip instead of host
2687b24 gdk-pixbuf: Avoid rebuild failures
94184a0 systemd: fix tmpfiles location when multilib in use
179ee77 p11-kit: configure without trust-paths
c7624b4 oe-pkgdata-util: avoid returning skipped packages
dd11f5c toolchain-shar-extract.sh: remove checkbashism
99fc786 archiver: stamp-base is dead, remove it
ce7bc12 gcc-shared-source: Set empty SRC_URI
47ef201 libgcc.inc: package baremetal multilib libraries
aff7e72 meta-selftest: add error recipe and error-image
261e68c libksba: fix pkgconfig patch
3235a64 systemd: disable problematic GCC 5.2 optimizations
6e7ed5e Revert "systemd: disable problematic GCC 5.2 optimizations"
9673278 oeqa/selftest/archiver: Test that archiver filters on recipe name
6807327 oeqa/utils/dump: Add default commands and directory
5d31e94 webkitgtk: add REQUIRED_DISTRO_FEATURES
8733b53 oeqa/runexported: Removed DEPLOY_DIR as mandatory.
f1e7fb0 oeqa/oetest: Remove bb as requirement for oetest.
d70c5cb gcc-5.2: disable isl
66dca4b kmod: Change SRCREV to fix return code in error path
61e77c7 oeqa/runtime/parselogs.py: Fix dmesg log retrieve in sato
dd26efb insane.bbclass: make package_qa_clean_path return a relative path
bdbd8b4 devtool: upgrade: use shutil.move instead of os.rename
346784b devtool: runqemu: avoid recipe parse
85d8b4a devtool: second fix for running from a different directory
6363a95 guile: cleanup buildpaths and add RDEPENDS on pkgconfig
6d1447b gmp: Use __gnu_inline__ attribute in 4.2.1
42dc902 pseudo_1.7.4.bb: fix f*open()
9f66aa1 bitbake: toaster: start script warning text formatting small improvement
c6eaef0 bitbake: tinfoil: remove logging handler at shutdown
fb26ea3 bitbake: toaster: remove time from builds in progress
15b482b bitbake: toaster: Add fake entry to Target_File for filesystem root
767fe69 bitbake: toaster: layerdetails Fix back button tab behaviour
4c0320f bitbake: toaster: UI test improvements
4c5af77 bitbake: toaster: support selenium testing from mac OS X
e6c4970 bitbake: toaster: add 2 UI tests
f6a70ad bitbake: toaster: change UI to show tasks
08000eb bitbake: toaster: don't re-create Target objects
ea37358 bitbake: toaster: store task name in Target objects
524ddd8 oeqa/utils/qemurunner.py: Remove duplicate message on LoggingThread start
376ce71 oeqa/utils/qemurunner.py: Fix HIGH CPU usage on LoggingThread
6c0066c devtool: add search command
0613301 devtool: add basic means of running runqemu within the extensible SDK
c4181c6 devtool / recipetool: add handling for binary-only packages
76084cd devtool: build-image: delete bbappend at end of build
ef197f9 devtool: build-image: improve image recipe handling
8f67bb7 devtool: build-image: tell user where to find output files
afb9340 devtool: build-image: fix recipe/package terminology
d736518 devtool: add: move important "recipe created" message to the end
3bd0f33 devtool: add: set up fetched source as a git repository by default
e759b0b devtool: better handling for recipes that don't unpack source
a34f733 devtool: fix extracting source for work-shared recipes
5bc437b devtool: show proper error when extracting source for recipes with disabled unpack task
210d959 recipetool: create: fix handling of URIs containing #
a35ad72 recipetool: create: fix creating empty shell functions
30c7e7a devtool: add: properly handle separate build directory
99fc284 devtool / lib/oe/recipeutils: ensure we can parse without bbappends
5d1a117 devtool: add: ensure --color=never turns off recipetool colour output
ae788fb devtool: check that source tree still exists
99cd79d scripts/contrib: add devtool stress tester
e0b9a96 lib/oe/patch: fix for git am not cleaning up after itself
8fb70c6 classes/externalsrc: fix setting of deps varflag as a string
586291f classes/externalsrc: scale back warning to a plain note
72810f9 toolchain-shar-extract.sh: show progress when extracting SDK
0dc9299 classes/populate_sdk_ext: drop work-config.inc
3a08728 classes/populate_sdk_ext: allow custom configuration for extensible SDK
b853dde classes/populate_sdk_ext: fix missing environment settings if running installer with sh
374e1fe lib/oe/recipeutils: properly split unexpanded variable values
7fb3fb9 linux-yocto/4.1: hid, bluetooth, aufs and yaffs2 updates
9241ec5 image_types.bbclass: Don't try to create ubi symlink twice
266e417 oeqa/selftest: buildoptions.py Removed unused imports
329d09f systemd: disable problematic GCC 5.2 optimizations
554c817 libgpg-error: Add support for nios2
84e1100 pixman: Fix missing FE_DIVBYZERO on nios2
9baffc1 libtool: Fix nios2 support
ba1e0ee linux-yocto: depend on libgcc for nios2
8efff24 kernel-arch: Add nios2 to valid archs
4d9af35 siteinfo: Add nios2-linux
76a8c74 insane: Add nios2 support
6adffd0 autotools: fix traversal bug in aclocal copying
6a02bbd python3-debugger: Adds pkgutils dependency to pdb
a7dd758 python3-debugger: fix importlib dependency
0e5a911 libsdl: depends on libglu when both x11 and opengl
d762ea1 lttng-tools: sessiond: disable: match app event by name
c8a7d76 testimage.bbclass: Fix break introduced with SIGTERM handling
7d166a6 sysstat: Include needed headers explicitly
d36384e connman: Fix build with musl
0df9b98 quota: Replace using -I= with STAGING_INCDIR
433a7a0 opkg: Include stdio.h for FILE definition
5aadabf syslinux: Dont bypass gcc driver for dependency generation options
05b9a0c gnu-efi, syslinux: Support gcc < 4.7
cdfd96e gummiboot: Fix build warnings seen with gcc5
0141652 qt4: Fix kmap2qmap build with clang
6b73a05 xz: Correctly specify GPL-3.0 with autoconf exception
a96069d insane.bbclass: drop extra line-feed in pkgname check
10fb575 insane.bbclass: show PN and relative path in package_qa_check_host_user
5624889 package.bbclass: add summary line to installed-vs-shipped QA check
d6e40e8 initramfs-framework: better error reporting for invalid root boot parameter
288a9ff initramfs-framework: fix "support dropping into shell on failure"
5ff7e8d qt4: remove already merged patch
9578b09 gdk-pixbuf: remove redundant libx11 DEPENDS line
fe70aa4 runqemu-internal: For qemumicroblaze use the QEMU provided device tree
9aaf7e3 runqemu-internal: Fix qemu networking for qemuzynq an qemumicroblaze
be493ba libpcre: Allow building 16 and 32bit libpcre versions
f32a6e1 oe-git-proxy: Allow socks4 as protocol in $ALL_PROXY
18309f0 oe-git-proxy: Correct the parsing of a port in $ALL_PROXY
c035f35 oe-git-proxy: Allow explicit IP addresses in $NO_PROXY
bbe06b4 oeqa/testimage: Enhance -v switch in testimage
e0b38f2 wic-image-minimal: add dependency to .wks
dd7726f wic: fix partition size calculation
219d73a wic: use ext4 in wic-image-minimal.wks
ce2cb45 wic: add dependencies to wic-image-minimal recipe
a66f586 testimage.bbclass: Don't require an image manifest
39c11d8 gstreamer1.0: Fix basesink drop buffer error
5f13793 grep: fix install if bindir == base_bindir
b17c02f gzip: fix install if bindir == base_bindir
b6f8ea1 cpio: fix install if bindir == base_bindir
fe0cdab tar: fix install if bindir == base_bindir
c6b52f3 bind: fix too long error from gen
81d65df ccache: fix file name too long
cdbe5c9 bitbake.conf: update APACHE_MIRROR
12772c8 linux-yocto/4.1: hid-core: Avoid uninitialized buffer access
88b11e6 kern-tools: optimize patching peformance
0864782 linux-yocto/4.1: aufs, yaffs2 and driver fixes

git-subtree-dir: yocto-poky
git-subtree-split: c8a4ed9a63de6124c8a3cceb80c7db48f12f7aea
diff --git a/meta/lib/oe/copy_buildsystem.py b/meta/lib/oe/copy_buildsystem.py
index 979578c..c0e7541 100644
--- a/meta/lib/oe/copy_buildsystem.py
+++ b/meta/lib/oe/copy_buildsystem.py
@@ -14,8 +14,9 @@
         shutil.copymode(src, dest)
 
 class BuildSystem(object):
-    def __init__(self, d):
+    def __init__(self, context, d):
         self.d = d
+        self.context = context
         self.layerdirs = d.getVar('BBLAYERS', True).split()
 
     def copy_bitbake_and_layers(self, destdir):
@@ -38,7 +39,7 @@
             if os.path.exists(layerconf):
                 with open(layerconf, 'r') as f:
                     if f.readline().startswith("# ### workspace layer auto-generated by devtool ###"):
-                        bb.warn("Skipping local workspace layer %s" % layer)
+                        bb.plain("NOTE: Excluding local workspace layer %s from %s" % (layer, self.context))
                         continue
 
             # If the layer was already under corebase, leave it there
diff --git a/meta/lib/oe/distro_check.py b/meta/lib/oe/distro_check.py
index 8ed5b0e..f92cd2e 100644
--- a/meta/lib/oe/distro_check.py
+++ b/meta/lib/oe/distro_check.py
@@ -1,7 +1,23 @@
-def get_links_from_url(url):
+from contextlib import contextmanager
+@contextmanager
+def create_socket(url, d):
+    import urllib
+    socket = urllib.urlopen(url, proxies=get_proxies(d))
+    try:
+        yield socket
+    finally:
+        socket.close()
+
+def get_proxies(d):
+    import os
+    proxykeys = ['http', 'https', 'ftp', 'ftps', 'no', 'all']
+    proxyvalues = map(lambda key: d.getVar(key+'_proxy', True), proxykeys)
+    return dict(zip(proxykeys, proxyvalues))
+
+def get_links_from_url(url, d):
     "Return all the href links found on the web location"
 
-    import urllib, sgmllib
+    import sgmllib
     
     class LinksParser(sgmllib.SGMLParser):
         def parse(self, s):
@@ -24,19 +40,18 @@
             "Return the list of hyperlinks."
             return self.hyperlinks
 
-    sock = urllib.urlopen(url)
-    webpage = sock.read()
-    sock.close()
+    with create_socket(url,d) as sock:
+        webpage = sock.read()
 
     linksparser = LinksParser()
     linksparser.parse(webpage)
     return linksparser.get_hyperlinks()
 
-def find_latest_numeric_release(url):
+def find_latest_numeric_release(url, d):
     "Find the latest listed numeric release on the given url"
     max=0
     maxstr=""
-    for link in get_links_from_url(url):
+    for link in get_links_from_url(url, d):
         try:
             release = float(link)
         except:
@@ -70,7 +85,7 @@
     return set.keys()
 
 
-def get_latest_released_meego_source_package_list():
+def get_latest_released_meego_source_package_list(d):
     "Returns list of all the name os packages in the latest meego distro"
 
     package_names = []
@@ -82,11 +97,11 @@
     package_list=clean_package_list(package_names)
     return "1.0", package_list
 
-def get_source_package_list_from_url(url, section):
+def get_source_package_list_from_url(url, section, d):
     "Return a sectioned list of package names from a URL list"
 
     bb.note("Reading %s: %s" % (url, section))
-    links = get_links_from_url(url)
+    links = get_links_from_url(url, d)
     srpms = filter(is_src_rpm, links)
     names_list = map(package_name_from_srpm, srpms)
 
@@ -96,44 +111,44 @@
 
     return new_pkgs
 
-def get_latest_released_fedora_source_package_list():
+def get_latest_released_fedora_source_package_list(d):
     "Returns list of all the name os packages in the latest fedora distro"
-    latest = find_latest_numeric_release("http://archive.fedoraproject.org/pub/fedora/linux/releases/")
+    latest = find_latest_numeric_release("http://archive.fedoraproject.org/pub/fedora/linux/releases/", d)
 
-    package_names = get_source_package_list_from_url("http://archive.fedoraproject.org/pub/fedora/linux/releases/%s/Fedora/source/SRPMS/" % latest, "main")
+    package_names = get_source_package_list_from_url("http://archive.fedoraproject.org/pub/fedora/linux/releases/%s/Fedora/source/SRPMS/" % latest, "main", d)
 
 #    package_names += get_source_package_list_from_url("http://download.fedora.redhat.com/pub/fedora/linux/releases/%s/Everything/source/SPRMS/" % latest, "everything")
-    package_names += get_source_package_list_from_url("http://archive.fedoraproject.org/pub/fedora/linux/updates/%s/SRPMS/" % latest, "updates")
+    package_names += get_source_package_list_from_url("http://archive.fedoraproject.org/pub/fedora/linux/updates/%s/SRPMS/" % latest, "updates", d)
 
     package_list=clean_package_list(package_names)
         
     return latest, package_list
 
-def get_latest_released_opensuse_source_package_list():
+def get_latest_released_opensuse_source_package_list(d):
     "Returns list of all the name os packages in the latest opensuse distro"
-    latest = find_latest_numeric_release("http://download.opensuse.org/source/distribution/")
+    latest = find_latest_numeric_release("http://download.opensuse.org/source/distribution/",d)
 
-    package_names = get_source_package_list_from_url("http://download.opensuse.org/source/distribution/%s/repo/oss/suse/src/" % latest, "main")
-    package_names += get_source_package_list_from_url("http://download.opensuse.org/update/%s/rpm/src/" % latest, "updates")
+    package_names = get_source_package_list_from_url("http://download.opensuse.org/source/distribution/%s/repo/oss/suse/src/" % latest, "main", d)
+    package_names += get_source_package_list_from_url("http://download.opensuse.org/update/%s/rpm/src/" % latest, "updates", d)
 
     package_list=clean_package_list(package_names)
     return latest, package_list
 
-def get_latest_released_mandriva_source_package_list():
+def get_latest_released_mandriva_source_package_list(d):
     "Returns list of all the name os packages in the latest mandriva distro"
-    latest = find_latest_numeric_release("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/")
-    package_names = get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/main/release/" % latest, "main")
+    latest = find_latest_numeric_release("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/", d)
+    package_names = get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/main/release/" % latest, "main", d)
 #    package_names += get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/contrib/release/" % latest, "contrib")
-    package_names += get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/main/updates/" % latest, "updates")
+    package_names += get_source_package_list_from_url("http://distrib-coffee.ipsl.jussieu.fr/pub/linux/MandrivaLinux/official/%s/SRPMS/main/updates/" % latest, "updates", d)
 
     package_list=clean_package_list(package_names)
     return latest, package_list
 
-def find_latest_debian_release(url):
+def find_latest_debian_release(url, d):
     "Find the latest listed debian release on the given url"
 
     releases = []
-    for link in get_links_from_url(url):
+    for link in get_links_from_url(url, d):
         if link[:6] == "Debian":
             if ';' not in link:
                 releases.append(link)
@@ -143,16 +158,15 @@
     except:
         return "_NotFound_"
 
-def get_debian_style_source_package_list(url, section):
+def get_debian_style_source_package_list(url, section, d):
     "Return the list of package-names stored in the debian style Sources.gz file"
-    import urllib
-    sock = urllib.urlopen(url)
-    import tempfile
-    tmpfile = tempfile.NamedTemporaryFile(mode='wb', prefix='oecore.', suffix='.tmp', delete=False)
-    tmpfilename=tmpfile.name
-    tmpfile.write(sock.read())
-    sock.close()
-    tmpfile.close()
+    with create_socket(url,d) as sock:
+        webpage = sock.read()
+        import tempfile
+        tmpfile = tempfile.NamedTemporaryFile(mode='wb', prefix='oecore.', suffix='.tmp', delete=False)
+        tmpfilename=tmpfile.name
+        tmpfile.write(sock.read())
+        tmpfile.close()
     import gzip
     bb.note("Reading %s: %s" % (url, section))
 
@@ -165,41 +179,41 @@
 
     return package_names
 
-def get_latest_released_debian_source_package_list():
+def get_latest_released_debian_source_package_list(d):
     "Returns list of all the name os packages in the latest debian distro"
-    latest = find_latest_debian_release("http://ftp.debian.org/debian/dists/")
+    latest = find_latest_debian_release("http://ftp.debian.org/debian/dists/", d)
     url = "http://ftp.debian.org/debian/dists/stable/main/source/Sources.gz" 
-    package_names = get_debian_style_source_package_list(url, "main")
+    package_names = get_debian_style_source_package_list(url, "main", d)
 #    url = "http://ftp.debian.org/debian/dists/stable/contrib/source/Sources.gz" 
 #    package_names += get_debian_style_source_package_list(url, "contrib")
     url = "http://ftp.debian.org/debian/dists/stable-proposed-updates/main/source/Sources.gz" 
-    package_names += get_debian_style_source_package_list(url, "updates")
+    package_names += get_debian_style_source_package_list(url, "updates", d)
     package_list=clean_package_list(package_names)
     return latest, package_list
 
-def find_latest_ubuntu_release(url):
+def find_latest_ubuntu_release(url, d):
     "Find the latest listed ubuntu release on the given url"
     url += "?C=M;O=D" # Descending Sort by Last Modified
-    for link in get_links_from_url(url):
+    for link in get_links_from_url(url, d):
         if link[-8:] == "-updates":
             return link[:-8]
     return "_NotFound_"
 
-def get_latest_released_ubuntu_source_package_list():
+def get_latest_released_ubuntu_source_package_list(d):
     "Returns list of all the name os packages in the latest ubuntu distro"
-    latest = find_latest_ubuntu_release("http://archive.ubuntu.com/ubuntu/dists/")
+    latest = find_latest_ubuntu_release("http://archive.ubuntu.com/ubuntu/dists/", d)
     url = "http://archive.ubuntu.com/ubuntu/dists/%s/main/source/Sources.gz" % latest
-    package_names = get_debian_style_source_package_list(url, "main")
+    package_names = get_debian_style_source_package_list(url, "main", d)
 #    url = "http://archive.ubuntu.com/ubuntu/dists/%s/multiverse/source/Sources.gz" % latest
 #    package_names += get_debian_style_source_package_list(url, "multiverse")
 #    url = "http://archive.ubuntu.com/ubuntu/dists/%s/universe/source/Sources.gz" % latest
 #    package_names += get_debian_style_source_package_list(url, "universe")
     url = "http://archive.ubuntu.com/ubuntu/dists/%s-updates/main/source/Sources.gz" % latest
-    package_names += get_debian_style_source_package_list(url, "updates")
+    package_names += get_debian_style_source_package_list(url, "updates", d)
     package_list=clean_package_list(package_names)
     return latest, package_list
 
-def create_distro_packages_list(distro_check_dir):
+def create_distro_packages_list(distro_check_dir, d):
     pkglst_dir = os.path.join(distro_check_dir, "package_lists")
     if not os.path.isdir (pkglst_dir):
         os.makedirs(pkglst_dir)
@@ -220,7 +234,7 @@
     begin = datetime.now()
     for distro in per_distro_functions:
         name = distro[0]
-        release, package_list = distro[1]()
+        release, package_list = distro[1](d)
         bb.note("Distro: %s, Latest Release: %s, # src packages: %d" % (name, release, len(package_list)))
         package_list_file = os.path.join(pkglst_dir, name + "-" + release)
         f = open(package_list_file, "w+b")
@@ -231,7 +245,7 @@
     delta = end - begin
     bb.note("package_list generatiosn took this much time: %d seconds" % delta.seconds)
 
-def update_distro_data(distro_check_dir, datetime):
+def update_distro_data(distro_check_dir, datetime, d):
     """
         If distro packages list data is old then rebuild it.
         The operations has to be protected by a lock so that
@@ -258,7 +272,7 @@
         if saved_datetime[0:8] != datetime[0:8]:
             bb.note("The build datetime did not match: saved:%s current:%s" % (saved_datetime, datetime))
             bb.note("Regenerating distro package lists")
-            create_distro_packages_list(distro_check_dir)
+            create_distro_packages_list(distro_check_dir, d)
             f.seek(0)
             f.write(datetime)
 
diff --git a/meta/lib/oe/image.py b/meta/lib/oe/image.py
index f9e9bfd..b9eb3de 100644
--- a/meta/lib/oe/image.py
+++ b/meta/lib/oe/image.py
@@ -5,7 +5,7 @@
 
 
 def generate_image(arg):
-    (type, subimages, create_img_cmd) = arg
+    (type, subimages, create_img_cmd, sprefix) = arg
 
     bb.note("Running image creation script for %s: %s ..." %
             (type, create_img_cmd))
@@ -54,14 +54,16 @@
             base_type = self._image_base_type(node)
             deps = (self.d.getVar('IMAGE_TYPEDEP_' + node, True) or "")
             base_deps = (self.d.getVar('IMAGE_TYPEDEP_' + base_type, True) or "")
-            if deps != "" or base_deps != "":
-                graph[node] = deps
 
-                for dep in deps.split() + base_deps.split():
-                    if not dep in graph:
-                        add_node(dep)
-            else:
-                graph[node] = ""
+            graph[node] = ""
+            for dep in deps.split() + base_deps.split():
+                if not dep in graph[node]:
+                    if graph[node] != "":
+                        graph[node] += " "
+                    graph[node] += dep
+
+                if not dep in graph:
+                    add_node(dep)
 
         for fstype in image_fstypes:
             add_node(fstype)
@@ -264,9 +266,9 @@
 
         return (alltypes, filtered_groups, cimages)
 
-    def _write_script(self, type, cmds):
+    def _write_script(self, type, cmds, sprefix=""):
         tempdir = self.d.getVar('T', True)
-        script_name = os.path.join(tempdir, "create_image." + type)
+        script_name = os.path.join(tempdir, sprefix + "create_image." + type)
         rootfs_size = self._get_rootfs_size()
 
         self.d.setVar('img_creation_func', '\n'.join(cmds))
@@ -284,7 +286,7 @@
 
         return script_name
 
-    def _get_imagecmds(self):
+    def _get_imagecmds(self, sprefix=""):
         old_overrides = self.d.getVar('OVERRIDES', 0)
 
         alltypes, fstype_groups, cimages = self._get_image_types()
@@ -320,9 +322,9 @@
                 else:
                     subimages.append(type)
 
-                script_name = self._write_script(type, cmds)
+                script_name = self._write_script(type, cmds, sprefix)
 
-                image_cmds.append((type, subimages, script_name))
+                image_cmds.append((type, subimages, script_name, sprefix))
 
             image_cmd_groups.append(image_cmds)
 
@@ -355,6 +357,27 @@
 
         image_cmd_groups = self._get_imagecmds()
 
+        # Process the debug filesystem...
+        debugfs_d = bb.data.createCopy(self.d)
+        if self.d.getVar('IMAGE_GEN_DEBUGFS', True) == "1":
+            bb.note("Processing debugfs image(s) ...")
+            orig_d = self.d
+            self.d = debugfs_d
+
+            self.d.setVar('IMAGE_ROOTFS', orig_d.getVar('IMAGE_ROOTFS', True) + '-dbg')
+            self.d.setVar('IMAGE_NAME', orig_d.getVar('IMAGE_NAME', True) + '-dbg')
+            self.d.setVar('IMAGE_LINK_NAME', orig_d.getVar('IMAGE_LINK_NAME', True) + '-dbg')
+
+            debugfs_image_fstypes = orig_d.getVar('IMAGE_FSTYPES_DEBUGFS', True)
+            if debugfs_image_fstypes:
+                self.d.setVar('IMAGE_FSTYPES', orig_d.getVar('IMAGE_FSTYPES_DEBUGFS', True))
+
+            self._remove_old_symlinks()
+
+            image_cmd_groups += self._get_imagecmds("debugfs.")
+
+            self.d = orig_d
+
         self._write_wic_env()
 
         for image_cmds in image_cmd_groups:
@@ -369,9 +392,16 @@
                 if result is not None:
                     bb.fatal(result)
 
-            for image_type, subimages, script in image_cmds:
-                bb.note("Creating symlinks for %s image ..." % image_type)
-                self._create_symlinks(subimages)
+            for image_type, subimages, script, sprefix in image_cmds:
+                if sprefix == 'debugfs.':
+                    bb.note("Creating symlinks for %s debugfs image ..." % image_type)
+                    orig_d = self.d
+                    self.d = debugfs_d
+                    self._create_symlinks(subimages)
+                    self.d = orig_d
+                else:
+                    bb.note("Creating symlinks for %s image ..." % image_type)
+                    self._create_symlinks(subimages)
 
         execute_pre_post_process(self.d, post_process_cmds)
 
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
index 292ed44..b9fa6d8 100644
--- a/meta/lib/oe/package_manager.py
+++ b/meta/lib/oe/package_manager.py
@@ -133,8 +133,11 @@
             if pkgfeed_gpg_name:
                 repomd_file = os.path.join(arch_dir, 'repodata', 'repomd.xml')
                 gpg_cmd = "%s --detach-sign --armor --batch --no-tty --yes " \
-                          "--passphrase-file '%s' -u '%s' %s" % (gpg_bin,
-                          pkgfeed_gpg_pass, pkgfeed_gpg_name, repomd_file)
+                          "--passphrase-file '%s' -u '%s' " % \
+                          (gpg_bin, pkgfeed_gpg_pass, pkgfeed_gpg_name)
+                if self.d.getVar('GPG_PATH', True):
+                    gpg_cmd += "--homedir %s " % self.d.getVar('GPG_PATH', True)
+                gpg_cmd += repomd_file
                 repo_sign_cmds.append(gpg_cmd)
 
             rpm_dirs_found = True
@@ -200,6 +203,8 @@
         result = oe.utils.multiprocess_exec(index_cmds, create_index)
         if result:
             bb.fatal('%s' % ('\n'.join(result)))
+        if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
+            raise NotImplementedError('Package feed signing not implementd for ipk')
 
 
 
@@ -275,6 +280,8 @@
         result = oe.utils.multiprocess_exec(index_cmds, create_index)
         if result:
             bb.fatal('%s' % ('\n'.join(result)))
+        if self.d.getVar('PACKAGE_FEED_SIGN', True) == '1':
+            raise NotImplementedError('Package feed signing not implementd for dpkg')
 
 
 
@@ -434,24 +441,30 @@
                 (self.opkg_cmd, self.opkg_args)
 
         try:
-            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).strip()
+            # bb.note(cmd)
+            tmp_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).strip()
+
         except subprocess.CalledProcessError as e:
             bb.fatal("Cannot get the installed packages list. Command '%s' "
                      "returned %d:\n%s" % (cmd, e.returncode, e.output))
 
-        if output and format == "file":
-            tmp_output = ""
-            for line in output.split('\n'):
+        output = list()
+        for line in tmp_output.split('\n'):
+            if len(line.strip()) == 0:
+                continue
+            if format == "file":
                 pkg, pkg_file, pkg_arch = line.split()
                 full_path = os.path.join(self.rootfs_dir, pkg_arch, pkg_file)
                 if os.path.exists(full_path):
-                    tmp_output += "%s %s %s\n" % (pkg, full_path, pkg_arch)
+                    output.append('%s %s %s' % (pkg, full_path, pkg_arch))
                 else:
-                    tmp_output += "%s %s %s\n" % (pkg, pkg_file, pkg_arch)
+                    output.append('%s %s %s' % (pkg, pkg_file, pkg_arch))
+            else:
+                output.append(line)
 
-            output = tmp_output
+        output.sort()
 
-        return output
+        return '\n'.join(output)
 
 
 class DpkgPkgsList(PkgsList):
@@ -605,12 +618,12 @@
             cmd.extend(['-x', exclude])
         try:
             bb.note("Installing complementary packages ...")
+            bb.note('Running %s' % cmd)
             complementary_pkgs = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
         except subprocess.CalledProcessError as e:
             bb.fatal("Could not compute complementary packages list. Command "
                      "'%s' returned %d:\n%s" %
                      (' '.join(cmd), e.returncode, e.output))
-
         self.install(complementary_pkgs.split(), attempt_only=True)
 
     def deploy_dir_lock(self):
@@ -1050,6 +1063,35 @@
     def update(self):
         self._invoke_smart('update rpmsys')
 
+    def get_rdepends_recursively(self, pkgs):
+        # pkgs will be changed during the loop, so use [:] to make a copy.
+        for pkg in pkgs[:]:
+            sub_data = oe.packagedata.read_subpkgdata(pkg, self.d)
+            sub_rdep = sub_data.get("RDEPENDS_" + pkg)
+            if not sub_rdep:
+                continue
+            done = bb.utils.explode_dep_versions2(sub_rdep).keys()
+            next = done
+            # Find all the rdepends on dependency chain
+            while next:
+                new = []
+                for sub_pkg in next:
+                    sub_data = oe.packagedata.read_subpkgdata(sub_pkg, self.d)
+                    sub_pkg_rdep = sub_data.get("RDEPENDS_" + sub_pkg)
+                    if not sub_pkg_rdep:
+                        continue
+                    for p in bb.utils.explode_dep_versions2(sub_pkg_rdep):
+                        # Already handled, skip it.
+                        if p in done or p in pkgs:
+                            continue
+                        # It's a new dep
+                        if oe.packagedata.has_subpkgdata(p, self.d):
+                            done.append(p)
+                            new.append(p)
+                next = new
+            pkgs.extend(done)
+        return pkgs
+
     '''
     Install pkgs with smart, the pkg name is oe format
     '''
@@ -1059,8 +1101,58 @@
             bb.note("There are no packages to install")
             return
         bb.note("Installing the following packages: %s" % ' '.join(pkgs))
-        pkgs = self._pkg_translate_oe_to_smart(pkgs, attempt_only)
+        if not attempt_only:
+            # Pull in multilib requires since rpm may not pull in them
+            # correctly, for example,
+            # lib32-packagegroup-core-standalone-sdk-target requires
+            # lib32-libc6, but rpm may pull in libc6 rather than lib32-libc6
+            # since it doesn't know mlprefix (lib32-), bitbake knows it and
+            # can handle it well, find out the RDEPENDS on the chain will
+            # fix the problem. Both do_rootfs and do_populate_sdk have this
+            # issue.
+            # The attempt_only packages don't need this since they are
+            # based on the installed ones.
+            #
+            # Separate pkgs into two lists, one is multilib, the other one
+            # is non-multilib.
+            ml_pkgs = []
+            non_ml_pkgs = pkgs[:]
+            for pkg in pkgs:
+                for mlib in (self.d.getVar("MULTILIB_VARIANTS", True) or "").split():
+                    if pkg.startswith(mlib + '-'):
+                        ml_pkgs.append(pkg)
+                        non_ml_pkgs.remove(pkg)
 
+            if len(ml_pkgs) > 0 and len(non_ml_pkgs) > 0:
+                # Found both foo and lib-foo
+                ml_pkgs = self.get_rdepends_recursively(ml_pkgs)
+                non_ml_pkgs = self.get_rdepends_recursively(non_ml_pkgs)
+                # Longer list makes smart slower, so only keep the pkgs
+                # which have the same BPN, and smart can handle others
+                # correctly.
+                pkgs_new = []
+                for pkg in non_ml_pkgs:
+                    for mlib in (self.d.getVar("MULTILIB_VARIANTS", True) or "").split():
+                        mlib_pkg = mlib + "-" + pkg
+                        if mlib_pkg in ml_pkgs:
+                            pkgs_new.append(pkg)
+                            pkgs_new.append(mlib_pkg)
+                for pkg in pkgs:
+                    if pkg not in pkgs_new:
+                        pkgs_new.append(pkg)
+                pkgs = pkgs_new
+                new_depends = {}
+                deps = bb.utils.explode_dep_versions2(" ".join(pkgs))
+                for depend in deps:
+                    data = oe.packagedata.read_subpkgdata(depend, self.d)
+                    key = "PKG_%s" % depend
+                    if key in data:
+                        new_depend = data[key]
+                    else:
+                        new_depend = depend
+                    new_depends[new_depend] = deps[depend]
+                pkgs = bb.utils.join_deps(new_depends, commasep=True).split(', ')
+        pkgs = self._pkg_translate_oe_to_smart(pkgs, attempt_only)
         if not attempt_only:
             bb.note('to be installed: %s' % ' '.join(pkgs))
             cmd = "%s %s install -y %s" % \
@@ -1379,6 +1471,16 @@
                                         self.d.getVar('FEED_DEPLOYDIR_BASE_URI', True),
                                         arch))
 
+            if self.opkg_dir != '/var/lib/opkg':
+                # There is no command line option for this anymore, we need to add
+                # info_dir and status_file to config file, if OPKGLIBDIR doesn't have
+                # the default value of "/var/lib" as defined in opkg:
+                # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_INFO_DIR      "/var/lib/opkg/info"
+                # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_STATUS_FILE   "/var/lib/opkg/status"
+                cfg_file.write("option info_dir     %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'info'))
+                cfg_file.write("option status_file  %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'status'))
+
+
     def _create_config(self):
         with open(self.config_file, "w+") as config_file:
             priority = 1
@@ -1394,6 +1496,15 @@
                     config_file.write("src oe-%s file:%s\n" %
                                       (arch, pkgs_dir))
 
+            if self.opkg_dir != '/var/lib/opkg':
+                # There is no command line option for this anymore, we need to add
+                # info_dir and status_file to config file, if OPKGLIBDIR doesn't have
+                # the default value of "/var/lib" as defined in opkg:
+                # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_INFO_DIR      "/var/lib/opkg/info"
+                # libopkg/opkg_conf.h:#define OPKG_CONF_DEFAULT_STATUS_FILE   "/var/lib/opkg/status"
+                config_file.write("option info_dir     %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'info'))
+                config_file.write("option status_file  %s\n" % os.path.join(self.d.getVar('OPKGLIBDIR', True), 'opkg', 'status'))
+
     def insert_feeds_uris(self):
         if self.feed_uris == "":
             return
@@ -1433,7 +1544,7 @@
         self.deploy_dir_unlock()
 
     def install(self, pkgs, attempt_only=False):
-        if attempt_only and len(pkgs) == 0:
+        if not pkgs:
             return
 
         cmd = "%s %s install %s" % (self.opkg_cmd, self.opkg_args, ' '.join(pkgs))
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py
index 108bf1d..2bf501e 100644
--- a/meta/lib/oe/patch.py
+++ b/meta/lib/oe/patch.py
@@ -337,12 +337,15 @@
         return (tmpfile, cmd)
 
     @staticmethod
-    def extractPatches(tree, startcommit, outdir):
+    def extractPatches(tree, startcommit, outdir, paths=None):
         import tempfile
         import shutil
         tempdir = tempfile.mkdtemp(prefix='oepatch')
         try:
             shellcmd = ["git", "format-patch", startcommit, "-o", tempdir]
+            if paths:
+                shellcmd.append('--')
+                shellcmd.extend(paths)
             out = runcmd(["sh", "-c", " ".join(shellcmd)], tree)
             if out:
                 for srcfile in out.split():
@@ -407,6 +410,13 @@
                     runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
                 except CmdError:
                     pass
+                # git am won't always clean up after itself, sadly, so...
+                shellcmd = ["git", "--work-tree=%s" % reporoot, "reset", "--hard", "HEAD"]
+                runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
+                # Also need to take care of any stray untracked files
+                shellcmd = ["git", "--work-tree=%s" % reporoot, "clean", "-f"]
+                runcmd(["sh", "-c", " ".join(shellcmd)], self.dir)
+
                 # Fall back to git apply
                 shellcmd = ["git", "--git-dir=%s" % reporoot, "apply", "-p%s" % patch['strippath']]
                 try:
diff --git a/meta/lib/oe/recipeutils.py b/meta/lib/oe/recipeutils.py
index d4fa726..119a688 100644
--- a/meta/lib/oe/recipeutils.py
+++ b/meta/lib/oe/recipeutils.py
@@ -31,9 +31,13 @@
     import bb.providers
 
     if pn in cooker.recipecache.pkg_pn:
-        filenames = cooker.recipecache.pkg_pn[pn]
         best = bb.providers.findBestProvider(pn, cooker.data, cooker.recipecache, cooker.recipecache.pkg_pn)
         return best[3]
+    elif pn in cooker.recipecache.providers:
+        filenames = cooker.recipecache.providers[pn]
+        eligible, foundUnique = bb.providers.filterProviders(filenames, pn, cooker.expanded_data, cooker.recipecache)
+        filename = eligible[0]
+        return filename
     else:
         return None
 
@@ -72,6 +76,8 @@
             raise bb.providers.NoProvider('Unable to find any recipe file matching %s' % pn)
     if appends:
         appendfiles = cooker.collection.get_file_appends(recipefile)
+    else:
+        appendfiles = None
     return parse_recipe(recipefile, appendfiles, d)
 
 
@@ -95,6 +101,63 @@
     return varfiles
 
 
+def split_var_value(value, assignment=True):
+    """
+    Split a space-separated variable's value into a list of items,
+    taking into account that some of the items might be made up of
+    expressions containing spaces that should not be split.
+    Parameters:
+        value:
+            The string value to split
+        assignment:
+            True to assume that the value represents an assignment
+            statement, False otherwise. If True, and an assignment
+            statement is passed in the first item in
+            the returned list will be the part of the assignment
+            statement up to and including the opening quote character,
+            and the last item will be the closing quote.
+    """
+    inexpr = 0
+    lastchar = None
+    out = []
+    buf = ''
+    for char in value:
+        if char == '{':
+            if lastchar == '$':
+                inexpr += 1
+        elif char == '}':
+            inexpr -= 1
+        elif assignment and char in '"\'' and inexpr == 0:
+            if buf:
+                out.append(buf)
+            out.append(char)
+            char = ''
+            buf = ''
+        elif char.isspace() and inexpr == 0:
+            char = ''
+            if buf:
+                out.append(buf)
+            buf = ''
+        buf += char
+        lastchar = char
+    if buf:
+        out.append(buf)
+
+    # Join together assignment statement and opening quote
+    outlist = out
+    if assignment:
+        assigfound = False
+        for idx, item in enumerate(out):
+            if '=' in item:
+                assigfound = True
+            if assigfound:
+                if '"' in item or "'" in item:
+                    outlist = [' '.join(out[:idx+1])]
+                    outlist.extend(out[idx+1:])
+                    break
+    return outlist
+
+
 def patch_recipe_file(fn, values, patch=False, relpath=''):
     """Update or insert variable values into a recipe file (assuming you
        have already identified the exact file you want to update.)
@@ -112,7 +175,7 @@
             if name in nowrap_vars:
                 tf.write(rawtext)
             elif name in list_vars:
-                splitvalue = values[name].split()
+                splitvalue = split_var_value(values[name], assignment=False)
                 if len(splitvalue) > 1:
                     linesplit = ' \\\n' + (' ' * (len(name) + 4))
                     tf.write('%s = "%s%s"\n' % (name, linesplit.join(splitvalue), linesplit))
@@ -277,6 +340,22 @@
     return remotes
 
 
+def get_recipe_local_files(d, patches=False):
+    """Get a list of local files in SRC_URI within a recipe."""
+    uris = (d.getVar('SRC_URI', True) or "").split()
+    fetch = bb.fetch2.Fetch(uris, d)
+    ret = {}
+    for uri in uris:
+        if fetch.ud[uri].type == 'file':
+            if (not patches and
+                    bb.utils.exec_flat_python_func('patch_path', uri, fetch, '')):
+                continue
+            # Skip files that are referenced by absolute path
+            if not os.path.isabs(fetch.ud[uri].basepath):
+                ret[fetch.ud[uri].basepath] = fetch.localpath(uri)
+    return ret
+
+
 def get_recipe_patches(d):
     """Get a list of the patches included in SRC_URI within a recipe."""
     patchfiles = []
@@ -518,7 +597,7 @@
                             instfunclines.append(line)
                     return (instfunclines, None, 4, False)
             else:
-                splitval = origvalue.split()
+                splitval = split_var_value(origvalue, assignment=False)
                 changed = False
                 removevar = varname
                 if varname in ['SRC_URI', 'SRC_URI_append%s' % appendoverride]:
@@ -673,11 +752,14 @@
     ru['type'] = 'U'
     ru['datetime'] = ''
 
+    pv = rd.getVar('PV', True)
+
     # XXX: If don't have SRC_URI means that don't have upstream sources so
-    # returns 1.0.
+    # returns the current recipe version, so that upstream version check
+    # declares a match.
     src_uris = rd.getVar('SRC_URI', True)
     if not src_uris:
-        ru['version'] = '1.0'
+        ru['version'] = pv
         ru['type'] = 'M'
         ru['datetime'] = datetime.now()
         return ru
@@ -686,8 +768,6 @@
     src_uri = src_uris.split()[0]
     uri_type, _, _, _, _, _ =  decodeurl(src_uri)
 
-    pv = rd.getVar('PV', True)
-
     manual_upstream_version = rd.getVar("RECIPE_UPSTREAM_VERSION", True)
     if manual_upstream_version:
         # manual tracking of upstream version.
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index 3b53fce..18df22d 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -66,6 +66,7 @@
                 m = r.search(line)
                 if m:
                     found_error = 1
+                    bb.warn('[log_check] In line: [%s]' % line)
                     bb.warn('[log_check] %s: found an error message in the logfile (keyword \'%s\'):\n[log_check] %s'
 				    % (self.d.getVar('PN', True), m.group(), line))
 
@@ -278,6 +279,7 @@
 
         bb.note("Running intercept scripts:")
         os.environ['D'] = self.image_rootfs
+        os.environ['STAGING_DIR_NATIVE'] = self.d.getVar('STAGING_DIR_NATIVE', True)
         for script in os.listdir(intercepts_dir):
             script_full = os.path.join(intercepts_dir, script)
 
@@ -595,7 +597,11 @@
 
         pkg_list = []
 
-        pkgs = self._get_pkgs_postinsts(status_file)
+        pkgs = None
+        if not self.d.getVar('PACKAGE_INSTALL', True).strip():
+            bb.note("Building empty image")
+        else:
+            pkgs = self._get_pkgs_postinsts(status_file)
         if pkgs:
             root = "__packagegroup_postinst__"
             pkgs[root] = pkgs.keys()
diff --git a/meta/lib/oe/sdk.py b/meta/lib/oe/sdk.py
index 53da0f0..3103f48 100644
--- a/meta/lib/oe/sdk.py
+++ b/meta/lib/oe/sdk.py
@@ -5,6 +5,7 @@
 import os
 import shutil
 import glob
+import traceback
 
 
 class Sdk(object):
@@ -25,7 +26,7 @@
         else:
             self.manifest_dir = manifest_dir
 
-        bb.utils.remove(self.sdk_output, True)
+        self.remove(self.sdk_output, True)
 
         self.install_order = Manifest.INSTALL_ORDER
 
@@ -34,29 +35,56 @@
         pass
 
     def populate(self):
-        bb.utils.mkdirhier(self.sdk_output)
+        self.mkdirhier(self.sdk_output)
 
         # call backend dependent implementation
         self._populate()
 
         # Don't ship any libGL in the SDK
-        bb.utils.remove(os.path.join(self.sdk_output, self.sdk_native_path,
-                                     self.d.getVar('libdir_nativesdk', True).strip('/'),
-                                     "libGL*"))
+        self.remove(os.path.join(self.sdk_output, self.sdk_native_path,
+                         self.d.getVar('libdir_nativesdk', True).strip('/'),
+                         "libGL*"))
 
         # Fix or remove broken .la files
-        bb.utils.remove(os.path.join(self.sdk_output, self.sdk_native_path,
-                                     self.d.getVar('libdir_nativesdk', True).strip('/'),
-                                     "*.la"))
+        self.remove(os.path.join(self.sdk_output, self.sdk_native_path,
+                         self.d.getVar('libdir_nativesdk', True).strip('/'),
+                         "*.la"))
 
         # Link the ld.so.cache file into the hosts filesystem
         link_name = os.path.join(self.sdk_output, self.sdk_native_path,
                                  self.sysconfdir, "ld.so.cache")
-        bb.utils.mkdirhier(os.path.dirname(link_name))
+        self.mkdirhier(os.path.dirname(link_name))
         os.symlink("/etc/ld.so.cache", link_name)
 
         execute_pre_post_process(self.d, self.d.getVar('SDK_POSTPROCESS_COMMAND', True))
 
+    def movefile(self, sourcefile, destdir):
+        try:
+            # FIXME: this check of movefile's return code to None should be
+            # fixed within the function to use only exceptions to signal when
+            # something goes wrong
+            if (bb.utils.movefile(sourcefile, destdir) == None):
+                raise OSError("moving %s to %s failed"
+                        %(sourcefile, destdir))
+        #FIXME: using umbrella exc catching because bb.utils method raises it
+        except Exception as e:
+            bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc())
+            bb.error("unable to place %s in final SDK location" % sourcefile)
+
+    def mkdirhier(self, dirpath):
+        try:
+            bb.utils.mkdirhier(dirpath)
+        except OSError as e:
+            bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc())
+            bb.fatal("cannot make dir for SDK: %s" % dirpath)
+
+    def remove(self, path, recurse=False):
+        try:
+            bb.utils.remove(path, recurse)
+        #FIXME: using umbrella exc catching because bb.utils method raises it
+        except Exception as e:
+            bb.debug(1, "printing the stack trace\n %s" %traceback.format_exc())
+            bb.warn("cannot remove SDK dir: %s" % path)
 
 class RpmSdk(Sdk):
     def __init__(self, d, manifest_dir=None):
@@ -143,15 +171,15 @@
                                             "lib",
                                             "rpm"
                                             )
-        bb.utils.mkdirhier(native_rpm_state_dir)
+        self.mkdirhier(native_rpm_state_dir)
         for f in glob.glob(os.path.join(self.sdk_output,
                                         "var",
                                         "lib",
                                         "rpm",
                                         "*")):
-            bb.utils.movefile(f, native_rpm_state_dir)
+            self.movefile(f, native_rpm_state_dir)
 
-        bb.utils.remove(os.path.join(self.sdk_output, "var"), True)
+        self.remove(os.path.join(self.sdk_output, "var"), True)
 
         # Move host sysconfig data
         native_sysconf_dir = os.path.join(self.sdk_output,
@@ -159,10 +187,10 @@
                                           self.d.getVar('sysconfdir',
                                                         True).strip('/'),
                                           )
-        bb.utils.mkdirhier(native_sysconf_dir)
+        self.mkdirhier(native_sysconf_dir)
         for f in glob.glob(os.path.join(self.sdk_output, "etc", "*")):
-            bb.utils.movefile(f, native_sysconf_dir)
-        bb.utils.remove(os.path.join(self.sdk_output, "etc"), True)
+            self.movefile(f, native_sysconf_dir)
+        self.remove(os.path.join(self.sdk_output, "etc"), True)
 
 
 class OpkgSdk(Sdk):
@@ -219,12 +247,12 @@
         target_sysconfdir = os.path.join(self.sdk_target_sysroot, self.sysconfdir)
         host_sysconfdir = os.path.join(self.sdk_host_sysroot, self.sysconfdir)
 
-        bb.utils.mkdirhier(target_sysconfdir)
+        self.mkdirhier(target_sysconfdir)
         shutil.copy(self.target_conf, target_sysconfdir)
         os.chmod(os.path.join(target_sysconfdir,
                               os.path.basename(self.target_conf)), 0644)
 
-        bb.utils.mkdirhier(host_sysconfdir)
+        self.mkdirhier(host_sysconfdir)
         shutil.copy(self.host_conf, host_sysconfdir)
         os.chmod(os.path.join(host_sysconfdir,
                               os.path.basename(self.host_conf)), 0644)
@@ -232,11 +260,11 @@
         native_opkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
                                              self.d.getVar('localstatedir_nativesdk', True).strip('/'),
                                              "lib", "opkg")
-        bb.utils.mkdirhier(native_opkg_state_dir)
+        self.mkdirhier(native_opkg_state_dir)
         for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "opkg", "*")):
-            bb.utils.movefile(f, native_opkg_state_dir)
+            self.movefile(f, native_opkg_state_dir)
 
-        bb.utils.remove(os.path.join(self.sdk_output, "var"), True)
+        self.remove(os.path.join(self.sdk_output, "var"), True)
 
 
 class DpkgSdk(Sdk):
@@ -264,7 +292,7 @@
     def _copy_apt_dir_to(self, dst_dir):
         staging_etcdir_native = self.d.getVar("STAGING_ETCDIR_NATIVE", True)
 
-        bb.utils.remove(dst_dir, True)
+        self.remove(dst_dir, True)
 
         shutil.copytree(os.path.join(staging_etcdir_native, "apt"), dst_dir)
 
@@ -306,11 +334,11 @@
 
         native_dpkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
                                              "var", "lib", "dpkg")
-        bb.utils.mkdirhier(native_dpkg_state_dir)
+        self.mkdirhier(native_dpkg_state_dir)
         for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "dpkg", "*")):
-            bb.utils.movefile(f, native_dpkg_state_dir)
+            self.movefile(f, native_dpkg_state_dir)
+        self.remove(os.path.join(self.sdk_output, "var"), True)
 
-        bb.utils.remove(os.path.join(self.sdk_output, "var"), True)
 
 
 def sdk_list_installed_packages(d, target, format=None, rootfs_dir=None):
diff --git a/meta/lib/oe/sstatesig.py b/meta/lib/oe/sstatesig.py
index cb46712..6d1be3e 100644
--- a/meta/lib/oe/sstatesig.py
+++ b/meta/lib/oe/sstatesig.py
@@ -94,6 +94,26 @@
         self.machine = data.getVar("MACHINE", True)
         self.mismatch_msgs = []
         pass
+
+    def tasks_resolved(self, virtmap, virtpnmap, dataCache):
+        # Translate virtual/xxx entries to PN values
+        newabisafe = []
+        for a in self.abisaferecipes:
+            if a in virtpnmap:
+                newabisafe.append(virtpnmap[a])
+            else:
+                newabisafe.append(a)
+        self.abisaferecipes = newabisafe
+        newsafedeps = []
+        for a in self.saferecipedeps:
+            a1, a2 = a.split("->")
+            if a1 in virtpnmap:
+                a1 = virtpnmap[a1]
+            if a2 in virtpnmap:
+                a2 = virtpnmap[a2]
+            newsafedeps.append(a1 + "->" + a2)
+        self.saferecipedeps = newsafedeps
+
     def rundep_check(self, fn, recipename, task, dep, depname, dataCache = None):
         return sstate_rundepfilter(self, fn, recipename, task, dep, depname, dataCache)
 
diff --git a/meta/lib/oeqa/oetest.py b/meta/lib/oeqa/oetest.py
index a6f89b6..6f9edec 100644
--- a/meta/lib/oeqa/oetest.py
+++ b/meta/lib/oeqa/oetest.py
@@ -11,9 +11,14 @@
 import unittest
 import inspect
 import subprocess
-import bb
-from oeqa.utils.decorators import LogResults, gettag
-from sys import exc_info, exc_clear
+try:
+    import bb
+except ImportError:
+    pass
+import logging
+from oeqa.utils.decorators import LogResults, gettag, getResults
+
+logger = logging.getLogger("BitBake")
 
 def getVar(obj):
     #extend form dict, if a variable didn't exists, need find it in testcase
@@ -89,7 +94,7 @@
                                 suite.dependencies.append(dep_suite)
                             break
                     else:
-                        bb.warn("Test %s was declared as @skipUnlessPassed('%s') but that test is either not defined or not active. Will run the test anyway." %
+                        logger.warning("Test %s was declared as @skipUnlessPassed('%s') but that test is either not defined or not active. Will run the test anyway." %
                                 (test, depends_on))
     # Use brute-force topological sort to determine ordering. Sort by
     # depth (higher depth = must run later), with original ordering to
@@ -106,14 +111,34 @@
     suites.sort(cmp=lambda a,b: cmp((a.depth, a.index), (b.depth, b.index)))
     return testloader.suiteClass(suites)
 
+_buffer = ""
+
+def custom_verbose(msg, *args, **kwargs):
+    global _buffer
+    if msg[-1] != "\n":
+        _buffer += msg
+    else:
+        _buffer += msg
+        try:
+            bb.plain(_buffer.rstrip("\n"), *args, **kwargs)
+        except NameError:
+            logger.info(_buffer.rstrip("\n"), *args, **kwargs)
+        _buffer = ""
+
 def runTests(tc, type="runtime"):
 
     suite = loadTests(tc, type)
-    bb.note("Test modules  %s" % tc.testslist)
+    logger.info("Test modules  %s" % tc.testslist)
     if hasattr(tc, "tagexp") and tc.tagexp:
-        bb.note("Filter test cases by tags: %s" % tc.tagexp)
-    bb.note("Found %s tests" % suite.countTestCases())
+        logger.info("Filter test cases by tags: %s" % tc.tagexp)
+    logger.info("Found %s tests" % suite.countTestCases())
     runner = unittest.TextTestRunner(verbosity=2)
+    try:
+        if bb.msg.loggerDefaultVerbose:
+            runner.stream.write = custom_verbose
+    except NameError:
+        # Not in bb environment?
+        pass
     result = runner.run(suite)
 
     return result
@@ -158,17 +183,24 @@
         pass
 
     def tearDown(self):
-        # If a test fails or there is an exception
-        if not exc_info() == (None, None, None):
-            exc_clear()
-            #Only dump for QemuTarget
-            if (type(self.target).__name__ == "QemuTarget"):
-                self.tc.host_dumper.create_dir(self._testMethodName)
-                self.tc.host_dumper.dump_host()
-                self.target.target_dumper.dump_target(
-                        self.tc.host_dumper.dump_dir)
-                print ("%s dump data stored in %s" % (self._testMethodName,
-                         self.tc.host_dumper.dump_dir))
+        res = getResults()
+        # If a test fails or there is an exception dump
+        # for QemuTarget only
+        if (type(self.target).__name__ == "QemuTarget" and
+                (self.id() in res.getErrorList() or
+                self.id() in  res.getFailList())):
+            self.tc.host_dumper.create_dir(self._testMethodName)
+            self.tc.host_dumper.dump_host()
+            self.target.target_dumper.dump_target(
+                    self.tc.host_dumper.dump_dir)
+            print ("%s dump data stored in %s" % (self._testMethodName,
+                     self.tc.host_dumper.dump_dir))
+
+        self.tearDownLocal()
+
+    # Method to be run after tearDown and implemented by child classes
+    def tearDownLocal(self):
+        pass
 
     #TODO: use package_manager.py to install packages on any type of image
     def install_packages(self, packagelist):
@@ -190,7 +222,7 @@
         return False
 
     def _run(self, cmd):
-        return subprocess.check_output(cmd, shell=True)
+        return subprocess.check_output(". %s; " % self.tc.sdkenv + cmd, shell=True)
 
 def getmodule(pos=2):
     # stack returns a list of tuples containg frame information
diff --git a/meta/lib/oeqa/runexported.py b/meta/lib/oeqa/runexported.py
index 96442b1..dba0d7a 100755
--- a/meta/lib/oeqa/runexported.py
+++ b/meta/lib/oeqa/runexported.py
@@ -21,7 +21,7 @@
 import sys
 import os
 import time
-from optparse import OptionParser
+import argparse
 
 try:
     import simplejson as json
@@ -49,8 +49,8 @@
     def exportStart(self):
         self.sshlog = os.path.join(self.testdir, "ssh_target_log.%s" % self.datetime)
         sshloglink = os.path.join(self.testdir, "ssh_target_log")
-        if os.path.islink(sshloglink):
-            os.unlink(sshloglink)
+        if os.path.exists(sshloglink):
+            os.remove(sshloglink)
         os.symlink(self.sshlog, sshloglink)
         print("SSH log file: %s" %  self.sshlog)
         self.connection = SSHControl(self.ip, logfile=self.sshlog)
@@ -76,43 +76,41 @@
 
 def main():
 
-    usage = "usage: %prog [options] <json file>"
-    parser = OptionParser(usage=usage)
-    parser.add_option("-t", "--target-ip", dest="ip", help="The IP address of the target machine. Use this to \
+    parser = argparse.ArgumentParser()
+    parser.add_argument("-t", "--target-ip", dest="ip", help="The IP address of the target machine. Use this to \
             overwrite the value determined from TEST_TARGET_IP at build time")
-    parser.add_option("-s", "--server-ip", dest="server_ip", help="The IP address of this machine. Use this to \
+    parser.add_argument("-s", "--server-ip", dest="server_ip", help="The IP address of this machine. Use this to \
             overwrite the value determined from TEST_SERVER_IP at build time.")
-    parser.add_option("-d", "--deploy-dir", dest="deploy_dir", help="Full path to the package feeds, that this \
+    parser.add_argument("-d", "--deploy-dir", dest="deploy_dir", help="Full path to the package feeds, that this \
             the contents of what used to be DEPLOY_DIR on the build machine. If not specified it will use the value \
             specified in the json if that directory actually exists or it will error out.")
-    parser.add_option("-l", "--log-dir", dest="log_dir", help="This sets the path for TEST_LOG_DIR. If not specified \
+    parser.add_argument("-l", "--log-dir", dest="log_dir", help="This sets the path for TEST_LOG_DIR. If not specified \
             the current dir is used. This is used for usually creating a ssh log file and a scp test file.")
+    parser.add_argument("json", help="The json file exported by the build system", default="testdata.json", nargs='?')
 
-    (options, args) = parser.parse_args()
-    if len(args) != 1:
-        parser.error("Incorrect number of arguments. The one and only argument should be a json file exported by the build system")
+    args = parser.parse_args()
 
-    with open(args[0], "r") as f:
+    with open(args.json, "r") as f:
         loaded = json.load(f)
 
-    if options.ip:
-        loaded["target"]["ip"] = options.ip
-    if options.server_ip:
-        loaded["target"]["server_ip"] = options.server_ip
+    if args.ip:
+        loaded["target"]["ip"] = args.ip
+    if args.server_ip:
+        loaded["target"]["server_ip"] = args.server_ip
 
     d = MyDataDict()
     for key in loaded["d"].keys():
         d[key] = loaded["d"][key]
 
-    if options.log_dir:
-        d["TEST_LOG_DIR"] = options.log_dir
+    if args.log_dir:
+        d["TEST_LOG_DIR"] = args.log_dir
     else:
         d["TEST_LOG_DIR"] = os.path.abspath(os.path.dirname(__file__))
-    if options.deploy_dir:
-        d["DEPLOY_DIR"] = options.deploy_dir
+    if args.deploy_dir:
+        d["DEPLOY_DIR"] = args.deploy_dir
     else:
         if not os.path.isdir(d["DEPLOY_DIR"]):
-            raise Exception("The path to DEPLOY_DIR does not exists: %s" % d["DEPLOY_DIR"])
+            print("WARNING: The path to DEPLOY_DIR does not exist: %s" % d["DEPLOY_DIR"])
 
 
     target = FakeTarget(d)
diff --git a/meta/lib/oeqa/runtime/_ptest.py b/meta/lib/oeqa/runtime/_ptest.py
index 81c9c43..0621028 100644
--- a/meta/lib/oeqa/runtime/_ptest.py
+++ b/meta/lib/oeqa/runtime/_ptest.py
@@ -98,7 +98,7 @@
 
         return complementary_pkgs.split()
 
-    def setUp(self):
+    def setUpLocal(self):
         self.ptest_log = os.path.join(oeRuntimeTest.tc.d.getVar("TEST_LOG_DIR",True), "ptest-%s.log" % oeRuntimeTest.tc.d.getVar('DATETIME', True))
 
     @skipUnlessPassed('test_ssh')
diff --git a/meta/lib/oeqa/runtime/connman.py b/meta/lib/oeqa/runtime/connman.py
index ee69e5d..bd9dba3 100644
--- a/meta/lib/oeqa/runtime/connman.py
+++ b/meta/lib/oeqa/runtime/connman.py
@@ -29,26 +29,3 @@
         if status != 0:
             print self.service_status("connman")
             self.fail("No connmand process running")
-
-    @testcase(223)
-    def test_only_one_connmand_in_background(self):
-        """
-        Summary:     Only one connmand in background
-        Expected:    There will be only one connmand instance in background.
-        Product:     BSPs
-        Author:      Alexandru Georgescu <alexandru.c.georgescu@intel.com>
-        AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
-        """
-
-        # Make sure that 'connmand' is running in background
-        (status, output) = self.target.run(oeRuntimeTest.pscmd + ' | grep [c]onnmand')
-        self.assertEqual(0, status, 'Failed to find "connmand" process running in background.')
-
-        # Start a new instance of 'connmand'
-        (status, output) = self.target.run('connmand')
-        self.assertEqual(0, status, 'Failed to start a new "connmand" process.')
-
-        # Make sure that only one 'connmand' is running in background
-        (status, output) = self.target.run(oeRuntimeTest.pscmd + ' | grep [c]onnmand | wc -l')
-        self.assertEqual(0, status, 'Failed to find "connmand" process running in background.')
-        self.assertEqual(1, int(output), 'Found {} connmand processes running, expected 1.'.format(output))
diff --git a/meta/lib/oeqa/runtime/date.py b/meta/lib/oeqa/runtime/date.py
index 3a8fe84..447987e 100644
--- a/meta/lib/oeqa/runtime/date.py
+++ b/meta/lib/oeqa/runtime/date.py
@@ -4,11 +4,11 @@
 
 class DateTest(oeRuntimeTest):
 
-    def setUp(self):
+    def setUpLocal(self):
         if oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", True) == "systemd":
             self.target.run('systemctl stop systemd-timesyncd')
 
-    def tearDown(self):
+    def tearDownLocal(self):
         if oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager", True) == "systemd":
             self.target.run('systemctl start systemd-timesyncd')
 
diff --git a/meta/lib/oeqa/runtime/files/testsdkmakefile b/meta/lib/oeqa/runtime/files/testsdkmakefile
new file mode 100644
index 0000000..fb05f82
--- /dev/null
+++ b/meta/lib/oeqa/runtime/files/testsdkmakefile
@@ -0,0 +1,5 @@
+test: test.o
+	$(CC) -o test test.o -lm
+test.o: test.c
+	$(CC) -c test.c
+
diff --git a/meta/lib/oeqa/runtime/kernelmodule.py b/meta/lib/oeqa/runtime/kernelmodule.py
index 2e81720..38ca184 100644
--- a/meta/lib/oeqa/runtime/kernelmodule.py
+++ b/meta/lib/oeqa/runtime/kernelmodule.py
@@ -10,7 +10,7 @@
 
 class KernelModuleTest(oeRuntimeTest):
 
-    def setUp(self):
+    def setUpLocal(self):
         self.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "hellomod.c"), "/tmp/hellomod.c")
         self.target.copy_to(os.path.join(oeRuntimeTest.tc.filesdir, "hellomod_makefile"), "/tmp/Makefile")
 
@@ -30,5 +30,5 @@
             (status, output) = self.target.run(cmd, 900)
             self.assertEqual(status, 0, msg="\n".join([cmd, output]))
 
-    def tearDown(self):
+    def tearDownLocal(self):
         self.target.run('rm -f /tmp/Makefile /tmp/hellomod.c')
diff --git a/meta/lib/oeqa/runtime/parselogs.py b/meta/lib/oeqa/runtime/parselogs.py
index e20947b..fc2bc38 100644
--- a/meta/lib/oeqa/runtime/parselogs.py
+++ b/meta/lib/oeqa/runtime/parselogs.py
@@ -36,6 +36,8 @@
     'VGA arbiter: cannot open kernel arbiter, no multi-card support',
     'Failed to find URL:http://ipv4.connman.net/online/status.html',
     'Online check failed for',
+    'netlink init failed',
+    'Fast TSC calibration',
     ]
 
 x86_common = [
@@ -46,7 +48,6 @@
 ] + common_errors
 
 qemux86_common = [
-    'Fast TSC calibration', 
     'wrong ELF class',
     "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
     "can't claim BAR ",
@@ -89,7 +90,7 @@
         '(EE) open /dev/fb0: No such file or directory',
         '(EE) AIGLX: reverting to software rendering',
         ] + x86_common,
-    'core2_32' : [
+    'intel-core2-32' : [
         'ACPI: No _BQC method, cannot determine initial brightness',
         '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
         '(EE) Failed to load module "psb"',
@@ -98,6 +99,7 @@
         '(EE) Failed to load module psbdrv',
         '(EE) open /dev/fb0: No such file or directory',
         '(EE) AIGLX: reverting to software rendering',
+        "controller can't do DEVSLP, turning off",
         ] + x86_common,
     'intel-corei7-64' : [
         "controller can't do DEVSLP, turning off",
@@ -108,13 +110,9 @@
     'edgerouter' : [
         'Fatal server error:',
         ] + common_errors,
-    'minnow' : [
-        'netlink init failed',
-        ] + common_errors,
     'jasperforest' : [
         'Activated service \'org.bluez\' failed:',
         'Unable to find NFC netlink family',
-        'netlink init failed',
         ] + common_errors,
 }
 
@@ -233,8 +231,7 @@
 
     #get the output of dmesg and write it in a file. This file is added to log_locations.
     def write_dmesg(self):
-        (status, dmesg) = self.target.run("dmesg")
-        (status, dmesg2) = self.target.run("echo \""+str(dmesg)+"\" > /tmp/dmesg_output.log")
+        (status, dmesg) = self.target.run("dmesg > /tmp/dmesg_output.log")
 
     @testcase(1059)
     @skipUnlessPassed('test_ssh')
diff --git a/meta/lib/oeqa/runtime/scanelf.py b/meta/lib/oeqa/runtime/scanelf.py
index 43a024a..67e02ff 100644
--- a/meta/lib/oeqa/runtime/scanelf.py
+++ b/meta/lib/oeqa/runtime/scanelf.py
@@ -8,7 +8,7 @@
 
 class ScanelfTest(oeRuntimeTest):
 
-    def setUp(self):
+    def setUpLocal(self):
         self.scancmd = 'scanelf --quiet --recursive --mount --ldpath --path'
 
     @testcase(966)
diff --git a/meta/lib/oeqa/sdk/gcc.py b/meta/lib/oeqa/sdk/gcc.py
index 67994b9..8395b9b 100644
--- a/meta/lib/oeqa/sdk/gcc.py
+++ b/meta/lib/oeqa/sdk/gcc.py
@@ -14,7 +14,7 @@
 
     @classmethod
     def setUpClass(self):
-        for f in ['test.c', 'test.cpp', 'testmakefile']:
+        for f in ['test.c', 'test.cpp', 'testsdkmakefile']:
             shutil.copyfile(os.path.join(self.tc.filesdir, f), self.tc.sdktestdir + f)
 
     def test_gcc_compile(self):
@@ -27,10 +27,10 @@
         self._run('$CXX %s/test.cpp -o %s/test -lm' % (self.tc.sdktestdir, self.tc.sdktestdir))
 
     def test_make(self):
-        self._run('cd %s; make -f testmakefile' % self.tc.sdktestdir)
+        self._run('cd %s; make -f testsdkmakefile' % self.tc.sdktestdir)
 
     @classmethod
     def tearDownClass(self):
-        files = [self.tc.sdktestdir + f for f in ['test.c', 'test.cpp', 'test.o', 'test', 'testmakefile']]
+        files = [self.tc.sdktestdir + f for f in ['test.c', 'test.cpp', 'test.o', 'test', 'testsdkmakefile']]
         for f in files:
             bb.utils.remove(f)
diff --git a/meta/lib/oeqa/selftest/archiver.py b/meta/lib/oeqa/selftest/archiver.py
new file mode 100644
index 0000000..f2030c4
--- /dev/null
+++ b/meta/lib/oeqa/selftest/archiver.py
@@ -0,0 +1,50 @@
+from oeqa.selftest.base import oeSelfTest
+from oeqa.utils.commands import bitbake, get_bb_var
+from oeqa.utils.decorators import testcase
+import glob
+import os
+import shutil
+
+
+class Archiver(oeSelfTest):
+
+    @testcase(1345)
+    def test_archiver_allows_to_filter_on_recipe_name(self):
+        """
+        Summary:     The archiver should offer the possibility to filter on the recipe. (#6929)
+        Expected:    1. Included recipe (busybox) should be included
+                     2. Excluded recipe (zlib) should be excluded
+        Product:     oe-core
+        Author:      Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+        AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
+        """
+
+        include_recipe = 'busybox'
+        exclude_recipe = 'zlib'
+
+        features = 'INHERIT += "archiver"\n'
+        features += 'ARCHIVER_MODE[src] = "original"\n'
+        features += 'COPYLEFT_PN_INCLUDE = "%s"\n' % include_recipe
+        features += 'COPYLEFT_PN_EXCLUDE = "%s"\n' % exclude_recipe
+
+        # Update local.conf
+        self.write_config(features)
+
+        tmp_dir = get_bb_var('TMPDIR')
+        deploy_dir_src = get_bb_var('DEPLOY_DIR_SRC')
+        target_sys = get_bb_var('TARGET_SYS')
+        src_path = os.path.join(deploy_dir_src, target_sys)
+
+        # Delete tmp directory
+        shutil.rmtree(tmp_dir)
+
+        # Build core-image-minimal
+        bitbake('core-image-minimal')
+
+        # Check that include_recipe was included
+        is_included = len(glob.glob(src_path + '/%s*' % include_recipe))
+        self.assertEqual(1, is_included, 'Recipe %s was not included.' % include_recipe)
+
+        # Check that exclude_recipe was excluded
+        is_excluded = len(glob.glob(src_path + '/%s*' % exclude_recipe))
+        self.assertEqual(0, is_excluded, 'Recipe %s was not excluded.' % exclude_recipe)
diff --git a/meta/lib/oeqa/selftest/base.py b/meta/lib/oeqa/selftest/base.py
index b2faa66..9bddc23 100644
--- a/meta/lib/oeqa/selftest/base.py
+++ b/meta/lib/oeqa/selftest/base.py
@@ -31,7 +31,7 @@
         self.testinc_bblayers_path = os.path.join(self.builddir, "conf/bblayers.inc")
         self.testlayer_path = oeSelfTest.testlayer_path
         self._extra_tear_down_commands = []
-        self._track_for_cleanup = []
+        self._track_for_cleanup = [self.testinc_path]
         super(oeSelfTest, self).__init__(methodName)
 
     def setUp(self):
diff --git a/meta/lib/oeqa/selftest/bbtests.py b/meta/lib/oeqa/selftest/bbtests.py
index 3d6860f..94ca79c 100644
--- a/meta/lib/oeqa/selftest/bbtests.py
+++ b/meta/lib/oeqa/selftest/bbtests.py
@@ -1,8 +1,5 @@
-import unittest
 import os
-import logging
 import re
-import shutil
 
 import oeqa.utils.ftools as ftools
 from oeqa.selftest.base import oeSelfTest
@@ -68,15 +65,43 @@
         bitbake('-cclean man')
         self.assertTrue("ERROR: Function failed: patch_do_patch" in result.output, msg = "Though no man-1.5h1-make.patch file exists, bitbake didn't output any err. message. bitbake output: %s" % result.output)
 
+    @testcase(1354)
+    def test_force_task_1(self):
+        # test 1 from bug 5875
+        test_recipe = 'zlib'
+        test_data = "Microsoft Made No Profit From Anyone's Zunes Yo"
+        image_dir = get_bb_var('D', test_recipe)
+        pkgsplit_dir = get_bb_var('PKGDEST', test_recipe)
+        man_dir = get_bb_var('mandir', test_recipe)
+
+        bitbake('-c cleansstate %s' % test_recipe)
+        bitbake(test_recipe)
+        self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
+
+        man_file = os.path.join(image_dir + man_dir, 'man3/zlib.3')
+        ftools.append_file(man_file, test_data)
+        bitbake('-c package -f %s' % test_recipe)
+
+        man_split_file = os.path.join(pkgsplit_dir, 'zlib-doc' + man_dir, 'man3/zlib.3')
+        man_split_content = ftools.read_file(man_split_file)
+        self.assertIn(test_data, man_split_content, 'The man file has not changed in packages-split.')
+
+        ret = bitbake(test_recipe)
+        self.assertIn('task do_package_write_rpm:', ret.output, 'Task do_package_write_rpm did not re-executed.')
+
     @testcase(163)
-    def test_force_task(self):
-        bitbake('m4-native')
-        self.add_command_to_tearDown('bitbake -c clean m4-native')
-        result = bitbake('-C compile m4-native')
-        look_for_tasks = ['do_compile', 'do_install', 'do_populate_sysroot']
+    def test_force_task_2(self):
+        # test 2 from bug 5875
+        test_recipe = 'zlib'
+
+        bitbake('-c cleansstate %s' % test_recipe)
+        bitbake(test_recipe)
+        self.add_command_to_tearDown('bitbake -c clean %s' % test_recipe)
+
+        result = bitbake('-C compile %s' % test_recipe)
+        look_for_tasks = ['do_compile:', 'do_install:', 'do_populate_sysroot:', 'do_package:']
         for task in look_for_tasks:
-            find_task = re.search("m4-native.*%s" % task, result.output)
-            self.assertTrue(find_task, msg = "Couldn't find %s task. bitbake output %s" % (task, result.output))
+            self.assertIn(task, result.output, msg="Couldn't find %s task.")
 
     @testcase(167)
     def test_bitbake_g(self):
@@ -101,6 +126,8 @@
         self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
 SSTATE_DIR = \"${TOPDIR}/download-selftest\"
 """)
+        self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
+
         bitbake('-ccleanall man')
         result = bitbake('-c fetch man', ignore_status=True)
         bitbake('-ccleanall man')
@@ -116,20 +143,20 @@
         self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
 SSTATE_DIR = \"${TOPDIR}/download-selftest\"
 """)
+        self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
+
         data = 'SRC_URI_append = ";downloadfilename=test-aspell.tar.gz"'
         self.write_recipeinc('aspell', data)
         bitbake('-ccleanall aspell')
         result = bitbake('-c fetch aspell', ignore_status=True)
         self.delete_recipeinc('aspell')
-        self.addCleanup(bitbake, '-ccleanall aspell')
         self.assertEqual(result.status, 0, msg = "Couldn't fetch aspell. %s" % result.output)
         self.assertTrue(os.path.isfile(os.path.join(get_bb_var("DL_DIR"), 'test-aspell.tar.gz')), msg = "File rename failed. No corresponding test-aspell.tar.gz file found under %s" % str(get_bb_var("DL_DIR")))
         self.assertTrue(os.path.isfile(os.path.join(get_bb_var("DL_DIR"), 'test-aspell.tar.gz.done')), "File rename failed. No corresponding test-aspell.tar.gz.done file found under %s" % str(get_bb_var("DL_DIR")))
 
     @testcase(1028)
     def test_environment(self):
-        self.append_config("TEST_ENV=\"localconf\"")
-        self.addCleanup(self.remove_config, "TEST_ENV=\"localconf\"")
+        self.write_config("TEST_ENV=\"localconf\"")
         result = runCmd('bitbake -e | grep TEST_ENV=')
         self.assertTrue('localconf' in result.output, msg = "bitbake didn't report any value for TEST_ENV variable. To test, run 'bitbake -e | grep TEST_ENV='")
 
@@ -156,8 +183,7 @@
         ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"")
         result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=')
         self.assertTrue('prefile' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration. ")
-        self.append_config("TEST_PREFILE=\"localconf\"")
-        self.addCleanup(self.remove_config, "TEST_PREFILE=\"localconf\"")
+        self.write_config("TEST_PREFILE=\"localconf\"")
         result = runCmd('bitbake -r conf/prefile.conf -e | grep TEST_PREFILE=')
         self.assertTrue('localconf' in result.output, "Preconfigure file \"prefile.conf\"was not taken into consideration.")
 
@@ -166,8 +192,7 @@
         postconf = os.path.join(self.builddir, 'conf/postfile.conf')
         self.track_for_cleanup(postconf)
         ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"")
-        self.append_config("TEST_POSTFILE=\"localconf\"")
-        self.addCleanup(self.remove_config, "TEST_POSTFILE=\"localconf\"")
+        self.write_config("TEST_POSTFILE=\"localconf\"")
         result = runCmd('bitbake -R conf/postfile.conf -e | grep TEST_POSTFILE=')
         self.assertTrue('postfile' in result.output, "Postconfigure file \"postfile.conf\"was not taken into consideration.")
 
@@ -181,6 +206,7 @@
         self.write_config("""DL_DIR = \"${TOPDIR}/download-selftest\"
 SSTATE_DIR = \"${TOPDIR}/download-selftest\"
 """)
+        self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
         self.write_recipeinc('man',"\ndo_fail_task () {\nexit 1 \n}\n\naddtask do_fail_task before do_fetch\n" )
         runCmd('bitbake -c cleanall man xcursor-transparent-theme')
         result = runCmd('bitbake man xcursor-transparent-theme -k', ignore_status=True)
diff --git a/meta/lib/oeqa/selftest/buildoptions.py b/meta/lib/oeqa/selftest/buildoptions.py
index 483803b..acf481f 100644
--- a/meta/lib/oeqa/selftest/buildoptions.py
+++ b/meta/lib/oeqa/selftest/buildoptions.py
@@ -1,9 +1,6 @@
-import unittest
 import os
-import logging
 import re
 import glob as g
-import pexpect as p
 
 from oeqa.selftest.base import oeSelfTest
 from oeqa.selftest.buildhistory import BuildhistoryBase
@@ -42,7 +39,7 @@
         for image_file in deploydir_files:
             if imagename in image_file and os.path.islink(os.path.join(deploydir, image_file)):
                 track_original_files.append(os.path.realpath(os.path.join(deploydir, image_file)))
-        self.append_config("RM_OLD_IMAGE = \"1\"")
+        self.write_config("RM_OLD_IMAGE = \"1\"")
         bitbake("-C rootfs core-image-minimal")
         deploydir_files = os.listdir(deploydir)
         remaining_not_expected = [path for path in track_original_files if os.path.basename(path) in deploydir_files]
@@ -100,7 +97,7 @@
 
     @testcase(278)
     def test_sanity_userspace_dependency(self):
-        self.append_config('WARN_QA_append = " unsafe-references-in-binaries unsafe-references-in-scripts"')
+        self.write_config('WARN_QA_append = " unsafe-references-in-binaries unsafe-references-in-scripts"')
         bitbake("-ccleansstate gzip nfs-utils")
         res = bitbake("gzip nfs-utils")
         self.assertTrue("WARNING: QA Issue: gzip" in res.output, "WARNING: QA Issue: gzip message is not present in bitbake's output: %s" % res.output)
@@ -128,7 +125,7 @@
         This method is used to test the build of directfb image for arm arch.
         In essence we build a coreimagedirectfb and test the exitcode of bitbake that in case of success is 0.
         """
-        self.add_command_to_tearDown('cleanupworkdir')
+        self.add_command_to_tearDown('cleanup-workdir')
         self.write_config("DISTRO_FEATURES_remove = \"x11\"\nDISTRO_FEATURES_append = \" directfb\"\nMACHINE ??= \"qemuarm\"")
         res = bitbake("core-image-directfb", ignore_status=True)
         self.assertEqual(res.status, 0, "\ncoreimagedirectfb failed to build. Please check logs for further details.\nbitbake output %s" % res.output)
@@ -139,7 +136,7 @@
         """
         Test for archiving the work directory and exporting the source files.
         """
-        self.add_command_to_tearDown('cleanupworkdir')
+        self.add_command_to_tearDown('cleanup-workdir')
         self.write_config("INHERIT = \"archiver\"\nARCHIVER_MODE[src] = \"original\"\nARCHIVER_MODE[srpm] = \"1\"")
         res = bitbake("xcursor-transparent-theme", ignore_status=True)
         self.assertEqual(res.status, 0, "\nCouldn't build xcursortransparenttheme.\nbitbake output %s" % res.output)
diff --git a/meta/lib/oeqa/selftest/devtool.py b/meta/lib/oeqa/selftest/devtool.py
index 6e731d6..dcdef5a 100644
--- a/meta/lib/oeqa/selftest/devtool.py
+++ b/meta/lib/oeqa/selftest/devtool.py
@@ -84,11 +84,44 @@
 
 class DevtoolTests(DevtoolBase):
 
+    def setUp(self):
+        """Test case setup function"""
+        super(DevtoolTests, self).setUp()
+        self.workspacedir = os.path.join(self.builddir, 'workspace')
+        self.assertTrue(not os.path.exists(self.workspacedir),
+                        'This test cannot be run with a workspace directory '
+                        'under the build directory')
+
+    def _check_src_repo(self, repo_dir):
+        """Check srctree git repository"""
+        self.assertTrue(os.path.isdir(os.path.join(repo_dir, '.git')),
+                        'git repository for external source tree not found')
+        result = runCmd('git status --porcelain', cwd=repo_dir)
+        self.assertEqual(result.output.strip(), "",
+                         'Created git repo is not clean')
+        result = runCmd('git symbolic-ref HEAD', cwd=repo_dir)
+        self.assertEqual(result.output.strip(), "refs/heads/devtool",
+                         'Wrong branch in git repo')
+
+    def _check_repo_status(self, repo_dir, expected_status):
+        """Check the worktree status of a repository"""
+        result = runCmd('git status . --porcelain',
+                        cwd=repo_dir)
+        for line in result.output.splitlines():
+            for ind, (f_status, fn_re) in enumerate(expected_status):
+                if re.match(fn_re, line[3:]):
+                    if f_status != line[:2]:
+                        self.fail('Unexpected status in line: %s' % line)
+                    expected_status.pop(ind)
+                    break
+            else:
+                self.fail('Unexpected modified file in line: %s' % line)
+        if expected_status:
+            self.fail('Missing file changes: %s' % expected_status)
+
     @testcase(1158)
     def test_create_workspace(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         result = runCmd('bitbake-layers show-layers')
         self.assertTrue('/workspace' not in result.output, 'This test cannot be run with a workspace layer in bblayers.conf')
         # Try creating a workspace layer with a specific path
@@ -99,19 +132,16 @@
         result = runCmd('bitbake-layers show-layers')
         self.assertIn(tempdir, result.output)
         # Try creating a workspace layer with the default path
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         result = runCmd('devtool create-workspace')
-        self.assertTrue(os.path.isfile(os.path.join(workspacedir, 'conf', 'layer.conf')), msg = "No workspace created. devtool output: %s " % result.output)
+        self.assertTrue(os.path.isfile(os.path.join(self.workspacedir, 'conf', 'layer.conf')), msg = "No workspace created. devtool output: %s " % result.output)
         result = runCmd('bitbake-layers show-layers')
         self.assertNotIn(tempdir, result.output)
-        self.assertIn(workspacedir, result.output)
+        self.assertIn(self.workspacedir, result.output)
 
     @testcase(1159)
     def test_devtool_add(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Fetch source
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
@@ -121,11 +151,11 @@
         srcdir = os.path.join(tempdir, 'pv-1.5.3')
         self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure')), 'Unable to find configure script in source directory')
         # Test devtool add
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake -c cleansstate pv')
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         result = runCmd('devtool add pv %s' % srcdir)
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
         # Test devtool status
         result = runCmd('devtool status')
         self.assertIn('pv', result.output)
@@ -144,9 +174,6 @@
 
     @testcase(1162)
     def test_devtool_add_library(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # We don't have the ability to pick up this dependency automatically yet...
         bitbake('libusb1')
         # Fetch source
@@ -158,10 +185,10 @@
         srcdir = os.path.join(tempdir, 'libftdi1-1.1')
         self.assertTrue(os.path.isfile(os.path.join(srcdir, 'CMakeLists.txt')), 'Unable to find CMakeLists.txt in source directory')
         # Test devtool add (and use -V so we test that too)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         result = runCmd('devtool add libftdi %s -V 1.1' % srcdir)
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
         # Test devtool status
         result = runCmd('devtool status')
         self.assertIn('libftdi', result.output)
@@ -185,9 +212,6 @@
 
     @testcase(1160)
     def test_devtool_add_fetch(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Fetch source
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
@@ -196,11 +220,11 @@
         testrecipe = 'python-markupsafe'
         srcdir = os.path.join(tempdir, testrecipe)
         # Test devtool add
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. %s' % result.output)
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. %s' % result.output)
         self.assertTrue(os.path.isfile(os.path.join(srcdir, 'setup.py')), 'Unable to find setup.py in source directory')
         # Test devtool status
         result = runCmd('devtool status')
@@ -232,9 +256,6 @@
 
     @testcase(1161)
     def test_devtool_add_fetch_git(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Fetch source
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
@@ -243,11 +264,11 @@
         testrecipe = 'libmatchbox2'
         srcdir = os.path.join(tempdir, testrecipe)
         # Test devtool add
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake -c cleansstate %s' % testrecipe)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         result = runCmd('devtool add %s %s -f %s' % (testrecipe, srcdir, url))
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created: %s' % result.output)
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created: %s' % result.output)
         self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure.ac in source directory')
         # Test devtool status
         result = runCmd('devtool status')
@@ -284,32 +305,25 @@
 
     @testcase(1164)
     def test_devtool_modify(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Clean up anything in the workdir/sysroot/sstate cache
         bitbake('mdadm -c cleansstate')
         # Try modifying a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         self.add_command_to_tearDown('bitbake -c clean mdadm')
         result = runCmd('devtool modify mdadm -x %s' % tempdir)
         self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found')
-        self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found')
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
-        matches = glob.glob(os.path.join(workspacedir, 'appends', 'mdadm_*.bbappend'))
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+        matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'mdadm_*.bbappend'))
         self.assertTrue(matches, 'bbappend not created %s' % result.output)
         # Test devtool status
         result = runCmd('devtool status')
         self.assertIn('mdadm', result.output)
         self.assertIn(tempdir, result.output)
         # Check git repo
-        result = runCmd('git status --porcelain', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "", 'Created git repo is not clean')
-        result = runCmd('git symbolic-ref HEAD', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo')
+        self._check_src_repo(tempdir)
         # Try building
         bitbake('mdadm')
         # Try making (minor) modifications to the source
@@ -336,13 +350,10 @@
 
     @testcase(1166)
     def test_devtool_modify_invalid(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Try modifying some recipes
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
 
         testrecipes = 'perf kernel-devsrc package-index core-image-minimal meta-toolchain packagegroup-core-sdk meta-ide-support'.split()
@@ -367,14 +378,14 @@
             self.assertNotEqual(result.status, 0, 'devtool modify on %s should have failed. devtool output: %s' %  (testrecipe, result.output))
             self.assertIn('ERROR: ', result.output, 'devtool modify on %s should have given an ERROR' % testrecipe)
 
+    @testcase(1365)
     def test_devtool_modify_native(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
+        self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Try modifying some recipes
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
 
         bbclassextended = False
@@ -400,8 +411,6 @@
     @testcase(1165)
     def test_devtool_modify_git(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         testrecipe = 'mkelfimage'
         src_uri = get_bb_var('SRC_URI', testrecipe)
         self.assertIn('git://', src_uri, 'This test expects the %s recipe to be a git recipe' % testrecipe)
@@ -410,32 +419,26 @@
         # Try modifying a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
         self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile')), 'Extracted source could not be found')
-        self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found')
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. devtool output: %s' % result.output)
-        matches = glob.glob(os.path.join(workspacedir, 'appends', 'mkelfimage_*.bbappend'))
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created. devtool output: %s' % result.output)
+        matches = glob.glob(os.path.join(self.workspacedir, 'appends', 'mkelfimage_*.bbappend'))
         self.assertTrue(matches, 'bbappend not created')
         # Test devtool status
         result = runCmd('devtool status')
         self.assertIn(testrecipe, result.output)
         self.assertIn(tempdir, result.output)
         # Check git repo
-        result = runCmd('git status --porcelain', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "", 'Created git repo is not clean')
-        result = runCmd('git symbolic-ref HEAD', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo')
+        self._check_src_repo(tempdir)
         # Try building
         bitbake(testrecipe)
 
     @testcase(1167)
     def test_devtool_modify_localfiles(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         testrecipe = 'lighttpd'
         src_uri = (get_bb_var('SRC_URI', testrecipe) or '').split()
         foundlocal = False
@@ -449,13 +452,13 @@
         # Try modifying a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
         self.assertTrue(os.path.exists(os.path.join(tempdir, 'configure.ac')), 'Extracted source could not be found')
-        self.assertTrue(os.path.exists(os.path.join(workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
-        matches = glob.glob(os.path.join(workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+        matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
         self.assertTrue(matches, 'bbappend not created')
         # Test devtool status
         result = runCmd('devtool status')
@@ -464,30 +467,46 @@
         # Try building
         bitbake(testrecipe)
 
+    @testcase(1378)
+    def test_devtool_modify_virtual(self):
+        # Try modifying a virtual recipe
+        virtrecipe = 'virtual/libx11'
+        realrecipe = 'libx11'
+        tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+        self.track_for_cleanup(tempdir)
+        self.track_for_cleanup(self.workspacedir)
+        self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+        result = runCmd('devtool modify %s -x %s' % (virtrecipe, tempdir))
+        self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found')
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir, 'conf', 'layer.conf')), 'Workspace directory not created')
+        matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % realrecipe))
+        self.assertTrue(matches, 'bbappend not created %s' % result.output)
+        # Test devtool status
+        result = runCmd('devtool status')
+        self.assertNotIn(virtrecipe, result.output)
+        self.assertIn(realrecipe, result.output)
+        # Check git repo
+        self._check_src_repo(tempdir)
+        # This is probably sufficient
+
+
     @testcase(1169)
     def test_devtool_update_recipe(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         testrecipe = 'minicom'
         recipefile = get_bb_var('FILE', testrecipe)
         src_uri = get_bb_var('SRC_URI', testrecipe)
         self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe)
+        self._check_repo_status(os.path.dirname(recipefile), [])
         # First, modify a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         # (don't bother with cleaning the recipe on teardown, we won't be building it)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
         # Check git repo
-        self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found')
-        result = runCmd('git status --porcelain', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "", 'Created git repo is not clean')
-        result = runCmd('git symbolic-ref HEAD', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo')
+        self._check_src_repo(tempdir)
         # Add a couple of commits
         # FIXME: this only tests adding, need to also test update and remove
         result = runCmd('echo "Additional line" >> README', cwd=tempdir)
@@ -497,25 +516,14 @@
         result = runCmd('git commit -m "Add a new file"', cwd=tempdir)
         self.add_command_to_tearDown('cd %s; rm %s/*.patch; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
         result = runCmd('devtool update-recipe %s' % testrecipe)
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertNotEqual(result.output.strip(), "", '%s recipe should be modified' % testrecipe)
-        status = result.output.splitlines()
-        self.assertEqual(len(status), 3, 'Less/more files modified than expected. Entire status:\n%s' % result.output)
-        for line in status:
-            if line.endswith('0001-Change-the-README.patch'):
-                self.assertEqual(line[:3], '?? ', 'Unexpected status in line: %s' % line)
-            elif line.endswith('0002-Add-a-new-file.patch'):
-                self.assertEqual(line[:3], '?? ', 'Unexpected status in line: %s' % line)
-            elif re.search('%s_[^_]*.bb$' % testrecipe, line):
-                self.assertEqual(line[:3], ' M ', 'Unexpected status in line: %s' % line)
-            else:
-                raise AssertionError('Unexpected modified file in status: %s' % line)
+        expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
+                           ('??', '.*/0001-Change-the-README.patch$'),
+                           ('??', '.*/0002-Add-a-new-file.patch$')]
+        self._check_repo_status(os.path.dirname(recipefile), expected_status)
 
     @testcase(1172)
     def test_devtool_update_recipe_git(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         testrecipe = 'mtd-utils'
         recipefile = get_bb_var('FILE', testrecipe)
         src_uri = get_bb_var('SRC_URI', testrecipe)
@@ -525,21 +533,16 @@
             if entry.startswith('file://') and entry.endswith('.patch'):
                 patches.append(entry[7:].split(';')[0])
         self.assertGreater(len(patches), 0, 'The %s recipe does not appear to contain any patches, so this test will not be effective' % testrecipe)
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe)
+        self._check_repo_status(os.path.dirname(recipefile), [])
         # First, modify a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         # (don't bother with cleaning the recipe on teardown, we won't be building it)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
         # Check git repo
-        self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found')
-        result = runCmd('git status --porcelain', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "", 'Created git repo is not clean')
-        result = runCmd('git symbolic-ref HEAD', cwd=tempdir)
-        self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo')
+        self._check_src_repo(tempdir)
         # Add a couple of commits
         # FIXME: this only tests adding, need to also test update and remove
         result = runCmd('echo "# Additional line" >> Makefile', cwd=tempdir)
@@ -549,19 +552,10 @@
         result = runCmd('git commit -m "Add a new file"', cwd=tempdir)
         self.add_command_to_tearDown('cd %s; rm -rf %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
         result = runCmd('devtool update-recipe -m srcrev %s' % testrecipe)
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertNotEqual(result.output.strip(), "", '%s recipe should be modified' % testrecipe)
-        status = result.output.splitlines()
-        for line in status:
-            for patch in patches:
-                if line.endswith(patch):
-                    self.assertEqual(line[:3], ' D ', 'Unexpected status in line: %s' % line)
-                    break
-            else:
-                if re.search('%s_[^_]*.bb$' % testrecipe, line):
-                    self.assertEqual(line[:3], ' M ', 'Unexpected status in line: %s' % line)
-                else:
-                    raise AssertionError('Unexpected modified file in status: %s' % line)
+        expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile))] + \
+                          [(' D', '.*/%s$' % patch) for patch in patches]
+        self._check_repo_status(os.path.dirname(recipefile), expected_status)
+
         result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile))
         addlines = ['SRCREV = ".*"', 'SRC_URI = "git://git.infradead.org/mtd-utils.git"']
         srcurilines = src_uri.split()
@@ -588,50 +582,33 @@
         # Now try with auto mode
         runCmd('cd %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, os.path.basename(recipefile)))
         result = runCmd('devtool update-recipe %s' % testrecipe)
-        result = runCmd('git rev-parse --show-toplevel')
+        result = runCmd('git rev-parse --show-toplevel', cwd=os.path.dirname(recipefile))
         topleveldir = result.output.strip()
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        status = result.output.splitlines()
         relpatchpath = os.path.join(os.path.relpath(os.path.dirname(recipefile), topleveldir), testrecipe)
-        expectedstatus = [('M', os.path.relpath(recipefile, topleveldir)),
-                          ('??', '%s/0001-Change-the-Makefile.patch' % relpatchpath),
-                          ('??', '%s/0002-Add-a-new-file.patch' % relpatchpath)]
-        for line in status:
-            statusline = line.split(None, 1)
-            for fstatus, fn in expectedstatus:
-                if fn == statusline[1]:
-                    if fstatus != statusline[0]:
-                        self.fail('Unexpected status in line: %s' % line)
-                    break
-            else:
-                self.fail('Unexpected modified file in line: %s' % line)
+        expected_status = [(' M', os.path.relpath(recipefile, topleveldir)),
+                           ('??', '%s/0001-Change-the-Makefile.patch' % relpatchpath),
+                           ('??', '%s/0002-Add-a-new-file.patch' % relpatchpath)]
+        self._check_repo_status(os.path.dirname(recipefile), expected_status)
 
     @testcase(1170)
     def test_devtool_update_recipe_append(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         testrecipe = 'mdadm'
         recipefile = get_bb_var('FILE', testrecipe)
         src_uri = get_bb_var('SRC_URI', testrecipe)
         self.assertNotIn('git://', src_uri, 'This test expects the %s recipe to NOT be a git recipe' % testrecipe)
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe)
+        self._check_repo_status(os.path.dirname(recipefile), [])
         # First, modify a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         tempsrcdir = os.path.join(tempdir, 'source')
         templayerdir = os.path.join(tempdir, 'layer')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         # (don't bother with cleaning the recipe on teardown, we won't be building it)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir))
         # Check git repo
-        self.assertTrue(os.path.isdir(os.path.join(tempsrcdir, '.git')), 'git repository for external source tree not found')
-        result = runCmd('git status --porcelain', cwd=tempsrcdir)
-        self.assertEqual(result.output.strip(), "", 'Created git repo is not clean')
-        result = runCmd('git symbolic-ref HEAD', cwd=tempsrcdir)
-        self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo')
+        self._check_src_repo(tempsrcdir)
         # Add a commit
         result = runCmd("sed 's!\\(#define VERSION\\W*\"[^\"]*\\)\"!\\1-custom\"!' -i ReadMe.c", cwd=tempsrcdir)
         result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir)
@@ -642,8 +619,7 @@
         result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
         self.assertNotIn('WARNING:', result.output)
         # Check recipe is still clean
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe)
+        self._check_repo_status(os.path.dirname(recipefile), [])
         # Check bbappend was created
         splitpath = os.path.dirname(recipefile).split(os.sep)
         appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
@@ -685,8 +661,6 @@
     @testcase(1171)
     def test_devtool_update_recipe_append_git(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         testrecipe = 'mtd-utils'
         recipefile = get_bb_var('FILE', testrecipe)
         src_uri = get_bb_var('SRC_URI', testrecipe)
@@ -695,23 +669,18 @@
             if entry.startswith('git://'):
                 git_uri = entry
                 break
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe)
+        self._check_repo_status(os.path.dirname(recipefile), [])
         # First, modify a recipe
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         tempsrcdir = os.path.join(tempdir, 'source')
         templayerdir = os.path.join(tempdir, 'layer')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         # (don't bother with cleaning the recipe on teardown, we won't be building it)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempsrcdir))
         # Check git repo
-        self.assertTrue(os.path.isdir(os.path.join(tempsrcdir, '.git')), 'git repository for external source tree not found')
-        result = runCmd('git status --porcelain', cwd=tempsrcdir)
-        self.assertEqual(result.output.strip(), "", 'Created git repo is not clean')
-        result = runCmd('git symbolic-ref HEAD', cwd=tempsrcdir)
-        self.assertEqual(result.output.strip(), "refs/heads/devtool", 'Wrong branch in git repo')
+        self._check_src_repo(tempsrcdir)
         # Add a commit
         result = runCmd('echo "# Additional line" >> Makefile', cwd=tempsrcdir)
         result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
@@ -731,8 +700,7 @@
         result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
         self.assertNotIn('WARNING:', result.output)
         # Check recipe is still clean
-        result = runCmd('git status . --porcelain', cwd=os.path.dirname(recipefile))
-        self.assertEqual(result.output.strip(), "", '%s recipe is not clean' % testrecipe)
+        self._check_repo_status(os.path.dirname(recipefile), [])
         # Check bbappend was created
         splitpath = os.path.dirname(recipefile).split(os.sep)
         appenddir = os.path.join(templayerdir, splitpath[-2], splitpath[-1])
@@ -779,28 +747,104 @@
             self.assertEqual(expectedlines, f.readlines())
         # Deleting isn't expected to work under these circumstances
 
+    @testcase(1370)
+    def test_devtool_update_recipe_local_files(self):
+        """Check that local source files are copied over instead of patched"""
+        testrecipe = 'makedevs'
+        recipefile = get_bb_var('FILE', testrecipe)
+        # Setup srctree for modifying the recipe
+        tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+        self.track_for_cleanup(tempdir)
+        self.track_for_cleanup(self.workspacedir)
+        self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+        # (don't bother with cleaning the recipe on teardown, we won't be
+        # building it)
+        result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
+        # Check git repo
+        self._check_src_repo(tempdir)
+        # Edit / commit local source
+        runCmd('echo "/* Foobar */" >> oe-local-files/makedevs.c', cwd=tempdir)
+        runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
+        runCmd('echo "Bar" > new-file', cwd=tempdir)
+        runCmd('git add new-file', cwd=tempdir)
+        runCmd('git commit -m "Add new file"', cwd=tempdir)
+        self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' %
+                                     os.path.dirname(recipefile))
+        runCmd('devtool update-recipe %s' % testrecipe)
+        expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
+                           (' M', '.*/makedevs/makedevs.c$'),
+                           ('??', '.*/makedevs/new-local$'),
+                           ('??', '.*/makedevs/0001-Add-new-file.patch$')]
+        self._check_repo_status(os.path.dirname(recipefile), expected_status)
+
+    @testcase(1371)
+    def test_devtool_update_recipe_local_files_2(self):
+        """Check local source files support when oe-local-files is in Git"""
+        testrecipe = 'lzo'
+        recipefile = get_bb_var('FILE', testrecipe)
+        # Setup srctree for modifying the recipe
+        tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+        self.track_for_cleanup(tempdir)
+        self.track_for_cleanup(self.workspacedir)
+        self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+        result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
+        # Check git repo
+        self._check_src_repo(tempdir)
+        # Add oe-local-files to Git
+        runCmd('rm oe-local-files/.gitignore', cwd=tempdir)
+        runCmd('git add oe-local-files', cwd=tempdir)
+        runCmd('git commit -m "Add local sources"', cwd=tempdir)
+        # Edit / commit local sources
+        runCmd('echo "# Foobar" >> oe-local-files/acinclude.m4', cwd=tempdir)
+        runCmd('git commit -am "Edit existing file"', cwd=tempdir)
+        runCmd('git rm oe-local-files/run-ptest', cwd=tempdir)
+        runCmd('git commit -m"Remove file"', cwd=tempdir)
+        runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir)
+        runCmd('git add oe-local-files/new-local', cwd=tempdir)
+        runCmd('git commit -m "Add new local file"', cwd=tempdir)
+        runCmd('echo "Gar" > new-file', cwd=tempdir)
+        runCmd('git add new-file', cwd=tempdir)
+        runCmd('git commit -m "Add new file"', cwd=tempdir)
+        self.add_command_to_tearDown('cd %s; git clean -fd .; git checkout .' %
+                                     os.path.dirname(recipefile))
+        # Checkout unmodified file to working copy -> devtool should still pick
+        # the modified version from HEAD
+        runCmd('git checkout HEAD^ -- oe-local-files/acinclude.m4', cwd=tempdir)
+        runCmd('devtool update-recipe %s' % testrecipe)
+        expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
+                           (' M', '.*/acinclude.m4$'),
+                           (' D', '.*/run-ptest$'),
+                           ('??', '.*/new-local$'),
+                           ('??', '.*/0001-Add-new-file.patch$')]
+        self._check_repo_status(os.path.dirname(recipefile), expected_status)
+
     @testcase(1163)
     def test_devtool_extract(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         # Try devtool extract
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         result = runCmd('devtool extract remake %s' % tempdir)
         self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found')
-        self.assertTrue(os.path.isdir(os.path.join(tempdir, '.git')), 'git repository for external source tree not found')
+        self._check_src_repo(tempdir)
+
+    @testcase(1379)
+    def test_devtool_extract_virtual(self):
+        tempdir = tempfile.mkdtemp(prefix='devtoolqa')
+        # Try devtool extract
+        self.track_for_cleanup(tempdir)
+        self.track_for_cleanup(self.workspacedir)
+        self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+        result = runCmd('devtool extract virtual/libx11 %s' % tempdir)
+        self.assertTrue(os.path.exists(os.path.join(tempdir, 'Makefile.am')), 'Extracted source could not be found')
+        self._check_src_repo(tempdir)
 
     @testcase(1168)
     def test_devtool_reset_all(self):
-        # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         testrecipe1 = 'mdadm'
         testrecipe2 = 'cronie'
@@ -823,6 +867,7 @@
         matches2 = glob.glob(stampprefix2 + '*')
         self.assertFalse(matches2, 'Stamp files exist for recipe %s that should have been cleaned' % testrecipe2)
 
+    @testcase(1272)
     def test_devtool_deploy_target(self):
         # NOTE: Whilst this test would seemingly be better placed as a runtime test,
         # unfortunately the runtime tests run under bitbake and you can't run
@@ -846,8 +891,7 @@
                 break
         else:
             self.skipTest('No tap devices found - you must set up tap devices with scripts/runqemu-gen-tapdevs before running this test')
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
+        self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Definitions
         testrecipe = 'mdadm'
         testfile = '/sbin/mdadm'
@@ -863,7 +907,7 @@
         # Try devtool modify
         tempdir = tempfile.mkdtemp(prefix='devtoolqa')
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
         result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
@@ -908,18 +952,19 @@
             result = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, testcommand), ignore_status=True)
             self.assertNotEqual(result, 0, 'undeploy-target did not remove command as it should have')
 
+    @testcase(1366)
     def test_devtool_build_image(self):
         """Test devtool build-image plugin"""
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
+        self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         image = 'core-image-minimal'
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
         self.add_command_to_tearDown('bitbake -c clean %s' % image)
         bitbake('%s -c clean' % image)
         # Add target and native recipes to workspace
-        for recipe in ('mdadm', 'parted-native'):
+        recipes = ['mdadm', 'parted-native']
+        for recipe in recipes:
             tempdir = tempfile.mkdtemp(prefix='devtoolqa')
             self.track_for_cleanup(tempdir)
             self.add_command_to_tearDown('bitbake -c clean %s' % recipe)
@@ -927,17 +972,24 @@
         # Try to build image
         result = runCmd('devtool build-image %s' % image)
         self.assertNotEqual(result, 0, 'devtool build-image failed')
-        # Check if image.bbappend has required content
-        bbappend = os.path.join(workspacedir, 'appends', image+'.bbappend')
-        self.assertTrue(os.path.isfile(bbappend), 'bbappend not created %s' % result.output)
-        # NOTE: native recipe parted-native should not be in IMAGE_INSTALL_append
-        self.assertTrue('IMAGE_INSTALL_append = " mdadm"\n' in open(bbappend).readlines(),
-                        'IMAGE_INSTALL_append = " mdadm" not found in %s' % bbappend)
+        # Check if image contains expected packages
+        deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
+        image_link_name = get_bb_var('IMAGE_LINK_NAME', image)
+        reqpkgs = [item for item in recipes if not item.endswith('-native')]
+        with open(os.path.join(deploy_dir_image, image_link_name + '.manifest'), 'r') as f:
+            for line in f:
+                splitval = line.split()
+                if splitval:
+                    pkg = splitval[0]
+                    if pkg in reqpkgs:
+                        reqpkgs.remove(pkg)
+        if reqpkgs:
+            self.fail('The following packages were not present in the image as expected: %s' % ', '.join(reqpkgs))
 
+    @testcase(1367)
     def test_devtool_upgrade(self):
         # Check preconditions
-        workspacedir = os.path.join(self.builddir, 'workspace')
-        self.assertTrue(not os.path.exists(workspacedir), 'This test cannot be run with a workspace directory under the build directory')
+        self.assertTrue(not os.path.exists(self.workspacedir), 'This test cannot be run with a workspace directory under the build directory')
         # Check parameters
         result = runCmd('devtool upgrade -h')
         for param in 'recipename srctree --version -V --branch -b --keep-temp --no-patch'.split():
@@ -955,9 +1007,9 @@
         # Check if srctree at least is populated
         self.assertTrue(len(os.listdir(tempdir)) > 0, 'scrtree (%s) should be populated with new (%s) source code' % (tempdir, version))
         # Check new recipe folder is present
-        self.assertTrue(os.path.exists(os.path.join(workspacedir,'recipes',recipe)), 'Recipe folder should exist')
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir,'recipes',recipe)), 'Recipe folder should exist')
         # Check new recipe file is present
-        self.assertTrue(os.path.exists(os.path.join(workspacedir,'recipes',recipe,"%s_%s.bb" % (recipe,version))), 'Recipe folder should exist')
+        self.assertTrue(os.path.exists(os.path.join(self.workspacedir,'recipes',recipe,"%s_%s.bb" % (recipe,version))), 'Recipe folder should exist')
         # Check devtool status and make sure recipe is present
         result = runCmd('devtool status')
         self.assertIn(recipe, result.output)
@@ -967,5 +1019,18 @@
         result = runCmd('devtool status')
         self.assertNotIn(recipe, result.output)
         self.track_for_cleanup(tempdir)
-        self.track_for_cleanup(workspacedir)
+        self.track_for_cleanup(self.workspacedir)
         self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+
+    @testcase(1352)
+    def test_devtool_layer_plugins(self):
+        """Test that devtool can use plugins from other layers.
+
+        This test executes the selftest-reverse command from meta-selftest."""
+
+        self.track_for_cleanup(self.workspacedir)
+        self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
+
+        s = "Microsoft Made No Profit From Anyone's Zunes Yo"
+        result = runCmd("devtool --quiet selftest-reverse \"%s\"" % s)
+        self.assertEqual(result.output, s[::-1])
diff --git a/meta/lib/oeqa/selftest/imagefeatures.py b/meta/lib/oeqa/selftest/imagefeatures.py
index fcffc42..4efb0d9 100644
--- a/meta/lib/oeqa/selftest/imagefeatures.py
+++ b/meta/lib/oeqa/selftest/imagefeatures.py
@@ -25,9 +25,7 @@
         features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh empty-root-password allow-empty-password"\n'
         features += 'INHERIT += "extrausers"\n'
         features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
-
-        # Append 'features' to local.conf
-        self.append_config(features)
+        self.write_config(features)
 
         # Build a core-image-minimal
         bitbake('core-image-minimal')
@@ -53,9 +51,7 @@
         features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh allow-empty-password"\n'
         features += 'INHERIT += "extrausers"\n'
         features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
-
-        # Append 'features' to local.conf
-        self.append_config(features)
+        self.write_config(features)
 
         # Build a core-image-minimal
         bitbake('core-image-minimal')
@@ -87,9 +83,7 @@
         features += 'IMAGE_INSTALL_append = " openssh"\n'
         features += 'EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password package-management"\n'
         features += 'RPMROOTFSDEPENDS_remove = "rpmresolve-native:do_populate_sysroot"'
-
-        # Append 'features' to local.conf
-        self.append_config(features)
+        self.write_config(features)
 
         # Build a core-image-minimal
         bitbake('core-image-minimal')
@@ -159,9 +153,7 @@
 
         features = 'DISTRO_FEATURES_append = " wayland"\n'
         features += 'CORE_IMAGE_EXTRA_INSTALL += "wayland weston"'
-
-        # Append 'features' to local.conf
-        self.append_config(features)
+        self.write_config(features)
 
         # Build a core-image-weston
         bitbake('core-image-weston')
diff --git a/meta/lib/oeqa/selftest/layerappend.py b/meta/lib/oeqa/selftest/layerappend.py
index a82a6c8..4de5034 100644
--- a/meta/lib/oeqa/selftest/layerappend.py
+++ b/meta/lib/oeqa/selftest/layerappend.py
@@ -46,10 +46,11 @@
 
 SRC_URI_append += "file://appendtest.txt"
 """
-    layerappend = "BBLAYERS += \"COREBASE/meta-layertest0 COREBASE/meta-layertest1 COREBASE/meta-layertest2\""
+    layerappend = ''
 
     def tearDownLocal(self):
-        ftools.remove_from_file(self.builddir + "/conf/bblayers.conf", self.layerappend.replace("COREBASE", self.builddir + "/.."))
+        if self.layerappend:
+            ftools.remove_from_file(self.builddir + "/conf/bblayers.conf", self.layerappend)
 
     @testcase(1196)
     def test_layer_appends(self):
@@ -79,7 +80,9 @@
                 with open(layer + "/recipes-test/layerappendtest/appendtest.txt", "w") as f:
                     f.write("Layer 2 test")
             self.track_for_cleanup(layer)
-        ftools.append_file(self.builddir + "/conf/bblayers.conf", self.layerappend.replace("COREBASE", self.builddir + "/.."))
+
+        self.layerappend = "BBLAYERS += \"{0}/meta-layertest0 {0}/meta-layertest1 {0}/meta-layertest2\"".format(corebase)
+        ftools.append_file(self.builddir + "/conf/bblayers.conf", self.layerappend)
         bitbake("layerappendtest")
         data = ftools.read_file(stagingdir + "/appendtest.txt")
         self.assertEqual(data, "Layer 2 test")
diff --git a/meta/lib/oeqa/selftest/manifest.py b/meta/lib/oeqa/selftest/manifest.py
new file mode 100644
index 0000000..44d0404
--- /dev/null
+++ b/meta/lib/oeqa/selftest/manifest.py
@@ -0,0 +1,165 @@
+import unittest
+import os
+
+from oeqa.selftest.base import oeSelfTest
+from oeqa.utils.commands import get_bb_var, bitbake
+from oeqa.utils.decorators import testcase
+
+class ManifestEntry:
+    '''A manifest item of a collection able to list missing packages'''
+    def __init__(self, entry):
+        self.file = entry
+        self.missing = []
+
+class VerifyManifest(oeSelfTest):
+    '''Tests for the manifest files and contents of an image'''
+
+    @classmethod
+    def check_manifest_entries(self, manifest, path):
+        manifest_errors = []
+        try:
+            with open(manifest, "r") as mfile:
+                for line in mfile:
+                    manifest_entry = os.path.join(path, line.split()[0])
+                    self.log.debug("{}: looking for {}"\
+                                    .format(self.classname, manifest_entry))
+                    if not os.path.isfile(manifest_entry):
+                        manifest_errors.append(manifest_entry)
+                        self.log.debug("{}: {} not found"\
+                                    .format(self.classname, manifest_entry))
+        except OSError as e:
+            self.log.debug("{}: checking of {} failed"\
+                    .format(self.classname, manifest))
+            raise e
+
+        return manifest_errors
+
+    #this will possibly move from here
+    @classmethod
+    def get_dir_from_bb_var(self, bb_var, target = None):
+        target == self.buildtarget if target == None else target
+        directory = get_bb_var(bb_var, target);
+        if not directory or not os.path.isdir(directory):
+            self.log.debug("{}: {} points to {} when target = {}"\
+                    .format(self.classname, bb_var, directory, target))
+            raise OSError
+        return directory
+
+    @classmethod
+    def setUpClass(self):
+
+        self.buildtarget = 'core-image-minimal'
+        self.classname = 'VerifyManifest'
+
+        self.log.info("{}: doing bitbake {} as a prerequisite of the test"\
+                .format(self.classname, self.buildtarget))
+        if bitbake(self.buildtarget).status:
+            self.log.debug("{} Failed to setup {}"\
+                    .format(self.classname, self.buildtarget))
+            unittest.SkipTest("{}: Cannot setup testing scenario"\
+                    .format(self.classname))
+
+    @testcase(1380)
+    def test_SDK_manifest_entries(self):
+        '''Verifying the SDK manifest entries exist, this may take a build'''
+
+        # the setup should bitbake core-image-minimal and here it is required
+        # to do an additional setup for the sdk
+        sdktask = '-c populate_sdk'
+        bbargs = sdktask + ' ' + self.buildtarget
+        self.log.debug("{}: doing bitbake {} as a prerequisite of the test"\
+                .format(self.classname, bbargs))
+        if bitbake(bbargs).status:
+            self.log.debug("{} Failed to bitbake {}"\
+                    .format(self.classname, bbargs))
+            unittest.SkipTest("{}: Cannot setup testing scenario"\
+                    .format(self.classname))
+
+
+        pkgdata_dir = reverse_dir = {}
+        mfilename = mpath = m_entry = {}
+        # get manifest location based on target to query about
+        d_target= dict(target = self.buildtarget,
+                         host = 'nativesdk-packagegroup-sdk-host')
+        try:
+            mdir = self.get_dir_from_bb_var('SDK_DEPLOY', self.buildtarget)
+            for k in d_target.keys():
+                mfilename[k] = "{}-toolchain-{}.{}.manifest".format(
+                        get_bb_var("SDK_NAME", self.buildtarget),
+                        get_bb_var("SDK_VERSION", self.buildtarget),
+                        k)
+                mpath[k] = os.path.join(mdir, mfilename[k])
+                if not os.path.isfile(mpath[k]):
+                    self.log.debug("{}: {} does not exist".format(
+                        self.classname, mpath[k]))
+                    raise IOError
+                m_entry[k] = ManifestEntry(mpath[k])
+
+                pkgdata_dir[k] = self.get_dir_from_bb_var('PKGDATA_DIR',
+                        d_target[k])
+                reverse_dir[k] = os.path.join(pkgdata_dir[k],
+                        'runtime-reverse')
+                if not os.path.exists(reverse_dir[k]):
+                    self.log.debug("{}: {} does not exist".format(
+                        self.classname, reverse_dir[k]))
+                    raise IOError
+        except OSError:
+            raise unittest.SkipTest("{}: Error in obtaining manifest dirs"\
+                .format(self.classname))
+        except IOError:
+            msg = "{}: Error cannot find manifests in the specified dir:\n{}"\
+                    .format(self.classname, mdir)
+            self.fail(msg)
+
+        for k in d_target.keys():
+            self.log.debug("{}: Check manifest {}".format(
+                self.classname, m_entry[k].file))
+
+            m_entry[k].missing = self.check_manifest_entries(\
+                                               m_entry[k].file,reverse_dir[k])
+            if m_entry[k].missing:
+                msg = '{}: {} Error has the following missing entries'\
+                        .format(self.classname, m_entry[k].file)
+                logmsg = msg+':\n'+'\n'.join(m_entry[k].missing)
+                self.log.debug(logmsg)
+                self.log.info(msg)
+                self.fail(logmsg)
+
+    @testcase(1381)
+    def test_image_manifest_entries(self):
+        '''Verifying the image manifest entries exist'''
+
+        # get manifest location based on target to query about
+        try:
+            mdir = self.get_dir_from_bb_var('DEPLOY_DIR_IMAGE',
+                                                self.buildtarget)
+            mfilename = get_bb_var("IMAGE_LINK_NAME", self.buildtarget)\
+                    + ".manifest"
+            mpath = os.path.join(mdir, mfilename)
+            if not os.path.isfile(mpath): raise IOError
+            m_entry = ManifestEntry(mpath)
+
+            pkgdata_dir = {}
+            pkgdata_dir = self.get_dir_from_bb_var('PKGDATA_DIR',
+                                                self.buildtarget)
+            revdir = os.path.join(pkgdata_dir, 'runtime-reverse')
+            if not os.path.exists(revdir): raise IOError
+        except OSError:
+            raise unittest.SkipTest("{}: Error in obtaining manifest dirs"\
+                .format(self.classname))
+        except IOError:
+            msg = "{}: Error cannot find manifests in dir:\n{}"\
+                    .format(self.classname, mdir)
+            self.fail(msg)
+
+        self.log.debug("{}: Check manifest {}"\
+                            .format(self.classname, m_entry.file))
+        m_entry.missing = self.check_manifest_entries(\
+                                                    m_entry.file, revdir)
+        if m_entry.missing:
+            msg = '{}: {} Error has the following missing entries'\
+                    .format(self.classname, m_entry.file)
+            logmsg = msg+':\n'+'\n'.join(m_entry.missing)
+            self.log.debug(logmsg)
+            self.log.info(msg)
+            self.fail(logmsg)
diff --git a/meta/lib/oeqa/selftest/recipetool.py b/meta/lib/oeqa/selftest/recipetool.py
index c34ad68..b1f1d2a 100644
--- a/meta/lib/oeqa/selftest/recipetool.py
+++ b/meta/lib/oeqa/selftest/recipetool.py
@@ -492,9 +492,12 @@
 
 
 class RecipetoolAppendsrcTests(RecipetoolAppendsrcBase):
+
+    @testcase(1273)
     def test_recipetool_appendsrcfile_basic(self):
         self._test_appendsrcfile('base-files', 'a-file')
 
+    @testcase(1274)
     def test_recipetool_appendsrcfile_basic_wildcard(self):
         testrecipe = 'base-files'
         self._test_appendsrcfile(testrecipe, 'a-file', options='-w')
@@ -502,12 +505,15 @@
         bbappendfile = self._check_bbappend(testrecipe, recipefile, self.templayerdir)
         self.assertEqual(os.path.basename(bbappendfile), '%s_%%.bbappend' % testrecipe)
 
+    @testcase(1281)
     def test_recipetool_appendsrcfile_subdir_basic(self):
         self._test_appendsrcfile('base-files', 'a-file', 'tmp')
 
+    @testcase(1282)
     def test_recipetool_appendsrcfile_subdir_basic_dirdest(self):
         self._test_appendsrcfile('base-files', destdir='tmp')
 
+    @testcase(1280)
     def test_recipetool_appendsrcfile_srcdir_basic(self):
         testrecipe = 'bash'
         srcdir = get_bb_var('S', testrecipe)
@@ -515,12 +521,14 @@
         subdir = os.path.relpath(srcdir, workdir)
         self._test_appendsrcfile(testrecipe, 'a-file', srcdir=subdir)
 
+    @testcase(1275)
     def test_recipetool_appendsrcfile_existing_in_src_uri(self):
         testrecipe = 'base-files'
         filepath = self._get_first_file_uri(testrecipe)
         self.assertTrue(filepath, 'Unable to test, no file:// uri found in SRC_URI for %s' % testrecipe)
         self._test_appendsrcfile(testrecipe, filepath, has_src_uri=False)
 
+    @testcase(1276)
     def test_recipetool_appendsrcfile_existing_in_src_uri_diff_params(self):
         testrecipe = 'base-files'
         subdir = 'tmp'
@@ -530,6 +538,7 @@
         output = self._test_appendsrcfile(testrecipe, filepath, subdir, has_src_uri=False)
         self.assertTrue(any('with different parameters' in l for l in output))
 
+    @testcase(1277)
     def test_recipetool_appendsrcfile_replace_file_srcdir(self):
         testrecipe = 'bash'
         filepath = 'Makefile.in'
@@ -541,6 +550,7 @@
         bitbake('%s:do_unpack' % testrecipe)
         self.assertEqual(open(self.testfile, 'r').read(), open(os.path.join(srcdir, filepath), 'r').read())
 
+    @testcase(1278)
     def test_recipetool_appendsrcfiles_basic(self, destdir=None):
         newfiles = [self.testfile]
         for i in range(1, 5):
@@ -550,5 +560,6 @@
             newfiles.append(testfile)
         self._test_appendsrcfiles('gcc', newfiles, destdir=destdir, options='-W')
 
+    @testcase(1279)
     def test_recipetool_appendsrcfiles_basic_subdir(self):
         self.test_recipetool_appendsrcfiles_basic(destdir='testdir')
diff --git a/meta/lib/oeqa/selftest/sstatetests.py b/meta/lib/oeqa/selftest/sstatetests.py
index c4efc47..3c23062 100644
--- a/meta/lib/oeqa/selftest/sstatetests.py
+++ b/meta/lib/oeqa/selftest/sstatetests.py
@@ -34,7 +34,7 @@
         targetarch = get_bb_var('TUNE_ARCH')
         self.run_test_sstate_creation(['binutils-cross-'+ targetarch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
 
-    @testcase(975)
+    @testcase(1374)
     def test_sstate_creation_distro_specific_fail(self):
         targetarch = get_bb_var('TUNE_ARCH')
         self.run_test_sstate_creation(['binutils-cross-'+ targetarch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False)
@@ -43,7 +43,7 @@
     def test_sstate_creation_distro_nonspecific_pass(self):
         self.run_test_sstate_creation(['glibc-initial'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
 
-    @testcase(976)
+    @testcase(1375)
     def test_sstate_creation_distro_nonspecific_fail(self):
         self.run_test_sstate_creation(['glibc-initial'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False)
 
@@ -70,11 +70,11 @@
         targetarch = get_bb_var('TUNE_ARCH')
         self.run_test_cleansstate_task(['binutils-cross-' + targetarch, 'binutils-native', 'glibc-initial'], distro_specific=True, distro_nonspecific=True, temp_sstate_location=True)
 
-    @testcase(977)
+    @testcase(1376)
     def test_cleansstate_task_distro_nonspecific(self):
         self.run_test_cleansstate_task(['glibc-initial'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
 
-    @testcase(977)
+    @testcase(1377)
     def test_cleansstate_task_distro_specific(self):
         targetarch = get_bb_var('TUNE_ARCH')
         self.run_test_cleansstate_task(['binutils-cross-'+ targetarch, 'binutils-native', 'glibc-initial'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
@@ -111,12 +111,12 @@
         targetarch = get_bb_var('TUNE_ARCH')
         self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + targetarch, 'binutils-native'], temp_sstate_location=True)
 
-    @testcase(175)
+    @testcase(1372)
     def test_rebuild_distro_specific_sstate_cross_target(self):
         targetarch = get_bb_var('TUNE_ARCH')
         self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + targetarch], temp_sstate_location=True)
 
-    @testcase(175)
+    @testcase(1373)
     def test_rebuild_distro_specific_sstate_native_target(self):
         self.run_test_rebuild_distro_specific_sstate(['binutils-native'], temp_sstate_location=True)
 
@@ -211,6 +211,8 @@
         they're built on a 32 or 64 bit system. Rather than requiring two different 
         build machines and running a builds, override the variables calling uname()
         manually and check using bitbake -S.
+        
+        Also check that SDKMACHINE changing doesn't change any of these stamps.
         """
 
         topdir = get_bb_var('TOPDIR')
@@ -219,6 +221,7 @@
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
 BUILD_ARCH = \"x86_64\"
 BUILD_OS = \"linux\"
+SDKMACHINE = \"x86_64\"
 """)
         self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
         bitbake("core-image-sato -S none")
@@ -226,6 +229,7 @@
 TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
 BUILD_ARCH = \"i686\"
 BUILD_OS = \"linux\"
+SDKMACHINE = \"i686\"
 """)
         self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
         bitbake("core-image-sato -S none")
@@ -233,11 +237,16 @@
         def get_files(d):
             f = []
             for root, dirs, files in os.walk(d):
+                if "core-image-sato" in root:
+                        # SDKMACHINE changing will change do_rootfs/do_testimage/do_build stamps of core-image-sato itself
+                        # which is safe to ignore
+                        continue
                 f.extend(os.path.join(root, name) for name in files)
             return f
         files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
         files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
         files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash").replace("i686-linux", "x86_64-linux").replace("i686" + targetvendor + "-linux", "x86_64" + targetvendor + "-linux", ) for x in files2]
+        self.maxDiff = None
         self.assertItemsEqual(files1, files2)
 
 
@@ -271,11 +280,13 @@
         files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
         files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
         files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
+        self.maxDiff = None
         self.assertItemsEqual(files1, files2)
 
+    @testcase(1368)
     def test_sstate_allarch_samesigs(self):
         """
-        The sstate checksums off allarch packages should be independent of whichever 
+        The sstate checksums of allarch packages should be independent of whichever 
         MACHINE is set. Check this using bitbake -S.
         Also, rather than duplicate the test, check nativesdk stamps are the same between
         the two MACHINE values.
@@ -319,4 +330,50 @@
         files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
         self.maxDiff = None
         self.assertItemsEqual(files1, files2)
-        
+
+    @testcase(1369)
+    def test_sstate_sametune_samesigs(self):
+        """
+        The sstate checksums of two identical machines (using the same tune) should be the 
+        same, apart from changes within the machine specific stamps directory. We use the
+        qemux86copy machine to test this. Also include multilibs in the test.
+        """
+
+        topdir = get_bb_var('TOPDIR')
+        targetos = get_bb_var('TARGET_OS')
+        targetvendor = get_bb_var('TARGET_VENDOR')
+        self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
+MACHINE = \"qemux86\"
+require conf/multilib.conf
+MULTILIBS = "multilib:lib32"
+DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
+""")
+        self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
+        bitbake("world meta-toolchain -S none")
+        self.write_config("""
+TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
+MACHINE = \"qemux86copy\"
+require conf/multilib.conf
+MULTILIBS = "multilib:lib32"
+DEFAULTTUNE_virtclass-multilib-lib32 = "x86"
+""")
+        self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
+        bitbake("world meta-toolchain -S none")
+
+        def get_files(d):
+            f = []
+            for root, dirs, files in os.walk(d):
+                for name in files:
+                    if "meta-environment" in root or "cross-canadian" in root:
+                        continue
+                    if "qemux86copy-" in root or "qemux86-" in root:
+                        continue
+                    if "do_build" not in name and "do_populate_sdk" not in name:
+                        f.append(os.path.join(root, name))
+            return f
+        files1 = get_files(topdir + "/tmp-sstatesamehash/stamps")
+        files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps")
+        files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
+        self.maxDiff = None
+        self.assertItemsEqual(files1, files2)
diff --git a/meta/lib/oeqa/selftest/wic.py b/meta/lib/oeqa/selftest/wic.py
index 3dc54a4..ea78e22 100644
--- a/meta/lib/oeqa/selftest/wic.py
+++ b/meta/lib/oeqa/selftest/wic.py
@@ -31,50 +31,54 @@
 
 from oeqa.selftest.base import oeSelfTest
 from oeqa.utils.commands import runCmd, bitbake, get_bb_var
+from oeqa.utils.decorators import testcase
+
 
 class Wic(oeSelfTest):
     """Wic test class."""
 
     resultdir = "/var/tmp/wic/build/"
+    image_is_ready = False
 
-    @classmethod
-    def setUpClass(cls):
-        """Build wic runtime dependencies."""
-        bitbake('syslinux syslinux-native parted-native gptfdisk-native '
-                'dosfstools-native mtools-native')
-        Wic.image_is_ready = False
-
-    def setUp(self):
+    def setUpLocal(self):
         """This code is executed before each test method."""
+        self.write_config('IMAGE_FSTYPES += " hddimg"\nMACHINE_FEATURES_append = " efi"\n')
+
+        # Do this here instead of in setUpClass as the base setUp does some
+        # clean up which can result in the native tools built earlier in
+        # setUpClass being unavailable.
         if not Wic.image_is_ready:
-            # build core-image-minimal with required features
-            features = 'IMAGE_FSTYPES += " hddimg"\nMACHINE_FEATURES_append = " efi"\n'
-            self.append_config(features)
+            bitbake('syslinux syslinux-native parted-native gptfdisk-native '
+                    'dosfstools-native mtools-native')
             bitbake('core-image-minimal')
-            # set this class variable to avoid buiding image many times
             Wic.image_is_ready = True
 
         rmtree(self.resultdir, ignore_errors=True)
 
-    def test01_help(self):
+    @testcase(1208)
+    def test_help(self):
         """Test wic --help"""
         self.assertEqual(0, runCmd('wic --help').status)
 
-    def test02_createhelp(self):
+    @testcase(1209)
+    def test_createhelp(self):
         """Test wic create --help"""
         self.assertEqual(0, runCmd('wic create --help').status)
 
-    def test03_listhelp(self):
+    @testcase(1210)
+    def test_listhelp(self):
         """Test wic list --help"""
         self.assertEqual(0, runCmd('wic list --help').status)
 
-    def test04_build_image_name(self):
+    @testcase(1211)
+    def test_build_image_name(self):
         """Test wic create directdisk --image-name core-image-minimal"""
         self.assertEqual(0, runCmd("wic create directdisk "
                                    "--image-name core-image-minimal").status)
         self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
 
-    def test05_build_artifacts(self):
+    @testcase(1212)
+    def test_build_artifacts(self):
         """Test wic create directdisk providing all artifacts."""
         vars = dict((var.lower(), get_bb_var(var, 'core-image-minimal')) \
                         for var in ('STAGING_DATADIR', 'DEPLOY_DIR_IMAGE',
@@ -87,34 +91,41 @@
         self.assertEqual(0, status)
         self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
 
-    def test06_gpt_image(self):
+    @testcase(1157)
+    def test_gpt_image(self):
         """Test creation of core-image-minimal with gpt table and UUID boot"""
         self.assertEqual(0, runCmd("wic create directdisk-gpt "
                                    "--image-name core-image-minimal").status)
         self.assertEqual(1, len(glob(self.resultdir + "directdisk-*.direct")))
 
-    def test07_unsupported_subcommand(self):
+    @testcase(1213)
+    def test_unsupported_subcommand(self):
         """Test unsupported subcommand"""
         self.assertEqual(1, runCmd('wic unsupported',
                          ignore_status=True).status)
 
-    def test08_no_command(self):
+    @testcase(1214)
+    def test_no_command(self):
         """Test wic without command"""
         self.assertEqual(1, runCmd('wic', ignore_status=True).status)
 
-    def test09_help_kickstart(self):
+    @testcase(1215)
+    def test_help_overview(self):
         """Test wic help overview"""
         self.assertEqual(0, runCmd('wic help overview').status)
 
-    def test10_help_plugins(self):
+    @testcase(1216)
+    def test_help_plugins(self):
         """Test wic help plugins"""
         self.assertEqual(0, runCmd('wic help plugins').status)
 
-    def test11_help_kickstart(self):
+    @testcase(1217)
+    def test_help_kickstart(self):
         """Test wic help kickstart"""
         self.assertEqual(0, runCmd('wic help kickstart').status)
 
-    def test12_compress_gzip(self):
+    @testcase(1264)
+    def test_compress_gzip(self):
         """Test compressing an image with gzip"""
         self.assertEqual(0, runCmd("wic create directdisk "
                                    "--image-name core-image-minimal "
@@ -122,7 +133,8 @@
         self.assertEqual(1, len(glob(self.resultdir + \
                                          "directdisk-*.direct.gz")))
 
-    def test13_compress_gzip(self):
+    @testcase(1265)
+    def test_compress_bzip2(self):
         """Test compressing an image with bzip2"""
         self.assertEqual(0, runCmd("wic create directdisk "
                                    "--image-name core-image-minimal "
@@ -130,7 +142,8 @@
         self.assertEqual(1, len(glob(self.resultdir + \
                                          "directdisk-*.direct.bz2")))
 
-    def test14_compress_gzip(self):
+    @testcase(1266)
+    def test_compress_xz(self):
         """Test compressing an image with xz"""
         self.assertEqual(0, runCmd("wic create directdisk "
                                    "--image-name core-image-minimal "
@@ -138,13 +151,15 @@
         self.assertEqual(1, len(glob(self.resultdir + \
                                          "directdisk-*.direct.xz")))
 
-    def test15_wrong_compressor(self):
+    @testcase(1267)
+    def test_wrong_compressor(self):
         """Test how wic breaks if wrong compressor is provided"""
         self.assertEqual(2, runCmd("wic create directdisk "
                                    "--image-name core-image-minimal "
                                    "-c wrong", ignore_status=True).status)
 
-    def test16_rootfs_indirect_recipes(self):
+    @testcase(1268)
+    def test_rootfs_indirect_recipes(self):
         """Test usage of rootfs plugin with rootfs recipes"""
         wks = "directdisk-multi-rootfs"
         self.assertEqual(0, runCmd("wic create %s "
@@ -154,7 +169,8 @@
                                    % wks).status)
         self.assertEqual(1, len(glob(self.resultdir + "%s*.direct" % wks)))
 
-    def test17_rootfs_artifacts(self):
+    @testcase(1269)
+    def test_rootfs_artifacts(self):
         """Test usage of rootfs plugin with rootfs paths"""
         vars = dict((var.lower(), get_bb_var(var, 'core-image-minimal')) \
                         for var in ('STAGING_DATADIR', 'DEPLOY_DIR_IMAGE',
@@ -171,14 +187,16 @@
         self.assertEqual(1, len(glob(self.resultdir + \
                                      "%(wks)s-*.direct" % vars)))
 
-    def test18_iso_image(self):
-        """Test creation of hybrid iso imagewith legacy and EFI boot"""
+    @testcase(1346)
+    def test_iso_image(self):
+        """Test creation of hybrid iso image with legacy and EFI boot"""
         self.assertEqual(0, runCmd("wic create mkhybridiso "
                                    "--image-name core-image-minimal").status)
         self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.direct")))
         self.assertEqual(1, len(glob(self.resultdir + "HYBRID_ISO_IMG-*.iso")))
 
-    def test19_image_env(self):
+    @testcase(1347)
+    def test_image_env(self):
         """Test generation of <image>.env files."""
         image = 'core-image-minimal'
         stdir = get_bb_var('STAGING_DIR_TARGET', image)
@@ -200,7 +218,8 @@
                 self.assertTrue(var in content, "%s is not in .env file" % var)
                 self.assertTrue(content[var])
 
-    def test20_wic_image_type(self):
+    @testcase(1351)
+    def test_wic_image_type(self):
         """Test building wic images by bitbake"""
         self.assertEqual(0, bitbake('wic-image-minimal').status)
 
@@ -214,21 +233,24 @@
             self.assertTrue(os.path.islink(path))
             self.assertTrue(os.path.isfile(os.path.realpath(path)))
 
-    def test21_qemux86_directdisk(self):
+    @testcase(1348)
+    def test_qemux86_directdisk(self):
         """Test creation of qemux-86-directdisk image"""
         image = "qemux86-directdisk"
         self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
                                    % image).status)
         self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
 
-    def test22_mkgummidisk(self):
+    @testcase(1349)
+    def test_mkgummidisk(self):
         """Test creation of mkgummidisk image"""
         image = "mkgummidisk"
         self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
                                    % image).status)
         self.assertEqual(1, len(glob(self.resultdir + "%s-*direct" % image)))
 
-    def test23_mkefidisk(self):
+    @testcase(1350)
+    def test_mkefidisk(self):
         """Test creation of mkefidisk image"""
         image = "mkefidisk"
         self.assertEqual(0, runCmd("wic create %s -e core-image-minimal" \
diff --git a/meta/lib/oeqa/utils/decorators.py b/meta/lib/oeqa/utils/decorators.py
index b6adcb1..0d79223 100644
--- a/meta/lib/oeqa/utils/decorators.py
+++ b/meta/lib/oeqa/utils/decorators.py
@@ -33,6 +33,10 @@
                     ret.append(s.replace("setUpModule (", "").replace(")",""))
                 else:
                     ret.append(s)
+                # Append also the test without the full path
+                testname = s.split('.')[-1]
+                if testname:
+                    ret.append(testname)
             return ret
         self.faillist = handleList(upperf.f_locals['result'].failures)
         self.errorlist = handleList(upperf.f_locals['result'].errors)
@@ -53,11 +57,11 @@
         self.testcase = testcase
 
     def __call__(self,f):
-        def wrapped_f(*args):
+        def wrapped_f(*args, **kwargs):
             res = getResults()
             if self.testcase in (res.getFailList() or res.getErrorList()):
                 raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
-            return f(*args)
+            return f(*args, **kwargs)
         wrapped_f.__name__ = f.__name__
         return wrapped_f
 
@@ -67,11 +71,11 @@
         self.testcase = testcase
 
     def __call__(self,f):
-        def wrapped_f(*args):
+        def wrapped_f(*args, **kwargs):
             res = getResults()
             if self.testcase in res.getSkipList():
                 raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
-            return f(*args)
+            return f(*args, **kwargs)
         wrapped_f.__name__ = f.__name__
         return wrapped_f
 
@@ -81,13 +85,13 @@
         self.testcase = testcase
 
     def __call__(self,f):
-        def wrapped_f(*args):
+        def wrapped_f(*args, **kwargs):
             res = getResults()
             if self.testcase in res.getSkipList() or \
                     self.testcase in res.getFailList() or \
                     self.testcase in res.getErrorList():
                 raise unittest.SkipTest("Testcase dependency not met: %s" % self.testcase)
-            return f(*args)
+            return f(*args, **kwargs)
         wrapped_f.__name__ = f.__name__
         wrapped_f._depends_on = self.testcase
         return wrapped_f
@@ -98,8 +102,8 @@
         self.test_case = test_case
 
     def __call__(self, func):
-        def wrapped_f(*args):
-            return func(*args)
+        def wrapped_f(*args, **kwargs):
+            return func(*args, **kwargs)
         wrapped_f.test_case = self.test_case
         wrapped_f.__name__ = func.__name__
         return wrapped_f
@@ -111,6 +115,12 @@
 def LogResults(original_class):
     orig_method = original_class.run
 
+    from time import strftime, gmtime
+    caller = os.path.basename(sys.argv[0])
+    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)
@@ -127,14 +137,13 @@
         #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',
@@ -162,7 +171,13 @@
         if passed:
             local_log.results("Testcase "+str(test_case)+": PASSED")
 
+        # 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
 
 class TimeOut(BaseException):
diff --git a/meta/lib/oeqa/utils/dump.py b/meta/lib/oeqa/utils/dump.py
index 4ae871c..63a591d 100644
--- a/meta/lib/oeqa/utils/dump.py
+++ b/meta/lib/oeqa/utils/dump.py
@@ -16,9 +16,20 @@
 
     def __init__(self, cmds, parent_dir):
         self.cmds = []
-        self.parent_dir = parent_dir
+        # Some testing doesn't inherit testimage, so it is needed
+        # to set some defaults.
+        self.parent_dir = parent_dir or "/tmp/oe-saved-tests"
+        dft_cmds = """  top -bn1
+                        iostat -x -z -N -d -p ALL 20 2
+                        ps -ef
+                        free
+                        df
+                        memstat
+                        dmesg
+                        ip -s link
+                        netstat -an"""
         if not cmds:
-            return
+            cmds = dft_cmds
         for cmd in cmds.split('\n'):
             cmd = cmd.lstrip()
             if not cmd or cmd[0] == '#':
diff --git a/meta/lib/oeqa/utils/ftools.py b/meta/lib/oeqa/utils/ftools.py
index 64ebe3d..1bd9a30 100644
--- a/meta/lib/oeqa/utils/ftools.py
+++ b/meta/lib/oeqa/utils/ftools.py
@@ -1,12 +1,19 @@
 import os
 import re
+import errno
 
 def write_file(path, data):
+    # In case data is None, return immediately
+    if data is None:
+        return
     wdata = data.rstrip() + "\n"
     with open(path, "w") as f:
         f.write(wdata)
 
 def append_file(path, data):
+    # In case data is None, return immediately
+    if data is None:
+        return
     wdata = data.rstrip() + "\n"
     with open(path, "a") as f:
             f.write(wdata)
@@ -18,7 +25,18 @@
     return data
 
 def remove_from_file(path, data):
-    lines = read_file(path).splitlines()
+    # In case data is None, return immediately
+    if data is None:
+        return
+    try:
+        rdata = read_file(path)
+    except IOError as e:
+        # if file does not exit, just quit, otherwise raise an exception
+        if e.errno == errno.ENOENT:
+            return
+        else:
+            raise
+    lines = rdata.splitlines()
     rmdata = data.strip().splitlines()
     for l in rmdata:
         for c in range(0, lines.count(l)):
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index d32c9db..bdc6e0a 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -13,12 +13,20 @@
 import socket
 import select
 import errno
+import string
 import threading
+import codecs
 from oeqa.utils.dump import HostDumper
 
 import logging
 logger = logging.getLogger("BitBake.QemuRunner")
 
+# Get Unicode non printable control chars
+control_range = range(0,32)+range(127,160)
+control_chars = [unichr(x) for x in control_range
+                if unichr(x) not in string.printable]
+re_control_char = re.compile('[%s]' % re.escape("".join(control_chars)))
+
 class QemuRunner:
 
     def __init__(self, machine, rootfs, display, tmpdir, deploy_dir_image, logfile, boottime, dump_dir, dump_host_cmds):
@@ -61,7 +69,10 @@
 
     def log(self, msg):
         if self.logfile:
-            with open(self.logfile, "a") as f:
+            # It is needed to sanitize the data received from qemu
+            # because is possible to have control characters
+            msg = re_control_char.sub('', unicode(msg, 'utf-8'))
+            with codecs.open(self.logfile, "a", encoding="utf-8") as f:
                 f.write("%s" % msg)
 
     def getOutput(self, o):
@@ -170,6 +181,9 @@
             cmdline = ''
             with open('/proc/%s/cmdline' % self.qemupid) as p:
                 cmdline = p.read()
+                # It is needed to sanitize the data received
+                # because is possible to have control characters
+                cmdline = re_control_char.sub('', cmdline)
             try:
                 ips = re.findall("((?:[0-9]{1,3}\.){3}[0-9]{1,3})", cmdline.split("ip=")[1])
                 if not ips or len(ips) != 3:
@@ -186,7 +200,6 @@
             logger.info("Target IP: %s" % self.ip)
             logger.info("Server IP: %s" % self.server_ip)
 
-            logger.info("Starting logging thread")
             self.thread = LoggingThread(self.log, threadsock, logger)
             self.thread.start()
             if not self.thread.connection_established.wait(self.boottime):
@@ -197,6 +210,7 @@
                 self.stop_thread()
                 return False
 
+            logger.info("Output from runqemu:\n%s", self.getOutput(output))
             logger.info("Waiting at most %d seconds for login banner" % self.boottime)
             endtime = time.time() + self.boottime
             socklist = [self.server_socket]
@@ -259,8 +273,9 @@
 
     def stop(self):
         self.stop_thread()
-        if self.runqemu:
+        if hasattr(self, "origchldhandler"):
             signal.signal(signal.SIGCHLD, self.origchldhandler)
+        if self.runqemu:
             os.kill(self.monitorpid, signal.SIGKILL)
             logger.info("Sending SIGTERM to runqemu")
             try:
@@ -280,7 +295,6 @@
             self.server_socket = None
         self.qemupid = None
         self.ip = None
-        signal.signal(signal.SIGCHLD, self.origchldhandler)
 
     def stop_thread(self):
         if self.thread and self.thread.is_alive():
@@ -440,9 +454,9 @@
 
     def eventloop(self):
         poll = select.poll()
-        eventmask = self.errorevents | self.readevents
+        event_read_mask = self.errorevents | self.readevents
         poll.register(self.serversock.fileno())
-        poll.register(self.readpipe, eventmask)
+        poll.register(self.readpipe, event_read_mask)
 
         breakout = False
         self.running = True
@@ -466,7 +480,7 @@
                     self.readsock, _ = self.serversock.accept()
                     self.readsock.setblocking(0)
                     poll.unregister(self.serversock.fileno())
-                    poll.register(self.readsock.fileno())
+                    poll.register(self.readsock.fileno(), event_read_mask)
 
                     self.logger.info("Setting connection established event")
                     self.connection_established.set()