=begin pod

=head1 NAME

Zef::Configuration - Manipulate Zef configurations

=head1 SYNOPSIS

=begin code :lang<raku>
use Zef::Configuration;

my $zc = Zef::Configuration.new;         # factory settings

my $zc = Zef::Configuration.new(:user);  # user settings

my $zc = Zef::Configuration.new($io);    # from a config file path
=end code

Or use the command-line interface:

=begin output
$ zef-configure

$ zef-configure enable something

$ zef-configure disable something

$ zef-configure reset
=end output

=head1 DESCRIPTION

Zef::Configuration is a class that allows you to manipulate the configuration
of Zef programmatically.  Perhaps more importantly, it provides a command-line
script C<zef-configure> that allows you to perform simple actions to Zef's
config-files.

=head1 COMMAND-LINE INTERFACE

=head2 General named arguments

=head3 config-path

=begin output
$ zef-configure --config-path=~/.zef/config.json
=end output

The C<config-path> named argument can be used to indicate the location
of the configuration to read from / write to.

=head3 dry-run

=begin output
$ zef-configure enable rea --dry-run
=end output

The C<dry-run> named argument can be used to inhibit writing any changes
to the configuration file.

=head2 Possible actions

The C<zef-configure> script that is installed with this module, allows for
the following actions.  Please note that sub-commands (such as "enable")
can be shortened as long as they are not ambiguous..

=head2 Getting an overview

=begin output
$ zef-configure
=end output

Calling C<zef-configure> without any parameters (except maybe the
C<config-path> parameter) will show an overview of all the settings in
the configuration.  The names shown can be used to indicate what part
of the configuration you want changed.

=head2 Enabling a setting

=begin output
$ zef-configure enable rea
=end output

If a setting is disabled, then you can enable it with the C<enable>
directive, followed by the name of the setting you want enabled.

=head2 Disabling a setting

=begin output
$ zef-configure disable cpan
=end output

If a setting is enabled, then you can disable it with the C<disable>
directive, followed by the name of the setting you want disabled.

=head2 Reset to factory settings

=begin output
$ zef-configure reset
=end output

To completely reset a configuration to the "factory" settings, you can
use the C<reset> directive.

=begin output
$ zef-configure reset --config-path=~/.zef/config.json
=end output

You can also use this function in combination with C<config-=path> to
create a configuration file with the "factory" settings.

=head1 GENERAL NOTES

All of the attributes of the classes provided by this distribution, are
either an C<Array> (and thus mutable), or a an attribute with the C<is rw>
trait applied to it.  This is generally ok, since it is expected that this
module will mostly only be used by a relatively short-lived CLI.

Note that if you change an object that is based on one of the default objects,
you will be changing the default as well.  This may or may not be what you
want.  If it is not, then you should probably first create a C<clone> of
the object, or use the C<clone> method with named arguments to create a
clone with changed values.

=head1 METHODS ON ALL CLASSES

All of these classes provided by this distribution provide these methods
(apart from the standard methods provided by Raku).

=head3 new

Apart from the normal way of creating objects with named arguments, one can
also specify a hash as returned with C<data> to create an object.

=head3 data

Return a Raku data-structure for the object.  This is usually a C<Map>, but
can also be a C<List>.

=head3 json

Return a pretty JSON string with sorted keys for the object.  Takes named
parameters C<:!pretty> and C<:!sorted-keys> should you not want the JSON
string to be pretty, or have sorted keys.

=head3 status

Return a string describing the status of the object.

=head1 METHODS ON MOST CLASSES

With the exception of the C<Zef::Configuration>, C<Zef::Configuration::License>
and C<Zef::Configuration::RepositoryGroup> classes, the following attributes /
methods are always provided.

=head3 short-name

A name identifying the object.  B<Must> be specified in the creation of the
object.

=head3 module

The name of the Raku module to be used by this object.  B<Must> be specified
in the creation of the object unless there is a default available for the
given object.

=head3 enabled

A boolean indicating whether the object is enabled.  Defaults to C<True>.

=head3 comment

Any comments applicable to this object.  Defaults to the C<Str> type object.

=head1 Zef::Configuration

The C<Zef::Configuration> class contains all information about a configuration
of C<Zef>.  A C<Zef::Configuration> object can be made in 6 different ways:

=head2 CREATION

=begin code :lang<raku>
my $zc = Zef::Configuration.new;         # "factory settings"

my $zc = Zef::Configuration.new(:user);  # from the user's Zef config

my $zc = Zef::Configuration.new($io);    # from a file as an IO object

my $zc = Zef::Configuration.new($json);  # a string containing JSON

my $zc = Zef::Configuration.new(%hash);  # a hash, as decoded from JSON

my $zc = Zef::Configuration.new:         # named arguments to set attributes
  ConfigurationVersion => 2,
  RootDir              => 'foo/bar',
  ...
;
=end code

=head2 ATTRIBUTES / METHODS

It contains the following attributes / methods:

=head3 ConfigurationVersion

The version of the configuration.  Defaults to C<1>.

=head3 RootDir

The directory in which Zef keeps all of its information.  Defaults to
C<$*HOME/.zef>.

=head3 StoreDir

The directory in which Zef keeps all of the information that has been
downloaded.  Defaults to C<RootDir ~ "/store">.

=head3 TempDir

The directory in which Zef stores temporary files.  Defaults to
C<RootDir ~ "/tmp">.

