aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml43
-rw-r--r--CHANGELOG.md32
-rw-r--r--META6.json17
-rw-r--r--README.md12
-rw-r--r--README.rakudoc90
-rw-r--r--lib/Hash/Merge.pm660
-rw-r--r--lib/Hash/Merge.rakumod78
-rw-r--r--lib/Hash/Merge/Augment.pm663
-rw-r--r--lib/Hash/Merge/Augment.rakumod33
-rw-r--r--t/01-thing.rakutest (renamed from t/01-thing.t)8
-rw-r--r--t/02-empty-source.rakutest24
-rw-r--r--t/02-empty-source.t28
-rw-r--r--t/03-unit.rakutest (renamed from t/03-unit.t)4
13 files changed, 315 insertions, 177 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..9b5e3a2
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,43 @@
+stages:
+ - Test
+ - Release
+
+#
+# Tests
+#
+
+Prove:
+ stage: Test
+ image: registry.gitlab.com/tyil/docker-perl6:debian-dev-latest
+ cache:
+ key: ${CI_COMMIT_REF_NAME}
+ paths:
+ - /usr/local/share/perl6/site
+ before_script:
+ - apt update
+ - apt install -y build-essential
+ - zef install App::Prove6
+ - zef install --deps-only --test-depends --/test .
+ script: prove6 -l
+
+#
+# Release targets
+#
+
+Distribution:
+ stage: Release
+ only:
+ refs:
+ - tags
+ - master
+ image: rakudo-star
+ script:
+ - echo "NOOP"
+ artifacts:
+ name: App-CPAN-${CI_COMMIT_TAG}
+ paths:
+ - META6.json
+ - lib
+ - bin
+ - t
+ - resources
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9bcec5..c9db860 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,19 +1,51 @@
# Changelog
+
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic
Versioning](http://semver.org/spec/v2.0.0.html).
+## [2.0.0] - 2020-11-15
+
+### Added
+
+- A `gitlab-ci.yaml` has been added to ensure tests for this module are being
+ ran when pushed to the GitLab mirror. It runs `prove6`, as well as queueing a
+ build on rakudist.raku.org.
+
+### Changed
+
+- `Hash::Merge` has been rewritten to accomodate my current knowledge on the
+ Raku programming language. This additionaly brings in a small change in the
+ merging functionality, making it so the first argument passed to `merge-hash`
+ is no longer modified itself, which could cause some awkward bugs in other
+ programs.
+
+- The README has been rewritten in Pod6.
+
+- Perl 6 references have been updated to Raku.
+
+- The main repository for this module has been moved from
+ [GitHub](https://github.com/scriptkitties/p6-Hash-Merge.git) to
+ [Sourcehut](https://git.sr.ht/~tyil/raku-hash-merge).
+
## [1.0.0] - 2018-03-28
+
### Added
+
- `:api` key in `META6.json`
+
- New `Hash::Merge` that exposes subs instead of augmenting `Hash`
### Changed
+
- Old `Hash::Merge` functionality moved to `Hash::Merge::Augment`
## [0.2.0] - 2018-03-14
+
### Added
+
- `LICENSE` file for Artistic License 2.0 ([GitHub#2](https://github.com/scriptkitties/p6-Hash-Merge/issues/2))
+
- `no precompilation` pragma ([GitHub#1](https://github.com/scriptkitties/p6-Hash-Merge/issues/1))
diff --git a/META6.json b/META6.json
index aff3030..3e09fbe 100644
--- a/META6.json
+++ b/META6.json
@@ -1,22 +1,21 @@
{
- "api": "1",
+ "api": "2",
"auth": "github:scriptkitties",
"authors": [
"Samantha McVey <samantham@posteo.net>",
"Patrick Spek <p.spek@tyil.work>"
],
"depends": [
-
],
- "description": "Module to add deep merge functionality to Hashes",
+ "description": "Raku module to deep merge Hashes",
"license": "Artistic-2.0",
"name": "Hash::Merge",
- "perl": "6.c",
+ "perl": "6.d",
"provides": {
- "Hash::Merge": "lib/Hash/Merge.pm6",
- "Hash::Merge::Augment": "lib/Hash/Merge/Augment.pm6"
+ "Hash::Merge": "lib/Hash/Merge.rakumod",
+ "Hash::Merge::Augment": "lib/Hash/Merge/Augment.rakumod"
},
- "source-url": "https://github.com/scriptkitties/p6-Hash-Merge.git",
+ "source-url": "https://git.tyil.nl/raku/hash-merge",
"tags": [
"hash",
"utils"
@@ -24,5 +23,5 @@
"test-depends": [
"Test::META"
],
- "version": "1.0.0"
-} \ No newline at end of file
+ "version": "2.0.0"
+}
diff --git a/README.md b/README.md
deleted file mode 100644
index a83e503..0000000
--- a/README.md
+++ /dev/null
@@ -1,12 +0,0 @@
-[![Build Status](https://travis-ci.org/scriptkitties/p6-Hash-Merge.svg?branch=master)](https://travis-ci.org/scriptkitties/p6-Hash-Merge)
-
-### method merge
-
-```perl6
-method merge(
- %b,
- Bool:D :$no-append-array = Bool::False
-) returns Mu
-```
-
-Merges a second hash into the hash the method is called on. Hash given as the argument is not modified. Traverses the full tree, replacing items in the original hash with the hash given in the argument. Does not replace positional elements by default, and instead appends the items from the supplied hash's array to the original hash's array. The object type of positionals is not retained and instead becomes an Array type. Use :no-append-array to replace arrays and positionals instead, which will also retain the original type and not convert to an Array
diff --git a/README.rakudoc b/README.rakudoc
new file mode 100644
index 0000000..c9f3fc3
--- /dev/null
+++ b/README.rakudoc
@@ -0,0 +1,90 @@
+=begin pod
+
+=NAME Hash::Merge
+=VERSION 2.0.0
+=AUTHOR Patrick Spek <p.spek+raku@tyil.nl>
+
+=head1 Description
+
+A module for the Raku programming language to easily deep-merge two hashes.
+
+=head2 Usage
+
+Base usage requires you to C<use> the module, and pass two C<Hash>es to the
+imported function, C<merge-hash>.
+
+=begin code
+use Hash::Merge;
+
+my %alpha =
+ a => 'b',
+ c => {
+ d => 'e',
+ f => 'g',
+ },
+;
+
+my %beta =
+ z => 'y',
+ c => {
+ x => 'w',
+ },
+;
+
+my %merged = merge-hash(%alpha, %beta);
+=end code
+
+There are two potential options to pass to C<merge-hash>:
+
+=defn C<Bool:D :$deep = True>
+When set to C<False>, this will not deep merge the C<Hash>es. This means that
+the second C<Hash> that is passed, will I<overwrite> C<Hash> elements in the
+first C<Hash>, instead of combining them.
+
+=defn C<Bool:D :$positional-append = True>
+When set to C<False>, this will not append C<Positional> elements. This means
+that any C<Positional> elements in the second C<Hash> will I<overwrite>
+C<Positional> elements in the first C<Hash>.
+
+There is also a C<use> in this module that allows you to call C<.merge> on
+existing C<Hash> objects. This requires C<Hash::Merge::Augment>. While this is
+a fancy way to work, it will break pre-compilation of whatever module is using
+it.
+
+=begin code
+use Hash::Merge::Augment
+
+my %alpha =
+ a => 'b',
+ c => {
+ d => 'e',
+ f => 'g',
+ },
+;
+
+%alpha.merge({
+ z => 'y',
+ c => {
+ x => 'w',
+ },
+});
+=end code
+
+=head2 Contributing
+
+The module's source code is available at the following locations:
+
+=item L<https://git.sr.ht/~tyil/raku-hash-merge>
+=item L<https://gitlab.com/tyil/raku-hash-merge>
+=item L<https://github.com/scriptkitties/p6-Hash-Merge>
+
+If you have a change you would like to include, please send a patch to
+L<mailto:~tyil/raku-devel@lists.sr.ht>.
+
+=head2 License
+
+This module is distributed under the terms of the Artistic License 2.0. For
+more information, consult the LICENSE file in the module's source code
+repository.
+
+=end pod
diff --git a/lib/Hash/Merge.pm6 b/lib/Hash/Merge.pm6
deleted file mode 100644
index 607e17b..0000000
--- a/lib/Hash/Merge.pm6
+++ /dev/null
@@ -1,60 +0,0 @@
-#! /usr/bin/env false
-
-use v6.c;
-
-unit module Hash::Merge;
-
-#| Merge any number of Hashes together.
-sub merge-hashes(
- *@hashes, #= Hashes to merge together
- --> Hash
-) is export {
- my %merge-into = @hashes.shift;
-
- # Nothing to do if we only got 1 argument
- return %merge-into unless @hashes.elems;
-
- for ^@hashes.elems {
- %merge-into = merge-hash(%merge-into, @hashes.shift);
- }
-
- %merge-into;
-}
-
-#| Merge two hashes together.
-sub merge-hash(
- %merge-into, #= The original Hash that should be merged into.
- %merge-source, #= Another Hash to merge into the original Hash.
- Bool:D :$no-append-array = False,
- --> Hash
-) is export {
- for %merge-source.keys -> $key {
- if %merge-into{$key}:exists {
- given %merge-source{$key} {
- when Hash {
- merge-hash(%merge-into{$key}, %merge-source{$key}, :$no-append-array);
- }
- when Positional {
- %merge-into{$key} = $no-append-array
- ?? %merge-source{$key}
- !!
- do {
- my @a;
- @a.push: $_ for %merge-into{$key}.list;
- @a.push: $_ for %merge-source{$key}.list;
- @a;
- }
- }
- default {
- %merge-into{$key} = %merge-source{$key}
- }
- }
- } else {
- %merge-into{$key} = %merge-source{$key};
- }
- }
-
- %merge-into;
-}
-
-# vim: ft=perl6 ts=4 sw=4 et
diff --git a/lib/Hash/Merge.rakumod b/lib/Hash/Merge.rakumod
new file mode 100644
index 0000000..5d496a4
--- /dev/null
+++ b/lib/Hash/Merge.rakumod
@@ -0,0 +1,78 @@
+#! /usr/bin/env false
+
+use v6.d;
+
+unit module Hash::Merge;
+
+#| Merge any number of Hashes together.
+sub merge-hashes (
+ #| Any number of Hashes to merge together.
+ *@hashes,
+
+ --> Hash
+) is export {
+ my %result = @hashes.shift;
+
+ # Nothing to do if we only got 1 argument
+ return %result unless @hashes.elems;
+
+ for ^@hashes.elems {
+ %result = merge-hash(%result, @hashes.shift);
+ }
+
+ %result;
+}
+
+#| Merge two hashes together.
+sub merge-hash (
+ #| The original Hash to merge the second Hash into.
+ %first,
+
+ #| The second hash, which will be merged into the first Hash.
+ %second,
+
+ #| Boolean to set whether Associative objects should be merged on their
+ #| own. When set to False, Associative objects in %second will
+ #| overwrite those from %first.
+ Bool:D :$deep = True,
+
+ #| Boolean to set whether Positional objects should be appended. When
+ #| set to False, Positional objects in %second will overwrite those
+ #| from %first.
+ Bool:D :$positional-append = True,
+
+ --> Hash
+) is export {
+ my %result = %first;
+
+ for %second.keys -> $key {
+ # If the key doesn't exist yet in %first, it can be inserted without worry.
+ if (%first{$key}:!exists) {
+ %result{$key} = %second{$key};
+ next;
+ }
+
+ given (%first{$key}) {
+ # Associative objects need to be merged deeply.
+ when Associative {
+ %result{$key} = $deep
+ ?? merge-hash(%first{$key}, %second{$key}, :$deep, :$positional-append)
+ !! %second{$key}
+ }
+ # Positional objects can be merged or overwritten depending on $append-array.
+ when Positional {
+ %result{$key} = $positional-append
+ ?? (|%first{$key}, |%second{$key})
+ !! %second{$key}
+ }
+ # Anything else will just overwrite.
+ default {
+ %result{$key} = %second{$key};
+ }
+ }
+ }
+
+ %result;
+}
+
+# vim: ft=raku ts=4 sw=4 et
diff --git a/lib/Hash/Merge/Augment.pm6 b/lib/Hash/Merge/Augment.pm6
deleted file mode 100644
index 8de7542..0000000
--- a/lib/Hash/Merge/Augment.pm6
+++ /dev/null
@@ -1,63 +0,0 @@
-#! /usr/bin/env false
-
-use v6.c;
-use MONKEY-TYPING;
-
-# Don't use precompilation in order to not conflict with other MONKEY-TYPING
-# modules.
-no precompilation;
-
-augment class Hash
-{
- #| Merges a second hash into the hash the method is called on. Hash given as
- #| the argument is not modified.
- #| Traverses the full tree, replacing items in the original hash with the
- #| hash given in the argument. Does not replace positional elements by default,
- #| and instead appends the items from the supplied hash's array to the original
- #| hash's array. The object type of positionals is not retained and instead
- #| becomes an Array type.
- #| Use :no-append-array to replace arrays and positionals instead, which will
- #| also retain the original type and not convert to an Array
- multi method merge (Hash:U: %b, Bool:D :$no-append-array = False)
- {
- return %b;
- }
-
- multi method merge (Hash:D: %b, Bool:D :$no-append-array = False)
- {
- hashmerge self, %b, :$no-append-array;
- }
-
- sub hashmerge (%merge-into, %merge-source, Bool:D :$no-append-array)
- {
- for %merge-source.keys -> $key {
- if %merge-into{$key}:exists {
- given %merge-source{$key} {
- when Hash {
- hashmerge %merge-into{$key},
- %merge-source{$key},
- :$no-append-array;
- }
- when Positional {
- %merge-into{$key} = $no-append-array
- ?? %merge-source{$key}
- !!
- do {
- my @a;
- @a.push: $_ for %merge-into{$key}.list;
- @a.push: $_ for %merge-source{$key}.list;
- @a;
- }
- }
- # Non-positionals, so strings or Bools or whatever
- default { %merge-into{$key} = %merge-source{$key} }
- }
- } else {
- %merge-into{$key} = %merge-source{$key};
- }
- }
- %merge-into;
- }
-}
-
-# vim: ft=perl6 ts=4 sw=4 et
diff --git a/lib/Hash/Merge/Augment.rakumod b/lib/Hash/Merge/Augment.rakumod
new file mode 100644
index 0000000..e719dc1
--- /dev/null
+++ b/lib/Hash/Merge/Augment.rakumod
@@ -0,0 +1,33 @@
+#! /usr/bin/env false
+
+use v6.d;
+use MONKEY-TYPING;
+
+use Hash::Merge;
+
+# Don't use precompilation in order to not conflict with other MONKEY-TYPING
+# modules.
+no precompilation;
+
+augment class Hash {
+ method merge (
+ Hash:D:
+
+ #| The Hash to merge into this one.
+ %hash,
+
+ #| Boolean to set whether Associative objects should be merged on their
+ #| own. When set to False, Associative objects in %second will
+ #| overwrite those from %first.
+ Bool:D :$deep = True,
+
+ #| Boolean to set whether Positional objects should be appended. When
+ #| set to False, Positional objects in %second will overwrite those
+ #| from %first.
+ Bool:D :$positional-append = True,
+ ) {
+ self = merge-hash(self, %hash, :$deep, :$positional-append);
+ }
+}
+
+# vim: ft=raku ts=4 sw=4 et
diff --git a/t/01-thing.t b/t/01-thing.rakutest
index ef674ec..46c8055 100644
--- a/t/01-thing.t
+++ b/t/01-thing.rakutest
@@ -1,4 +1,4 @@
-#! /usr/bin/env perl6
+#! /usr/bin/env raku
use v6;
use lib 'lib';
@@ -46,9 +46,11 @@ is-deeply %a, {Z => 'new', a => 2, b => 1, y => {a => 1, z => 2}};
%z<y><p> = (1,2,3,4);
%y<y><p> = (5,4,6,7);
- %z.merge(%y, :no-append-array);
+ %z.merge(%y, :!positional-append);
- is-deeply %z, ${:y(${:p($(5, 4, 6, 7))})}, "no-append-array (replaces the instead)";
+ is-deeply %z, ${:y(${:p($(5, 4, 6, 7))})}, ":!positional-append makes lists overwrite";
}
done-testing;
+
+# vim: ft=raku ts=4 sw=4 et
diff --git a/t/02-empty-source.rakutest b/t/02-empty-source.rakutest
new file mode 100644
index 0000000..2e6b609
--- /dev/null
+++ b/t/02-empty-source.rakutest
@@ -0,0 +1,24 @@
+#! /usr/bin/env raku
+
+use v6.d;
+
+use Test;
+
+use Hash::Merge::Augment;
+
+plan 1;
+
+my %hash =
+ a => "a",
+ b => {
+ c => "c"
+ },
+;
+
+my %empty;
+
+%empty.merge(%hash);
+
+is-deeply %empty, %hash, "Merge into empty hash";
+
+# vim: ft=raku ts=4 sw=4 et
diff --git a/t/02-empty-source.t b/t/02-empty-source.t
deleted file mode 100644
index 2737d2d..0000000
--- a/t/02-empty-source.t
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /usr/bin/env perl6
-
-use v6.c;
-use lib 'lib';
-use Test;
-
-plan 3;
-
-use Hash::Merge::Augment;
-
-my Hash $hash = {
- a => "a",
- b => {
- c => "c"
- }
-};
-
-my Hash $empty = {};
-
-$empty.merge($hash);
-
-is-deeply $empty, $hash, "Merge into empty hash";
-
-my Hash $nil;
-
-
-throws-like $nil.merge($hash), Exception, "Merge into uninitialized hash";
-is-deeply $nil.merge($hash), $hash, "Returns supplied hash if it throws";
diff --git a/t/03-unit.t b/t/03-unit.rakutest
index 5230398..75d763f 100644
--- a/t/03-unit.t
+++ b/t/03-unit.rakutest
@@ -1,4 +1,4 @@
-#! /usr/bin/env perl6
+#! /usr/bin/env raku
use v6.c;
@@ -56,4 +56,4 @@ subtest "merge-hashes" => {
is-deeply merge-hashes(%original, %(b => %(d => "d")), %(b => %(e => "e"))), %result, "Hash merges correctly";
}
-# vim: ft=perl6 ts=4 sw=4 et
+# vim: ft=raku ts=4 sw=4 et