* [PATCH] get_maintainer: add --json output mode
@ 2026-04-06 17:01 Sasha Levin
2026-04-07 2:38 ` Joe Perches
2026-04-08 19:45 ` [PATCH v2] " Sasha Levin
0 siblings, 2 replies; 4+ messages in thread
From: Sasha Levin @ 2026-04-06 17:01 UTC (permalink / raw)
To: joe; +Cc: linux-kernel, Sasha Levin
Add a --json flag to get_maintainer.pl that emits structured JSON
output, making results machine-parseable for CI systems, IDE
integrations, and AI-assisted development tools.
The JSON output includes a maintainers array with structured name,
email, and role fields, plus optional arrays for scm, status,
subsystem, web, and bug information when those flags are enabled.
Normal text output behavior is completely unchanged when --json is
not specified.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
scripts/get_maintainer.pl | 114 +++++++++++++++++++++++++++++---------
1 file changed, 87 insertions(+), 27 deletions(-)
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 4414194bedcfd..37817ca701bd6 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -68,6 +68,7 @@ my $pattern_depth = 0;
my $self_test = undef;
my $version = 0;
my $help = 0;
+my $json = 0;
my $find_maintainer_files = 0;
my $maintainer_path;
my $vcs_used = 0;
@@ -285,6 +286,7 @@ if (!GetOptions(
'find-maintainer-files' => \$find_maintainer_files,
'mpath|maintainer-path=s' => \$maintainer_path,
'self-test:s' => \$self_test,
+ 'json!' => \$json,
'v|version' => \$version,
'h|help|usage' => \$help,
)) {
@@ -648,39 +650,74 @@ my %deduplicate_name_hash = ();
my %deduplicate_address_hash = ();
my @maintainers = get_maintainers();
-if (@maintainers) {
- @maintainers = merge_email(@maintainers);
- output(@maintainers);
-}
-if ($scm) {
- @scm = uniq(@scm);
- output(@scm);
-}
+if ($json) {
+ my @json_maintainers;
+ if (@maintainers) {
+ my %saw;
+ for (@maintainers) {
+ my ($address, $role) = @$_;
+ if (!$saw{$address}) {
+ my ($name, $email_addr) = parse_email($address);
+ my $entry = '{"name":"' . json_escape_str($name) .
+ '","email":"' . json_escape_str($email_addr) . '"';
+ $entry .= ',"role":"' . json_escape_str($role) . '"' if ($output_roles && $role ne '');
+ $entry .= '}';
+ push(@json_maintainers, $entry);
+ $saw{$address} = 1;
+ }
+ }
+ }
-if ($output_substatus) {
- @substatus = uniq(@substatus);
- output(@substatus);
-}
+ @scm = uniq(@scm) if ($scm);
+ @status = uniq(@status) if ($status);
+ @subsystem = uniq(@subsystem) if ($subsystem);
+ @web = uniq(@web) if ($web);
+ @bug = uniq(@bug) if ($bug);
-if ($status) {
- @status = uniq(@status);
- output(@status);
-}
+ my @fields;
+ push(@fields, '"maintainers":[' . join(',', @json_maintainers) . ']');
+ push(@fields, '"scm":' . json_str_array(@scm)) if ($scm);
+ push(@fields, '"status":' . json_str_array(@status)) if ($status);
+ push(@fields, '"subsystem":' . json_str_array(@subsystem)) if ($subsystem);
+ push(@fields, '"web":' . json_str_array(@web)) if ($web);
+ push(@fields, '"bug":' . json_str_array(@bug)) if ($bug);
+ print('{' . join(',', @fields) . '}' . "\n");
+} else {
+ if (@maintainers) {
+ @maintainers = merge_email(@maintainers);
+ output(@maintainers);
+ }
-if ($subsystem) {
- @subsystem = uniq(@subsystem);
- output(@subsystem);
-}
+ if ($scm) {
+ @scm = uniq(@scm);
+ output(@scm);
+ }
-if ($web) {
- @web = uniq(@web);
- output(@web);
-}
+ if ($output_substatus) {
+ @substatus = uniq(@substatus);
+ output(@substatus);
+ }
-if ($bug) {
- @bug = uniq(@bug);
- output(@bug);
+ if ($status) {
+ @status = uniq(@status);
+ output(@status);
+ }
+
+ if ($subsystem) {
+ @subsystem = uniq(@subsystem);
+ output(@subsystem);
+ }
+
+ if ($web) {
+ @web = uniq(@web);
+ output(@web);
+ }
+
+ if ($bug) {
+ @bug = uniq(@bug);
+ output(@bug);
+ }
}
exit($exit);
@@ -1099,6 +1136,7 @@ Output type options:
--separator [, ] => separator for multiple entries on 1 line
using --separator also sets --nomultiline if --separator is not [, ]
--multiline => print 1 entry per line
+ --json => output results as JSON
Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
@@ -2549,6 +2587,28 @@ sub merge_email {
return @lines;
}
+sub json_escape_str {
+ my ($str) = @_;
+ $str =~ s/\\/\\\\/g;
+ $str =~ s/"/\\"/g;
+ $str =~ s/\n/\\n/g;
+ $str =~ s/\r/\\r/g;
+ $str =~ s/\t/\\t/g;
+ $str =~ s/\x08/\\b/g;
+ $str =~ s/\x0c/\\f/g;
+ $str =~ s/([\x00-\x07\x0b\x0e-\x1f])/sprintf("\\u%04x", ord($1))/ge;
+ return $str;
+}
+
+sub json_str_array {
+ my (@arr) = @_;
+ my @quoted;
+ foreach my $s (@arr) {
+ push(@quoted, '"' . json_escape_str($s) . '"');
+ }
+ return '[' . join(',', @quoted) . ']';
+}
+
sub output {
my (@parms) = @_;
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] get_maintainer: add --json output mode
2026-04-06 17:01 [PATCH] get_maintainer: add --json output mode Sasha Levin
@ 2026-04-07 2:38 ` Joe Perches
2026-04-08 19:45 ` [PATCH v2] " Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Joe Perches @ 2026-04-07 2:38 UTC (permalink / raw)
To: Sasha Levin; +Cc: linux-kernel
On Mon, 2026-04-06 at 13:01 -0400, Sasha Levin wrote:
> Add a --json flag to get_maintainer.pl that emits structured JSON
> output, making results machine-parseable for CI systems, IDE
> integrations, and AI-assisted development tools.
OK here too but perhaps the code can be consolidated a bit more.
> diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
> index 4414194bedcfd..37817ca701bd6 100755
> --- a/scripts/get_maintainer.pl
> +++ b/scripts/get_maintainer.pl
> @@ -68,6 +68,7 @@ my $pattern_depth = 0;
> my $self_test = undef;
> my $version = 0;
> my $help = 0;
> +my $json = 0;
> my $find_maintainer_files = 0;
> my $maintainer_path;
> my $vcs_used = 0;
> @@ -285,6 +286,7 @@ if (!GetOptions(
> 'find-maintainer-files' => \$find_maintainer_files,
> 'mpath|maintainer-path=s' => \$maintainer_path,
> 'self-test:s' => \$self_test,
> + 'json!' => \$json,
> 'v|version' => \$version,
> 'h|help|usage' => \$help,
> )) {
> @@ -648,39 +650,74 @@ my %deduplicate_name_hash = ();
> my %deduplicate_address_hash = ();
>
> my @maintainers = get_maintainers();
> -if (@maintainers) {
> - @maintainers = merge_email(@maintainers);
> - output(@maintainers);
> -}
>
> -if ($scm) {
> - @scm = uniq(@scm);
> - output(@scm);
> -}
> +if ($json) {
> + my @json_maintainers;
> + if (@maintainers) {
> + my %saw;
> + for (@maintainers) {
> + my ($address, $role) = @$_;
> + if (!$saw{$address}) {
> + my ($name, $email_addr) = parse_email($address);
> + my $entry = '{"name":"' . json_escape_str($name) .
> + '","email":"' . json_escape_str($email_addr) . '"';
> + $entry .= ',"role":"' . json_escape_str($role) . '"' if ($output_roles && $role ne '');
> + $entry .= '}';
> + push(@json_maintainers, $entry);
> + $saw{$address} = 1;
Isn't this effectively the merge_email(@maintainers) above?
Why not use it?
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v2] get_maintainer: add --json output mode
2026-04-06 17:01 [PATCH] get_maintainer: add --json output mode Sasha Levin
2026-04-07 2:38 ` Joe Perches
@ 2026-04-08 19:45 ` Sasha Levin
2026-04-08 20:06 ` Joe Perches
1 sibling, 1 reply; 4+ messages in thread
From: Sasha Levin @ 2026-04-08 19:45 UTC (permalink / raw)
To: joe; +Cc: linux-kernel, Sasha Levin
Add a --json flag to get_maintainer.pl that emits structured JSON
output, making results machine-parseable for CI systems, IDE
integrations, and AI-assisted development tools.
The JSON output includes a maintainers array with structured name,
email, and role fields, plus optional arrays for scm, status,
subsystem, web, and bug information when those flags are enabled.
Normal text output behavior is completely unchanged when --json is
not specified.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
Changes since v1:
- Replace hand-rolled json_escape_str()/json_str_array() with JSON::PP
module (core since perl 5.14)
- Reuse merge_email() for deduplication instead of reimplementing it,
per Joe's review
- Consolidate uniq() dedup calls before the json/non-json branch so
both paths share the same logic
---
scripts/get_maintainer.pl | 73 +++++++++++++++++++++++----------------
1 file changed, 43 insertions(+), 30 deletions(-)
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 4414194bedcfd..1bd4170684483 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -21,6 +21,7 @@ use Cwd;
use File::Find;
use File::Spec::Functions;
use open qw(:std :encoding(UTF-8));
+use JSON::PP;
my $cur_path = fastgetcwd() . '/';
my $lk_path = "./";
@@ -68,6 +69,7 @@ my $pattern_depth = 0;
my $self_test = undef;
my $version = 0;
my $help = 0;
+my $json = 0;
my $find_maintainer_files = 0;
my $maintainer_path;
my $vcs_used = 0;
@@ -285,6 +287,7 @@ if (!GetOptions(
'find-maintainer-files' => \$find_maintainer_files,
'mpath|maintainer-path=s' => \$maintainer_path,
'self-test:s' => \$self_test,
+ 'json!' => \$json,
'v|version' => \$version,
'h|help|usage' => \$help,
)) {
@@ -648,39 +651,48 @@ my %deduplicate_name_hash = ();
my %deduplicate_address_hash = ();
my @maintainers = get_maintainers();
-if (@maintainers) {
- @maintainers = merge_email(@maintainers);
- output(@maintainers);
-}
-
-if ($scm) {
- @scm = uniq(@scm);
- output(@scm);
-}
-
-if ($output_substatus) {
- @substatus = uniq(@substatus);
- output(@substatus);
-}
-
-if ($status) {
- @status = uniq(@status);
- output(@status);
-}
-if ($subsystem) {
- @subsystem = uniq(@subsystem);
- output(@subsystem);
-}
+@maintainers = merge_email(@maintainers) if (@maintainers);
+@scm = uniq(@scm) if ($scm);
+@substatus = uniq(@substatus) if ($output_substatus);
+@status = uniq(@status) if ($status);
+@subsystem = uniq(@subsystem) if ($subsystem);
+@web = uniq(@web) if ($web);
+@bug = uniq(@bug) if ($bug);
+
+if ($json) {
+ my @json_maintainers;
+ for my $m (@maintainers) {
+ my ($addr, $role);
+ if ($output_roles && $m =~ /^(.*?)\s+\((.+)\)\s*$/) {
+ $addr = $1;
+ $role = $2;
+ } else {
+ $addr = $m;
+ }
+ my ($name, $email_addr) = parse_email($addr);
+ my %entry = (name => $name, email => $email_addr);
+ $entry{role} = $role if (defined $role && $role ne '');
+ push(@json_maintainers, \%entry);
+ }
-if ($web) {
- @web = uniq(@web);
- output(@web);
-}
+ my %result = (maintainers => \@json_maintainers);
+ $result{scm} = \@scm if ($scm);
+ $result{status} = \@status if ($status);
+ $result{subsystem} = \@subsystem if ($subsystem);
+ $result{web} = \@web if ($web);
+ $result{bug} = \@bug if ($bug);
-if ($bug) {
- @bug = uniq(@bug);
- output(@bug);
+ my $json_encoder = JSON::PP->new->canonical->utf8;
+ print($json_encoder->encode(\%result) . "\n");
+} else {
+ output(@maintainers) if (@maintainers);
+ output(@scm) if ($scm);
+ output(@substatus) if ($output_substatus);
+ output(@status) if ($status);
+ output(@subsystem) if ($subsystem);
+ output(@web) if ($web);
+ output(@bug) if ($bug);
}
exit($exit);
@@ -1099,6 +1111,7 @@ Output type options:
--separator [, ] => separator for multiple entries on 1 line
using --separator also sets --nomultiline if --separator is not [, ]
--multiline => print 1 entry per line
+ --json => output results as JSON
Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
--
2.53.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] get_maintainer: add --json output mode
2026-04-08 19:45 ` [PATCH v2] " Sasha Levin
@ 2026-04-08 20:06 ` Joe Perches
0 siblings, 0 replies; 4+ messages in thread
From: Joe Perches @ 2026-04-08 20:06 UTC (permalink / raw)
To: Sasha Levin, Andrew Morton; +Cc: linux-kernel
On Wed, 2026-04-08 at 15:45 -0400, Sasha Levin wrote:
> Add a --json flag to get_maintainer.pl that emits structured JSON
> output, making results machine-parseable for CI systems, IDE
> integrations, and AI-assisted development tools.
>
> The JSON output includes a maintainers array with structured name,
> email, and role fields, plus optional arrays for scm, status,
> subsystem, web, and bug information when those flags are enabled.
>
> Normal text output behavior is completely unchanged when --json is
> not specified.
>
> Assisted-by: Claude:claude-opus-4-6
> Signed-off-by: Sasha Levin <[sashal@kernel.org](mailto:sashal@kernel.org)>
Thanks Sasha. Looks nicer now.
Acked-by: Joe Perches <joe@perches.com>
> ---
> Changes since v1:
> - Replace hand-rolled json_escape_str()/json_str_array() with JSON::PP
> module (core since perl 5.14)
> - Reuse merge_email() for deduplication instead of reimplementing it,
> per Joe's review
> - Consolidate uniq() dedup calls before the json/non-json branch so
> both paths share the same logic
> ---
> scripts/get_maintainer.pl | 73 +++++++++++++++++++++++----------------
> 1 file changed, 43 insertions(+), 30 deletions(-)
>
> diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
> index 4414194bedcfd..1bd4170684483 100755
> --- a/scripts/get_maintainer.pl
> +++ b/scripts/get_maintainer.pl
> @@ -21,6 +21,7 @@ use Cwd;
> use File::Find;
> use File::Spec::Functions;
> use open qw(:std :encoding(UTF-8));
> +use JSON::PP;
>
> my $cur_path = fastgetcwd() . '/';
> my $lk_path = "./";
> @@ -68,6 +69,7 @@ my $pattern_depth = 0;
> my $self_test = undef;
> my $version = 0;
> my $help = 0;
> +my $json = 0;
> my $find_maintainer_files = 0;
> my $maintainer_path;
> my $vcs_used = 0;
> @@ -285,6 +287,7 @@ if (!GetOptions(
> 'find-maintainer-files' => \$find_maintainer_files,
> 'mpath|maintainer-path=s' => \$maintainer_path,
> 'self-test:s' => \$self_test,
> + 'json!' => \$json,
> 'v|version' => \$version,
> 'h|help|usage' => \$help,
> )) {
> @@ -648,39 +651,48 @@ my %deduplicate_name_hash = ();
> my %deduplicate_address_hash = ();
>
> my @maintainers = get_maintainers();
> -if (@maintainers) {
> - @maintainers = merge_email(@maintainers);
> - output(@maintainers);
> -}
> -
> -if ($scm) {
> - @scm = uniq(@scm);
> - output(@scm);
> -}
> -
> -if ($output_substatus) {
> - @substatus = uniq(@substatus);
> - output(@substatus);
> -}
> -
> -if ($status) {
> - @status = uniq(@status);
> - output(@status);
> -}
>
> -if ($subsystem) {
> - @subsystem = uniq(@subsystem);
> - output(@subsystem);
> -}
> +@maintainers = merge_email(@maintainers) if (@maintainers);
> +@scm = uniq(@scm) if ($scm);
> +@substatus = uniq(@substatus) if ($output_substatus);
> +@status = uniq(@status) if ($status);
> +@subsystem = uniq(@subsystem) if ($subsystem);
> +@web = uniq(@web) if ($web);
> +@bug = uniq(@bug) if ($bug);
> +
> +if ($json) {
> + my @json_maintainers;
> + for my $m (@maintainers) {
> + my ($addr, $role);
> + if ($output_roles && $m =~ /^(.*?)\s+\((.+)\)\s*$/) {
> + $addr = $1;
> + $role = $2;
> + } else {
> + $addr = $m;
> + }
> + my ($name, $email_addr) = parse_email($addr);
> + my %entry = (name => $name, email => $email_addr);
> + $entry{role} = $role if (defined $role && $role ne '');
> + push(@json_maintainers, \%entry);
> + }
>
> -if ($web) {
> - @web = uniq(@web);
> - output(@web);
> -}
> + my %result = (maintainers => \@json_maintainers);
> + $result{scm} = \@scm if ($scm);
> + $result{status} = \@status if ($status);
> + $result{subsystem} = \@subsystem if ($subsystem);
> + $result{web} = \@web if ($web);
> + $result{bug} = \@bug if ($bug);
>
> -if ($bug) {
> - @bug = uniq(@bug);
> - output(@bug);
> + my $json_encoder = JSON::PP->new->canonical->utf8;
> + print($json_encoder->encode(\%result) . "\n");
> +} else {
> + output(@maintainers) if (@maintainers);
> + output(@scm) if ($scm);
> + output(@substatus) if ($output_substatus);
> + output(@status) if ($status);
> + output(@subsystem) if ($subsystem);
> + output(@web) if ($web);
> + output(@bug) if ($bug);
> }
>
> exit($exit);
> @@ -1099,6 +1111,7 @@ Output type options:
> --separator [, ] => separator for multiple entries on 1 line
> using --separator also sets --nomultiline if --separator is not [, ]
> --multiline => print 1 entry per line
> + --json => output results as JSON
>
> Other options:
> --pattern-depth => Number of pattern directory traversals (default: 0 (all))
>
> ```
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-04-08 20:06 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-06 17:01 [PATCH] get_maintainer: add --json output mode Sasha Levin
2026-04-07 2:38 ` Joe Perches
2026-04-08 19:45 ` [PATCH v2] " Sasha Levin
2026-04-08 20:06 ` Joe Perches
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®