Ctrl K
ComunidadGuías…

script/adr-index

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env perl
# SPDX-FileCopyrightText: 2026 GPForum Contributors
# SPDX-License-Identifier: BSD-3-Clause

package main;

use v5.40;

use Carp qw(croak);
use Const::Fast;
use English qw(-no_match_vars);

our $VERSION = '0.001';

# Writes the index of docs/adr/ into docs/adr/README.md, between two markers.
#
# There were 103 ADRs and a README that indexed none of them, so the only way
# to find the decision on, say, effective visibility was to guess a filename.
# A hand-kept list would drift the day the next ADR landed; this one is
# generated, and `--check` fails when the README no longer matches the files,
# which the test suite runs.

const my $DIRECTORY => 'docs/adr';
const my $README    => "$DIRECTORY/README.md";
const my $START     => '<!-- adr-index:start -->';
const my $END       => '<!-- adr-index:end -->';

my $check = grep { $_ eq '--check' } @ARGV;

my $index   = _index();
my $current = _slurp($README);
my $wanted  = _with_index( $current, $index );

if ($check) {
    if ( $wanted ne $current ) {
        _say( *STDERR, "adr-index: $README is stale; run script/adr-index" );
        exit 1;
    }
    _say( *STDOUT, 'adr-index status=ok' );
    exit 0;
}

if ( $wanted ne $current ) {
    open my $handle, '>', $README or croak "open $README: $ERRNO";
    print {$handle} $wanted or croak "write $README: $ERRNO";
    close $handle           or croak "close $README: $ERRNO";
}
_say( *STDOUT, "adr-index wrote $README" );
exit 0;

sub _index {
    opendir my $dir, $DIRECTORY or croak "opendir $DIRECTORY: $ERRNO";
    my @files = sort grep { /\A [[:digit:]]{4} - .+ [.]md \z/msx } readdir $dir;
    closedir $dir or croak "closedir $DIRECTORY: $ERRNO";

    my @rows;
    my %seen;
    for my $file (@files) {
        my ($number) = $file =~ /\A ([[:digit:]]{4})/msx;
        next if $number eq '0000';
        $seen{ $number + 0 } = 1;
        my $text = _slurp("$DIRECTORY/$file");
        my ($title) =
          $text =~ /\A [#] \s* ADR \s* [[:digit:]]+ : \s* ([^\n]+)/msx;
        my ($status) =
          $text =~ /^[#][#] \s* Status \s*\n+ \s* ([[:alpha:]]+)/msx;
        $title  //= $file;
        $status //= 'Unstated';
        push @rows, "| [$number]($file) | $title | $status |";
    }

    my @gaps =
      grep { !$seen{$_} } 1 .. ( reverse sort { $a <=> $b } keys %seen )[0];
    my $note = q{};
    if (@gaps) {
        $note =
            "\nNumbers "
          . join( q{, }, map { sprintf '%04d', $_ } @gaps )
          . " were never assigned. They are left unused rather than\n"
          . "renumbered, because other documents cite ADRs by number.\n";
    }

    return join "\n",
      '| ADR | Decision | Status |',
      '| --- | --- | --- |',
      @rows, q{},
      'Generated by `script/adr-index` from the files in this'
      . ' directory; `script/adr-index --check` fails when it is stale.'
      . $note;
}

sub _with_index {
    my ( $text, $table ) = @_;

    my $block = "$START\n$table\n$END";
    if ( $text =~ /\Q$START\E .*? \Q$END\E/msx ) {
        $text =~ s/\Q$START\E .*? \Q$END\E/$block/msx;
        return $text;
    }

    return $text . "\n## Index\n\n$block\n";
}

sub _say {
    my ( $handle, $line ) = @_;

    print {$handle} "$line\n" or croak "write: $ERRNO";

    return;
}

sub _slurp {
    my ($path) = @_;

    open my $handle, '<', $path or croak "open $path: $ERRNO";
    local $INPUT_RECORD_SEPARATOR = undef;
    my $text = <$handle>;
    close $handle or croak "close $path: $ERRNO";

    return $text;
}