Skip to content

feat!: per-language [[headers]] rules with existingStrategy - #212

Open
hubcio wants to merge 1 commit into
korandoru:mainfrom
hubcio:feat/headers-existing-strategy
Open

feat!: per-language [[headers]] rules with existingStrategy#212
hubcio wants to merge 1 commit into
korandoru:mainfrom
hubcio:feat/headers-existing-strategy

Conversation

@hubcio

@hubcio hubcio commented Jun 23, 2026

Copy link
Copy Markdown

Replace the style-keyed [mapping.STYLE] config and useDefaultMapping
with a per-language [[headers]] rule list carrying styles (preferred
first) and an existingStrategy (replace|skip|error). Fixes #210:
format no longer stacks a duplicate header when a file already has a
header in a different comment style.

An existing header is detected style-agnostically by a whole-word,
case-insensitive scan for the configured keywords. A foreign-but-listed
header (e.g. /* */ under a // rule) is migrated to the preferred style,
not duplicated. One in an unlisted style, or a stray keyword that cannot
be normalized, is left unchanged and reported as "foreign": under
existingStrategy=replace this fails the run (exit non-zero) rather than
silently passing un-normalized; skip leaves it and exits zero. check
adds a "foreign" category; --output JSON gains foreign/skipped/conflict.

format and remove now write files atomically (temp, fsync, rename);
a symlinked path is replaced by a regular file, and source permissions
are preserved on a best-effort basis.

BREAKING CHANGE: [mapping.STYLE] blocks and useDefaultMapping are
removed. Replace each [mapping.FOO] { extensions = [...] } with a
[[headers]] rule carrying styles = ["FOO"], and rename
useDefaultMapping to useDefaultHeaders. A 6.x config is rejected
with a migration hint. format now exits non-zero when it finds an
existing license-looking header it cannot normalize to the preferred
style; hawkeye remove's --output "removed" entries are now bare paths
(previously path=removed).

Tested on downstream hawkeye users by migrating their configs:
apache/opendal, datafuselabs/databend and apache/fory match 6.5.1
with no new diagnostics; apache/iggy needs one gitignored file excluded.

Closes #210

Replace the style-keyed [mapping.STYLE] config and useDefaultMapping
with a per-language [[headers]] rule list carrying styles (preferred
first) and an existingStrategy (replace|skip|error). Fixes korandoru#210:
format no longer stacks a duplicate header when a file already has a
header in a different comment style.

An existing header is detected style-agnostically by a whole-word,
case-insensitive scan for the configured keywords. A foreign-but-listed
header (e.g. /* */ under a // rule) is migrated to the preferred style,
not duplicated. One in an unlisted style, or a stray keyword that cannot
be normalized, is left unchanged and reported as "foreign": under
existingStrategy=replace this fails the run (exit non-zero) rather than
silently passing un-normalized; skip leaves it and exits zero. check
adds a "foreign" category; --output JSON gains foreign/skipped/conflict.

format and remove now write files atomically (temp, fsync, rename);
a symlinked path is replaced by a regular file, and source permissions
are preserved on a best-effort basis.

BREAKING CHANGE: [mapping.STYLE] blocks and useDefaultMapping are
removed. Replace each [mapping.FOO] { extensions = [...] } with a
[[headers]] rule carrying styles = ["FOO"], and rename
useDefaultMapping to useDefaultHeaders. A 6.x config is rejected
with a migration hint. format now exits non-zero when it finds an
existing license-looking header it cannot normalize to the preferred
style; hawkeye remove's --output "removed" entries are now bare paths
(previously path=removed).

Tested on downstream hawkeye users by migrating their configs:
apache/opendal, datafuselabs/databend and apache/fory match 6.5.1
with no new diagnostics; apache/iggy needs one gitignored file excluded.

Closes korandoru#210
@tisonkun

Copy link
Copy Markdown
Member

Thanks for your contribution @hubcio! I'm going to review this patch on the weekend.

Feel free to ping me next week if I miss this review.

@tisonkun
tisonkun self-requested a review June 28, 2026 07:00
Comment thread README.md
# Options to configure Git features.
[git]
# If enabled, do not process files that are ignored by Git; possible value: ['auto', 'enable', 'disable']
# If enabled, do not process files that are ignored by Git AND untracked; a file matched by a

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it? Untracked files that do not ignored should be processed always.

@tisonkun tisonkun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a huge PR I just noticed.

Let me review it in the following days.

Actually I'm considering a full rewrite to cover:

  1. Use snake_case options always
  2. Drop GitHub Actions support; everyone can use cargo-binstall and run the command as a faster way.
  3. Rework the integration tests framework.
  4. Forward quite a few Rust best practices.

That said, I'm taking these on my own. And thanks a lot for @hubcio your patch and nudge to me for finally working on these.

Hopefully I can get all these arranged and delievered in July.

@hubcio

hubcio commented Jun 28, 2026

Copy link
Copy Markdown
Author

Thanks @tisonkun. Let me know if you need any help.

Sign up for free to 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.

enhancement: Replace mismatched license headers instead of appending a new header during auto-fix

2 participants