devtool: Drop oe-local-files and simplify

The only real reason for oe-local-files was to support S = WORKDIR. With changes to
drop support for that, it makes sense to simplify devtool and to try and make both
the code and the processes/workflows simpler.

This patch drops support for S = WORKDIR, removes oe-local-files and then updates
the test cases to match this new situation.

At the code level, we assume we can always now track code changes using git and
that things committed into git are handled as patches (as before) but delta against
HEAD is saved as specific file level changes to the recipe.

One test is disabled as it is no longer approproate. It is being keped until we can
make WORKDIR != UNPACKDIR at which point it should be revisited.

(From OE-Core rev: ce8190c519052fed10b5233697b69a75868db45a)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie 2024-05-01 22:36:50 +01:00
parent d6ae8d2004
commit 6d77296d83
5 changed files with 87 additions and 220 deletions

View File

@ -6,5 +6,8 @@ SRC_URI = "file://file1 \
SRC_URI:append:class-native = " file://file3" SRC_URI:append:class-native = " file://file3"
S = "${WORKDIR}/sources"
UNPACKDIR = "${S}"
EXCLUDE_FROM_WORLD = "1" EXCLUDE_FROM_WORLD = "1"
BBCLASSEXTEND = "native" BBCLASSEXTEND = "native"

View File

