* [PATCH 0/2] combo-layer: exclude files @ 2015-03-10 10:10 Patrick Ohly 2015-03-10 10:10 ` [PATCH 1/2] combo-layer: runcmd() with separate output Patrick Ohly 2015-03-10 10:10 ` [PATCH 2/2] combo-layer: exclude files Patrick Ohly 0 siblings, 2 replies; 5+ messages in thread From: Patrick Ohly @ 2015-03-10 10:10 UTC (permalink / raw) To: openembedded-core I ran into the merge conflicts described in the second patch recently due to changes in OE-core's conf sample files. Richard told me that he is aware of the issue and just deals with it manually because he never had time to automate it; I hope these patches do that sufficiently well to be included. They worked for me when I re-imported all patches in OE-core and bitbake since Dizzy was branched off. I also tested "combo-layer init" with files excluded. Note that these patches may apply directly to master, but I haven't tested that because in my tree I have them on top of the other two, independent patches to combo-layer that I posted yesterday. I can resend as a single patch series if that's preferred. Patrick Ohly (2): combo-layer: runcmd() with separate output combo-layer: exclude files scripts/combo-layer | 59 ++++++++++++++++++++++++++++++++++------ scripts/combo-layer.conf.example | 14 ++++++++++ 2 files changed, 65 insertions(+), 8 deletions(-) -- 2.1.4 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] combo-layer: runcmd() with separate output 2015-03-10 10:10 [PATCH 0/2] combo-layer: exclude files Patrick Ohly @ 2015-03-10 10:10 ` Patrick Ohly 2015-03-12 18:33 ` Paul Eggleton 2015-03-10 10:10 ` [PATCH 2/2] combo-layer: exclude files Patrick Ohly 1 sibling, 1 reply; 5+ messages in thread From: Patrick Ohly @ 2015-03-10 10:10 UTC (permalink / raw) To: openembedded-core Allow the caller to specify a separate output stream. stderr is always a temporary file opened by runcmd(), so read from that to capture output for error reporting *and* the return value. The reasoning for the latter is a) that this preserves the traditional behavior when out=None and b) if the caller wants the content of stdout, it can read from the stream itself, which is not possible for the temporary stderr. Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> --- scripts/combo-layer | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/combo-layer b/scripts/combo-layer index 5f10e83..fb3fb50 100755 --- a/scripts/combo-layer +++ b/scripts/combo-layer @@ -149,23 +149,27 @@ class Configuration(object): logger.error("ERROR: patchutils package is missing, please install it (e.g. # apt-get install patchutils)") sys.exit(1) -def runcmd(cmd,destdir=None,printerr=True): +def runcmd(cmd,destdir=None,printerr=True,out=None): """ execute command, raise CalledProcessError if fail return output if succeed """ logger.debug("run cmd '%s' in %s" % (cmd, os.getcwd() if destdir is None else destdir)) - out = os.tmpfile() + if not out: + out = os.tmpfile() + err = out + else: + err = os.tmpfile() try: - subprocess.check_call(cmd, stdout=out, stderr=out, cwd=destdir, shell=True) + subprocess.check_call(cmd, stdout=out, stderr=err, cwd=destdir, shell=isinstance(cmd, str)) except subprocess.CalledProcessError,e: - out.seek(0) + err.seek(0) if printerr: - logger.error("%s" % out.read()) + logger.error("%s" % err.read()) raise e - out.seek(0) - output = out.read() + err.seek(0) + output = err.read() logger.debug("output: %s" % output ) return output -- 2.1.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] combo-layer: runcmd() with separate output 2015-03-10 10:10 ` [PATCH 1/2] combo-layer: runcmd() with separate output Patrick Ohly @ 2015-03-12 18:33 ` Paul Eggleton 0 siblings, 0 replies; 5+ messages in thread From: Paul Eggleton @ 2015-03-12 18:33 UTC (permalink / raw) To: openembedded-core On Tuesday 10 March 2015 11:10:48 Patrick Ohly wrote: > Allow the caller to specify a separate output stream. stderr is always > a temporary file opened by runcmd(), so read from that to capture > output for error reporting *and* the return value. > > The reasoning for the latter is a) that this preserves the traditional > behavior when out=None and b) if the caller wants the content of > stdout, it can read from the stream itself, which is not possible for > the temporary stderr. > > Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> > --- > scripts/combo-layer | 18 +++++++++++------- > 1 file changed, 11 insertions(+), 7 deletions(-) > > diff --git a/scripts/combo-layer b/scripts/combo-layer > index 5f10e83..fb3fb50 100755 > --- a/scripts/combo-layer > +++ b/scripts/combo-layer > @@ -149,23 +149,27 @@ class Configuration(object): > logger.error("ERROR: patchutils package is missing, please > install it (e.g. # apt-get install patchutils)") sys.exit(1) > > -def runcmd(cmd,destdir=None,printerr=True): > +def runcmd(cmd,destdir=None,printerr=True,out=None): > """ > execute command, raise CalledProcessError if fail > return output if succeed > """ > logger.debug("run cmd '%s' in %s" % (cmd, os.getcwd() if destdir is > None else destdir)) - out = os.tmpfile() > + if not out: > + out = os.tmpfile() > + err = out > + else: > + err = os.tmpfile() > try: > - subprocess.check_call(cmd, stdout=out, stderr=out, cwd=destdir, > shell=True) + subprocess.check_call(cmd, stdout=out, stderr=err, > cwd=destdir, shell=isinstance(cmd, str)) except > subprocess.CalledProcessError,e: > - out.seek(0) > + err.seek(0) > if printerr: > - logger.error("%s" % out.read()) > + logger.error("%s" % err.read()) > raise e > > - out.seek(0) > - output = out.read() > + err.seek(0) > + output = err.read() > logger.debug("output: %s" % output ) > return output I'm fine with this change, but FYI unfortunately we have a number of copies of this function floating around. We'll probably end up having to do a refactoring of these at some point soon. Cheers, Paul -- Paul Eggleton Intel Open Source Technology Centre ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] combo-layer: exclude files 2015-03-10 10:10 [PATCH 0/2] combo-layer: exclude files Patrick Ohly 2015-03-10 10:10 ` [PATCH 1/2] combo-layer: runcmd() with separate output Patrick Ohly @ 2015-03-10 10:10 ` Patrick Ohly 2015-03-12 18:37 ` Paul Eggleton 1 sibling, 1 reply; 5+ messages in thread From: Patrick Ohly @ 2015-03-10 10:10 UTC (permalink / raw) To: openembedded-core Some combined repos intentionally do not include certain files. For example, Poky does not include bitbake's setup files and OE-core's sample files under meta/conf. When these files get modified in the upstream repository, applying the patches fails and requires manual intervention. That is merely a nuisance for someone familiar with the problem, but a real show stopper when having the import run automatically or by someone less experienced. Therefore this change introduces "file_exclude", a new per-repo list of file patterns which removes all matching files when initializing or updating a combined repository. Because fnmatch is used under the hood to match full path strings, removing entire directories must be done with a pattern ending in a '/*' (in contrast to file_filter). For Poky, the additional configuration looks like this: [bitbake] ... file_exclude = classes/base.bbclass conf/bitbake.conf .gitignore MANIFEST.in setup.py TODO [openembedded-core] ... file_exclude = meta/conf/bblayers.conf.sample meta/conf/local.conf.sample meta/conf/local.conf.sample.extended meta/conf/site.conf.sample --- scripts/combo-layer | 41 +++++++++++++++++++++++++++++++++++++++- scripts/combo-layer.conf.example | 14 ++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/scripts/combo-layer b/scripts/combo-layer index fb3fb50..b121c99 100755 --- a/scripts/combo-layer +++ b/scripts/combo-layer @@ -20,6 +20,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +import fnmatch import os, sys import optparse import logging @@ -208,7 +209,18 @@ def action_init(conf, args): else: extract_dir = os.getcwd() file_filter = repo.get('file_filter', "") - runcmd("git archive %s | tar -x -C %s %s" % (initialrev, extract_dir, file_filter), ldir) + files = runcmd("git archive %s | tar -x -v -C %s %s" % (initialrev, extract_dir, file_filter), ldir) + exclude_patterns = repo.get('file_exclude', '').split() + if exclude_patterns: + # Implement file removal by letting tar create the + # file and then deleting it in the file system + # again. Uses the list of files created by tar (easier + # than walking the tree). + for file in files.split('\n'): + for pattern in exclude_patterns: + if fnmatch.fnmatch(file, pattern): + os.unlink(os.path.join(extract_dir, file)) + break if not lastrev: lastrev = runcmd("git rev-parse %s" % initialrev, ldir).strip() conf.update(name, "last_revision", lastrev, initmode=True) @@ -423,6 +435,33 @@ def action_update(conf, args): runcmd("%s %s %s %s" % (repo['hook'], patch, revlist[count], name)) count=count-1 + # Step 3a: Filter out unwanted files and patches. + exclude = repo.get('file_exclude', '') + if exclude: + filter = ['filterdiff', '-p1'] + for path in exclude.split(): + filter.append('-x') + filter.append(path) + for patch in patchlist[:]: + filtered = patch + '.tmp' + with open(filtered, 'w') as f: + runcmd(filter + [patch], out=f) + # Now check for empty patches. + if runcmd(['filterdiff', '--list', filtered]): + # Possibly modified. + os.unlink(patch) + os.rename(filtered, patch) + else: + # Empty, ignore it. Must also remove from revlist. + fromline = open(patch, 'r').readline() + m = re.match(r'''^From ([0-9a-fA-F]+) .*\n''', fromline) + rev = m.group(1) + logger.debug('skipping empty patch %s = %s' % (patch, rev)) + os.unlink(patch) + os.unlink(filtered) + patchlist.remove(patch) + revlist.remove(rev) + # Step 4: write patch list and revision list to file, for user to edit later patchlist_file = os.path.join(os.getcwd(), patch_dir, "patchlist-%s" % name) repo['patchlist'] = patchlist_file diff --git a/scripts/combo-layer.conf.example b/scripts/combo-layer.conf.example index 8ad8615..0ef80cb 100644 --- a/scripts/combo-layer.conf.example +++ b/scripts/combo-layer.conf.example @@ -38,6 +38,20 @@ last_revision = # file_filter = src/*.c : only include the src *.c file # file_filter = src/main.c src/Makefile.am : only include these two files +# file_exclude: filter out these file(s) +# file_exclude = [path] [path] ... +# +# Each entry must match a file name. In contrast do file_filter, matching +# a directory has no effect. To achieve that, use append a * wildcard +# at the end. +# +# Wildcards are applied to the complete path and also match slashes. +# +# example: +# file_exclude = src/foobar/* : exclude everything under src/foobar +# file_exclude = src/main.c : filter out main.c after including it with file_filter = src/*.c +# file_exclude = *~ : exclude backup files + # hook: if provided, the tool will call the hook to process the generated # patch from upstream, and then apply the modified patch to the combo # repo. -- 2.1.4 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] combo-layer: exclude files 2015-03-10 10:10 ` [PATCH 2/2] combo-layer: exclude files Patrick Ohly @ 2015-03-12 18:37 ` Paul Eggleton 0 siblings, 0 replies; 5+ messages in thread From: Paul Eggleton @ 2015-03-12 18:37 UTC (permalink / raw) To: Patrick Ohly; +Cc: openembedded-core On Tuesday 10 March 2015 11:10:49 Patrick Ohly wrote: > Some combined repos intentionally do not include certain files. > For example, Poky does not include bitbake's setup files and > OE-core's sample files under meta/conf. > > When these files get modified in the upstream repository, applying the > patches fails and requires manual intervention. That is merely a > nuisance for someone familiar with the problem, but a real show > stopper when having the import run automatically or by someone less > experienced. > > Therefore this change introduces "file_exclude", a new per-repo list > of file patterns which removes all matching files when initializing or > updating a combined repository. Because fnmatch is used under the hood > to match full path strings, removing entire directories must be done > with a pattern ending in a '/*' (in contrast to file_filter). > > For Poky, the additional configuration looks like this: > > [bitbake] > ... > file_exclude = classes/base.bbclass > conf/bitbake.conf > .gitignore > MANIFEST.in > setup.py > TODO > > [openembedded-core] > ... > file_exclude = meta/conf/bblayers.conf.sample > meta/conf/local.conf.sample > meta/conf/local.conf.sample.extended > meta/conf/site.conf.sample > --- > scripts/combo-layer | 41 > +++++++++++++++++++++++++++++++++++++++- scripts/combo-layer.conf.example | > 14 ++++++++++++++ > 2 files changed, 54 insertions(+), 1 deletion(-) > > diff --git a/scripts/combo-layer b/scripts/combo-layer > index fb3fb50..b121c99 100755 > --- a/scripts/combo-layer > +++ b/scripts/combo-layer > @@ -20,6 +20,7 @@ > # with this program; if not, write to the Free Software Foundation, Inc., > # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. > > +import fnmatch > import os, sys > import optparse > import logging > @@ -208,7 +209,18 @@ def action_init(conf, args): > else: > extract_dir = os.getcwd() > file_filter = repo.get('file_filter', "") > - runcmd("git archive %s | tar -x -C %s %s" % (initialrev, > extract_dir, file_filter), ldir) + files = runcmd("git archive > %s | tar -x -v -C %s %s" % (initialrev, extract_dir, file_filter), ldir) + > exclude_patterns = repo.get('file_exclude', '').split() + > if exclude_patterns: > + # Implement file removal by letting tar create the > + # file and then deleting it in the file system > + # again. Uses the list of files created by tar (easier > + # than walking the tree). > + for file in files.split('\n'): > + for pattern in exclude_patterns: > + if fnmatch.fnmatch(file, pattern): > + os.unlink(os.path.join(extract_dir, file)) > + break > if not lastrev: > lastrev = runcmd("git rev-parse %s" % initialrev, > ldir).strip() conf.update(name, "last_revision", lastrev, initmode=True) @@ > -423,6 +435,33 @@ def action_update(conf, args): > runcmd("%s %s %s %s" % (repo['hook'], patch, > revlist[count], name)) count=count-1 > > + # Step 3a: Filter out unwanted files and patches. > + exclude = repo.get('file_exclude', '') > + if exclude: > + filter = ['filterdiff', '-p1'] > + for path in exclude.split(): > + filter.append('-x') > + filter.append(path) > + for patch in patchlist[:]: > + filtered = patch + '.tmp' > + with open(filtered, 'w') as f: > + runcmd(filter + [patch], out=f) > + # Now check for empty patches. > + if runcmd(['filterdiff', '--list', filtered]): > + # Possibly modified. > + os.unlink(patch) > + os.rename(filtered, patch) > + else: > + # Empty, ignore it. Must also remove from revlist. > + fromline = open(patch, 'r').readline() Can you use "with open(..." here? Otherwise looks good. Cheers, Paul -- Paul Eggleton Intel Open Source Technology Centre ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-03-12 18:37 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-03-10 10:10 [PATCH 0/2] combo-layer: exclude files Patrick Ohly 2015-03-10 10:10 ` [PATCH 1/2] combo-layer: runcmd() with separate output Patrick Ohly 2015-03-12 18:33 ` Paul Eggleton 2015-03-10 10:10 ` [PATCH 2/2] combo-layer: exclude files Patrick Ohly 2015-03-12 18:37 ` Paul Eggleton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox