Skip to content

Commit 18b5662

Browse files
authored
Merge pull request #5 from xp-forge/refactor/sources
Unique given sources
2 parents d2bdbf6 + f18ee36 commit 18b5662

File tree

4 files changed

+130
-24
lines changed

4 files changed

+130
-24
lines changed

src/main/php/xp/lambda/PackageLambda.class.php

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
11
<?php namespace xp\lambda;
22

33
use io\Path;
4-
use io\archive\zip\{ZipFile, ZipDirEntry, ZipFileEntry, Compression};
4+
use io\archive\zip\{ZipFile, ZipArchiveWriter, ZipDirEntry, ZipFileEntry, Compression};
55
use io\streams\StreamTransfer;
66
use util\cmd\Console;
77

88
class PackageLambda {
99
const COMPRESSION_THRESHOLD = 24;
1010

11-
private $target, $sources, $base, $exclude, $compression;
11+
private $target, $sources, $exclude, $compression;
1212

13-
public function __construct(Path $target, Path $base, array $sources, string $exclude= '#(^|/)(\..+|src/test|src/it)(/|$)#') {
13+
public function __construct(Path $target, Sources $sources, string $exclude= '#(^|/)(\..+|src/test|src/it)(/|$)#') {
1414
$this->target= $target;
15-
$this->base= $base->asRealpath();
1615
$this->sources= $sources;
1716
$this->exclude= $exclude;
1817

@@ -26,38 +25,38 @@ public function __construct(Path $target, Path $base, array $sources, string $ex
2625
}
2726
}
2827

29-
/** Returns ZIP file entries */
30-
private function entries(Path $path) {
28+
/** Adds ZIP file entries */
29+
private function add(ZipArchiveWriter $zip, Path $path) {
3130
if (preg_match($this->exclude, $path->toString('/'))) return;
3231

33-
$relative= trim(str_replace($this->base, '', $path), DIRECTORY_SEPARATOR);
32+
$relative= $path->relativeTo($this->sources->base);
3433
if ($path->isFile()) {
35-
yield function($z) use($relative, $path) {
36-
$file= $z->add(new ZipFileEntry($relative));
34+
$file= $zip->add(new ZipFileEntry($relative));
3735

38-
// See https://stackoverflow.com/questions/46716095/minimum-file-size-for-compression-algorithms
39-
if (filesize($path) > self::COMPRESSION_THRESHOLD) {
40-
$file->setCompression($this->compression, 9);
41-
}
42-
(new StreamTransfer($path->asFile()->in(), $file->out()))->transferAll();
43-
return $file;
44-
};
36+
// See https://stackoverflow.com/questions/46716095/minimum-file-size-for-compression-algorithms
37+
if (filesize($path) > self::COMPRESSION_THRESHOLD) {
38+
$file->setCompression($this->compression, 9);
39+
}
40+
(new StreamTransfer($path->asFile()->in(), $file->out()))->transferAll();
41+
yield $file;
4542
} else {
46-
yield function($z) use($relative) { return $z->add(new ZipDirEntry($relative)); };
43+
yield $zip->add(new ZipDirEntry($relative));
4744
foreach ($path->asFolder()->entries() as $entry) {
48-
yield from $this->entries($entry);
45+
yield from $this->add($zip, $entry);
4946
}
5047
}
5148
}
5249

5350
public function run(): int {
5451
Console::writeLine('[+] Creating ', $this->target, ' (compression: ', $this->compression, ')');
5552
$z= ZipFile::create($this->target->asFile()->out());
56-
foreach ($this->sources as $i => $source) {
57-
Console::writef("\e[34m => [%d/%d] ", $i + 1, sizeof($this->sources) + 1);
53+
54+
$sources= [...$this->sources];
55+
$total= sizeof($sources) + 1;
56+
foreach ($sources as $i => $source) {
57+
Console::writef("\e[34m => [%d/%d] ", $i + 1, $total);
5858
$entries= 0;
59-
foreach ($this->entries(new Path($source)) as $action) {
60-
$entry= $action($z);
59+
foreach ($this->add($z, new Path($source)) as $entry) {
6160
$entries++;
6261
Console::writef('%-60s %4d%s', substr($entry->getName(), -60), $entries, str_repeat("\x08", 65));
6362
}
@@ -66,7 +65,7 @@ public function run(): int {
6665

6766
$file= $z->add(new ZipFileEntry('class.pth'));
6867
$file->out()->write(preg_replace($this->exclude.'m', '?$1', file_get_contents('class.pth')));
69-
Console::writeLinef("\e[34m => [%1\$d/%1\$d] class.pth\e[0m", sizeof($this->sources) + 1);
68+
Console::writeLinef("\e[34m => [%1\$d/%1\$d] class.pth\e[0m", $total);
7069

7170
$z->close();
7271
Console::writeLine();

src/main/php/xp/lambda/Runner.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private static function resolve(string $version= null): string {
5252
private static function command(string $name, array $args): object {
5353
sscanf($name, "%[^:]:%[^\r]", $command, $version);
5454
switch ($command) {
55-
case 'package': return new PackageLambda(new Path('function.zip'), new Path('.'), [...$args, 'src', 'vendor']);
55+
case 'package': return new PackageLambda(new Path('function.zip'), new Sources(new Path('.'), [...$args, 'src', 'vendor']));
5656
case 'runtime': return new CreateRuntime(self::resolve($version), new Path('runtime-%s.zip'), in_array('-b', $args));
5757
case 'test': return new TestLambda(self::resolve($version), new Path('.'), $args[0] ?? 'Handler', $args[1] ?? '{}');
5858
default: return new DisplayError('Unknown command "'.$args[0].'"');
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php namespace xp\lambda;
2+
3+
use IteratorAggregate, Traversable;
4+
use io\Path;
5+
6+
/** Returns a unique list of sources */
7+
class Sources implements IteratorAggregate {
8+
public $base;
9+
private $sources;
10+
11+
public function __construct(Path $base, array $sources) {
12+
$this->base= $base->asRealpath();
13+
$this->sources= $sources;
14+
}
15+
16+
public function getIterator(): Traversable {
17+
$seen= [];
18+
foreach ($this->sources as $source) {
19+
$path= ($source instanceof Path ? $source : new Path($source))->asRealpath();
20+
21+
$key= $path->hashCode();
22+
if (isset($seen[$key])) continue;
23+
24+
yield $path;
25+
$seen[$key]= true;
26+
}
27+
}
28+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php namespace com\amazon\aws\lambda\unittest;
2+
3+
use io\{Folder, File, Path};
4+
use lang\Environment;
5+
use unittest\{Assert, After, Test, Values};
6+
use xp\lambda\Sources;
7+
8+
class SourcesTest {
9+
private $cleanup= [];
10+
11+
/** Creates a directory given a layout */
12+
private function directory(array $layout): Path {
13+
$dir= new Folder(Environment::tempDir(), uniqid());
14+
$dir->create() && $this->cleanup[]= $dir;
15+
16+
foreach ($layout as $name => $contents) {
17+
if (null === $contents) {
18+
$f= new Folder($dir, $name);
19+
$f->create();
20+
} else {
21+
$f= new File($dir, $name);
22+
$f->touch();
23+
}
24+
}
25+
26+
return new Path($dir);
27+
}
28+
29+
#[After]
30+
public function cleanup() {
31+
foreach ($this->cleanup as $folder) {
32+
$folder->unlink();
33+
}
34+
}
35+
36+
#[Test]
37+
public function can_create() {
38+
new Sources(new Path('.'), []);
39+
}
40+
41+
#[Test, Values([[['%s/test.txt']], [['%s/test.txt', '%s/test.txt', '%s/./test.txt', '%s/../%s/test.txt']]])]
42+
public function with_one_file($sources) {
43+
$dir= $this->directory(['test.txt' => 'Test']);
44+
45+
Assert::equals(
46+
[new Path($dir, 'test.txt')],
47+
iterator_to_array(new Sources($dir, array_map(
48+
function($source) use($dir) { return sprintf($source, $dir, $dir->name()); },
49+
$sources
50+
)))
51+
);
52+
}
53+
54+
#[Test, Values([[['%s/src']], [['%s/src', '%s/src', '%s/./src', '%s/../%s/src']]])]
55+
public function with_one_directory($sources) {
56+
$dir= $this->directory(['src' => null]);
57+
58+
Assert::equals(
59+
[new Path($dir, 'src')],
60+
iterator_to_array(new Sources($dir, array_map(
61+
function($source) use($dir) { return sprintf($source, $dir, $dir->name()); },
62+
$sources
63+
)))
64+
);
65+
}
66+
67+
#[Test, Values([[['%s/src', '%s/vendor', '%s/test.txt']], [['%s/src', '%s/vendor', '%s/test.txt', '%s/src', '%s/./vendor']]])]
68+
public function with_files_and_directories($sources) {
69+
$dir= $this->directory(['src' => null, 'vendor' => null, 'test.txt' => 'Test']);
70+
71+
Assert::equals(
72+
[new Path($dir, 'src'), new Path($dir, 'vendor'), new Path($dir, 'test.txt')],
73+
iterator_to_array(new Sources($dir, array_map(
74+
function($source) use($dir) { return sprintf($source, $dir, $dir->name()); },
75+
$sources
76+
)))
77+
);
78+
}
79+
}

0 commit comments

Comments
 (0)