Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / Config / GitLike.pm
1 package Config::GitLike;
2 use Any::Moose;
3
4 use File::Spec;
5 use Cwd;
6 use Scalar::Util qw(openhandle);
7 use Fcntl qw(O_CREAT O_EXCL O_WRONLY);
8 use 5.008;
9
10 our $VERSION = '1.04';
11
12
13 has 'confname' => (
14     is => 'rw',
15     required => 1,
16     isa => 'Str',
17 );
18
19 # not defaulting to {} allows the predicate is_loaded
20 # to determine whether data has been loaded yet or not
21 has 'data' => (
22     is => 'rw',
23     predicate => 'is_loaded',
24     isa => 'HashRef',
25 );
26
27 # key => bool
28 has 'multiple' => (
29     is => 'rw',
30     isa => 'HashRef',
31     default => sub { +{} },
32 );
33
34 # filename where the definition of each key was loaded from
35 has 'origins' => (
36     is => 'rw',
37     isa => 'HashRef',
38     default => sub { +{} },
39 );
40
41 has 'config_files' => (
42     is => 'rw',
43     isa => 'ArrayRef',
44     default => sub { [] },
45 );
46
47 # default to being more relaxed than git, but allow enforcement
48 # of only-write-things-that-git-config-can-read if you want to
49 has 'compatible' => (
50     is => 'rw',
51     isa => 'Bool',
52     default => 0,
53 );
54
55 has 'cascade' => (
56     is => 'rw',
57     isa => 'Bool',
58     default => 0,
59 );
60
61 sub set_multiple {
62     my $self = shift;
63     my ($name, $mult) = (@_, 1);
64     $self->multiple->{$name} = $mult;
65 }
66
67 sub is_multiple {
68     my $self = shift;
69     my $name = shift;
70     return if !defined $name;
71     return $self->multiple->{$name};
72 }
73
74 sub load {
75     my $self = shift;
76     my $path = shift || Cwd::cwd;
77     $self->data({});
78     $self->multiple({});
79     $self->config_files([]);
80     $self->load_global;
81     $self->load_user;
82     $self->load_dirs( $path );
83     return wantarray ? %{$self->data} : \%{$self->data};
84 }
85
86 sub dir_file {
87     my $self = shift;
88     return "." . $self->confname;
89 }
90
91 sub load_dirs {
92     my $self = shift;
93     my $path = shift;
94     my($vol, $dirs, undef) = File::Spec->splitpath( $path, 1 );
95     my @dirs = File::Spec->splitdir( $dirs );
96     my @found;
97     while (@dirs) {
98         my $path = File::Spec->catpath(
99             $vol, File::Spec->catdir(@dirs), $self->dir_file
100         );
101         if (-f $path) {
102             push @found, $path;
103             last unless $self->cascade;
104         }
105         pop @dirs;
106     }
107     $self->load_file( $_ ) for reverse @found;
108 }
109
110 sub global_file {
111     my $self = shift;
112     return "/etc/" . $self->confname;
113 }
114
115 sub load_global {
116     my $self = shift;
117     return unless -f $self->global_file;
118     return $self->load_file( $self->global_file );
119 }
120
121 sub user_file {
122     my $self = shift;
123     return
124         File::Spec->catfile( $ENV{'HOME'}, "." . $self->confname );
125 }
126
127 sub load_user {
128     my $self = shift;
129     return unless -f $self->user_file;
130     return $self->load_file( $self->user_file );
131 }
132
133 # returns undef if the file was unable to be opened
134 sub _read_config {
135     my $self = shift;
136     my $filename = shift;
137
138     open(my $fh, '<', $filename) or return;
139
140     my $c = do {local $/; <$fh>};
141
142     $c =~ s/\n*$/\n/; # Ensure it ends with a newline
143
144     return $c;
145 }
146
147 sub load_file {
148     my $self = shift;
149     my ($filename) = @_;
150     $self->data({}) unless $self->is_loaded;
151
152     return $self->data if grep {$_ eq $filename} @{$self->config_files};
153
154     my $c = $self->_read_config($filename);
155     $self->parse_content(
156         content  => $c,
157         callback => sub {
158             $self->define(@_, origin => $filename);
159         },
160         error    => sub {
161             error_callback( @_, filename => $filename );
162         },
163     );
164
165     # note this filename as having been loaded
166     push @{$self->config_files}, $filename;
167
168     return $self->data;
169 }
170
171 sub error_callback {
172     my %args = @_;
173
174     my $offset_of_prev_newline = rindex( $args{content}, "\n", $args{offset} );
175     my $offset_of_next_newline = index( $args{content}, "\n", $args{offset} );
176     my $line = substr(
177         $args{content},
178         $offset_of_prev_newline + 1,
179         $offset_of_next_newline - ($offset_of_prev_newline + 1),
180     );
181
182     my $line_number = 1;
183     my $current_offset = 0;
184
185     while ($current_offset <= $args{offset}) {
186         # nibble off a line of content
187         $args{content} =~ s/(.*\n)//;
188         $line_number++;
189         $current_offset += length $1;
190     }
191     my $position = (length $line) - ($current_offset - ($args{offset} + 1));
192     die "Error parsing $args{filename} at line $line_number, position $position."
193         ."\nBad line was: '$line'\n";
194 }
195
196 sub parse_content {
197     my $self = shift;
198     my %args = (
199         content  => '',
200         callback => sub {},
201         error    => sub {},
202         @_,
203     );
204     my $c = $args{content};
205     return if !$c;          # nothing to do if content is empty
206     my $length = length $c;
207
208     my $section_regex
209         = $self->compatible ? qr/\A\[([0-9a-z.-]+)(?:[\t ]*"([^\n]*?)")?\]/im
210                             : qr/\A\[([^\s\[\]"]+)(?:[\t ]*"([^\n]*?)")?\]/im;
211
212     my $key_regex
213         = $self->compatible ? qr/\A([a-z][0-9a-z-]*)[\t ]*(?:[#;].*)?$/im
214                             : qr/\A([^\[=\n][^=\n]*?)[\t ]*(?:[#;].*)?$/im;
215
216     my $key_value_regex
217         = $self->compatible ? qr/\A([a-z][0-9a-z-]*)[\t ]*=[\t ]*/im
218                             : qr/\A([^\[=\n][^=\n]*?)[\t ]*=[\t ]*/im;
219
220     my($section, $prev) = (undef, '');
221     while (1) {
222         # drop leading white space and blank lines
223         $c =~ s/\A\s*//im;
224
225         my $offset = $length - length($c);
226         # drop to end of line on comments
227         if ($c =~ s/\A[#;].*?$//im) {
228             next;
229         }
230         # [sub]section headers of the format [section "subsection"] (with
231         # unlimited whitespace between) or [section.subsection] variable
232         # definitions may directly follow the section header, on the same line!
233         # - rules for sections: not case sensitive, only alphanumeric
234         #   characters, -, and . allowed
235         # - rules for subsections enclosed in ""s: case sensitive, can
236         #   contain any character except newline, " and \ must be escaped
237         # - rules for subsections with section.subsection alternate syntax:
238         #   same rules as for sections
239         elsif ($c =~ s/$section_regex//) {
240             $section = lc $1;
241             if ($2) {
242                 my $subsection = $2;
243                 my $check = $2;
244                 $check =~ s{\\\\}{}g;
245                 $check =~ s{\\"}{}g;
246                 return $args{error}->(
247                     content => $args{content},
248                     offset  => $offset,
249
250                     # don't allow quoted subsections to contain unescaped
251                     # double-quotes or backslashes
252                 ) if $check =~ /\\|"/;
253
254                 $subsection =~ s{\\\\}{\\}g;
255                 $subsection =~ s{\\"}{"}g;
256                 $section .= ".$subsection";
257             }
258
259             $args{callback}->(
260                 section    => $section,
261                 offset     => $offset,
262                 length     => ($length - length($c)) - $offset,
263             );
264         }
265         # keys followed by a unlimited whitespace and (optionally) a comment
266         # (no value)
267         #
268         # for keys, we allow any characters that won't screw up the parsing
269         # (= and newline) in non-compatible mode, and match non-greedily to
270         # allow any trailing whitespace to be dropped
271         #
272         # in compatible mode, keys can contain only 0-9a-z-
273         elsif ($c =~ s/$key_regex//) {
274             $args{callback}->(
275                 section    => $section,
276                 name       => lc $1,
277                 offset     => $offset,
278                 length     => ($length - length($c)) - $offset,
279             );
280         }
281         # key/value pairs (this particular regex matches only the key part and
282         # the =, with unlimited whitespace around the =)
283         elsif ($c =~ s/$key_value_regex//) {
284             my $name = lc $1;
285             my $value = "";
286             # parse the value
287             while (1) {
288                 # comment or no content left on line
289                 if ($c =~ s/\A([ \t]*[#;].*?)?$//im) {
290                     last;
291                 }
292                 # any amount of whitespace between words becomes a single space
293                 elsif ($c =~ s/\A[\t ]+//im) {
294                     $value .= ' ';
295                 }
296                 # line continuation (\ character followed by new line)
297                 elsif ($c =~ s/\A\\\r?\n//im) {
298                     next;
299                 }
300                 # escaped backslash characters is translated to actual \
301                 elsif ($c =~ s/\A\\\\//im) {
302                     $value .= '\\';
303                 }
304                 # escaped quote characters are part of the value
305                 elsif ($c =~ s/\A\\(['"])//im) {
306                     $value .= $1;
307                 }
308                 # escaped newline in config is translated to actual newline
309                 elsif ($c =~ s/\A\\n//im) {
310                     $value .= "\n";
311                 }
312                 # escaped tab in config is translated to actual tab
313                 elsif ($c =~ s/\A\\t//im) {
314                     $value .= "\t";
315                 }
316                 # escaped backspace in config is translated to actual backspace
317                 elsif ($c =~ s/\A\\b//im) {
318                     $value .= "\b";
319                 }
320                 # quote-delimited value (possibly containing escape codes)
321                 elsif ($c =~ s/\A"([^"\\]*(?:(?:\\\n|\\[tbn"\\])[^"\\]*)*)"//im) {
322                     my $v = $1;
323                     # remove all continuations (\ followed by a newline)
324                     $v =~ s/\\\n//g;
325                     # swap escaped newlines with actual newlines
326                     $v =~ s/\\n/\n/g;
327                     # swap escaped tabs with actual tabs
328                     $v =~ s/\\t/\t/g;
329                     # swap escaped backspaces with actual backspaces
330                     $v =~ s/\\b/\b/g;
331                     # swap escaped \ with actual \
332                     $v =~ s/\\\\/\\/g;
333                     $value .= $v;
334                 }
335                 # valid value (no escape codes)
336                 elsif ($c =~ s/\A([^\t \\\n]+)//im) {
337                     $value .= $1;
338                 # unparseable
339                 }
340                 else {
341                     # Note that $args{content} is the _original_
342                     # content, not the nibbled $c, which is the
343                     # remaining unparsed content
344                     return $args{error}->(
345                         content => $args{content},
346                         offset =>  $offset,
347                     );
348                 }
349             }
350             $args{callback}->(
351                 section    => $section,
352                 name       => $name,
353                 value      => $value,
354                 offset     => $offset,
355                 length     => ($length - length($c)) - $offset,
356             );
357         }
358         # end of content string; all done now
359         elsif (not length $c) {
360             last;
361         }
362         # unparseable
363         else {
364             # Note that $args{content} is the _original_ content, not
365             # the nibbled $c, which is the remaining unparsed content
366             return $args{error}->(
367                 content => $args{content},
368                 offset  => $offset,
369             );
370         }
371     }
372 }
373
374 sub define {
375     my $self = shift;
376     my %args = (
377         section => undef,
378         name    => undef,
379         value   => undef,
380         origin  => undef,
381         @_,
382     );
383     return unless defined $args{name};
384     $args{name} = lc $args{name};
385     my $key = join(".", grep {defined} @args{qw/section name/});
386
387     # we're either adding a whole new key or adding a multiple key from
388     # the same file
389     if ( !defined $self->origins->{$key}
390         || $self->origins->{$key} eq $args{origin} ) {
391         if ($self->is_multiple($key)) {
392             push @{$self->data->{$key} ||= []}, $args{value};
393         }
394         elsif (exists $self->data->{$key}) {
395             $self->set_multiple($key);
396             $self->data->{$key} = [$self->data->{$key}, $args{value}];
397         }
398         else {
399             $self->data->{$key} = $args{value};
400         }
401     }
402     # we're overriding a key set previously from a different file
403     else {
404         # un-mark as multiple if it was previously marked as such
405         $self->set_multiple( $key, 0 ) if $self->is_multiple( $key );
406
407         # set the new value
408         $self->data->{$key} = $args{value};
409     }
410     $self->origins->{$key} = $args{origin};
411 }
412
413 sub cast {
414     my $self = shift;
415     my %args = (
416         value => undef,
417         as    => undef, # bool, int, or num
418         human => undef, # true value / false value
419         @_,
420     );
421
422     use constant {
423         BOOL_TRUE_REGEX  => qr/^(?:true|yes|on|-?0*1)$/i,
424         BOOL_FALSE_REGEX => qr/^(?:false|no|off|0*)$/i,
425         NUM_REGEX        => qr/^-?[0-9]*\.?[0-9]*[kmg]?$/,
426     };
427
428     if (defined $args{as} && $args{as} eq 'bool-or-int') {
429         if ( $args{value} =~ NUM_REGEX ) {
430             $args{as} = 'int';
431         }
432         elsif ( $args{value} =~ BOOL_TRUE_REGEX ||
433             $args{value} =~ BOOL_FALSE_REGEX ) {
434             $args{as} = 'bool';
435         }
436         elsif ( !defined $args{value} ) {
437             $args{as} = 'bool';
438         }
439         else {
440             die "Invalid bool-or-int '$args{value}'\n";
441         }
442     }
443
444     my $v = $args{value};
445     return $v unless defined $args{as};
446     if ($args{as} =~ /bool/i) {
447         return 1 unless defined $v;
448         if ( $v =~  BOOL_TRUE_REGEX ) {
449             if ( $args{human} ) {
450                 return 'true';
451             }
452             else {
453                 return 1;
454             }
455         }
456         elsif ($v =~ BOOL_FALSE_REGEX ) {
457             if ( $args{human} ) {
458                 return 'false';
459             }
460             else {
461                 return 0;
462             }
463         }
464         else {
465             die "Invalid bool '$args{value}'\n";
466         }
467     }
468     elsif ($args{as} =~ /int|num/) {
469         die "Invalid unit while casting to $args{as}\n"
470             unless $v =~ NUM_REGEX;
471
472         if ($v =~ s/([kmg])$//) {
473             $v *= 1024 if $1 eq "k";
474             $v *= 1024*1024 if $1 eq "m";
475             $v *= 1024*1024*1024 if $1 eq "g";
476         }
477
478         return $args{as} eq 'int' ? int $v : $v + 0;
479     }
480 }
481
482 sub get {
483     my $self = shift;
484     my %args = (
485         key => undef,
486         as  => undef,
487         human  => undef,
488         filter => '',
489         @_,
490     );
491     $self->load unless $self->is_loaded;
492
493     my ($section, $subsection, $name) = _split_key($args{key});
494     $args{key} = join( '.',
495         grep { defined } (lc $section, $subsection, lc $name),
496     );
497
498     return undef unless exists $self->data->{$args{key}};
499     my $v = $self->data->{$args{key}};
500     if (ref $v) {
501         my @results;
502         if (defined $args{filter}) {
503             if ($args{filter} =~ s/^!//) {
504                 @results = grep { !/$args{filter}/i } @{$v};
505             }
506             else {
507                 @results = grep { m/$args{filter}/i } @{$v};
508             }
509         }
510         die "Multiple values" unless @results <= 1;
511         $v = $results[0];
512     }
513     return $self->cast( value => $v, as => $args{as},
514         human => $args{human} );
515 }
516
517 # I'm pretty sure that someone can come up with an edge case where stripping
518 # all balanced quotes like this is not the right thing to do, but I don't
519 # see it actually being a problem in practice.
520 sub _remove_balanced_quotes {
521     my $key = shift;
522
523     no warnings 'uninitialized';
524     $key = join '', map { s/"(.*)"/$1/; $_ } split /("[^"]+"|[^.]+)/, $key;
525     $key = join '', map { s/'(.*)'/$1/; $_ } split /('[^']+'|[^.]+)/, $key;
526
527     return $key;
528 }
529
530 sub get_all {
531     my $self = shift;
532     my %args = (
533         key => undef,
534         as  => undef,
535         @_,
536     );
537     $self->load unless $self->is_loaded;
538     my ($section, $subsection, $name) = _split_key($args{key});
539     $args{key} = join('.',
540         grep { defined } (lc $section, $subsection, lc $name),
541     );
542
543     return undef unless exists $self->data->{$args{key}};
544     my $v = $self->data->{$args{key}};
545     my @v = ref $v ? @{$v} : ($v);
546
547     if (defined $args{filter}) {
548         if ($args{filter} =~ s/^!//) {
549             @v = grep { !/$args{filter}/i } @v;
550         }
551         else {
552             @v = grep { m/$args{filter}/i } @v;
553         }
554     }
555
556     @v = map {$self->cast( value => $_, as => $args{as} )} @v;
557     return wantarray ? @v : \@v;
558 }
559
560 sub get_regexp {
561     my $self = shift;
562
563     my %args = (
564         key => undef,
565         filter => undef,
566         as  => undef,
567         @_,
568     );
569
570     $self->load unless $self->is_loaded;
571
572     $args{key} = lc $args{key};
573
574     my %results;
575     for my $key (keys %{$self->data}) {
576         $results{$key} = $self->data->{$key} if lc $key =~ m/$args{key}/i;
577     }
578
579     if (defined $args{filter}) {
580         if ($args{filter} =~ s/^!//) {
581             map { delete $results{$_} if $results{$_} =~ m/$args{filter}/i }
582                 keys %results;
583         }
584         else {
585             map { delete $results{$_} if $results{$_} !~ m/$args{filter}/i }
586                 keys %results;
587         }
588     }
589
590     @results{keys %results} =
591         map { $self->cast(
592                 value => $results{$_},
593                 as => $args{as}
594             ); } keys %results;
595     return wantarray ? %results : \%results;
596 }
597
598 sub dump {
599     my $self = shift;
600
601     return %{$self->data} if wantarray;
602
603     my $data = '';
604     for my $key (sort keys %{$self->data}) {
605         my $str;
606         if (defined $self->data->{$key}) {
607             $str = "$key=";
608             if ( $self->is_multiple($key) ) {
609                 $str .= '[';
610                 $str .= join(', ', @{$self->data->{$key}});
611                 $str .= "]\n";
612             }
613             else {
614                 $str .= $self->data->{$key}."\n";
615             }
616         }
617         else {
618             $str = "$key\n";
619         }
620         if (!defined wantarray) {
621             print $str;
622         }
623         else {
624             $data .= $str;
625         }
626     }
627
628     return $data if defined wantarray;
629 }
630
631 sub format_section {
632     my $self = shift;
633
634     my %args = (
635         section => undef,
636         bare    => undef,
637         @_,
638     );
639
640     if ($args{section} =~ /^(.*?)\.(.*)$/) {
641         my ($section, $subsection) = ($1, $2);
642         my $ret = qq|[$section "$subsection"]|;
643         $ret .= "\n" unless $args{bare};
644         return $ret;
645     }
646     else {
647         my $ret = qq|[$args{section}]|;
648         $ret .= "\n" unless $args{bare};
649         return $ret;
650     }
651 }
652
653 sub format_definition {
654     my $self = shift;
655     my %args = (
656         key   => undef,
657         value => undef,
658         bare  => undef,
659         @_,
660     );
661     my $quote = $args{value} =~ /(^\s|;|#|\s$)/ ? '"' : '';
662     $args{value} =~ s/\\/\\\\/g;
663     $args{value} =~ s/"/\\"/g;
664     $args{value} =~ s/\t/\\t/g;
665     $args{value} =~ s/\n/\\n/g;
666     my $ret = "$args{key} = $quote$args{value}$quote";
667     $ret = "\t$ret\n" unless $args{bare};
668     return $ret;
669 }
670
671 # Given a key, return its variable name, section, and subsection
672 # parts. Doesn't do any lowercase transformation.
673 sub _split_key {
674     my $key = shift;
675
676     my ($name, $section, $subsection);
677     # allow quoting of the key to, for example, preserve
678     # . characters in the key
679     if ( $key =~ s/\.["'](.*)["']$// ) {
680         $name = $1;
681         $section = $key;
682     }
683     else {
684         $key =~ /^(?:(.*)\.)?(.*)$/;
685         # If we wanted, we could interpret quoting of the section name to
686         # allow for setting keys with section names including . characters.
687         # But git-config doesn't do that, so we won't bother for now. (Right
688         # now it will read these section names correctly but won't set them.)
689         ($section, $name) = map { _remove_balanced_quotes($_) }
690             grep { defined $_ } ($1, $2);
691     }
692
693     # Make sure the section name we're comparing against has
694     # case-insensitive section names and case-sensitive subsection names.
695     if (defined $section) {
696         $section =~ m/^([^.]+)(?:\.(.*))?$/;
697         ($section, $subsection) = ($1, $2);
698     }
699     else {
700         ($section, $subsection) = (undef) x 2;
701     }
702     return ($section, $subsection, $name);
703 }
704
705 sub group_set {
706     my $self = shift;
707     my ($filename, $args_ref) = @_;
708
709     my $c = $self->_read_config($filename);  # undef if file doesn't exist
710
711     # loop through each value to set, modifying the content to be written
712     # or erroring out as we go
713     for my $args_hash (@{$args_ref}) {
714         my %args = %{$args_hash};
715
716         my ($section, $subsection, $name) = _split_key($args{key});
717         my $key = join( '.',
718             grep { defined } (lc $section, $subsection, lc $name),
719         );
720
721         $args{multiple} = $self->is_multiple($key)
722             unless defined $args{multiple};
723
724         die "No section given in key or invalid key $args{key}\n"
725             unless defined $section;
726
727         die "Invalid variable name $name\n"
728             if $self->_invalid_variable_name($name);
729
730         die "Invalid section name $section\n"
731             if $self->_invalid_section_name($section);
732
733         # if the subsection to write contains unescaped \ or ", escape them
734         # automatically
735         my $unescaped_subsection;
736         if ( defined $subsection ) {
737             $unescaped_subsection = $subsection;
738             $subsection =~ s{\\}{\\\\}g;
739             $subsection =~ s{"}{\\"}g;
740         }
741
742         $args{value} = $self->cast(
743             value => $args{value},
744             as    => $args{as},
745             human => 1,
746         ) if defined $args{value} && defined $args{as};
747
748         my $new;
749         my @replace;
750
751         # use this for comparison
752         my $cmp_section =
753           defined $unescaped_subsection
754           ? join( '.', lc $section, $unescaped_subsection )
755           : lc $section;
756         # ...but this for writing (don't lowercase)
757         my $combined_section
758             = defined $subsection ? join('.', $section, $subsection)
759                                   : $section;
760
761         # There's not really a good, simple way to get around parsing the
762         # content for each of the values we're setting. If we wanted to
763         # extract the offsets for every single one using only a single parse
764         # run, we'd end up having to munge all the offsets afterwards as we
765         # did the actual replacement since every time we did a replacement it
766         # would change the offsets for anything that was formerly to be added
767         # at a later offset. Which I'm not sure is any better than just
768         # parsing it again.
769         $self->parse_content(
770             content  => $c,
771             callback => sub {
772                 my %got = @_;
773                 return unless $got{section} eq $cmp_section;
774                 $new = $got{offset} + $got{length};
775                 return unless defined $got{name};
776
777                 my $matched = 0;
778                 # variable names are case-insensitive
779                 if (lc $name eq $got{name}) {
780                     if (defined $args{filter}) {
781                         # copy the filter arg here since this callback may
782                         # be called multiple times and we don't want to
783                         # modify the original value
784                         my $filter = $args{filter};
785                         if ($filter =~ s/^!//) {
786                             $matched = 1 if ($got{value} !~ m/$filter/i);
787                         }
788                         elsif ($got{value} =~ m/$filter/i) {
789                             $matched = 1;
790                         }
791                     }
792                     else {
793                         $matched = 1;
794                     }
795                 }
796
797                 push @replace, {offset => $got{offset}, length => $got{length}}
798                     if $matched;
799             },
800             error    => sub {
801                 error_callback(@_, filename => $args{filename})
802             },
803         );
804
805         die "Multiple occurrences of non-multiple key?"
806             if @replace > 1 && !$args{multiple};
807
808         # We're only replacing the first occurrance unless they said
809         # to replace them all.
810         @replace = ($replace[0]) if @replace and $args{value} and not $args{replace_all};
811
812         if (defined $args{value}) {
813             if (@replace
814                     && (!$args{multiple} || $args{filter} || $args{replace_all})) {
815                 # Replacing existing value(s)
816
817                 # if the string we're replacing with is not the same length as
818                 # what's being replaced, any offsets following will be wrong.
819                 # save the difference between the lengths here and add it to
820                 # any offsets that follow.
821                 my $difference = 0;
822
823                 # when replacing multiple values, we combine them all into one,
824                 # which is kept at the position of the last one
825                 my $last = pop @replace;
826
827                 # kill all values that are not last
828                 ($c, $difference) = _unset_variables(\@replace, $c,
829                     $difference);
830
831                 # substitute the last occurrence with the new value
832                 substr(
833                     $c,
834                     $last->{offset}-$difference,
835                     $last->{length},
836                     $self->format_definition(
837                         key   => $name,
838                         value => $args{value},
839                         bare  => 1,
840                         ),
841                     );
842             }
843             elsif (defined $new) {
844                 # Adding a new value to the end of an existing block
845                 substr(
846                     $c,
847                     index($c, "\n", $new)+1,
848                     0,
849                     $self->format_definition(
850                         key   => $name,
851                         value => $args{value}
852                     )
853                 );
854             }
855             else {
856                 # Adding a new section
857                 $c .= $self->format_section( section => $combined_section );
858                 $c .= $self->format_definition(
859                     key => $name,
860                     value => $args{value},
861                 );
862             }
863         }
864         else {
865             # Removing an existing value (unset / unset-all)
866             die "No occurrence of $args{key} found to unset in $filename\n"
867                 unless @replace;
868
869             ($c, undef) = _unset_variables(\@replace, $c, 0);
870         }
871     }
872     return $self->_write_config( $filename, $c );
873 }
874
875 sub set {
876     my $self = shift;
877     my (%args) = (
878         key      => undef,
879         value    => undef,
880         filename => undef,
881         filter   => undef,
882         as       => undef,
883         multiple => undef,
884         @_
885     );
886
887     my $filename = $args{filename};
888     delete $args{filename};
889
890     return $self->group_set( $filename, [ \%args ] );
891 }
892
893 sub _unset_variables {
894     my ($variables, $c, $difference) = @_;
895
896     for my $var (@{$variables}) {
897         # start from either the last newline or the last section
898         # close bracket, since variable definitions can occur
899         # immediately following a section header without a \n
900         my $newline = rindex($c, "\n", $var->{offset}-$difference);
901         # need to add 1 here to not kill the ] too
902         my $bracket = rindex($c, ']', $var->{offset}-$difference) + 1;
903         my $start = $newline > $bracket ? $newline : $bracket;
904
905         my $length =
906             index($c, "\n", $var->{offset}-$difference+$var->{length})-$start;
907
908         substr(
909             $c,
910             $start,
911             $length,
912             '',
913         );
914         $difference += $length;
915     }
916
917     return ($c, $difference);
918 }
919
920 # In non-git-compatible mode, variables names can contain any characters that
921 # aren't newlines or = characters, but cannot start or end with whitespace.
922 #
923 # Allowing . characters in variable names actually makes it so you
924 # can get collisions between identifiers for things that are not
925 # actually the same.
926 #
927 # For example, you could have a collision like this:
928 # [section "foo"] bar.com = 1
929 # [section] foo.bar.com = 1
930 #
931 # Both of these would be turned into 'section.foo.bar.com'. But it's
932 # unlikely to ever actually come up, since you'd have to have
933 # a *need* to have two things like this that are very similar
934 # and yet different.
935 sub _invalid_variable_name {
936     my ($self, $name) = @_;
937
938     if ($self->compatible) {
939         return $name !~ /^[a-z][0-9a-z-]*$/i;
940     }
941     else {
942         return $name !~ /^[^=\n\[][^=\n]*$/ || $name =~ /(?:^[ \t]+|[ \t+]$)/;
943     }
944 }
945
946 # section, NOT subsection!
947 sub _invalid_section_name {
948     my ($self, $section) = @_;
949
950     if ($self->compatible) {
951         return $section !~ /^[0-9a-z-.]+$/i;
952     }
953     else {
954         return $section =~ /\s|\[|\]|"/;
955     }
956 }
957
958 # write config with locking
959 sub _write_config {
960     my $self = shift;
961     my($filename, $content) = @_;
962
963     # allow nested symlinks but only within reason
964     my $max_depth = 5;
965
966     # resolve symlinks
967     while ($max_depth--) {
968         my $readlink = readlink $filename;
969         $filename = $readlink if defined $readlink;
970     }
971
972     # write new config file to temp file
973     # (the only reason we call it .lock is because that's the
974     # way git does it)
975     sysopen(my $fh, "${filename}.lock", O_CREAT|O_EXCL|O_WRONLY)
976         or die "Can't open ${filename}.lock for writing: $!\n";
977     print $fh $content;
978     close $fh;
979
980     # atomic rename
981     rename("${filename}.lock", ${filename})
982         or die "Can't rename ${filename}.lock to ${filename}: $!\n";
983 }
984
985 sub rename_section {
986     my $self = shift;
987
988     my (%args) = (
989         from        => undef,
990         to          => undef,
991         filename    => undef,
992         @_
993     );
994
995     die "No section to rename from given\n" unless defined $args{from};
996
997     my $c = $self->_read_config($args{filename});
998     # file couldn't be opened = nothing to rename
999     return if !defined($c);
1000
1001     ($args{from}, $args{to}) = map { _remove_balanced_quotes($_) }
1002                                 grep { defined $_ } ($args{from}, $args{to});
1003
1004     my @replace;
1005     my $prev_matched = 0;
1006     $self->parse_content(
1007         content  => $c,
1008         callback => sub {
1009             my %got = @_;
1010
1011             $replace[-1]->{section_is_last} = 0
1012                 if (@replace && !defined($got{name}));
1013
1014             if (lc($got{section}) eq lc($args{from})) {
1015                 if (defined $got{name}) {
1016                     # if we're removing rather than replacing and
1017                     # there was a previous section match, increase
1018                     # its length so it will kill this variable
1019                     # assignment too
1020                     if ($prev_matched && !defined $args{to} ) {
1021                         $replace[-1]->{length} += ($got{offset} + $got{length})
1022                             - ($replace[-1]{offset} + $replace[-1]->{length});
1023                     }
1024                 }
1025                 else {
1026                     # if we're removing rather than replacing, increase
1027                     # the length of the previous match so when it's
1028                     # replaced it will kill all the way up to the
1029                     # beginning of this next section (this will kill
1030                     # any leading whitespace on the line of the
1031                     # next section, but that's OK)
1032                     $replace[-1]->{length} += $got{offset} -
1033                         ($replace[-1]->{offset} + $replace[-1]->{length})
1034                         if @replace && $prev_matched && !defined($args{to});
1035
1036                     push @replace, {offset => $got{offset}, length =>
1037                         $got{length}, section_is_last => 1};
1038                     $prev_matched = 1;
1039                 }
1040             }
1041             else {
1042                 # if we're removing rather than replacing and there was
1043                 # a previous section match, increase its length to kill all
1044                 # the way up to this non-matching section (takes care
1045                 # of newlines between here and there, etc.)
1046                 $replace[-1]->{length} += $got{offset} -
1047                     ($replace[-1]->{offset} + $replace[-1]->{length})
1048                     if @replace && $prev_matched && !defined($args{to});
1049                 $prev_matched = 0;
1050             }
1051         },
1052         error    => sub {
1053             error_callback( @_, filename => $args{filename} );
1054         },
1055     );
1056     die "No such section '$args{from}'\n"
1057         unless @replace;
1058
1059     # if the string we're replacing with is not the same length as what's
1060     # being replaced, any offsets following will be wrong. save the difference
1061     # between the lengths here and add it to any offsets that follow.
1062     my $difference = 0;
1063
1064     # rename ALL section headers that matched to
1065     # (there may be more than one)
1066     my $replace_with = defined $args{to} ?
1067         $self->format_section( section => $args{to}, bare => 1 ) : '';
1068
1069     for my $header (@replace) {
1070         substr(
1071             $c,
1072             $header->{offset} + $difference,
1073             # if we're removing the last section, just kill all the way to the
1074             # end of the file
1075             !defined($args{to}) && $header->{section_is_last} ? length($c) -
1076                 ($header->{offset} + $difference) : $header->{length},
1077             $replace_with,
1078         );
1079         $difference += (length($replace_with) - $header->{length});
1080     }
1081
1082     return $self->_write_config($args{filename}, $c);
1083 }
1084
1085 sub remove_section {
1086     my $self = shift;
1087
1088     my (%args) = (
1089         section     => undef,
1090         filename    => undef,
1091         @_
1092     );
1093
1094     die "No section given to remove\n" unless $args{section};
1095
1096     # remove section is just a rename to nothing
1097     return $self->rename_section( from => $args{section}, filename =>
1098         $args{filename} );
1099 }
1100
1101 1;
1102
1103 __END__
1104
1105 =head1 NAME
1106
1107 Config::GitLike - git-compatible config file parsing
1108
1109 =head1 SYNOPSIS
1110
1111 This module parses git-style config files, which look like this:
1112
1113     [core]
1114         repositoryformatversion = 0
1115         filemode = true
1116         bare = false
1117         logallrefupdates = true
1118     [remote "origin"]
1119         url = spang.cc:/srv/git/home.git
1120         fetch = +refs/heads/*:refs/remotes/origin/*
1121     [another-section "subsection"]
1122         key = test
1123         key = multiple values are OK
1124         emptyvalue =
1125         novalue
1126
1127 Code that uses this config module might look like:
1128
1129     use Config::GitLike;
1130
1131     my $c = Config::GitLike->new(confname => 'config');
1132     $c->load;
1133
1134     $c->get( key => 'section.name' );
1135     # make the return value a Perl true/false value
1136     $c->get( key => 'core.filemode', as => 'bool' );
1137
1138     # replace the old value
1139     $c->set(
1140         key => 'section.name',
1141         value => 'val1',
1142         filename => '/home/user/.config',
1143     );
1144
1145     # make this key have multiple values rather than replacing the
1146     # old value
1147     $c->set(
1148         key => 'section.name',
1149         value => 'val2',
1150         filename => '/home/user/.config',
1151         multiple => 1,
1152     );
1153
1154     # replace all occurrences of the old value for section.name with a new one
1155     $c->set(
1156         key => 'section.name',
1157         value => 'val3',
1158         filename => '/home/user/.config',
1159         multiple => 1,
1160         replace_all => 1,
1161     );
1162
1163     # make sure to reload the config files before reading if you've set
1164     # any variables!
1165     $c->load;
1166
1167     # get only the value of 'section.name' that matches '2'
1168     $c->get( key => 'section.name', filter => '2' );
1169     $c->get_all( key => 'section.name' );
1170     # prefixing a search regexp with a ! negates it
1171     $c->get_regexp( key => '!na' );
1172
1173     $c->rename_section(
1174         from => 'section',
1175         to => 'new-section',
1176         filename => '/home/user/.config'
1177     );
1178
1179     $c->remove_section(
1180         section => 'section',
1181         filename => '/home/user/.config'
1182     );
1183
1184     # unsets all instances of the given key
1185     $c->set( key => 'section.name', filename => '/home/user/.config' );
1186
1187     my %config_vals = $config->dump;
1188     # string representation of config data
1189     my $str = $config->dump;
1190     # prints rather than returning
1191     $config->dump;
1192
1193 =head1 DESCRIPTION
1194
1195 This module handles interaction with configuration files of the style used
1196 by the version control system Git. It can both parse and modify these
1197 files, as well as create entirely new ones.
1198
1199 You only need to know a few things about the configuration format in order
1200 to use this module. First, a configuration file is made up of key/value
1201 pairs. Every key must be contained in a section. Sections can have
1202 subsections, but they don't have to. For the purposes of setting and
1203 getting configuration variables, we join the section name,
1204 subsection name, and variable name together with dots to get a key
1205 name that looks like "section.subsection.variable". These are the
1206 strings that you'll be passing in to C<key> arguments.
1207
1208 Configuration files inherit from each other. By default, C<Config::GitLike>
1209 loads data from a system-wide configuration file, a per-user
1210 configuration file, and a per-directory configuration file, but by
1211 subclassing and overriding methods you can obtain any combination of
1212 configuration files. By default, configuration files that don't
1213 exist are just skipped.
1214
1215 See
1216 L<http://www.kernel.org/pub/software/scm/git/docs/git-config.html#_configuration_file>
1217 for details on the syntax of git configuration files. We won't waste pixels
1218 on the nitty gritty here.
1219
1220 While the behaviour of a couple of this module's methods differ slightly
1221 from the C<git config> equivalents, this module can read any config file
1222 written by git. The converse is usually true, but only if you don't take
1223 advantage of this module's increased permissiveness when it comes to key
1224 names. (See L<DIFFERENCES FROM GIT-CONFIG> for details.)
1225
1226 This is an object-oriented module using L<Any::Moose|Any::Moose>. All
1227 subroutines are object method calls.
1228
1229 A few methods have parameters that are always used for the same purpose:
1230
1231 =head2 Filenames
1232
1233 All methods that change things in a configuration file require a filename to
1234 write to, via the C<filename> parameter. Since a C<Config::GitLike> object can
1235 be working with multiple config files that inherit from each other, we don't
1236 try to figure out which one to write to automatically and let you specify
1237 instead.
1238
1239 =head2 Casting
1240
1241 All get and set methods can make sure the values they're returning or
1242 setting are valid values of a certain type: C<bool>, C<int>,
1243 C<num>, or C<bool-or-int> (or at least as close as Perl can get
1244 to having these types). Do this by passing one of these types
1245 in via the C<as> parameter. The set method, if told to write
1246 bools, will always write "true" or "false" (not anything else that
1247 C<cast> considers a valid bool).
1248
1249 Methods that are told to cast values will throw exceptions if
1250 the values they're trying to cast aren't valid values of the
1251 given type.
1252
1253 See the L<"cast"> method documentation for more on what is considered valid
1254 for each type.
1255
1256 =head2 Filtering
1257
1258 All get and set methods can filter what values they return via their
1259 C<filter> parameter, which is expected to be a string that is a valid
1260 regex. If you want to filter items OUT instead of IN, you can
1261 prefix your regex with a ! and that'll do the trick.
1262
1263 Now, on the the methods!
1264
1265 =head1 MAIN METHODS
1266
1267 There are the methods you're likely to use the most.
1268
1269 =head2 new( confname => 'config' )
1270
1271 Create a new configuration object with the base config name C<confname>.
1272
1273 C<confname> is used to construct the filenames that will be loaded; by
1274 default, these are C</etc/confname> (global configuration file),
1275 C<~/.confname> (user configuration file), and C<<Cwd>/.confname> (directory
1276 configuration file).
1277
1278 You can override these defaults by subclassing C<Config::GitLike> and
1279 overriding the methods C<global_file>, C<user_file>, and C<dir_file>. (See
1280 L<"METHODS YOU MAY WISH TO OVERRIDE"> for details.)
1281
1282 If you wish to enforce only being able to read/write config files that
1283 git can read or write, pass in C<compatible =E<gt> 1> to this
1284 constructor. The default rules for some components of the config
1285 file are more permissive than git's (see L<"DIFFERENCES FROM GIT-CONFIG">).
1286
1287 =head2 confname
1288
1289 The configuration filename that you passed in when you created
1290 the C<Config::GitLike> object. You can change it if you want by
1291 passing in a new name (and then reloading via L<"load">).
1292
1293 =head2 load
1294
1295 Load the global, local, and directory configuration file with the filename
1296 C<confname>(if they exist). Configuration variables loaded later
1297 override those loaded earlier, so variables from the directory
1298 configuration file have the highest precedence.
1299
1300 Pass in an optional path, and it will be passed on to L<"load_dirs"> (which
1301 loads the directory configuration file(s)).
1302
1303 Returns a hash copy of all loaded configuration data stored in the module
1304 after the files have been loaded, or a hashref to this hash in
1305 scalar context.
1306
1307 =head2 config_filenames
1308
1309 An array reference containing the absolute filenames of all config files
1310 that are currently loaded, in the order they were loaded.
1311
1312 =head2 get
1313
1314 Parameters:
1315
1316     key => 'sect.subsect.key'
1317     as => 'int'
1318     filter => '!foo
1319
1320 Return the config value associated with C<key> cast as an C<as>.
1321
1322 The C<key> option is required (will return undef if unspecified); the C<as>
1323 option is not (will return a string by default). Sections and subsections
1324 are specified in the key by separating them from the key name with a .
1325 character. Sections, subsections, and keys may all be quoted (double or
1326 single quotes).
1327
1328 If C<key> doesn't exist in the config, undef is returned. Dies with
1329 the exception "Multiple values" if the given key has more than one
1330 value associated with it. (Use L<"get_all"> to retrieve multiple values.)
1331
1332 Calls L<"load"> if it hasn't been done already. Note that if you've run any
1333 C<set> calls to the loaded configuration files since the last time they were
1334 loaded, you MUST call L<"load"> again before getting, or the returned
1335 configuration data may not match the configuration variables on-disk.
1336
1337 =head2 get_all
1338
1339 Parameters:
1340
1341     key => 'section.sub'
1342     filter => 'regex'
1343     as => 'int'
1344
1345 Like L<"get"> but does not fail if the number of values for the key is not
1346 exactly one.
1347
1348 Returns a list of values (or an arrayref in scalar context).
1349
1350 =head2 get_regexp
1351
1352 Parameters:
1353
1354     key => 'regex'
1355     filter => 'regex'
1356     as => 'bool'
1357
1358 Similar to L<"get_all"> but searches for values based on a key regex.
1359
1360 Returns a hash of name/value pairs (or a hashref in scalar context).
1361
1362 =head2 dump
1363
1364 In scalar context, return a string containing all configuration data, sorted in
1365 ASCII order, in the form:
1366
1367     section.key=value
1368     section2.key=value
1369
1370 If called in void context, this string is printed instead.
1371
1372 In list context, returns a hash containing all the configuration data.
1373
1374 =head2 set
1375
1376 Parameters:
1377
1378     key => 'section.name'
1379     value => 'bar'
1380     filename => File::Spec->catfile(qw/home user/, '.'.$config->confname)
1381     filter => 'regex'
1382     as => 'bool'
1383     multiple => 1
1384     replace_all => 1
1385
1386 Set the key C<foo> in the configuration section C<section> to the value C<bar>
1387 in the given filename.
1388
1389 Replace C<key>'s value if C<key> already exists.
1390
1391 To unset a key, pass in C<key> but not C<value>.
1392
1393 Returns true on success.
1394
1395 If you need to have a . character in your variable name, you can surround the
1396 name with quotes (single or double): C<key =&gt 'section."foo.bar.com"'>
1397 Don't do this unless you really have to.
1398
1399 =head3 multiple values
1400
1401 By default, set will replace the old value rather than giving a key multiple
1402 values. To override this, pass in C<multiple =E<gt> 1>. If you want to replace
1403 all instances of a multiple-valued key with a new value, you need to pass
1404 in C<replace_all =E<gt> 1> as well.
1405
1406 =head2 group_set
1407
1408 Parameters:
1409
1410     filename => '/home/foo/.bar'
1411     args_ref => $ref
1412
1413 Same as L<"set">, but set a group of variables at the same time without
1414 writing to disk separately for each.
1415
1416 C<args_ref> is an array reference containing a list of hash references which
1417 are essentially hashes of arguments to C<set>, excluding the C<filename>
1418 argument since that is specified separately and the same file is used for all
1419 variables to be set at once.
1420
1421 =head2 rename_section
1422
1423 Parameters:
1424
1425     from => 'name.subname'
1426     to => 'new.subname'
1427     filename => '/file/to/edit'
1428
1429 Rename the section existing in C<filename> given by C<from> to the section
1430 given by C<to>.
1431
1432 Throws an exception C<No such section> if the section in C<from> doesn't exist
1433 in C<filename>.
1434
1435 If no value is given for C<to>, the section is removed instead of renamed.
1436
1437 Returns true on success, false if C<filename> didn't exist and thus
1438 the rename did nothing.
1439
1440 =head2 remove_section
1441
1442 Parameters:
1443
1444     section => 'section.subsection'
1445     filename => '/file/to/edit'
1446
1447 Just a convenience wrapper around L<"rename_section"> for readability's sake.
1448 Removes the given section (which you can do by renaming to nothing as well).
1449
1450 =head2 cascade( $bool )
1451
1452 Gets or sets if only the B<deepest> configuration file in a directory
1453 tree is loaded, or if all of them are loaded, shallowest to deepest.
1454 Alternately, C<cascade =E<gt> 1> can be passed to C<new>.
1455
1456 =head1 METHODS YOU MAY WISH TO OVERRIDE
1457
1458 If your application's configuration layout is different from the default, e.g.
1459 if its home directory config files are in a directory within the home
1460 directory (like C<~/.git/config>) instead of just dot-prefixed, override these
1461 methods to return the right directory names. For fancier things like altering
1462 precedence, you'll need to override L<"load"> as well.
1463
1464 =head2 dir_file
1465
1466 Return a string containing the path to a configuration file with the
1467 name C<confname> in a directory. The directory isn't specified here.
1468
1469 =head2 global_file
1470
1471 Return the string C</etc/confname>, the absolute name of the system-wide
1472 configuration file with name C<confname>.
1473
1474 =head2 user_file
1475
1476 Return a string containing the path to a configuration file
1477 in the current user's home directory with filename C<confname>.
1478
1479 =head2 load_dirs
1480
1481 Parameters:
1482
1483     '/path/to/look/in/'
1484
1485 Load the configuration file with the filename L<"dir_file"> in the current
1486 working directory into the memory or, if there is no config matching
1487 C<dir_file> in the current working directory, walk up the directory tree until
1488 one is found. (No error is thrown if none is found.) If an optional path
1489 is passed in, that directory will be used as the base directory instead
1490 of the working directory.
1491
1492 You'll want to use L<"load_file"> to load config files from your overridden
1493 version of this subroutine.
1494
1495 Returns nothing of note.
1496
1497 =head1 OTHER METHODS
1498
1499 These are mostly used internally in other methods, but could be useful anyway.
1500
1501 =head2 load_global
1502
1503 If a global configuration file with the absolute name given by
1504 L<"global_file"> exists, load its configuration variables into memory.
1505
1506 Returns the current contents of all the loaded configuration variables
1507 after the file has been loaded, or undef if no global config file is found.
1508
1509 =head2 load_user
1510
1511 If a configuration file with the absolute name given by
1512 L<"user_file"> exists, load its config variables into memory.
1513
1514 Returns the current contents of all the loaded configuration variables
1515 after the file has been loaded, or undef if no user config file is found.
1516
1517 =head2 load_file( $filename )
1518
1519 Takes a string containing the path to a file, opens it if it exists, loads its
1520 config variables into memory, and returns the currently loaded config
1521 variables (a hashref).
1522
1523 Note that you ought to only call this subroutine with an argument that you
1524 know exists, otherwise config files that don't exist will be recorded as
1525 havind been loaded.
1526
1527 =head2 parse_content
1528
1529 Parameters:
1530
1531     content => 'str'
1532     callback => sub {}
1533     error => sub {}
1534
1535 Parses the given content and runs callbacks as it finds valid information.
1536
1537 Returns undef on success and C<error($content)> (the original content) on
1538 failure.
1539
1540 C<callback> is called like:
1541
1542     callback(section => $str, offset => $num, length => $num, name => $str, value => $str)
1543
1544 C<name> and C<value> may be omitted if the callback is not being called on a
1545 key/value pair, or if it is being called on a key with no value.
1546
1547 C<error> is called like:
1548
1549     error( content => $content, offset => $offset )
1550
1551 Where C<offset> is the point in the content where the parse error occurred.
1552
1553 If you need to use this method, you might be interested in L<"error_callback">
1554 as well.
1555
1556 =head2 error_callback
1557
1558 Parameters:
1559
1560     content => 'str'
1561     offset => 45
1562     filename => '/foo/bar/.baz'
1563
1564 Made especially for passing to L<"parse_content">, passed through the
1565 C<error> parameter like this:
1566
1567     error => sub {
1568         error_callback( @_, filename => '/file/you/were/parsing' )
1569     }
1570
1571 It's used internally wherever L<"parse_content"> is used and will throw
1572 an exception with a useful message detailing the line number, position on
1573 the line, and contents of the bad line; if you find the need to use
1574 L<"parse_content"> elsewhere, you may find it useful as well.
1575
1576 =head2 set_multiple( $name )
1577
1578 Mark the key string C<$name> as containing multiple values.
1579
1580 Returns nothing.
1581
1582 =head2 is_multiple( $name )
1583
1584 Return a true value if the key string C<$name> contains multiple values; false
1585 otherwise.
1586
1587 =head2 define
1588
1589 Parameters:
1590
1591     section => 'str'
1592     name => 'str'
1593     value => 'str'
1594
1595 Given a section, a key name, and a value¸ store this information
1596 in memory in the config object.
1597
1598 Returns the value that was just defined on success, or undef
1599 if no name is given and thus the key cannot be defined.
1600
1601 =head2 cast
1602
1603 Parameters:
1604
1605     value => 'foo'
1606     as => 'int'
1607     human => 1
1608
1609 Return C<value> cast into the type specified by C<as>.
1610
1611 Valid values for C<as> are C<bool>, C<int>, C<num>, or C<bool-or-num>. For
1612 C<bool>, C<true>, C<yes>, C<on>, C<1>, and undef are translated into a true
1613 value (for Perl); anything else is false. Specifying a true value for the
1614 C<human> arg will get you a human-readable 'true' or 'false' rather than a
1615 value that plays along with Perl's definition of truthiness (0 or 1).
1616
1617 For C<int>s and C<num>s, if C<value> ends in C<k>, C<m>, or C<g>, it will be
1618 multiplied by 1024, 1048576, and 1073741824, respectively, before being
1619 returned. C<int>s are truncated after being multiplied, if they have
1620 a decimal portion.
1621
1622 C<bool-or-int>, as you might have guessed, gives you either
1623 a bool or an int depending on which one applies.
1624
1625 If C<as> is unspecified, C<value> is returned unchanged.
1626
1627 =head2 format_section
1628
1629 Parameters:
1630
1631     section => 'section.subsection'
1632     base => 1
1633
1634 Return a string containing the section/subsection header, formatted
1635 as it should appear in a config file. If C<bare> is true, the returned
1636 value is not followed be a newline.
1637
1638 =head2 format_definition
1639
1640 Parameters:
1641
1642     key => 'str'
1643     value => 'str'
1644     bare => 1
1645
1646 Return a string containing the key/value pair as they should be printed in the
1647 config file. If C<bare> is true, the returned value is not tab-indented nor
1648 followed by a newline.
1649
1650 =head1 DIFFERENCES FROM GIT-CONFIG
1651
1652 This module does the following things differently from git-config:
1653
1654 We are much more permissive about valid key names and section names.
1655 For variables, instead of limiting variable names to alphanumeric characters
1656 and -, we allow any characters except for = and newlines, including spaces as
1657 long as they are not leading or trailing, and . as long as the key name is
1658 quoted. For sections, any characters but whitespace, [], and " are allowed.
1659 You can enforce reading/writing only git-compatible variable names and section
1660 headers by passing C<compatible =E<gt> 1> to the constructor.
1661
1662 When replacing variable values and renaming sections, we merely use
1663 a substring replacement rather than writing out new lines formatted in the
1664 default manner for new lines. Git's replacement/renaming (as of
1665 1.6.3.2) is currently buggy and loses trailing comments and variables
1666 that are defined on the same line as a section being renamed. Our
1667 method preserves original formatting and surrounding information.
1668
1669 We also allow the 'num' type for casting, since in many cases we
1670 might want to be more lenient on numbers.
1671
1672 We truncate decimal numbers that are cast to C<int>s, whereas
1673 Git just rejects them.
1674
1675 We don't support NUL-terminating output (the --null flag to
1676 git-config). Who needs it?
1677
1678 =head1 BUGS
1679
1680 If you find any bugs in this module, report them at:
1681
1682   http://rt.cpan.org/
1683
1684 Include the version of the module you're using and any relevant problematic
1685 configuration files or code snippets.
1686
1687 =head1 SEE ALSO
1688
1689 L<http://www.kernel.org/pub/software/scm/git/docs/git-config.html#_configuration_file>,
1690 L<Config::GitLike::Git>, L<http://syncwith.us/> (C<Config::GitLike> is
1691 used in Prophet/SD and provides a working example)
1692
1693 =head1 LICENSE
1694
1695 This program is free software; you may modify and/or redistribute it
1696 under the same terms as Perl itself.
1697
1698 =head1 COPYRIGHT
1699
1700 Copyright 2010 Best Practical Solutions, LLC
1701
1702 =head1 AUTHORS
1703
1704 Alex Vandiver <alexmv@bestpractical.com>,
1705 Christine Spang <spang@bestpractical.com>