diff options
Diffstat (limited to 'scripts/lib/devtool/standard.py')
-rw-r--r-- | scripts/lib/devtool/standard.py | 231 |
1 files changed, 87 insertions, 144 deletions
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py index 6674e67267..1d0fe13788 100644 --- a/scripts/lib/devtool/standard.py +++ b/scripts/lib/devtool/standard.py @@ -387,6 +387,19 @@ def _git_ls_tree(repodir, treeish='HEAD', recursive=False): ret[split[3]] = split[0:3] 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): """Return pathspec (list of paths) that excludes certain path""" # NOTE: "Filtering out" files/paths in this way is not entirely reliable - @@ -460,32 +473,6 @@ def sync(args, config, basepath, workspace): finally: 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): """Extract sources of a recipe""" import oe.recipeutils @@ -657,35 +644,22 @@ def _extract_source(srctree, keep_temp, devbranch, sync, config, basepath, works elif not os.path.exists(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: - bb.process.run('git fetch file://' + srcsubdir + ' ' + devbranch + ':' + devbranch, cwd=srctree) - - # 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: - # 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) + try: + logger.info('Backing up current %s branch as branch: %s.bak' % (devbranch, devbranch)) + bb.process.run('git branch -f ' + devbranch + '.bak', cwd=srctree) + + # Use git fetch to update the source with the current recipe + # To be able to update the currently checked out branch with + # possibly new history (no fast-forward) git needs to be told + # that's ok + logger.info('Syncing source files including patches to git branch: %s' % devbranch) + bb.process.run('git fetch --update-head-ok --force file://' + srcsubdir + ' ' + devbranch + ':' + devbranch, cwd=srctree) + except bb.process.ExecutionError as e: + raise DevtoolError("Error when syncing source files to local checkout: %s" % str(e)) + else: shutil.move(srcsubdir, srctree) - symlink_oelocal_files_srctree(d, srctree) if is_kernel_yocto: logger.info('Copying kernel config to srctree') @@ -841,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): oe.path.copyhardlinktree(srcdir, srctree) workdir = rd.getVar('WORKDIR') + unpackdir = rd.getVar('UNPACKDIR') srcsubdir = rd.getVar('S') 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)] - 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} + # Add locally copied files to gitignore as we add back to the metadata directly + local_files = oe.recipeutils.get_recipe_local_files(rd) 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: - for fname in local_files: - _move_file(os.path.join(workdir, fname), os.path.join(srctree, 'oe-local-files', fname)) - with open(os.path.join(srctree, 'oe-local-files', '.gitignore'), 'w') as f: - f.write('# Ignore local files, by default. Remove this file if you want to commit the directory to Git\n*\n') - - symlink_oelocal_files_srctree(rd, srctree) + with open(os.path.join(srctree, '.gitignore'), 'a+') as f: + f.write('# Ignore local files, by default. Remove following lines' + 'if you want to commit the directory to Git\n') + for fname in local_files: + f.write('%s\n' % fname) task = 'do_configure' res = tinfoil.build_targets(pn, task, handle_events=True) @@ -893,7 +855,10 @@ def modify(args, config, basepath, workspace): (stdout, _) = bb.process.run('git rev-list --reverse %s..HEAD' % initial_revs["."], cwd=srctree) commits["."] = stdout.split() check_commits = True - (stdout, _) = bb.process.run('git submodule --quiet foreach --recursive \'echo `git rev-parse devtool-base` $PWD\'', cwd=srctree) + try: + (stdout, _) = bb.process.run('git submodule --quiet foreach --recursive \'echo `git rev-parse devtool-base` $PWD\'', cwd=srctree) + except bb.process.ExecutionError: + stdout = "" for line in stdout.splitlines(): (rev, submodule_path) = line.split() submodule = os.path.relpath(submodule_path, srctree) @@ -1452,8 +1417,10 @@ def _export_local_files(srctree, rd, destdir, srctreebase): 1. updated - files that already exist in SRCURI 2. added - new files files that don't exist in SRCURI 3 removed - files that exist in SRCURI but not in exported files - In each dict the key is the 'basepath' of the URI and value is the - absolute path to the existing file in recipe space (if any). + In each dict the key is the 'basepath' of the URI and value is: + - for updated and added dicts, a dict with 1 optionnal key: + - 'path': the absolute path to the existing file in recipe space (if any) + - for removed dict, the absolute path to the existing file in recipe space """ import oe.recipeutils @@ -1462,6 +1429,7 @@ def _export_local_files(srctree, rd, destdir, srctreebase): # Instead they are directly copied over the original source files (in # recipe space). existing_files = oe.recipeutils.get_recipe_local_files(rd) + new_set = None updated = OrderedDict() added = OrderedDict() @@ -1478,24 +1446,28 @@ def _export_local_files(srctree, rd, destdir, srctreebase): if branchname.startswith(override_branch_prefix): return (updated, added, removed) - local_files_dir = os.path.join(srctreebase, 'oe-local-files') - git_files = _git_ls_tree(srctree) - if 'oe-local-files' in git_files: - # If tracked by Git, take the files from srctree HEAD. First get - # the tree object of the directory - tmp_index = os.path.join(srctree, '.git', 'index.tmp.devtool') - tree = git_files['oe-local-files'][2] - bb.process.run(['git', 'checkout', tree, '--', '.'], cwd=srctree, - env=dict(os.environ, GIT_WORK_TREE=destdir, - GIT_INDEX_FILE=tmp_index)) - new_set = list(_git_ls_tree(srctree, tree, True).keys()) - elif os.path.isdir(local_files_dir): - # If not tracked by Git, just copy from working copy - new_set = _ls_tree(local_files_dir) - bb.process.run(['cp', '-ax', - os.path.join(local_files_dir, '.'), destdir]) - else: - new_set = [] + files = _git_modified(srctree) + #if not files: + # files = _ls_tree(srctree) + for f in files: + fullfile = os.path.join(srctree, f) + if os.path.exists(os.path.join(fullfile, ".git")): + # submodules handled elsewhere + continue + if f not in existing_files: + added[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)) + elif not os.path.exists(fullfile): + removed[f] = existing_files[f] + elif f in existing_files: + 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 if bb.data.inherits_class('kernel-yocto', rd): @@ -1503,17 +1475,14 @@ def _export_local_files(srctree, rd, destdir, srctreebase): fragment_path = os.path.join(destdir, fragment_fn) if _create_kconfig_diff(srctree, rd, fragment_path): if os.path.exists(fragment_path): - if fragment_fn not in new_set: - new_set.append(fragment_fn) - # Copy fragment to local-files - if os.path.isdir(local_files_dir): - shutil.copy2(fragment_path, local_files_dir) + if fragment_fn in removed: + del removed[fragment_fn] + if fragment_fn not in updated and fragment_fn not in added: + added[fragment_fn] = {} else: - if fragment_fn in new_set: - new_set.remove(fragment_fn) - # Remove fragment from local-files - if os.path.exists(os.path.join(local_files_dir, fragment_fn)): - os.unlink(os.path.join(local_files_dir, fragment_fn)) + if fragment_fn in updated: + revoved[fragment_fn] = updated[fragment_fn] + del updated[fragment_fn] # Special handling for cml1, ccmake, etc bbclasses that generated # configuration fragment files that are consumed as source files @@ -1521,42 +1490,13 @@ def _export_local_files(srctree, rd, destdir, srctreebase): if bb.data.inherits_class(frag_class, rd): srcpath = os.path.join(rd.getVar('WORKDIR'), frag_name) if os.path.exists(srcpath): - if frag_name not in new_set: - new_set.append(frag_name) + if frag_name in removed: + del removed[frag_name] + if frag_name not in updated: + added[frag_name] = {} # copy fragment into 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] = origpath - elif fname != '.gitignore': - added[fname] = None - - 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] = origpath - - removed = existing_files + return (updated, added, removed) @@ -1640,7 +1580,8 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi redirect_output=dry_run_outdir) else: files_dir = _determine_files_dir(rd) - for basepath, path in upd_f.items(): + for basepath, param in upd_f.items(): + path = param['path'] logger.info('Updating file %s%s' % (basepath, dry_run_suffix)) if os.path.isabs(basepath): # Original file (probably with subdir pointing inside source tree) @@ -1650,7 +1591,8 @@ def _update_recipe_srcrev(recipename, workspace, srctree, rd, appendlayerdir, wi _move_file(os.path.join(local_files_dir, basepath), path, dry_run_outdir=dry_run_outdir, base_outdir=recipedir) update_srcuri= True - for basepath, path in new_f.items(): + for basepath, param in new_f.items(): + path = param['path'] logger.info('Adding new file %s%s' % (basepath, dry_run_suffix)) _move_file(os.path.join(local_files_dir, basepath), os.path.join(files_dir, basepath), @@ -1772,7 +1714,8 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil else: # Update existing files files_dir = _determine_files_dir(rd) - for basepath, path in upd_f.items(): + for basepath, param in upd_f.items(): + path = param['path'] logger.info('Updating file %s' % basepath) if os.path.isabs(basepath): # Original file (probably with subdir pointing inside source tree) @@ -1806,7 +1749,7 @@ def _update_recipe_patch(recipename, workspace, srctree, rd, appendlayerdir, wil dry_run_outdir=dry_run_outdir, base_outdir=recipedir) updatefiles = True # Add any new files - for basepath, path in new_f.items(): + for basepath, param in new_f.items(): logger.info('Adding new file %s%s' % (basepath, dry_run_suffix)) _move_file(os.path.join(local_files_dir, basepath), os.path.join(files_dir, basepath), |