Config::GitLike(3pm)
๐ Config::GitLike(3pm) ๐
โจ NAME โจ
Config::GitLike โ git-compatible config file parsing ๐
๐ฆ SYNOPSIS ๐ฆ
okay so, this module parses git-style config files, and they look like this:
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = spang.cc:/srv/git/home.git
fetch = +refs/heads/*:refs/remotes/origin/*
[another-section "subsection"]
key = test
key = multiple values are OK
emptyvalue =
novalue
Code that uses this config module might look like this:
use Config::GitLike;
# just load a specific file
my $data = Config::GitLike->load_file("~/.fooconf");
# or use the object interface to load /etc/config, ~/.config, and
# `pwd`/.config
my $c = Config::GitLike->new(confname => 'config');
$c->get( key => 'section.name' );
# make the return value a Perl true/false value
$c->get( key => 'core.filemode', as => 'bool' );
# replace the old value
$c->set(
key => 'section.name',
value => 'val1',
filename => '/home/user/.config',
);
# make this key have multiple values rather than replacing the
# old value
$c->set(
key => 'section.name',
value => 'val2',
filename => '/home/user/.config',
multiple => 1,
);
# replace all occurrences of the old value for section.name with a new one
$c->set(
key => 'section.name',
value => 'val3',
filename => '/home/user/.config',
multiple => 1,
replace_all => 1,
);
# make sure to reload the config files before reading if you've set
# any variables!
$c->load;
# get only the value of 'section.name' that matches '2'
$c->get( key => 'section.name', filter => '2' );
$c->get_all( key => 'section.name' );
# prefixing a search regexp with a ! negates it
$c->get_regexp( key => '!na' );
$c->rename_section(
from => 'section',
to => 'new-section',
filename => '/home/user/.config'
);
$c->remove_section(
section => 'section',
filename => '/home/user/.config'
);
# unsets all instances of the given key
$c->set( key => 'section.name', filename => '/home/user/.config' );
my %config_vals = $config->dump;
# string representation of config data
my $str = $config->dump;
# prints rather than returning
$config->dump;
๐ธ DESCRIPTION ๐ธ
So Config::GitLike handles interaction with configuration files of the style used by the version control system Git. It can both parse and modify these files, as well as create entirely new ones. โจ
You only need to know a few things about the configuration format in order to use this module. First, a configuration file is made up of key/value pairs. Every key must be contained in a section. Sections can have subsections, but they don't have to. For the purposes of setting and getting configuration variables, we join the section name, subsection name, and variable name together with dots to get a key name that looks like "section.subsection.variable". These are the strings that you'll be passing in to key arguments. ๐
Configuration files inherit from each other. By default, Config::GitLike loads data from a system-wide configuration file, a per-user configuration file, and a per-directory configuration file, but by subclassing and overriding methods you can obtain any combination of configuration files. By default, configuration files that don't exist are just skipped. ๐ซถ
See http://www.kernel.org/pub/software/scm/git/docs/git-config.html#_configuration_file for details on the syntax of git configuration files. We won't waste pixels on the nitty gritty here. ๐
While the behavior of a couple of this module's methods differ slightly from the git config equivalents, this module can read any config file written by git. The converse is usually true, but only if you don't take advantage of this module's increased permissiveness when it comes to key names. (See "DIFFERENCES FROM GIT-CONFIG" for details.) ๐
This is an object-oriented module using Moo. All subroutines are object method calls. Periodt.
A few methods have parameters that are always used for the same purpose:
๐ Filenames ๐
All methods that change things in a configuration file require a filename to write to, via the filename parameter. Since a Config::GitLike object can be working with multiple config files that inherit from each other, we don't try to figure out which one to write to automatically and let you specify instead. ๐
โจ Casting โจ
All get and set methods can make sure the values they're returning or setting are valid values of a certain type: bool, int, num, or bool-or-int (or at least as close as Perl can get to having these types). Do this by passing one of these types in via the as parameter. The set method, if told to write bools, will always write true or false (not anything else that cast considers a valid bool). ๐ฅ
Methods that are told to cast values will throw exceptions if the values they're trying to cast aren't valid values of the given type. ๐ญ
See the cast method documentation for more on what is considered valid for each type. ๐
๐ Filtering ๐
All get and set methods can filter what values they return via their filter parameter, which is expected to be a string that is a valid regex. If you want to filter items OUT instead of IN, you can prefix your regex with a ! and that will do the trick. ๐
Now, on the the methods! ๐
๐ MAIN METHODS ๐
okay bestie, these are the ones you're gonna be living in. the main-character methods, if you will ๐
๐ธ new( confname => 'config', encoding => 'UTF-8' )
spawns a brand-new config object, and it's named after the base config name confname. if all you wanna do is load one specific file โ like, no automatic global file, no per-user file, no per-directory file โ then skip this and go look at load_file down below, iykyk.
confname is what gets used to build the filenames that'll be loaded. the defaults are these three girlies:
/etc/confnameโ the global configuration file~/.confnameโ the user configuration file<Cwd"/.confname>โ the directory configuration file
you can override all of those defaults by subclassing Config::GitLike and overriding the methods global_file, user_file, and dir_file. (peep "METHODS YOU MAY WISH TO OVERRIDE" for the deets โจ)
if you wanna strictly enforce that you can only read/write config files that git itself could read or write, pass in compatible => 1 to this constructor. lowkey important: the default rules for some parts of the config file are more permissive than git's own rules (check "DIFFERENCES FROM GIT-CONFIG" for that whole thing).
and if you know for a fact that your Git config files are encoded with a specific character encoding, pass in encoding => $encoding with the name of that encoding. then Config::GitLike will properly serialize and deserialize the files using that encoding. ngl, config files written with git config are usually in UTF-8 but not required to be. ๐
๐ confname
the config filename you handed over when you made the Config::GitLike object. you can change it if you want, by passing in a new name (and then reloading via load). glow-up available on request ๐
โจ load
usually this one gets called implicitly the very first time you hit get, get_all, get_regex, or dump โ the only reason to call it yourself is if you want to explicitly reload the data.
it loads the global, local, and directory configuration file with the filename confname (if they exist, bestie โ no drama if they don't). config variables loaded later override the ones loaded earlier, which means variables from the directory configuration file have the HIGHEST precedence. main character energy, tbh ๐
pass in an optional path and it gets passed on to load_dirs (which loads the directory config file(s)).
returns a hash copy of all the loaded config data stored in the module once the files are loaded โ or, in scalar context, a hashref to that hash. your pick, queen.
๐ฆ config_files
an array reference holding the absolute filenames of every config file that's currently loaded, in the order they were loaded. receipts, basically ๐งพ
๐ get
Parameters:
key => 'sect.subsect.key'as => 'int'human => 1filter => '!foo'
returns the config value tied to key, cast as whatever you said.
key is required (if you don't specify it, you get undef, sorry bestie); as and human are optional (go check cast for what they actually mean). sections and subsections go in the key separated from the key name by a . character. and get this โ sections, subsections, and keys can ALL be quoted (double or single quotes). versatile ๐
if key isn't in the config, or has no values matching the filter, you get undef. it dies with the exception Multiple values if that key has more than one value matching the filter. (use get_all if you want multiple values, babe.)
it calls load if that hasn't happened yet. but heads up: if you've run any set calls on the loaded config files since the last time they were loaded, you MUST call load again before getting โ otherwise the returned config data may not match the variables actually on-disk. no cap. โ ๏ธ
๐ get_all
Parameters:
key => 'section.sub'as => 'int'human => 1filter => 'regex'
like get, except it does NOT freak out if the number of values for the key isn't exactly one. chill vibes only ๐
returns a list of values (or an arrayref if you're in scalar context).
๐ get_regexp
Parameters:
key => 'regex'as => 'bool'human => 1filter => 'regex'
basically get_all's cousin, but it searches for values based on a key regex instead.
returns a hash of name/value pairs (or a hashref in scalar context).
โญ dump
in scalar context, returns a string with ALL the config data, sorted in ASCII order, looking like this:
section.key=value
section2.key=value
if you call it in void context, it just prints that string instead. and in list context, it returns a hash with all the configuration data. three moods, one method โจ
๐ set
Parameters:
key => 'section.name'value => 'bar'filename => File::Spec->catfile(qw/home user/, '.'.$config->confname)filter => 'regex'as => 'bool'multiple => 1replace_all => 1
sets the key foo in the configuration section section to the value bar in the given filename.
it replaces key's value if key already exists.
to unset a key, pass in key but NOT value.
returns true on success. slay.
if you really need a . character inside your variable name, you can wrap the name in quotes (single or double): key => 'section."foo.bar.com"' โ but honestly? don't do this unless you genuinely have to. like, really really have to. ๐
๐ญ multiple values
by default, set replaces the old value rather than giving a key multiple values. to override that, pass in multiple => 1. and if you want to replace ALL instances of a multiple-valued key with a new value, you ALSO need to pass in replace_all => 1 as well. both, bestie. both. ๐ซถ
๐ธ group_set( $filename, $array_ref )
same as set, except you set a whole group of variables at the same time without writing to disk separately for each one. efficiency queen ๐
$array_ref holds a list of hash references which are basically hashes of arguments to set โ minus the $filename argument, because that one's specified separately and the same file gets used for all the variables being set at once.
๐ง rename_section
Parameters:
from => 'name.subname'to => 'new.subname'filename => '/file/to/edit'
renames the section in filename given by from to the section given by to.
throws an exception No such section if the section in from doesn't actually exist in filename. she will NOT be gaslit into renaming something that isn't there ๐
if you give no value for to, the section gets removed instead of renamed. gone. ghosted.
returns true on success, false if filename didn't exist and the rename therefore did absolutely nothing.
๐ remove_section
Parameters:
section => 'section.subsection'filename => '/file/to/edit'
just a convenience wrapper around rename_section for readability's sake. removes the given section (which, yeah, you could also do by renaming it to nothing). same thing, cuter name. ๐
๐ซถ add_comment
Parameters:
comment => "Begin editing here\n and then stop",filename => '/file/to/edit'indented => 1,semicolon => 0,
drops a comment into the specified configuration file. comment and filename are required โ no exceptions. comments get added to the file with # at the beginning of every line of the comment. pass a true value to semicolon if you'd rather they start with ; instead. and if your comments are indented with leading white space and you want that white space to show up in FRONT of the comment character rather than after it, pass a true value to indented. little details, huge difference โจ
๐ฅ cascade( $bool )
gets or sets whether only the deepest configuration file in a directory tree gets loaded, or whether all of them get loaded, shallowest to deepest. alternately, you can just pass cascade => 1 to new. dealer's choice, bestie.
๐ origins
returns a hash mapping each config key to the file it was loaded from. so you can always find out where something came from โ no mystery, no cap. ๐ต๏ธโโ๏ธ
๐ฆ METHODS YOU MAY WISH TO OVERRIDE ๐ฆ
if your app's config layout is different from the default โ like, say its home directory config files live in a directory inside the home directory (think ~/.git/config) instead of just being dot-prefixed โ then override these methods to return the right directory names. and for fancier stuff, like altering precedence? you're gonna need to override load too. good luck, you got this ๐ช
๐ธ dir_file
returns a string with the path to a configuration file named confname in a directory. call it with no arguments and you get the path for a generic directory; call it with a directory as an argument and you get the path for THAT directory. flexible fr fr.
โจ global_file
returns the string /etc/confname โ the absolute name of the system-wide configuration file named confname.
๐ user_file
returns a string with the path to a configuration file in the current user's home directory, with filename confname.
๐ load_dirs
Parameters:
'/path/to/look/in/'
loads the configuration file with the filename dir_file in the current working directory into memory. or โ if there's no config matching dir_file in the current working directory โ it walks up the directory tree until it finds one. (no error gets thrown if none is found, so like, breathe.) if you pass in an optional path, that directory gets used as the base directory instead of the working directory.
you're gonna wanna use load_file to load config files from your overridden version of this subroutine. iykyk.
returns nothing of note. literally nothing worth mentioning. ๐
โจ OTHER METHODS โจ
Okay so these are the ones that are mostly behind-the-scenes stuff that the other methods use, but bestie, they're still useful so let's not skip them ๐
load_global
If a global configuration file with the absolute name given by global_file exists, it loads its config variables into memory. ๐
Returns the current contents of all the loaded configuration variables after the file has been loaded, or undef if no global config file is found.
load_user
If a configuration file with the absolute name given by user_file exists, it loads its config variables into memory. โจ
Returns the current contents of all the loaded configuration variables after the file has been loaded, or undef if no user config file is found.
load_file( $filename )
Takes a string containing the path to a file, opens it if it exists, loads its config variables into memory, and returns the currently loaded config variables (a hashref). ๐ซถ
This method can also be called as a class method, which will die if the file cannot be read. If you call it as an instance method instead, it returns undef on failure.
This method may also be passed additional key-value parameters which control how the file is loaded:
silentโ defaults to off; if set, it just... returns instead of die'ing when the file can't be found or read. (It's giving "no thoughts, head empty, no drama" ๐ญ)includesโ defaults to on; if you pass it a false value, it ignores theincludedirective.forceโ defaults to off; if set, it will re-load a file even if it was previously loaded. (Yes, we're doing it again, and what about it ๐ )
parse_content
Parameters:
content => 'str'
callback => sub {}
error => sub {}
Parses the given content and runs callbacks as it finds valid information. ๐
Returns undef on success and error($content) (the original content) on failure.
callback is called like:
callback(section => $str, offset => $num, length => $num, name => $str, value => $str)
name and value may be omitted if the callback is not being called on a key/value pair, or if it's being called on a key with no value.
error is called like:
error( content => $content, offset => $offset )
Where offset is the point in the content where the parse error occurred.
If you need to use this method, you might be interested in error_callback as well. ๐
error_callback
Parameters:
content => 'str'
offset => 45
filename => '/foo/bar/.baz'
Made especially for passing to parse_content, passed through the error parameter like this:
error => sub {
error_callback( @_, filename => '/file/you/were/parsing' )
}
It's used internally wherever parse_content is used and it will throw an exception with a super useful message detailing the line number, the position on the line, and the contents of the bad line. If you find the need to use parse_content elsewhere, you may find this useful as well. ๐ฉน
include ( $name )
When reading configuration files, Git versions 1.7.10 and later parse the include.path key as a directive to include an additional configuration file. This option controls the equivalent behavior; setting it to a false value will disable inclusion, and any true value will be taken as the name of the configuration parameter which controls inclusion. Defaults to include.path, as Git does. ๐
set_multiple( $name )
Mark the key string $name as containing multiple values.
Returns nothing. That's it, that's the whole vibe. ๐
is_multiple( $name )
Return a true value if the key string $name contains multiple values; false otherwise. โจ
define
Parameters:
section => 'str'
name => 'str'
value => 'str'
Given a section, a key name, and a value, store this information in memory in the config object. ๐พ
Returns the value that was just defined on success, or undef if no name and section were given and thus the key cannot be defined.
cast
Parameters:
value => 'foo'
as => 'int'
human => 1
Return value cast into the type specified by as. ๐ฎ
Valid values for as are bool, int, num, or bool-or-num. For bool, true, yes, on, 1, and undef are translated into a true value (for Perl); anything else is false. Specifying a true value for the human argument will get you a human-readable 'true' or 'false' rather than a value that plays along with Perl's definition of truthiness (0 or 1).
For ints and nums, if value ends in k, m, or g, it will be multiplied by 1024, 1048576, and 1073741824, respectively, before being returned. ints are truncated after being multiplied, if they have a decimal portion.
bool-or-int, as you might have guessed, gives you either a bool or an int depending on which one applies.
If as is unspecified, value is returned unchanged. ๐
format_section
Parameters:
section => 'section.subsection'
base => 1
Return a string containing the section/subsection header, formatted as it should appear in a config file. If bare is true, the returned value is not followed be a newline. ๐
format_definition
Parameters:
key => 'str'
value => 'str'
bare => 1
Return a string containing the key/value pair as they should be printed in the config file. If bare is true, the returned value is not tab-indented nor followed by a newline.
canonical_case( $name )
Given a full key name, returns the canonical name of the key; this is the key with the section and name lower-cased; the subsection is left as-is. ๐
original_key( $name )
Given a full key name, returns the key as it was last loaded from the file, retaining what ever upper/lower case was used. Note that for multiple-valued keys, this returns an array reference of key names, as each definition may have been provided in a different choice of case. ๐
๐ธ DIFFERENCES FROM GIT-CONFIG ๐ธ
This module does the following things differently from git-config:
- We are much more permissive about valid key names and section names. For variables, instead of limiting variable names to alphanumeric characters and
-, we allow any characters except for=and newlines, including spaces as long as they are not leading or trailing, and.as long as the key name is quoted. For sections, any characters but whitespace,[], and"are allowed. You can enforce reading/writing only git-compatible variable names and section headers by passingcompatible => 1to the constructor. ๐ซถ - When replacing variable values and renaming sections, we merely use a substring replacement rather than writing out new lines formatted in the default manner for new lines. Git's replacement/renaming (as of 1.6.3.2) is currently buggy and loses trailing comments and variables that are defined on the same line as a section being renamed. Our method preserves original formatting and surrounding information. โจ
- We also allow the 'num' type for casting, since in many cases we might want to be more lenient on numbers.
- We truncate decimal numbers that are cast to
ints, whereas Git just rejects them. - We don't support NUL-terminating output (the
--nullflag togit-config). Who needs it? ๐ - Git only supports reading UNIX- and DOS-style newlines (
\nand\r\n), and always uses\nwhen modifying files. We also support reading Mac-style newlines (\r), and write updates to files using the same newlines as they were read with. ๐
๐ BUGS ๐
If you find any bugs in this module, report them at:
http://rt.cpan.org/
Include the version of the module you're using and any relevant problematic configuration files or code snippets. ๐
๐ SEE ALSO ๐
- <http://www.kernel.org/pub/software/scm/git/docs/git-config.html#_configuration_file>,
Config::GitLike::Git,- <http://syncwith.us/> ("
Config::GitLike" is used in Prophet/SD and provides a working example)
๐ LICENSE ๐
This program is free software; you may modify and/or redistribute it under the same terms as Perl itself. ๐ซถ
ยฉ๏ธ COPYRIGHT ยฉ๏ธ
Copyright 2010 Best Practical Solutions, LLC
๐ AUTHORS ๐
Alex Vandiver <alexmv@bestpractical.com>, Christine Spang <spang@bestpractical.com>
and that's a wrap bestie ๐ this whole thing is perl v5.36.0, dated 2022-10-16, straight out of the Config::GitLike(3pm) part of your friendly neighborhood User Contributed Perl Documentation. go forth and config, you absolute icon, no cap ๐โจ๐ฆ
๐ฆ where this page comes from
- ubuntu noble: libconfig-gitlike-perl 1.18-2 ยท Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libconfig-gitlike-perl 1.18-2 ยท Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libconfig-gitlike-perl 1.18-2 ยท Artistic-1.0-Perl OR GPL-1.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms