Compare commits
No commits in common. "ffe113a10c8b184a8b7ea90fbf6b4bc2011cc781" and "3ff7bfd9f303dd870f6e235961729bf565897375" have entirely different histories.
ffe113a10c
...
3ff7bfd9f3
@ -4,16 +4,14 @@ project:
|
|||||||
homepage: https://git.babyl.ca/yanick/App-Changelord
|
homepage: https://git.babyl.ca/yanick/App-Changelord
|
||||||
releases:
|
releases:
|
||||||
- version: ~
|
- version: ~
|
||||||
date: ~
|
|
||||||
changes:
|
changes:
|
||||||
- Initial release
|
- Initial release
|
||||||
- desc: Doing the thing
|
|
||||||
change_types:
|
change_types:
|
||||||
- keywords:
|
- feat:
|
||||||
- feat
|
|
||||||
level: minor
|
level: minor
|
||||||
title: Features
|
title: Features
|
||||||
- keywords:
|
keywords: []
|
||||||
- fix
|
- fix:
|
||||||
level: patch
|
level: patch
|
||||||
title: Bug fixes
|
title: Bug fixes
|
||||||
|
keywords: []
|
||||||
|
@ -1,47 +1,39 @@
|
|||||||
package App::Changelord;
|
package App::Changelord;
|
||||||
# SYNOPSIS: cli-based changelog manager
|
|
||||||
|
|
||||||
# version next latest
|
# version next latest
|
||||||
|
|
||||||
use 5.36.0;
|
use 5.36.0;
|
||||||
|
|
||||||
use Moo;
|
use Moo;
|
||||||
use CLI::Osprey
|
use CLI::Osprey;
|
||||||
desc => 'changelog manager';
|
|
||||||
|
|
||||||
use YAML;
|
use YAML;
|
||||||
|
|
||||||
use List::AllUtils qw/ pairmap partition_by /;
|
use List::AllUtils qw/ pairmap partition_by /;
|
||||||
|
|
||||||
use App::Changelord::Role::ChangeTypes;
|
use App::Changelord::Role::ChangeTypes;
|
||||||
|
|
||||||
|
option source => (
|
||||||
|
is => 'ro',
|
||||||
|
format => 's',
|
||||||
|
doc => 'changelog yaml file',
|
||||||
|
default => 'CHANGELOG.yml',
|
||||||
|
);
|
||||||
|
|
||||||
|
has changelog => ( is => 'lazy' );
|
||||||
|
|
||||||
|
sub _build_changelog($self) {
|
||||||
|
return YAML::LoadFile($self->source)
|
||||||
|
}
|
||||||
|
|
||||||
|
with 'App::Changelord::Role::ChangeTypes';
|
||||||
|
with 'App::Changelord::Role::Render';
|
||||||
|
|
||||||
sub run($self) {
|
sub run($self) {
|
||||||
App::Changelord::Command::Print->new(
|
no warnings 'utf8';
|
||||||
parent_command => $self,
|
print $self->as_markdown;
|
||||||
)->run;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subcommand $_ => 'App::Changelord::Command::' . ucfirst $_ =~ s/-(.)/uc $1/er
|
subcommand $_ => 'App::Changelord::Command::' . ucfirst $_ =~ s/-(.)/uc $1/er
|
||||||
for qw/ schema validate version bump init add git-gather print /;
|
for qw/ schema validate version bump init add git-gather /;
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
__END__
|
|
||||||
|
|
||||||
=head1 DESCRIPTION
|
|
||||||
|
|
||||||
C<App::Changelord> offers a collection of cli commands to
|
|
||||||
interact with a YAML-based CHANGELOG file format, from which
|
|
||||||
a Markdown CHANGELOG fit for general comsumption can be generated.
|
|
||||||
|
|
||||||
See the original blog entry in the C<SEE ALSO> section for the full
|
|
||||||
motivation.
|
|
||||||
|
|
||||||
For a list of the commands, C<changelord --help>, then to
|
|
||||||
get information on the individual commands C<changelord *subcommand* --man>.
|
|
||||||
|
|
||||||
=head1 SEE ALSO
|
|
||||||
|
|
||||||
L<Changelord, registrar of deeds extraordinaire|https://techblog.babyl.ca/entry/changelord> - the introducing blog entry.
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,17 +3,15 @@ package App::Changelord::Command::Add;
|
|||||||
use 5.36.0;
|
use 5.36.0;
|
||||||
|
|
||||||
use Moo;
|
use Moo;
|
||||||
use CLI::Osprey
|
use CLI::Osprey desc => 'add a change to the changelog';
|
||||||
desc => 'add a change to the NEXT release',
|
|
||||||
description_pod => <<'END';
|
|
||||||
Add a change entry to the NEXT release.
|
|
||||||
END
|
|
||||||
|
|
||||||
use PerlX::Maybe;
|
use PerlX::Maybe;
|
||||||
use Path::Tiny;
|
use Path::Tiny;
|
||||||
use App::Changelord::Command::Init;
|
use App::Changelord::Command::Init;
|
||||||
|
|
||||||
with 'App::Changelord::Role::Changelog';
|
has changelog => ( is => 'lazy' );
|
||||||
|
|
||||||
|
sub _build_changelog ($self) { $self->parent_command->changelog }
|
||||||
|
|
||||||
# TODO validate the type
|
# TODO validate the type
|
||||||
option type => (
|
option type => (
|
||||||
@ -50,7 +48,7 @@ sub next_release($self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub save_changelog($self) {
|
sub save_changelog($self) {
|
||||||
my $src = $self->source;
|
my $src = $self->parent_command->source;
|
||||||
|
|
||||||
path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) );
|
path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) );
|
||||||
}
|
}
|
||||||
@ -65,8 +63,6 @@ sub run ($self) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$self->save_changelog;
|
$self->save_changelog;
|
||||||
|
|
||||||
say "change added to the changelog";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
'end of App::Changelog::Command::Add';
|
'end of App::Changelog::Command::Add';
|
||||||
|
@ -3,11 +3,7 @@ package App::Changelord::Command::Bump;
|
|||||||
use 5.36.0;
|
use 5.36.0;
|
||||||
|
|
||||||
use Moo;
|
use Moo;
|
||||||
use CLI::Osprey desc => 'bump next version',
|
use CLI::Osprey desc => 'bump next version';
|
||||||
description_pod => <<'END';
|
|
||||||
Set a version for the NEXT release based on the types of its changes.
|
|
||||||
Also set the release date of that release to today.
|
|
||||||
END
|
|
||||||
|
|
||||||
use Path::Tiny;
|
use Path::Tiny;
|
||||||
use JSON;
|
use JSON;
|
||||||
@ -15,11 +11,15 @@ use YAML qw/ Bless /;
|
|||||||
use List::AllUtils qw/ first min uniq /;
|
use List::AllUtils qw/ first min uniq /;
|
||||||
use Version::Dotted::Semantic;
|
use Version::Dotted::Semantic;
|
||||||
|
|
||||||
with 'App::Changelord::Role::Changelog';
|
|
||||||
with 'App::Changelord::Role::ChangeTypes';
|
with 'App::Changelord::Role::ChangeTypes';
|
||||||
|
|
||||||
|
has changelog => ( is => 'lazy' );
|
||||||
|
|
||||||
with 'App::Changelord::Role::Versions';
|
with 'App::Changelord::Role::Versions';
|
||||||
with 'App::Changelord::Role::Stats';
|
with 'App::Changelord::Role::Stats';
|
||||||
|
|
||||||
|
sub _build_changelog ($self) { $self->parent_command->changelog }
|
||||||
|
|
||||||
sub run ($self) {
|
sub run ($self) {
|
||||||
my $bump = shift @ARGV;
|
my $bump = shift @ARGV;
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ sub run ($self) {
|
|||||||
Bless($_)->keys( [ uniq qw/ version date changes /, sort keys %$_ ] );
|
Bless($_)->keys( [ uniq qw/ version date changes /, sort keys %$_ ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
path( $self->source )->spew( YAML::Dump($change) );
|
path( $self->parent_command->source )->spew( YAML::Dump($change) );
|
||||||
|
|
||||||
say "new version minted: $version";
|
say "new version minted: $version";
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,10 @@ END_POD
|
|||||||
use Path::Tiny;
|
use Path::Tiny;
|
||||||
use Git::Repository;
|
use Git::Repository;
|
||||||
|
|
||||||
with 'App::Changelord::Role::Changelog';
|
has changelog => ( is => 'lazy' );
|
||||||
|
|
||||||
|
sub _build_changelog ($self) { $self->parent_command->changelog }
|
||||||
|
|
||||||
with 'App::Changelord::Role::Versions';
|
with 'App::Changelord::Role::Versions';
|
||||||
with 'App::Changelord::Role::ChangeTypes';
|
with 'App::Changelord::Role::ChangeTypes';
|
||||||
|
|
||||||
@ -66,7 +69,7 @@ sub _build_commit_regex($self) {
|
|||||||
|
|
||||||
sub lower_bound($self) {
|
sub lower_bound($self) {
|
||||||
# either the most recent commit in the current release
|
# either the most recent commit in the current release
|
||||||
my @sha1s = grep { $_ } map { $_->{commit} } grep { ref } $self->next_release->{changes}->@*;
|
my @sha1s = grep { $_ } map { $_->{commit} } $self->next_release->{changes}->@*;
|
||||||
|
|
||||||
return pop @sha1s if @sha1s;
|
return pop @sha1s if @sha1s;
|
||||||
|
|
||||||
@ -89,7 +92,7 @@ sub munge_message($self,$message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub save_changelog($self) {
|
sub save_changelog($self) {
|
||||||
my $src = $self->source;
|
my $src = $self->parent_command->source;
|
||||||
|
|
||||||
path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) );
|
path($src)->spew( App::Changelord::Command::Init::serialize_changelog($self) );
|
||||||
}
|
}
|
||||||
@ -101,7 +104,7 @@ sub run ($self) {
|
|||||||
# figure out lower bound
|
# figure out lower bound
|
||||||
my $from = $self->lower_bound;
|
my $from = $self->lower_bound;
|
||||||
|
|
||||||
say "checking since ", ( $from || 'the dawn of time' );
|
say "checking from ", ( $from || 'the dawn of time' ), " on";
|
||||||
|
|
||||||
my @messages = map { $self->munge_message($_) } $self->get_commits($from);
|
my @messages = map { $self->munge_message($_) } $self->get_commits($from);
|
||||||
|
|
||||||
@ -118,7 +121,7 @@ sub run ($self) {
|
|||||||
|
|
||||||
$self->save_changelog;
|
$self->save_changelog;
|
||||||
|
|
||||||
say $self->source, " updated";
|
say $self->parent_command->source, " updated";
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -12,9 +12,13 @@ use List::AllUtils qw/ first min uniq /;
|
|||||||
use Version::Dotted::Semantic;
|
use Version::Dotted::Semantic;
|
||||||
|
|
||||||
with 'App::Changelord::Role::ChangeTypes';
|
with 'App::Changelord::Role::ChangeTypes';
|
||||||
with 'App::Changelord::Role::Changelog';
|
|
||||||
|
has changelog => ( is => 'lazy' );
|
||||||
|
|
||||||
with 'App::Changelord::Role::Versions';
|
with 'App::Changelord::Role::Versions';
|
||||||
|
|
||||||
|
sub _build_changelog ($self) { $self->parent_command->changelog }
|
||||||
|
|
||||||
sub serialize_changelog($self, $changelog = undef) {
|
sub serialize_changelog($self, $changelog = undef) {
|
||||||
|
|
||||||
$changelog //= $self->changelog;
|
$changelog //= $self->changelog;
|
||||||
@ -38,7 +42,7 @@ sub serialize_changelog($self, $changelog = undef) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub run ($self) {
|
sub run ($self) {
|
||||||
my $src = $self->source;
|
my $src = $self->parent_command->source;
|
||||||
die "file '$src' already exists, aborting\n" if -f $src;
|
die "file '$src' already exists, aborting\n" if -f $src;
|
||||||
|
|
||||||
my $change = {
|
my $change = {
|
||||||
@ -47,7 +51,7 @@ sub run ($self) {
|
|||||||
homepage => undef,
|
homepage => undef,
|
||||||
with_stats => 'true',
|
with_stats => 'true',
|
||||||
ticket_url => undef,
|
ticket_url => undef,
|
||||||
commit_regex => q/^(?<type>[^: ]+):(?<desc>.*?)(\[(?<ticket>[^\]]+)\])?$/,
|
commit_regex => /^(?<type>[^:]+):(?<desc>.*?)(\[(?<ticket>[^\]]+)\])?$/,
|
||||||
},
|
},
|
||||||
change_types => $self->change_types,
|
change_types => $self->change_types,
|
||||||
releases => [
|
releases => [
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
package App::Changelord::Command::Print;
|
|
||||||
|
|
||||||
use 5.36.0;
|
|
||||||
|
|
||||||
use Moo;
|
|
||||||
use CLI::Osprey
|
|
||||||
desc => 'print the changelog',
|
|
||||||
description_pod => <<'END';
|
|
||||||
Render the full changelog. The default is to render the changelog
|
|
||||||
in markdow, but the option C<--json> can be used to have a JSON
|
|
||||||
version instead.
|
|
||||||
|
|
||||||
To generate the changelog without the NEXT release, uses the
|
|
||||||
C<--no-next> option.
|
|
||||||
END
|
|
||||||
|
|
||||||
with 'App::Changelord::Role::Changelog';
|
|
||||||
with 'App::Changelord::Role::ChangeTypes';
|
|
||||||
with 'App::Changelord::Role::Render';
|
|
||||||
|
|
||||||
option json => (
|
|
||||||
is => 'ro',
|
|
||||||
default => 0,
|
|
||||||
doc => 'output schema as json',
|
|
||||||
);
|
|
||||||
|
|
||||||
option next => (
|
|
||||||
is => 'ro',
|
|
||||||
default => 1,
|
|
||||||
negatable => 1,
|
|
||||||
doc => 'include the NEXT release. Defaults to true.',
|
|
||||||
);
|
|
||||||
|
|
||||||
sub run($self) {
|
|
||||||
no warnings 'utf8';
|
|
||||||
print $self->as_markdown( $self->next );
|
|
||||||
}
|
|
||||||
|
|
||||||
'end of App::Changelog::Command::Print';
|
|
@ -4,14 +4,7 @@ package App::Changelord::Command::Schema;
|
|||||||
use 5.36.0;
|
use 5.36.0;
|
||||||
|
|
||||||
use Moo;
|
use Moo;
|
||||||
use CLI::Osprey
|
use CLI::Osprey;
|
||||||
doc => 'print JSON schema for the changelog format',
|
|
||||||
description_pod => <<'END';
|
|
||||||
Print the JSON schema describing the data format used by changelord.
|
|
||||||
|
|
||||||
By defaults prints the schema in YAML. Can also be printed as JSON
|
|
||||||
via the C<--json> option.
|
|
||||||
END
|
|
||||||
|
|
||||||
use Path::Tiny;
|
use Path::Tiny;
|
||||||
use JSON;
|
use JSON;
|
||||||
|
@ -3,19 +3,13 @@ package App::Changelord::Command::Validate;
|
|||||||
use 5.36.0;
|
use 5.36.0;
|
||||||
|
|
||||||
use Moo;
|
use Moo;
|
||||||
use CLI::Osprey
|
use CLI::Osprey;
|
||||||
doc => 'validate the changelog yaml',
|
|
||||||
description_pod => <<'END';
|
|
||||||
Validate the changelog against the JSON Schema used by changelord.
|
|
||||||
END
|
|
||||||
|
|
||||||
use Path::Tiny;
|
use Path::Tiny;
|
||||||
use JSON;
|
use JSON;
|
||||||
use YAML::XS;
|
use YAML::XS;
|
||||||
use JSON::Schema::Modern;
|
use JSON::Schema::Modern;
|
||||||
|
|
||||||
with 'App::Changelord::Role::Changelog';
|
|
||||||
|
|
||||||
option json => (
|
option json => (
|
||||||
is => 'ro',
|
is => 'ro',
|
||||||
default => 0,
|
default => 0,
|
||||||
@ -30,7 +24,7 @@ sub run($self) {
|
|||||||
my $result = JSON::Schema::Modern->new(
|
my $result = JSON::Schema::Modern->new(
|
||||||
output_format => 'detailed',
|
output_format => 'detailed',
|
||||||
)->evaluate(
|
)->evaluate(
|
||||||
$self->changelog,
|
$self->parent_command->changelog,
|
||||||
YAML::XS::Load($schema),
|
YAML::XS::Load($schema),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -13,9 +13,38 @@ use YAML::XS;
|
|||||||
use List::AllUtils qw/ first min /;
|
use List::AllUtils qw/ first min /;
|
||||||
use Version::Dotted::Semantic;
|
use Version::Dotted::Semantic;
|
||||||
|
|
||||||
with 'App::Changelord::Role::Changelog';
|
|
||||||
with 'App::Changelord::Role::ChangeTypes';
|
with 'App::Changelord::Role::ChangeTypes';
|
||||||
with 'App::Changelord::Role::Versions';
|
|
||||||
|
has changelog => (
|
||||||
|
is => 'lazy'
|
||||||
|
);
|
||||||
|
|
||||||
|
sub _build_changelog($self){ $self->parent_command->changelog }
|
||||||
|
|
||||||
|
sub latest_version($self){
|
||||||
|
first { $_ } grep { $_ ne 'NEXT' } map { eval { $_->{version} } } $self->changelog->{releases}->@*;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub next_version($self) {
|
||||||
|
my $version = Version::Dotted::Semantic->new($self->latest_version // '0.0.0');
|
||||||
|
|
||||||
|
my $upcoming = $self->changelog->{releases}[0];
|
||||||
|
|
||||||
|
if( $upcoming->{version} and $upcoming->{version} ne 'NEXT') {
|
||||||
|
$upcoming = { changes => [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
my %mapping = map {
|
||||||
|
my $level = $_->{level};
|
||||||
|
map { $_ => $level } $_->{keywords}->@*
|
||||||
|
} $self->change_types->@*;
|
||||||
|
|
||||||
|
my $bump =min 2, map { $_ eq 'major' ? 0 : $_ eq 'minor' ? 1 : 2 } map { $mapping{$_->{type}} || 'patch' } $upcoming->{changes}->@*;
|
||||||
|
|
||||||
|
$version->bump($bump);
|
||||||
|
|
||||||
|
return $version->normal;
|
||||||
|
}
|
||||||
|
|
||||||
sub run($self) {
|
sub run($self) {
|
||||||
my $param = shift @ARGV;
|
my $param = shift @ARGV;
|
||||||
|
@ -42,14 +42,12 @@ properties:
|
|||||||
- type: object
|
- type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
version: { type: [ 'null', string ] }
|
version: { type: string }
|
||||||
date: { type: ['null',string] }
|
date: { type: ['null',string] }
|
||||||
changes: { type: 'array', items: { $ref: '#/$defs/change' } }
|
changes: { type: 'array', items: { $ref: '#/$defs/change' } }
|
||||||
$defs:
|
$defs:
|
||||||
change:
|
change:
|
||||||
oneOf:
|
type: object
|
||||||
- type: string
|
|
||||||
- type: object
|
|
||||||
required: [ desc ]
|
required: [ desc ]
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package App::Changelord::Role::Changelog;
|
|
||||||
|
|
||||||
use v5.36.0;
|
|
||||||
|
|
||||||
use Moo::Role;
|
|
||||||
use CLI::Osprey;
|
|
||||||
|
|
||||||
option source => (
|
|
||||||
is => 'ro',
|
|
||||||
format => 's',
|
|
||||||
doc => q{changelog yaml file. Defaults to the env variable $CHANGELOG, or 'CHANGELOG.yml'},
|
|
||||||
default => $ENV{CHANGELOG} || 'CHANGELOG.yml',
|
|
||||||
);
|
|
||||||
|
|
||||||
has changelog => ( is => 'lazy' );
|
|
||||||
|
|
||||||
sub _build_changelog($self) {
|
|
||||||
return YAML::LoadFile($self->source)
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
|
@ -40,18 +40,14 @@ sub render_refs ( $self, %links ) {
|
|||||||
return $output . "\n";
|
return $output . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub as_markdown ($self, $with_next = 1) {
|
sub as_markdown ($self) {
|
||||||
my $changelog = $self->changelog;
|
my $changelog = $self->changelog;
|
||||||
|
|
||||||
my $output = $self->render_header;
|
my $output = $self->render_header;
|
||||||
|
|
||||||
my $n = 0;
|
my $n = 0;
|
||||||
$output .= join "\n",
|
$output .= join "\n",
|
||||||
map { $self->render_release( $_, $n++ ) }
|
map { $self->render_release( $_, $n++ ) } $changelog->{releases}->@*;
|
||||||
grep {
|
|
||||||
$with_next ? 1 : ( $_->{version} && $_->version ne 'NEXT' )
|
|
||||||
}
|
|
||||||
$changelog->{releases}->@*;
|
|
||||||
|
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use feature 'try';
|
|||||||
requires 'changelog';
|
requires 'changelog';
|
||||||
|
|
||||||
sub latest_version($self){
|
sub latest_version($self){
|
||||||
first { $_ } grep { $_ ne 'NEXT' } map { eval { $_->{version} || '' } } $self->changelog->{releases}->@*, { version => 'v0.0.0' };
|
first { $_ } grep { $_ ne 'NEXT' } map { eval { $_->{version} } } $self->changelog->{releases}->@*;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub next_version($self) {
|
sub next_version($self) {
|
||||||
@ -29,10 +29,7 @@ sub next_version($self) {
|
|||||||
map { $_ => $level } $_->{keywords}->@*
|
map { $_ => $level } $_->{keywords}->@*
|
||||||
} $self->change_types->@*;
|
} $self->change_types->@*;
|
||||||
|
|
||||||
no warnings;
|
my $bump =min 2, map { $_ eq 'major' ? 0 : $_ eq 'minor' ? 1 : 2 } map { $mapping{$_->{type}} || 'patch' } $upcoming->{changes}->@*;
|
||||||
my $bump =min 2, map { $_ eq 'major' ? 0 : $_ eq 'minor' ? 1 : 2 } map { $mapping{$_->{type}} || 'patch' }
|
|
||||||
map { ref ? $_ : { desc => $_ } }
|
|
||||||
$upcoming->{changes}->@*;
|
|
||||||
|
|
||||||
$version->bump($bump);
|
$version->bump($bump);
|
||||||
|
|
||||||
|
@ -2,9 +2,9 @@ use 5.36.0;
|
|||||||
|
|
||||||
use Test2::V0;
|
use Test2::V0;
|
||||||
|
|
||||||
use App::Changelord::Command::Print;
|
use App::Changelord;
|
||||||
|
|
||||||
my $change = App::Changelord::Command::Print->new(
|
my $change = App::Changelord->new(
|
||||||
changelog => {
|
changelog => {
|
||||||
project => { name => 'Foo' },
|
project => { name => 'Foo' },
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user