Skip to content

Instantly share code, notes, and snippets.

@perlpunk
Created May 14, 2020 14:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save perlpunk/f90f9a4f2ab36565c2f7da19d5bced7d to your computer and use it in GitHub Desktop.
Save perlpunk/f90f9a4f2ab36565c2f7da19d5bced7d to your computer and use it in GitHub Desktop.
inherit
---
- desc: lala
settings:
a: A
b: B
---
- crypt1:
desc: lala
settings:
a: NEW A
b: B
c: C
- crypt2:
desc: lala
settings:
a: NEW A
b: B
d: D
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
use Data::Dumper;
use YAML::PP;
my $yp = YAML::PP->new(
);
my $schema = $yp->schema;
$schema->add_sequence_resolver(
tag => '!deepmerge',
on_create => sub {
return {};
},
on_data => \&deepmerge,
);
$schema->add_mapping_resolver(
tag => '!inherit',
on_create => sub {
return {};
},
on_data => \&deepmerge,
);
sub deepmerge {
my ($constructor, $data, $list) = @_;
for my $hash (@$list) {
unless (ref($hash) eq 'HASH') {
die "Expected hash for !deepmerge but got $hash";
}
_deepmerge($$data, $hash);
}
}
sub _deepmerge {
my ($data, $merge) = @_;
for my $key (sort keys %$merge) {
my $value = $merge->{ $key };
unless (ref $value) {
# string
$data->{ $key } = $value;
next;
}
unless (exists $data->{ $key }) {
$data->{ $key } = ref $value eq 'HASH' ? {} : [];
_deepmerge($data->{ $key }, $value);
next;
}
if (ref $data->{ $key } ne 'HASH' or ref $value ne 'HASH') {
die "Merging not supported";
}
_deepmerge($data->{ $key }, $value);
}
}
my $yaml = do { local $/; <DATA> };
my @docs = $yp->load_string($yaml);
my $def = $docs[0]->{def};
my $data = $docs[0]->{scenarios};
say $yp->dump_string($def);
say $yp->dump_string($data);
__DATA__
def:
- &defaults
settings:
a: A
b: B
desc: lala
scenarios:
- crypt1: !deepmerge
- *defaults
- settings:
a: NEW A
c: C
- crypt2: !inherit
*defaults :
settings:
a: NEW A
d: D
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment