Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add config to compose for filter-whilst-staging - #2012

Open
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging
Open

Add config to compose for filter-whilst-staging#2012
harrysarson wants to merge 1 commit into
apache:masterfrom
harrysarson:harry/compose-filter-whilst-staging

Conversation

@harrysarson

Copy link
Copy Markdown
Contributor

The configuration allows applying filers based on include, exclude and include-orphans whilst staging dependencies rather than when assembling the artifact. This is useful to avoid overlapping files errors.

The configuration allows applying filers based on `include`, `exclude`
and `include-orphans` whilst staging dependencies rather than when
assembling the artifact. This is useful to avoid overlapping files
errors.
@harrysarson
harrysarsonforce-pushed the harry/compose-filter-whilst-staging branch from 8b8f97a to 4e0500eCompareMay 22, 2025 10:52
@gtristan

gtristan commented May 22, 2025

Copy link
Copy Markdown
Contributor

I think this needs some deeper thought.

Right now compose does:

 stage dependencies in /
|
V
run integration commands
|
V
apply splits to resulting
filesystem after integration commands
|
V
place selected files into %{install-root}

The problem you are trying to solve, is that this approach conflicts with overlaps, in the case that initially staged artifact dependency chains have multiple artifacts which provide the same groups of files.

In what ways can we address this ?

  • It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of why are these files overlapping is relevant
  • If we address this in the way that you propose
    • We render the integration command file capturing possibly useless in cases with the proposed option added
    • We are applying splits for different reasons
    • It may be that what we want is to have a different set of include/exclude elements in the staging process, that molds the input in advance of integration commands and before the original set of include/exclude rules are employed to curate the output of the compose element.
  • In the case of handling overlap errors raised in compose's Element.stage() implementation, I wonder if it makes sense to carve out an escape hatch of sorts ?
    • I.e. if it is valid to have overlap errors enabled in a project, does it still make sense to not enforce overlap whitelisting ?
    • If we can deem that it is indeed a case worthy of a special case escape hatch for the specific case of compose elements, would it make sense to (optionally) catch the exception raised by Element.stage_dependency_artifacts() and cause it to be non-fatal in this case ?
  • Would it change something if, for example, we handled the case where integration commands are not going to run differently, and just do the Element.stage_dependency_artifacts() with the include/exclude/orphans options, directly into %{install-root}, and circumvent the issue in this case ?

If we're going to add configuration here, we should consider what will be maximally useful for different possible use-cases.

Also, I think it would be good to avoid breaking expectations of setting overlap warnings as fatal warnings (as mentioned above, it seems telling that this error you are trying to circumvent would still be occurring if this were a build element and not a compose element).

@harrysarson

Copy link
Copy Markdown
ContributorAuthor
* It seems to me that we would have this overlap problem even if it was a build element and not a compose element, so the question of _why are these files overlapping_ is relevant
* Does it make more sense for the overlapping element to use the [overlap whitelist](https://docs.buildstream.build/master/format_public.html#overlap-whitelist) ?

There are two elements that provide the same file, one from FDSDK (so I cannot edit it) and one in my project (so I can edit it). If I add overlap whitelist to my element that would allow the version of the file from my element to replace the one from FDSDK. However, I want to do the oposite. I want the version of the file from my element to be replaced by the one from FDSDK.


For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

@gtristan

Copy link
Copy Markdown
Contributor

[...]

For context my work around is to add the following to the element in my project:


config:
(>):
# This file causes overlapping issues with trace from perf.bst
- |
rm %{install-root}/usr/bin/trace

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

@harrysarson

Copy link
Copy Markdown
ContributorAuthor

Not shipping the file which conflicts with perf seems to be a perfectly sound approach. This, or distributing your trace program under a different name if it is a different tool.

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

@abderrahim

Copy link
Copy Markdown
Contributor

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

@gtristan

Copy link
Copy Markdown
Contributor

@harrysarson:

With the split-rule + compose approach (that requires the changes in this PR) we give the element that integrates the elements the choice on whether to remove the offending file, if perf isn't going into the disk image then it would make sense to be able to keep the other version of trace.

Sure. I think that the approach you currently taking is sensible.

That said, I'm not happy with the implementation you propose, and I've asked for more thinking in my above comment #2012 (comment) to find an API that is more all around generally useful.

One approach I've suggested there, would be to instead have a separate splitting at staging time (e.g. it could be stage-include/stage-exclude/stage-orphans kind of API to be applied at staging, before integration occurs).

However, I rather like @abderrahim's line of thinking too:

FWIW, I've been thinking about this "filter while staging" idea. I feel that it makes more sense as a dependency configuration that is more generically applicable rather than being specific to compose.

This would make it usable for other use cases as well.

The way the code is structured, at least some duplication is needed in base Element classes to do the dependency configuration support, that said I agree it can make sense to do some kind of filtering at staging time for script, compose and build elements (probably with the same consistent API).

Expressing the dependency on partial artifacts is also reminiscent of past suggestions from @sstriker, the idea you propose makes me wonder if just having this data expressed might leave some window open to improve build avoidance in the future (i.e. "If the part of my dependency artifact which I use, has not changed, I don't need to rebuild"), while this is a bit far fetched given the nature of cache keys, it's at least worth noting in the context of this discussion.

Orthogonal to this (but somewhat relevant to this conflicting "/usr/bin/perf" program), something that I've been mulling over, is; why do we limit ourselves to filtering ? I think that elements like compose and filter which do these inclusions/exclusions, might also benefit from the ability to do relocations, i.e. renaming/relocating files on a per-split or per-file basis.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@harrysarson@gtristan@abderrahim