Skip to content

Commit 808cbd3

Browse files
authored
feat(overlays): add file rename/delete + file glob pattern support (#391)
* Adds new non-spec overlays for manipulating loose files next to specs * Adds file glob support to (most of) these non-spec overlays * Adds a new afero.FS implementation that supports constraining updates to a target dir * Adds various tests
1 parent f8a17df commit 808cbd3

14 files changed

Lines changed: 2590 additions & 95 deletions

File tree

docs/reference/overlays.md

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,19 @@ These overlays modify non-spec source files directly. They cannot be used on `.s
2828
overlays are typically only used to modify loose files next to specs when standard patching mechanisms
2929
can't easily be used.
3030

31-
| Type | Description | Required Fields |
32-
|------|-------------|-----------------|
33-
| `file-prepend-lines` | Prepends lines to a file | `file`, `lines` |
34-
| `file-search-replace` | Regex-based search and replace on a file | `file`, `regex` |
35-
| `file-add` | Copies a new file from a source location | `file`, `source` |
31+
For overlays that use the `file` field and may apply to multiple files, this field is
32+
interpreted as a glob pattern for files to match; the table below details this.
33+
Glob patterns support doublestar (`**`) for recursive matching (e.g., `**/*.conf` matches all `.conf` files in any subdirectory).
34+
For `file-search-replace`, the overlay is considered to have been correctly applied if it
35+
successfully makes a replacement to at least one matching file.
36+
37+
| Type | Description | Required Fields | Interpretation of `file` field |
38+
|------|-------------|-----------------|--------------------------------|
39+
| `file-prepend-lines` | Prepends lines to a file | `file`, `lines` | Glob pattern for files to transform |
40+
| `file-search-replace` | Regex-based search and replace on a file | `file`, `regex` | Glob pattern for files to transform |
41+
| `file-add` | Copies a new file from a source location; **fails if destination already exists** | `file`, `source` | Name of destination file |
42+
| `file-remove` | Removes a file | `file` | Glob pattern for files to remove |
43+
| `file-rename` | Renames a file within the same directory | `file`, `replacement` | Name of file to rename |
3644

3745
## Field Reference
3846

@@ -45,11 +53,13 @@ can't easily be used.
4553
| Section | `section` | The spec section to target (e.g., `%build`, `%install`, `%files`, `%description`) | `spec-prepend-lines`, `spec-append-lines`, `spec-search-replace` (optional) |
4654
| Package | `package` | The sub-package name for multi-package specs; omit to target the main package | All spec overlays (optional) |
4755
| Regex | `regex` | Regular expression pattern to match | `spec-search-replace`, `file-search-replace` |
48-
| Replacement | `replacement` | Literal replacement text; omit or leave empty to delete matched text | `spec-search-replace`, `file-search-replace` (optional) |
56+
| Replacement | `replacement` | Literal replacement text; capture group references like `$1` are **not** expanded. Omit or leave empty to delete matched text. | `spec-search-replace`, `file-search-replace`, `file-rename` |
4957
| Lines | `lines` | Array of text lines to insert | `spec-prepend-lines`, `spec-append-lines`, `file-prepend-lines` |
50-
| File | `file` | The name of the non-spec file to modify or add | `file-prepend-lines`, `file-search-replace`, `file-add` |
58+
| File | `file` | The name of the non-spec file to modify or add | `file-prepend-lines`, `file-search-replace`, `file-add`, `file-remove`, `file-rename` |
5159
| Source | `source` | Path to source file for `file-add`; relative paths are relative to the config file | `file-add` |
5260

61+
> **Note:** For `file-rename`, the `replacement` field is a **filename only** (not a path). The file is renamed within its current directory.
62+
5363
## Examples
5464

5565
### Adding a Build Dependency
@@ -171,6 +181,23 @@ source = "files/mypackage/extra-config.conf"
171181
description = "Add custom configuration file"
172182
```
173183

184+
### Removing a File
185+
186+
```toml
187+
[[components.mypackage.overlays]]
188+
type = "file-remove"
189+
file = "undesired.conf"
190+
```
191+
192+
### Renaming a File
193+
194+
```toml
195+
[[components.mypackage.overlays]]
196+
type = "file-rename"
197+
file = "oldname.conf"
198+
replacement = "newname.conf"
199+
```
200+
174201
## Validation
175202

176203
Overlay configurations are validated when the config file is loaded. Validation checks:

internal/app/azldev/cmds/component/preparesources.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import (
1717
type PrepareSourcesOptions struct {
1818
ComponentFilter components.ComponentFilter
1919

20-
OutputDir string
20+
OutputDir string
21+
SkipOverlays bool
2122
}
2223

2324
func prepareOnAppInit(_ *azldev.App, sourceCmd *cobra.Command) {
@@ -48,6 +49,8 @@ func NewPrepareSourcesCmd() *cobra.Command {
4849
_ = cmd.MarkFlagRequired("output-dir")
4950
_ = cmd.MarkFlagDirname("output-dir")
5051

52+
cmd.Flags().BoolVar(&options.SkipOverlays, "skip-overlays", false, "skip applying overlays to prepared sources")
53+
5154
return cmd
5255
}
5356

@@ -73,7 +76,7 @@ func PrepareComponentSources(env *azldev.Env, options *PrepareSourcesOptions) er
7376

7477
component := comps.Components()[0]
7578

76-
event := env.StartEvent("Preparing sources", "component", component.GetName())
79+
event := env.StartEvent("Preparing sources", "component", component.GetName(), "outputDir", options.OutputDir)
7780
defer event.End()
7881

7982
var sourceManager sourceproviders.SourceManager
@@ -89,7 +92,7 @@ func PrepareComponentSources(env *azldev.Env, options *PrepareSourcesOptions) er
8992
return fmt.Errorf("failed to create source preparer:\n%w", err)
9093
}
9194

92-
err = preparer.PrepareSources(env, component, options.OutputDir)
95+
err = preparer.PrepareSources(env, component, options.OutputDir, !options.SkipOverlays)
9396
if err != nil {
9497
return fmt.Errorf("failed to prepare sources for component %q:\n%w", component.GetName(), err)
9598
}

internal/app/azldev/core/componentbuilder/componentbuilder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func (b *Builder) prepSourcesForSRPM(
123123
return "", fmt.Errorf("failed to create work dir for source preparation:\n%w", err)
124124
}
125125

126-
err = b.sourcePreparer.PrepareSources(ctx, component, preparedSourcesDir)
126+
err = b.sourcePreparer.PrepareSources(ctx, component, preparedSourcesDir, true /*applyOverlays?*/)
127127
if err != nil {
128128
return "", fmt.Errorf("failed to prepare sources:\n%w", err)
129129
}

0 commit comments

Comments
 (0)