@ -234,8 +234,6 @@ do_kernel_metadata() {
for f in ${feat_dirs}; do for f in ${feat_dirs}; do
if [ -d "${UNPACKDIR}/$f/kernel-meta" ]; then if [ -d "${UNPACKDIR}/$f/kernel-meta" ]; then
includes="$includes -I${UNPACKDIR}/$f/kernel-meta" includes="$includes -I${UNPACKDIR}/$f/kernel-meta"
elif [ -d "${UNPACKDIR}/../oe-local-files/$f" ]; then
includes="$includes -I${UNPACKDIR}/../oe-local-files/$f"
elif [ -d "${UNPACKDIR}/$f" ]; then elif [ -d "${UNPACKDIR}/$f" ]; then
includes="$includes -I${UNPACKDIR}/$f" includes="$includes -I${UNPACKDIR}/$f"
fi fi

View File

@ -26,8 +26,6 @@
DEVTOOL_TEMPDIR ?= "" DEVTOOL_TEMPDIR ?= ""
DEVTOOL_PATCH_SRCDIR = "${DEVTOOL_TEMPDIR}/patchworkdir"
python() { python() {
tempdir = d.getVar('DEVTOOL_TEMPDIR') tempdir = d.getVar('DEVTOOL_TEMPDIR')
@ -60,7 +58,6 @@ python() {
else: else:
unpacktask = 'do_unpack' unpacktask = 'do_unpack'
d.appendVarFlag(unpacktask, 'postfuncs', ' devtool_post_unpack') d.appendVarFlag(unpacktask, 'postfuncs', ' devtool_post_unpack')
d.prependVarFlag('do_patch', 'prefuncs', ' devtool_pre_patch')
d.appendVarFlag('do_patch', 'postfuncs', ' devtool_post_patch') d.appendVarFlag('do_patch', 'postfuncs', ' devtool_post_patch')
# NOTE: in order for the patch stuff to be fully functional, # NOTE: in order for the patch stuff to be fully functional,
@ -79,67 +76,23 @@ python devtool_post_unpack() {
tempdir = d.getVar('DEVTOOL_TEMPDIR') tempdir = d.getVar('DEVTOOL_TEMPDIR')
workdir = d.getVar('WORKDIR') workdir = d.getVar('WORKDIR')
unpackdir = d.getVar('UNPACKDIR')
srcsubdir = d.getVar('S') srcsubdir = d.getVar('S')
def _move_file(src, dst): # Add locally copied files to gitignore as we add back to the metadata directly
"""Move a file. Creates all the directory components of destination path."""
dst_d = os.path.dirname(dst)
if dst_d:
bb.utils.mkdirhier(dst_d)
shutil.move(src, dst)
def _ls_tree(directory):
"""Recursive listing of files in a directory"""
ret = []
for root, dirs, files in os.walk(directory):
ret.extend([os.path.relpath(os.path.join(root, fname), directory) for
fname in files])
return ret
is_kernel_yocto = bb.data.inherits_class('kernel-yocto', d)
# Move local source files into separate subdir
recipe_patches = [os.path.basename(patch) for patch in
oe.recipeutils.get_recipe_patches(d)]
local_files = oe.recipeutils.get_recipe_local_files(d) local_files = oe.recipeutils.get_recipe_local_files(d)
if is_kernel_yocto:
for key in [f for f in local_files if f.endswith('scc')]:
with open(local_files[key], 'r') as sccfile:
for l in sccfile:
line = l.split()
if line and line[0] in ('kconf', 'patch'):
cfg = os.path.join(os.path.dirname(local_files[key]), line[-1])
if cfg not in local_files.values():
local_files[line[-1]] = cfg
shutil.copy2(cfg, workdir)
# Ignore local files with subdir={BP}
srcabspath = os.path.abspath(srcsubdir) srcabspath = os.path.abspath(srcsubdir)
local_files = [fname for fname in local_files if local_files = [fname for fname in local_files if
os.path.exists(os.path.join(workdir, fname)) and os.path.exists(os.path.join(unpackdir, fname)) and
(srcabspath == workdir or not srcabspath == unpackdir]
os.path.join(workdir, fname).startswith(srcabspath +
os.sep))]
if local_files: if local_files:
for fname in local_files: with open(os.path.join(tempdir, '.gitignore'), 'a+') as f:
_move_file(os.path.join(workdir, fname), f.write('# Ignore local files, by default. Remove following lines'
os.path.join(tempdir, 'oe-local-files', fname)) 'if you want to commit the directory to Git\n')
with open(os.path.join(tempdir, 'oe-local-files', '.gitignore'), for fname in local_files:
'w') as f: f.write('%s\n' % fname)
f.write('# Ignore local files, by default. Remove this file '
'if you want to commit the directory to Git\n*\n')
if srcsubdir == workdir: if os.path.dirname(srcsubdir) != workdir:
# Find non-patch non-local sources that were "unpacked" to srctree
# directory
src_files = [fname for fname in _ls_tree(workdir) if
os.path.basename(fname) not in recipe_patches]
srcsubdir = d.getVar('DEVTOOL_PATCH_SRCDIR')
# Move source files to S
for path in src_files:
_move_file(os.path.join(workdir, path),
os.path.join(srcsubdir, path))
elif os.path.dirname(srcsubdir) != workdir:
# Handle if S is set to a subdirectory of the source # Handle if S is set to a subdirectory of the source
srcsubdir = os.path.join(workdir, os.path.relpath(srcsubdir, workdir).split(os.sep)[0]) srcsubdir = os.path.join(workdir, os.path.relpath(srcsubdir, workdir).split(os.sep)[0])
@ -164,11 +117,6 @@ python devtool_post_unpack() {
f.write(srcsubdir) f.write(srcsubdir)
} }
python devtool_pre_patch() {
if d.getVar('S') == d.getVar('WORKDIR'):
d.setVar('S', '${DEVTOOL_PATCH_SRCDIR}')
}
python devtool_post_patch() { python devtool_post_patch() {
import shutil import shutil
tempdir = d.getVar('DEVTOOL_TEMPDIR') tempdir = d.getVar('DEVTOOL_TEMPDIR')

View File

@ -879,13 +879,8 @@ class DevtoolModifyTests(DevtoolBase):
self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe) self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe)
self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') self.add_command_to_tearDown('bitbake-layers remove-layer */workspace')
result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
srcfile = os.path.join(tempdir, 'oe-local-files/share/dot.bashrc') srcfile = os.path.join(tempdir, 'share/dot.bashrc')
srclink = os.path.join(tempdir, 'share/dot.bashrc')
self.assertExists(srcfile, 'Extracted source could not be found') self.assertExists(srcfile, 'Extracted source could not be found')
if os.path.islink(srclink) and os.path.exists(srclink) and os.path.samefile(srcfile, srclink):
correct_symlink = True
self.assertTrue(correct_symlink, 'Source symlink to oe-local-files is broken')
matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe)) matches = glob.glob(os.path.join(self.workspacedir, 'appends', '%s_*.bbappend' % testrecipe))
self.assertTrue(matches, 'bbappend not created') self.assertTrue(matches, 'bbappend not created')
# Test devtool status # Test devtool status
@ -1278,7 +1273,7 @@ class DevtoolUpdateTests(DevtoolBase):
with open(bbappendfile, 'r') as f: with open(bbappendfile, 'r') as f:
self.assertEqual(expectedlines, f.readlines()) self.assertEqual(expectedlines, f.readlines())
# Drop new commit and check patch gets deleted # Drop new commit and check patch gets deleted
result = runCmd('git reset HEAD^', cwd=tempsrcdir) result = runCmd('git reset HEAD^ --hard', cwd=tempsrcdir)
result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
self.assertNotExists(patchfile, 'Patch file not deleted') self.assertNotExists(patchfile, 'Patch file not deleted')
expectedlines2 = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n', expectedlines2 = ['FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n',
@ -1287,6 +1282,7 @@ class DevtoolUpdateTests(DevtoolBase):
self.assertEqual(expectedlines2, f.readlines()) self.assertEqual(expectedlines2, f.readlines())
# Put commit back and check we can run it if layer isn't in bblayers.conf # Put commit back and check we can run it if layer isn't in bblayers.conf
os.remove(bbappendfile) os.remove(bbappendfile)
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) result = runCmd('git commit -a -m "Add our custom version"', cwd=tempsrcdir)
result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir) result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir)) result = runCmd('devtool update-recipe %s -a %s' % (testrecipe, templayerdir))
@ -1361,7 +1357,7 @@ class DevtoolUpdateTests(DevtoolBase):
with open(bbappendfile, 'r') as f: with open(bbappendfile, 'r') as f:
self.assertEqual(expectedlines, set(f.readlines())) self.assertEqual(expectedlines, set(f.readlines()))
# Drop new commit and check SRCREV changes # Drop new commit and check SRCREV changes
result = runCmd('git reset HEAD^', cwd=tempsrcdir) result = runCmd('git reset HEAD^ --hard', cwd=tempsrcdir)
result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir)) result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created') self.assertNotExists(os.path.join(appenddir, testrecipe), 'Patch directory should not be created')
result = runCmd('git rev-parse HEAD', cwd=tempsrcdir) result = runCmd('git rev-parse HEAD', cwd=tempsrcdir)
@ -1373,6 +1369,7 @@ class DevtoolUpdateTests(DevtoolBase):
self.assertEqual(expectedlines, set(f.readlines())) self.assertEqual(expectedlines, set(f.readlines()))
# Put commit back and check we can run it if layer isn't in bblayers.conf # Put commit back and check we can run it if layer isn't in bblayers.conf
os.remove(bbappendfile) os.remove(bbappendfile)
result = runCmd('echo "# Additional line" >> Makefile.am', cwd=tempsrcdir)
result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir) result = runCmd('git commit -a -m "Change the Makefile"', cwd=tempsrcdir)
result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir) result = runCmd('bitbake-layers remove-layer %s' % templayerdir, cwd=self.builddir)
result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir)) result = runCmd('devtool update-recipe -m srcrev %s -a %s' % (testrecipe, templayerdir))
@ -1404,11 +1401,12 @@ class DevtoolUpdateTests(DevtoolBase):
# Try building just to ensure we haven't broken that # Try building just to ensure we haven't broken that
bitbake("%s" % testrecipe) bitbake("%s" % testrecipe)
# Edit / commit local source # Edit / commit local source
runCmd('echo "/* Foobar */" >> oe-local-files/makedevs.c', cwd=tempdir) runCmd('echo "/* Foobar */" >> makedevs.c', cwd=tempdir)
runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir) runCmd('echo "Foo" > new-local', cwd=tempdir)
runCmd('echo "Bar" > new-file', cwd=tempdir) runCmd('echo "Bar" > new-file', cwd=tempdir)
runCmd('git add new-file', cwd=tempdir) runCmd('git add new-file', cwd=tempdir)
runCmd('git commit -m "Add new file"', cwd=tempdir) runCmd('git commit -m "Add new file"', cwd=tempdir)
runCmd('git add new-local', cwd=tempdir)
runCmd('devtool update-recipe %s' % testrecipe) runCmd('devtool update-recipe %s' % testrecipe)
expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)), expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
(' M', '.*/makedevs/makedevs.c$'), (' M', '.*/makedevs/makedevs.c$'),
@ -1434,8 +1432,8 @@ class DevtoolUpdateTests(DevtoolBase):
self.assertExists(local_file, 'File makedevs.c not created') self.assertExists(local_file, 'File makedevs.c not created')
self.assertExists(patchfile, 'File new_local not created') self.assertExists(patchfile, 'File new_local not created')
def test_devtool_update_recipe_local_files_2(self): def _test_devtool_update_recipe_local_files_2(self):
"""Check local source files support when oe-local-files is in Git""" """Check local source files support when editing local files in Git"""
testrecipe = 'devtool-test-local' testrecipe = 'devtool-test-local'
recipefile = get_bb_var('FILE', testrecipe) recipefile = get_bb_var('FILE', testrecipe)
recipedir = os.path.dirname(recipefile) recipedir = os.path.dirname(recipefile)
@ -1450,17 +1448,13 @@ class DevtoolUpdateTests(DevtoolBase):
result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir))
# Check git repo # Check git repo
self._check_src_repo(tempdir) 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 # Edit / commit local sources
runCmd('echo "# Foobar" >> oe-local-files/file1', cwd=tempdir) runCmd('echo "# Foobar" >> file1', cwd=tempdir)
runCmd('git commit -am "Edit existing file"', cwd=tempdir) runCmd('git commit -am "Edit existing file"', cwd=tempdir)
runCmd('git rm oe-local-files/file2', cwd=tempdir) runCmd('git rm file2', cwd=tempdir)
runCmd('git commit -m"Remove file"', cwd=tempdir) runCmd('git commit -m"Remove file"', cwd=tempdir)
runCmd('echo "Foo" > oe-local-files/new-local', cwd=tempdir) runCmd('echo "Foo" > new-local', cwd=tempdir)
runCmd('git add oe-local-files/new-local', cwd=tempdir) runCmd('git add new-local', cwd=tempdir)
runCmd('git commit -m "Add new local file"', cwd=tempdir) runCmd('git commit -m "Add new local file"', cwd=tempdir)
runCmd('echo "Gar" > new-file', cwd=tempdir) runCmd('echo "Gar" > new-file', cwd=tempdir)
runCmd('git add new-file', cwd=tempdir) runCmd('git add new-file', cwd=tempdir)
@ -1469,7 +1463,7 @@ class DevtoolUpdateTests(DevtoolBase):
os.path.dirname(recipefile)) os.path.dirname(recipefile))
# Checkout unmodified file to working copy -> devtool should still pick # Checkout unmodified file to working copy -> devtool should still pick
# the modified version from HEAD # the modified version from HEAD
runCmd('git checkout HEAD^ -- oe-local-files/file1', cwd=tempdir) runCmd('git checkout HEAD^ -- file1', cwd=tempdir)
runCmd('devtool update-recipe %s' % testrecipe) runCmd('devtool update-recipe %s' % testrecipe)
expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)), expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)),
(' M', '.*/file1$'), (' M', '.*/file1$'),
@ -1544,7 +1538,7 @@ class DevtoolUpdateTests(DevtoolBase):
# (don't bother with cleaning the recipe on teardown, we won't be building it) # (don't bother with cleaning the recipe on teardown, we won't be building it)
result = runCmd('devtool modify %s' % testrecipe) result = runCmd('devtool modify %s' % testrecipe)
# Modify one file # Modify one file
runCmd('echo "Another line" >> file2', cwd=os.path.join(self.workspacedir, 'sources', testrecipe, 'oe-local-files')) runCmd('echo "Another line" >> file2', cwd=os.path.join(self.workspacedir, 'sources', testrecipe))
self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile))) self.add_command_to_tearDown('cd %s; rm %s/*; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, testrecipe, os.path.basename(recipefile)))
result = runCmd('devtool update-recipe %s' % testrecipe) result = runCmd('devtool update-recipe %s' % testrecipe)
expected_status = [(' M', '.*/%s/file2$' % testrecipe)] expected_status = [(' M', '.*/%s/file2$' % testrecipe)]

View File

@ -387,6 +387,19 @@ def _git_ls_tree(repodir, treeish='HEAD', recursive=False):
ret[split[3]] = split[0:3] ret[split[3]] = split[0:3]
return ret return ret
def _git_modified(repodir):
"""List the difference between HEAD and the index"""
import bb
cmd = ['git', 'status', '--porcelain']
out, _ = bb.process.run(cmd, cwd=repodir)
ret = []
if out:
for line in out.split("\n"):
if line and not line.startswith('??'):
ret.append(line[3:])
return ret
def _git_exclude_path(srctree, path): def _git_exclude_path(srctree, path):
"""Return pathspec (list of paths) that excludes certain path""" """Return pathspec (list of paths) that excludes certain path"""
# NOTE: "Filtering out" files/paths in this way is not entirely reliable - # NOTE: "Filtering out" files/paths in this way is not entirely reliable -
@ -460,32 +473,6 @@ def sync(args, config, basepath, workspace):
finally: finally:
tinfoil.shutdown() tinfoil.shutdown()
def symlink_oelocal_files_srctree(rd, srctree):
import oe.patch
if os.path.abspath(rd.getVar('S')) == os.path.abspath(rd.getVar('WORKDIR')):
# If recipe extracts to ${WORKDIR}, symlink the files into the srctree
# (otherwise the recipe won't build as expected)
local_files_dir = os.path.join(srctree, 'oe-local-files')
addfiles = []
for root, _, files in os.walk(local_files_dir):
relpth = os.path.relpath(root, local_files_dir)
if relpth != '.':
bb.utils.mkdirhier(os.path.join(srctree, relpth))
for fn in files:
if fn == '.gitignore':
continue
destpth = os.path.join(srctree, relpth, fn)
if os.path.exists(destpth):
os.unlink(destpth)
if relpth != '.':
back_relpth = os.path.relpath(local_files_dir, root)
os.symlink('%s/oe-local-files/%s/%s' % (back_relpth, relpth, fn), destpth)
else:
os.symlink('oe-local-files/%s' % fn, destpth)
addfiles.append(os.path.join(relpth, fn))
if addfiles:
oe.patch.GitApplyTree.commitIgnored("Add local file symlinks", dir=srctree, files=addfiles, d=rd)
def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, workspace, fixed_setup, d, tinfoil, no_overrides=False): def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, workspace, fixed_setup, d, tinfoil, no_overrides=False):
"""Extract sources of a recipe""" """Extract sources of a recipe"""
import oe.recipeutils import oe.recipeutils
@ -657,9 +644,6 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works
elif not os.path.exists(workshareddir): elif not os.path.exists(workshareddir):
oe.path.copyhardlinktree(srcsubdir, workshareddir) oe.path.copyhardlinktree(srcsubdir, workshareddir)
tempdir_localdir = os.path.join(tempdir, 'oe-local-files')
srctree_localdir = os.path.join(srctree, 'oe-local-files')
if sync: if sync:
try: try:
logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch)) logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch))
@ -674,29 +658,8 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works
except bb.process.ExecutionError as e: except bb.process.ExecutionError as e:
raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e)) raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e))
# Move the oe-local-files directory to srctree.
# As oe-local-files is not part of the constructed git tree,
# removing it directly during the synchronization might surprise
# the user. Instead, we move it to oe-local-files.bak and remind
# the user in the log message.
if os.path.exists(srctree_localdir + '.bak'):
shutil.rmtree(srctree_localdir + '.bak')
if os.path.exists(srctree_localdir):
logger.info('Backing up current local file directory %s' % srctree_localdir)
shutil.move(srctree_localdir, srctree_localdir + '.bak')
if os.path.exists(tempdir_localdir):
logger.info('Syncing local source files to srctree...')
shutil.copytree(tempdir_localdir, srctree_localdir)
else: else:
# Move oe-local-files directory to srctree
if os.path.exists(tempdir_localdir):
logger.info('Adding local source files to srctree...')
shutil.move(tempdir_localdir, srcsubdir)
shutil.move(srcsubdir, srctree) shutil.move(srcsubdir, srctree)
symlink_oelocal_files_srctree(d, srctree)
if is_kernel_yocto: if is_kernel_yocto:
logger.info('Copying kernel config to srctree') logger.info('Copying kernel config to srctree')
@ -852,34 +815,22 @@ def modify(args, config, basepath, workspace):
if (os.path.exists(srcdir) and os.listdir(srcdir)) and (kernelVersion in staging_kerVer and staging_kbranch == kbranch): if (os.path.exists(srcdir) and os.listdir(srcdir)) and (kernelVersion in staging_kerVer and staging_kbranch == kbranch):
oe.path.copyhardlinktree(srcdir, srctree) oe.path.copyhardlinktree(srcdir, srctree)
workdir = rd.getVar('WORKDIR') workdir = rd.getVar('WORKDIR')
unpackdir = rd.getVar('UNPACKDIR')
srcsubdir = rd.getVar('S') srcsubdir = rd.getVar('S')
localfilesdir = os.path.join(srctree, 'oe-local-files') localfilesdir = os.path.join(srctree, 'oe-local-files')
# Move local source files into separate subdir
recipe_patches = [os.path.basename(patch) for patch in oe.recipeutils.get_recipe_patches(rd)] # Add locally copied files to gitignore as we add back to the metadata directly
local_files = oe.recipeutils.get_recipe_local_files(rd) local_files = oe.recipeutils.get_recipe_local_files(rd)
for key in local_files.copy():
if key.endswith('scc'):
sccfile = open(local_files[key], 'r')
for l in sccfile:
line = l.split()
if line and line[0] in ('kconf', 'patch'):
cfg = os.path.join(os.path.dirname(local_files[key]), line[-1])
if not cfg in local_files.values():
local_files[line[-1]] = cfg
shutil.copy2(cfg, workdir)
sccfile.close()
# Ignore local files with subdir={BP}
srcabspath = os.path.abspath(srcsubdir) srcabspath = os.path.abspath(srcsubdir)
local_files = [fname for fname in local_files if os.path.exists(os.path.join(workdir, fname)) and (srcabspath == workdir or not os.path.join(workdir, fname).startswith(srcabspath + os.sep))] local_files = [fname for fname in local_files if
os.path.exists(os.path.join(unpackdir, fname)) and
srcabspath == unpackdir]
if local_files: if local_files:
for fname in local_files: with open(os.path.join(srctree, '.gitignore'), 'a+') as f:
_move_file(os.path.join(workdir, fname), os.path.join(srctree, 'oe-local-files', fname)) f.write('# Ignore local files, by default. Remove following lines'
with open(os.path.join(srctree, 'oe-local-files', '.gitignore'), 'w') as f: 'if you want to commit the directory to Git\n')
f.write('# Ignore local files, by default. Remove this file if you want to commit the directory to Git\n*\n') for fname in local_files:
f.write('%s\n' % fname)
symlink_oelocal_files_srctree(rd, srctree)
task = 'do_configure' task = 'do_configure'
res = tinfoil.build_targets(pn, task, handle_events=True) res = tinfoil.build_targets(pn, task, handle_events=True)
@ -1478,6 +1429,7 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
# Instead they are directly copied over the original source files (in # Instead they are directly copied over the original source files (in
# recipe space). # recipe space).
existing_files = oe.recipeutils.get_recipe_local_files(rd) existing_files = oe.recipeutils.get_recipe_local_files(rd)
new_set = None new_set = None
updated = OrderedDict() updated = OrderedDict()
added = OrderedDict() added = OrderedDict()
@ -1494,24 +1446,28 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
if branchname.startswith(override_branch_prefix): if branchname.startswith(override_branch_prefix):
return (updated, added, removed) return (updated, added, removed)
local_files_dir = os.path.join(srctreebase, 'oe-local-files') files = _git_modified(srctree)
git_files = _git_ls_tree(srctree) #if not files:
if 'oe-local-files' in git_files: # files = _ls_tree(srctree)
# If tracked by Git, take the files from srctree HEAD. First get for f in files:
# the tree object of the directory fullfile = os.path.join(srctree, f)
tmp_index = os.path.join(srctree, '.git', 'index.tmp.devtool') if os.path.exists(os.path.join(fullfile, ".git")):
tree = git_files['oe-local-files'][2] # submodules handled elsewhere
bb.process.run(['git', 'checkout', tree, '--', '.'], cwd=srctree, continue
env=dict(os.environ, GIT_WORK_TREE=destdir, if f not in existing_files:
GIT_INDEX_FILE=tmp_index)) added[f] = {}
new_set = list(_git_ls_tree(srctree, tree, True).keys()) if os.path.isdir(os.path.join(srctree, f)):
elif os.path.isdir(local_files_dir): shutil.copytree(fullfile, os.path.join(destdir, f))
# If not tracked by Git, just copy from working copy else:
new_set = _ls_tree(local_files_dir) shutil.copy2(fullfile, os.path.join(destdir, f))
bb.process.run(['cp', '-ax', elif not os.path.exists(fullfile):
os.path.join(local_files_dir, '.'), destdir]) removed[f] = existing_files[f]
else: elif f in existing_files:
new_set = [] updated[f] = {'path' : existing_files[f]}
if os.path.isdir(os.path.join(srctree, f)):
shutil.copytree(fullfile, os.path.join(destdir, f))
else:
shutil.copy2(fullfile, os.path.join(destdir, f))
# Special handling for kernel config # Special handling for kernel config
if bb.data.inherits_class('kernel-yocto', rd): if bb.data.inherits_class('kernel-yocto', rd):
@ -1519,17 +1475,14 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
fragment_path = os.path.join(destdir, fragment_fn) fragment_path = os.path.join(destdir, fragment_fn)
if _create_kconfig_diff(srctree, rd, fragment_path): if _create_kconfig_diff(srctree, rd, fragment_path):
if os.path.exists(fragment_path): if os.path.exists(fragment_path):
if fragment_fn not in new_set: if fragment_fn in removed:
new_set.append(fragment_fn) del removed[fragment_fn]
# Copy fragment to local-files if fragment_fn not in updated and fragment_fn not in added:
if os.path.isdir(local_files_dir): added[fragment_fn] = {}
shutil.copy2(fragment_path, local_files_dir)
else: else:
if fragment_fn in new_set: if fragment_fn in updated:
new_set.remove(fragment_fn) revoved[fragment_fn] = updated[fragment_fn]
# Remove fragment from local-files del updated[fragment_fn]
if os.path.exists(os.path.join(local_files_dir, fragment_fn)):
os.unlink(os.path.join(local_files_dir, fragment_fn))
# Special handling for cml1, ccmake, etc bbclasses that generated # Special handling for cml1, ccmake, etc bbclasses that generated
# configuration fragment files that are consumed as source files # configuration fragment files that are consumed as source files
@ -1537,42 +1490,13 @@ def _export_local_files(srctree, rd, destdir, srctreebase):
if bb.data.inherits_class(frag_class, rd): if bb.data.inherits_class(frag_class, rd):
srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name) srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name)
if os.path.exists(srcpath): if os.path.exists(srcpath):
if frag_name not in new_set: if frag_name in removed:
new_set.append(frag_name) del removed[frag_name]
if frag_name not in updated:
added[frag_name] = {}
# copy fragment into destdir # copy fragment into destdir
shutil.copy2(srcpath, destdir) shutil.copy2(srcpath, destdir)
# copy fragment into local files if exists
if os.path.isdir(local_files_dir):
shutil.copy2(srcpath, local_files_dir)
if new_set is not None:
for fname in new_set:
if fname in existing_files:
origpath = existing_files.pop(fname)
workpath = os.path.join(local_files_dir, fname)
if not filecmp.cmp(origpath, workpath):
updated[fname] = {'path' : origpath}
elif fname != '.gitignore':
added[fname] = {}
workdir = rd.getVar('WORKDIR')
s = rd.getVar('S')
if not s.endswith(os.sep):
s += os.sep
if workdir != s:
# Handle files where subdir= was specified
for fname in list(existing_files.keys()):
# FIXME handle both subdir starting with BP and not?
fworkpath = os.path.join(workdir, fname)
if fworkpath.startswith(s):
fpath = os.path.join(srctree, os.path.relpath(fworkpath, s))
if os.path.exists(fpath):
origpath = existing_files.pop(fname)
if not filecmp.cmp(origpath, fpath):
updated[fpath] = {'path' : origpath}
removed = existing_files
return (updated, added, removed) return (updated, added, removed)