├── .github └── workflows │ └── linux.yml ├── .gitignore ├── Changes ├── META6.json ├── README.md ├── bin └── 6pm ├── dist.ini ├── lib ├── App │ └── six-pm │ │ ├── Installer.rakumod │ │ ├── Meta6.rakumod │ │ ├── SixPM.rakumod │ │ └── ZefInstaller.rakumod └── SixPM.rakumod └── t ├── 00-test-meta.rakutest └── 01-six-pm.rakutest /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: linux 2 | 3 | on: 4 | - push 5 | 6 | jobs: 7 | perl6: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | strategy: 12 | matrix: 13 | rakudo-star-version: 14 | - 'latest' 15 | 16 | container: 17 | image: rakudo-star:${{ matrix.rakudo-star-version }} 18 | 19 | steps: 20 | - uses: actions/checkout@v1 21 | - name: perl6 -v 22 | run: perl6 -v 23 | - name: Install Dependencies 24 | run: zef install --deps-only --/test . 25 | - name: Run Tests 26 | run: PERL6LIB=$PWD/lib prove -e perl6 -vr t 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.precomp 2 | raku-modules 3 | SixPM-0.0.11.tar.gz 4 | SixPM-0.0.11 5 | -------------------------------------------------------------------------------- /Changes: -------------------------------------------------------------------------------- 1 | Revision history for SixPM 2 | 3 | {{$NEXT}} 4 | 5 | 0.0.11 2024-08-09T00:09:12+01:00 6 | - Initial version 7 | -------------------------------------------------------------------------------- /META6.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": "zef:FCO", 3 | "authors": [ 4 | "Fernando Correa de Oliveira" 5 | ], 6 | "bin": { 7 | "6pm": "bin/6pm" 8 | }, 9 | "build-depends": [ 10 | ], 11 | "depends": [ 12 | "zef", 13 | "JSON::Class:auth" 14 | ], 15 | "description": "Raku module dependency manager (aka npm for Raku)", 16 | "license": "Artistic-2.0", 17 | "name": "SixPM", 18 | "perl": "v6.*", 19 | "production": true, 20 | "provides": { 21 | "App::six-pm::Installer": "lib/App/six-pm/Installer.rakumod", 22 | "App::six-pm::Meta6": "lib/App/six-pm/Meta6.rakumod", 23 | "App::six-pm::SixPM": "lib/App/six-pm/SixPM.rakumod", 24 | "App::six-pm::ZefInstaller": "lib/App/six-pm/ZefInstaller.rakumod", 25 | "SixPM": "lib/SixPM.rakumod" 26 | }, 27 | "resources": [ 28 | ], 29 | "scripts": { 30 | "test": "zef test ." 31 | }, 32 | "source-url": "https://github.com/FCO/6pm.git", 33 | "support": { 34 | "source": "git://github.com/FCO/6pm.git" 35 | }, 36 | "tags": [ 37 | "PACKAGE", 38 | "INSTALL", 39 | "CLI", 40 | "DEVEL", 41 | "TERMINAL", 42 | "UTILS", 43 | "COMMAND LINE" 44 | ], 45 | "test-depends": [ 46 | "Test::Mock", 47 | "Test::META" 48 | ], 49 | "version": "0.0.11" 50 | } 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 🕕 - 6pm 2 | ======= 3 | 4 | 6pm is a NPM for raku 5 | 6 | Create META6.json 7 | ----------------- 8 | 9 | ```bash 10 | $ mkdir TestProject 11 | $ cd TestProject/ 12 | $ 6pm init 13 | Project name [TestProject]: 14 | Project tags: 15 | raku version [6.*]: 16 | ``` 17 | 18 | Locally install a Module 19 | ------------------------ 20 | 21 | ```bash 22 | $ 6pm install Heap 23 | ===> Searching for: Heap 24 | ===> Testing: Heap:ver('0.0.1') 25 | ===> Testing [OK]: Heap:ver('0.0.1') 26 | ===> Installing: Heap:ver('0.0.1') 27 | ``` 28 | 29 | Locally install a Module and add it on depends of META6.json 30 | ------------------------------------------------------------ 31 | 32 | ```bash 33 | $ 6pm install Heap --save 34 | ===> Searching for: Heap 35 | ===> Testing: Heap:ver('0.0.1') 36 | ===> Testing [OK]: Heap:ver('0.0.1') 37 | ===> Installing: Heap:ver('0.0.1') 38 | ``` 39 | 40 | Run code using the local dependencies 41 | ------------------------------------- 42 | 43 | ```bash 44 | $ 6pm exec -- raku -MHeap -e 'say Heap.new: ' 45 | Heap.new: [e r q w] 46 | ``` 47 | 48 | Run a file using the local dependencies 49 | --------------------------------------- 50 | 51 | ```bash 52 | $ echo "use Heap; say Heap.new: " > bla.p6 53 | $ 6pm exec-file bla.p6 54 | Heap.new: [e r q w] 55 | ``` 56 | 57 | Make your code always use 6pm 58 | ----------------------------- 59 | 60 | ```bash 61 | $ echo "use SixPM; use Heap; say Heap.new: " > bla.p6 62 | $ raku bla.p6 63 | Heap.new: [e r q w] 64 | ``` 65 | 66 | Running scripts 67 | --------------- 68 | 69 | Add your script at your META6.json scripts field and run it with: 70 | 71 | ```bash 72 | $ cat META6.json 73 | { 74 | "name": "TestProject", 75 | "source-url": "", 76 | "perl": "6.*", 77 | "resources": [ 78 | 79 | ], 80 | "scripts": { 81 | "test": "zef test .", 82 | "my-script": "raku -MHeap -e 'say Heap.new: ^10'" 83 | }, 84 | "depends": [ 85 | 86 | ], 87 | "test-depends": [ 88 | "Test", 89 | "Test::META" 90 | ], 91 | "provides": { 92 | 93 | }, 94 | "tags": [ 95 | 96 | ], 97 | "version": "0.0.1", 98 | "authors": [ 99 | "fernando" 100 | ], 101 | "description": "" 102 | } 103 | $ 6pm run my-script 104 | Heap.new: [0 1 2 3 4 5 6 7 8 9] 105 | ``` 106 | 107 | -------------------------------------------------------------------------------- /bin/6pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env raku 2 | use v6; 3 | use App::six-pm::SixPM; 4 | my $*MAIN-ALLOW-NAMED-ANYWHERE = True; 5 | 6 | my $*DEBUG = so %*ENV<_6PM_DEBUG>; 7 | 8 | my IO::Path $base-dir = ".".IO.resolve; 9 | my IO::Path $default-to = $base-dir.child: "raku-modules"; 10 | 11 | my $six-pm = SixPM.new: :$base-dir, :$default-to; 12 | 13 | multi MAIN("init") { 14 | $six-pm.init 15 | } 16 | 17 | multi MAIN("install", Bool :f(:$force)) { 18 | $six-pm.install-deps: :$force 19 | } 20 | 21 | multi MAIN("install", +@modules, Bool :f(:$force), Bool :$save, Bool :$save-test, Bool :$save-build) { 22 | $six-pm.install: @modules, :$force, :$save, :$save-test, :$save-build 23 | } 24 | 25 | multi MAIN("exec", +@argv, *%pars where *.elems >= 1) is hidden-from-USAGE { 26 | die "Please, use -- before the command" 27 | } 28 | 29 | multi MAIN("exec", +@argv) { 30 | $six-pm.exec: @argv 31 | } 32 | 33 | multi MAIN("exec-file", $file, +@argv) { 34 | $six-pm.exec: ["raku", $file, |@argv], :path($file.IO); 35 | } 36 | 37 | multi MAIN("run", Str() $script) { 38 | $six-pm.run: $script 39 | } 40 | 41 | enum Scripts ; 42 | 43 | multi MAIN(Scripts $script) { 44 | $six-pm.run: $script.key 45 | } 46 | -------------------------------------------------------------------------------- /dist.ini: -------------------------------------------------------------------------------- 1 | name = 6pm 2 | 3 | [ReadmeFromPod] 4 | ; enable = false 5 | filename = lib/SixPM.rakumod 6 | 7 | [PruneFiles] 8 | ; match = ^ 'xt/' 9 | 10 | [UploadToZef] 11 | -------------------------------------------------------------------------------- /lib/App/six-pm/Installer.rakumod: -------------------------------------------------------------------------------- 1 | role Installer { 2 | method install(+@argv, *%pars) {...} 3 | } 4 | -------------------------------------------------------------------------------- /lib/App/six-pm/Meta6.rakumod: -------------------------------------------------------------------------------- 1 | use JSON::Class:auth; 2 | 3 | unit class App::six-pm::Meta6 does JSON::Class; 4 | 5 | has IO::Path $!file handles = "./META6.json".IO; 6 | 7 | has Str $.meta6 is json-skip-null is rw; 8 | has Str $.perl is json-skip-null is rw = "v6.*"; 9 | has Str $.name is json-skip-null is rw = ".".IO.resolve.basename; 10 | has Str $.version is json-skip-null is rw = "0.0.1"; 11 | has Str $.description is json-skip-null is rw = ""; 12 | has Str @.authors is json-skip-null is rw = [%*ENV // Empty]; 13 | has Str %.provides is json-skip-null is rw; 14 | has Str %.bin is json-skip-null is rw; 15 | has Str %.emulates is json-skip-null is rw; 16 | has Str %.supersedes is json-skip-null is rw; 17 | has Str %.superseded-by is json-skip-null is rw; 18 | has Str %.excludes is json-skip-null is rw; 19 | has Str @.depends is json-skip-null is rw = []; 20 | has Str @.build-depends is json-skip-null is rw = []; 21 | has Str @.test-depends is json-skip-null is rw = []; 22 | has Str %.resources is json-skip-null is rw; 23 | has Str %.support is json-skip-null is rw; 24 | has Bool $.production is json-skip-null is rw = False; 25 | has Str $.license is json-skip-null is rw = "https://opensource.org/licenses/Artistic-2.0"; 26 | has Str @.tags is json-skip-null is rw; 27 | has Str $.source-url is json-skip-null is rw; 28 | has Str %.scripts is json-skip-null is rw = { 29 | test => "zef test ." 30 | } 31 | 32 | method set-file($!file) {} 33 | 34 | method create(IO::Path:D $file) { 35 | my ::?CLASS:D $obj; 36 | if $file.f { 37 | $obj = ::?CLASS.from-json: $file.slurp 38 | } else { 39 | $obj = ::?CLASS.bless; 40 | } 41 | $obj.set-file: $file; 42 | $obj 43 | } 44 | 45 | method save() {$!file.spurt: $.to-json; self} 46 | 47 | method add-dependency(*@dep) { 48 | @!depends.append: @dep; 49 | @!depends .= unique; 50 | } 51 | 52 | method add-test-dependency(*@dep) { 53 | @!test-depends.append: @dep; 54 | @!test-depends .= unique; 55 | } 56 | 57 | method add-build-dependency(*@dep) { 58 | @!build-depends.append: @dep; 59 | @!build-depends .= unique; 60 | } 61 | 62 | method Bool(--> Bool()) {self.?f} 63 | -------------------------------------------------------------------------------- /lib/App/six-pm/SixPM.rakumod: -------------------------------------------------------------------------------- 1 | use App::six-pm::Meta6; 2 | use App::six-pm::Installer; 3 | use App::six-pm::ZefInstaller; 4 | use SixPM True; 5 | class SixPM { 6 | has IO::Path $.base-dir = ".".IO.resolve; 7 | has IO::Path $.default-to = find-sixpm-path $!base-dir; 8 | has App::six-pm::Meta6 $.meta .= create: $!base-dir.child: "META6.json"; 9 | 10 | has Bool $.DEBUG = False; 11 | has Installer $.installer = ZefInstaller.new: :$!default-to, :$!DEBUG; 12 | 13 | method get-project-name { prompt "Project name [{$!meta.name}]: " } 14 | method get-project-tags { prompt("Project tags (separated by space): ") } 15 | method get-raku-version { prompt "raku version [{$!meta.perl}]: " } 16 | 17 | method init(:$name, :@tags, :$perl-version) { 18 | unless $!meta { 19 | with $name -> $name { 20 | $!meta.name = $name 21 | } else { 22 | if $.get-project-name -> $name { 23 | $!meta.name = $name 24 | } 25 | } 26 | $!meta.tags = @tags || $.get-project-tags.words; 27 | with $perl-version -> $perl { 28 | $!meta.perl = $perl 29 | } else { 30 | if $.get-raku-version -> $perl { 31 | $!meta.perl = $perl 32 | } 33 | } 34 | 35 | if ".git/config".IO.e { 36 | my $git-config = ".git/config".IO.slurp; 37 | $!meta.source-url = ($git-config ~~ m{ \[remote \s+ \"origin\"\] \s+ url \s+ \= \s+ <(\S*)> }).Str; 38 | } 39 | $!meta.save 40 | } 41 | } 42 | 43 | method install-deps(Bool :f(:$force)) { 44 | %*ENV = "inst#{$!default-to.absolute}"; 45 | %*ENV ~= ":{$!default-to.absolute}/bin"; 46 | if 47 | $!meta and 48 | ( 49 | $!meta.depends.elems > 0 50 | or $!meta.test-depends.elems > 0 51 | or $!meta.build-depends.elems > 0 52 | ) 53 | { 54 | $.install(flat(|$!meta.build-depends, |$!meta.test-depends, |$!meta.depends), :$force) 55 | } else { 56 | die "Deu ruim"; 57 | } 58 | } 59 | 60 | method install(+@modules, Bool :f(:$force), Bool :$save, Bool :$save-test, Bool :$save-build) { 61 | %*ENV = "inst#{$!default-to.absolute}"; 62 | %*ENV ~= ":{$!default-to.absolute}/bin"; 63 | if $.installer.install(|@modules, :to($!default-to.absolute), :$force) { 64 | if $save { 65 | $!meta.add-dependency: @modules; 66 | $!meta.add-test-dependency: @modules; 67 | $!meta.add-build-dependency: @modules; 68 | $!meta.save 69 | } 70 | } else { 71 | die "Deu ruim" 72 | } 73 | } 74 | 75 | method exec(+@argv, IO::Path :$path) { 76 | my $inst = do with $path { 77 | find-sixpm-path $path 78 | } else { 79 | $!default-to.absolute 80 | } 81 | %*ENV = "inst#{$inst}"; 82 | %*ENV ~= ":{$inst}/bin"; 83 | run |@argv 84 | } 85 | 86 | method run(Str() $script) { 87 | %*ENV = "inst#{$!default-to.absolute}"; 88 | %*ENV ~= ":{$!default-to.absolute}/bin"; 89 | shell $_ with $!meta.scripts{$script} 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/App/six-pm/ZefInstaller.rakumod: -------------------------------------------------------------------------------- 1 | use App::six-pm::Installer; 2 | use SixPM True; 3 | class ZefInstaller does Installer { 4 | has $.DEBUG = False; 5 | has $.default-to = find-sixpm-path; 6 | method install(+@argv, :$to = $!default-to, *%pars) { 7 | $.run-zef("install", |@argv, :$to, |%pars) 8 | } 9 | 10 | method run-zef($zef-cmd, +@argv, IO::Path :$to = $!default-to, *%pars) { 11 | my @pars = %pars.kv.map: -> $k, $v { 12 | my $par = $k.chars == 1 ?? "-" !! "--"; 13 | do if $v ~~ Bool { 14 | "{$par}{$v ?? "" !! "/"}$k" if $v.DEFINITE 15 | } else { 16 | "$par$k=$v" 17 | } 18 | } 19 | my $cmd = "zef --to=inst#{$to.?absolute // $to} @pars[] $zef-cmd " 20 | ~ @argv.map({"'{.trans( [「'」] => [「\'」] )}'"}); 21 | note $cmd if $!DEBUG; 22 | shell $cmd, :err($*ERR), :out($*OUT) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/SixPM.rakumod: -------------------------------------------------------------------------------- 1 | #!raku 2 | no precompilation; 3 | 4 | sub find-sixpm-path($cwd is copy = $*PROGRAM.resolve.parent) { 5 | repeat { 6 | last if $++ > 10; 7 | my $p6m = $cwd.child("raku-modules"); 8 | return $p6m.resolve if $p6m.d; 9 | $cwd .= parent 10 | } while $cwd.resolve.absolute !~~ "/"; 11 | "./raku-modules".IO 12 | } 13 | 14 | sub EXPORT($find-path? --> Map()) { 15 | unless $find-path { 16 | if find-sixpm-path() -> IO::Path $path { 17 | use MONKEY-SEE-NO-EVAL; 18 | EVAL "use lib 'inst#{$path.absolute}'"; 19 | } else { 20 | die "'raku-modules' not found"; 21 | } 22 | } 23 | 24 | { 25 | '&find-sixpm-path' => &find-sixpm-path 26 | } 27 | } 28 | 29 | =begin pod 30 | 31 | =head1 🕕 - 6pm 32 | 33 | 6pm is a NPM for raku 34 | 35 | =head2 Create META6.json 36 | 37 | =begin code :lang 38 | 39 | $ mkdir TestProject 40 | $ cd TestProject/ 41 | $ 6pm init 42 | Project name [TestProject]: 43 | Project tags: 44 | raku version [6.*]: 45 | 46 | =end code 47 | 48 | =head2 Locally install a Module 49 | 50 | =begin code :lang 51 | 52 | $ 6pm install Heap 53 | ===> Searching for: Heap 54 | ===> Testing: Heap:ver('0.0.1') 55 | ===> Testing [OK]: Heap:ver('0.0.1') 56 | ===> Installing: Heap:ver('0.0.1') 57 | 58 | =end code 59 | 60 | =head2 Locally install a Module and add it on depends of META6.json 61 | 62 | =begin code :lang 63 | 64 | $ 6pm install Heap --save 65 | ===> Searching for: Heap 66 | ===> Testing: Heap:ver('0.0.1') 67 | ===> Testing [OK]: Heap:ver('0.0.1') 68 | ===> Installing: Heap:ver('0.0.1') 69 | 70 | =end code 71 | 72 | =head2 Run code using the local dependencies 73 | 74 | =begin code :lang 75 | 76 | $ 6pm exec -- raku -MHeap -e 'say Heap.new: ' 77 | Heap.new: [e r q w] 78 | 79 | =end code 80 | 81 | =head2 Run a file using the local dependencies 82 | 83 | =begin code :lang 84 | 85 | $ echo "use Heap; say Heap.new: " > bla.p6 86 | $ 6pm exec-file bla.p6 87 | Heap.new: [e r q w] 88 | 89 | =end code 90 | 91 | =head2 Make your code always use 6pm 92 | 93 | =begin code :lang 94 | 95 | $ echo "use SixPM; use Heap; say Heap.new: " > bla.p6 96 | $ raku bla.p6 97 | Heap.new: [e r q w] 98 | 99 | =end code 100 | 101 | =head2 Running scripts 102 | 103 | Add your script at your META6.json scripts field and run it with: 104 | 105 | =begin code :lang 106 | 107 | $ cat META6.json 108 | { 109 | "name": "TestProject", 110 | "source-url": "", 111 | "perl": "6.*", 112 | "resources": [ 113 | 114 | ], 115 | "scripts": { 116 | "test": "zef test .", 117 | "my-script": "raku -MHeap -e 'say Heap.new: ^10'" 118 | }, 119 | "depends": [ 120 | 121 | ], 122 | "test-depends": [ 123 | "Test", 124 | "Test::META" 125 | ], 126 | "provides": { 127 | 128 | }, 129 | "tags": [ 130 | 131 | ], 132 | "version": "0.0.1", 133 | "authors": [ 134 | "fernando" 135 | ], 136 | "description": "" 137 | } 138 | $ 6pm run my-script 139 | Heap.new: [0 1 2 3 4 5 6 7 8 9] 140 | 141 | =end code 142 | 143 | =end pod 144 | -------------------------------------------------------------------------------- /t/00-test-meta.rakutest: -------------------------------------------------------------------------------- 1 | #!raku 2 | 3 | use v6; 4 | use lib 'lib'; 5 | 6 | use Test; 7 | use Test::META; 8 | 9 | plan 1; 10 | 11 | # That's it 12 | meta-ok(); 13 | 14 | done-testing; 15 | -------------------------------------------------------------------------------- /t/01-six-pm.rakutest: -------------------------------------------------------------------------------- 1 | use lib "lib"; 2 | use Test; 3 | use Test::Mock; 4 | use App::six-pm::Meta6; 5 | use App::six-pm::Installer; 6 | use App::six-pm::ZefInstaller; 7 | 8 | plan 8; 9 | 10 | use-ok "App::six-pm::SixPM"; 11 | 12 | sub name is rw { state $a } 13 | 14 | { 15 | use App::six-pm::SixPM; 16 | 17 | subtest { 18 | my $meta = mocked(App::six-pm::Meta6, 19 | returning => { 20 | "Bool" => True 21 | } 22 | ); 23 | 24 | my $_6pm = SixPM.new: :$meta; 25 | 26 | $_6pm.init; 27 | 28 | check-mock $meta, 29 | *.called('Bool', :1times, with => :()) 30 | ; 31 | } 32 | 33 | subtest { 34 | my $meta = mocked(App::six-pm::Meta6, 35 | returning => { 36 | "Bool" => False, 37 | "depends" => [], 38 | "test-depends" => [], 39 | "build-depends" => [] 40 | }, 41 | ); 42 | 43 | my $_6pm = SixPM.new: :$meta; 44 | $_6pm does role :: { 45 | has $.get-project-name is rw = "my_test"; 46 | has $.get-project-tags is rw = "bla ble bli"; 47 | has $.get-raku-version is rw = "v6.*"; 48 | }; 49 | 50 | $_6pm.init; 51 | 52 | check-mock $meta, 53 | *.called('Bool', :1times), 54 | *.called('name', :1times), 55 | *.called('tags', :1times), 56 | *.called('perl', :1times), 57 | *.called('save', :1times), 58 | ; 59 | 60 | is $meta.name, "my_test"; 61 | is-deeply $meta.tags, ; 62 | is $meta.perl, "v6.*"; 63 | isnt $meta.source-url, ""; 64 | } 65 | 66 | subtest { 67 | my $meta = mocked(App::six-pm::Meta6, 68 | returning => { 69 | "Bool" => False, 70 | }, 71 | ); 72 | 73 | my $_6pm = SixPM.new: :$meta; 74 | 75 | $_6pm.init: :name:tags:perl-version; 76 | 77 | check-mock $meta, 78 | *.called('Bool', :1times), 79 | *.called('name', :1times), 80 | *.called('tags', :1times), 81 | *.called('perl', :1times), 82 | *.called('save', :1times), 83 | ; 84 | } 85 | 86 | subtest { 87 | my $meta = mocked(App::six-pm::Meta6, 88 | returning => { 89 | "Bool" => False, 90 | }, 91 | ); 92 | 93 | my $_6pm = SixPM.new: :$meta; 94 | dies-ok { 95 | $_6pm.install-deps; 96 | } 97 | } 98 | 99 | subtest { 100 | my $meta = mocked(App::six-pm::Meta6, 101 | returning => { 102 | "Bool" => True, 103 | "depends" => [], 104 | "test-depends" => [], 105 | "build-depends" => [] 106 | }, 107 | ); 108 | 109 | my $_6pm = SixPM.new: :$meta; 110 | 111 | $_6pm does role :: { 112 | method install(*@mod, :$save) { 113 | is-deeply @mod.Set, set ; 114 | nok $save; 115 | } 116 | } 117 | 118 | lives-ok { 119 | $_6pm.install-deps; 120 | } 121 | } 122 | 123 | subtest { 124 | my $meta = mocked(App::six-pm::Meta6, 125 | returning => { 126 | "Bool" => True, 127 | "depends" => [], 128 | "test-depends" => [], 129 | "build-depends" => [] 130 | }, 131 | ); 132 | 133 | my $_6pm = SixPM.new: :$meta; 134 | 135 | $_6pm does role :: { 136 | method install(+@mod, :$force, :$save) { 137 | is-deeply @mod.Set, set ; 138 | ok $force; 139 | nok $save; 140 | } 141 | } 142 | 143 | lives-ok { 144 | $_6pm.install-deps: :force; 145 | } 146 | } 147 | 148 | # TODO: Test::Mock doesn't work with roles 149 | subtest { 150 | my $installer = mocked(ZefInstaller, computing => { 151 | install => -> |c {say c; True} 152 | }); 153 | 154 | my $_6pm = SixPM.new: :$installer; 155 | 156 | $_6pm.install: "Bla"; 157 | 158 | check-mock $installer, 159 | *.called: "install", :1time, with => :("Bla", :$to!, :$force) 160 | ; 161 | } 162 | 163 | } 164 | --------------------------------------------------------------------------------