=head3 License

A C<Zef::Configuration::License> object.  Defaults to
C<Zef::Configuration.default-licenses<default>>.

=head3 Repository

An array of C<Zef::Configuration::RepositoryGroup> objects in the order in
which they will be checked when searching for distributions.  Defaults to
C<Zef::Configuration.default-repository-groups> in the order: C<primary>,
C<secondary>, C<tertiary>, C<last>.

=head3 Fetch

An array of C<Zef::Configuration::Fetch> objects.  Defaults to
C<Zef::Configuration.default-fetch>.

=head3 Extract

An array of C<Zef::Configuration::Extract> objects.  Defaults to
C<Zef::Configuration.default-extract>.

=head3 Build

An array of C<Zef::Configuration::Build> objects.  Defaults to
C<Zef::Configuration.default-build>.

=head3 Test

An array of C<Zef::Configuration::Test> objects.  Defaults to
C<Zef::Configuration.default-test>.

=head3 Report

An array of C<Zef::Configuration::Report> objects.  Defaults to
C<Zef::Configuration.default-report>.

=head3 Install

An array of C<Zef::Configuration::Install> objects.  Defaults to
C<Zef::Configuration.default-install>.

=head3 DefaultCUR

An array of strings indicating which C<CompUnitRepository>(s) to be used when
installing a module.  Defaults to C<Zef::Configuration.default-defaultCUR>.

=head2 ADDITIONAL CLASS METHODS

=head3 is-configuration-writeable

Class method that takes an C<IO::Path> of a configuration file (e.g. as
returned by C<user-configuration>) and returns whether that file is safe
to write to (files part of the installation should not be written to).

=head3 new-user-configuration

Class method that returns an C<IO::Path> with location at which a new
configuration file can be stored, to be visible with future default
incantations of Zef.  Returns C<Nil> if no such location could be found.

=head3 user-configuration

Class method that returns an C<IO::Path> object of the configuration file
that Zef is using by default.

=head2 ADDITIONAL INSTANCE METHODS

=head3 default-...

Instance methods for getting the default state of a given aspect of the
C<Zef::Configuration> object.

=item default-license
=item default-repository
=item default-repositorygroup
=item default-fetch
=item default-extract
=item default-build
=item default-test
=item default-report
=item default-install
=item default-defaultCUR

Each of these can either called without any arguments: in that case a C<Map>
will be returned with each of the applicable objects, associated with a
B<tag>.  Or it can be called with one of the valid tags, in which case the
associated object will be returned.

=head3 object-from-tag

Instance method that allows selection of an object by its tag (usually the
C<short-name>) in one of the attributes of the C<Zef::Configuration> object.

Tags can be specified just by themselves if they are not ambiguous, else
the group name should be prefixed with a hyphen inbetween (e.g.
C<license-default>).

If an ambiguous tag is given, then a C<List> of C<Pair>s will be returned in
which the key is a group name, and the value is the associated object.

If only one object was found, then that will be returned.  If no objects
were found, then C<Nil> will be returned.

=head2 Zef::Configuration::License

Contains which licenses are C<blacklist>ed and which ones are C<whitelist>ed.
Defaults to no blacklisted licenses, and C<"*"> in the whitelist, indicating
that any license will be acceptable.  Does not contain any other information.

=head2 Zef::Configuration::Repository

Contains the information about a repository in which distributions are
located.  It provided these additional attributes / methods:

=head3 name

The full name of the repository.  Defaults to the C<short-name>.

=head3 module

The Raku module to be used for handling the C<Zef::Configuration::Repository>
defaults to C<Zef::Repository::Ecosystems>.

=head3 auto-update

The number of hours that should pass until a local copy of the distribution
information about a repository should be considered stale.  Defaults to C<1>.

=head3 uses-path

A boolean indicating whether the C<path> field in the distribution should be
used to obtain a distribution.  Defaults to C<False>, unless the repository's
C<short-name> equals C<zef>.

=head3 mirrors

An array of URLs that should be used to fetch the information about all the
distributions in the repository. B<Must> be specified with the URL of at
least one mirror if C<auto-update> has been (implicitely) set to a non-zero
value.

=head2 Zef::Configuration::RepositoryGroup

Contains a list of C<Zef::Configuration::Repository> objects in the order in
which a search should be done for modules.  Does not contain any other
information.

=head2 Zef::Configuration::Fetch

Information on how to fetch a distribution from a
C<Zef::Configuration::Repository>.

=head2 Zef::Configuration::Extract

Information on how to extract information from a fetched distribution.

=head2 Zef::Configuration::Build

Information on how to build modules from a fetched distribution.

=head2 Zef::Configuration::Test

Information on how to perform tesing on a fetched distribution.

=head2 Zef::Configuration::Report

Information about how a report of a distribution test should be reported.

=head2 Zef::Configuration::Install

Information about how a distribution should be installed.

=head1 AUTHOR

Elizabeth Mattijsen <liz@raku.rocks>

Source can be located at: https://github.com/lizmat/Zef-Configuration .
Comments and Pull Requests are welcome.

If you like this module, or what I’m doing more generally, committing to a
L<small sponsorship|https://github.com/sponsors/lizmat/>  would mean a great
deal to me!

=head1 COPYRIGHT AND LICENSE

Copyright 2022, 2023, 2024, 2025, 2026 Elizabeth Mattijsen

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

=end pod

# vim: expandtab shiftwidth=4
