This repository has been archived by the owner on Nov 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlive.php
150 lines (126 loc) · 4.92 KB
/
live.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?php declare(strict_types=1);
namespace Bref;
use AsyncAws\Core\Exception\Http\RedirectionException;
use AsyncAws\S3\Exception\NoSuchKeyException;
use AsyncAws\S3\S3Client;
use RuntimeException;
use ZipArchive;
if (! function_exists('Bref\live')) {
function live(string $entryPoint)
{
if (!getenv('BREF_LIVE_ENABLE')) return;
$baseRoot = getenv('LAMBDA_TASK_ROOT');
$newRoot = '/tmp/.bref-live';
// Not on Lambda
if (! $baseRoot) return;
// We are in /tmp, let the application execute as usual
if (strpos($entryPoint, $newRoot) === 0) return;
$stderr = fopen('php://stderr', 'ab');
if (! is_dir($newRoot)) {
$startCopy = microtime(true);
recursiveCopy($baseRoot, $newRoot);
$copyDuration = (int) ((microtime(true) - $startCopy) * 1000);
fwrite($stderr, "Bref Live Edit: Initialized in $copyDuration ms\n");
}
chdir($newRoot);
// Require the new autoloader from now on (we'll need it for the S3 client)
require $newRoot . '/vendor/autoload.php';
$startSync = microtime(true);
applyChanges($baseRoot, $newRoot, $stderr);
$syncDuration = (int) ((microtime(true) - $startSync) * 1000);
fwrite($stderr, "Bref Live Edit: Synchronized live code in $syncDuration ms\n");
// Run the original file in the new /tmp copy
require str_replace($baseRoot, $newRoot, $entryPoint);
fclose($stderr);
// Stop the rest of the application from running (it's the /var/task original version)
exit(0);
}
function recursiveCopy($source, $target)
{
// Missing file
if (! file_exists($source)) {
unlink($target);
return;
}
// Check for symlinks
if (is_link($source)) {
symlink(readlink($source), $target);
return;
}
// Simple copy for a file
if (is_file($source)) {
copy($source, $target);
return;
}
// Make destination directory
if (! is_dir($target)) {
if (! mkdir($target) && ! is_dir($target)) {
throw new RuntimeException(sprintf('Directory "%s" was not created', $target));
}
}
// Loop through the folder
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry === '.' || $entry === '..') continue;
// Deep copy directories
recursiveCopy("$source/$entry", "$target/$entry");
}
$dir->close();
}
function applyChanges(string $baseRoot, string $newRoot, $stderr)
{
$region = getenv('AWS_REGION');
$functionName = getenv('AWS_LAMBDA_FUNCTION_NAME');
$zipKey = "$region/$functionName.zip";
$s3 = new S3Client([
'region' => getenv('BREF_LIVE_BUCKET_REGION'),
]);
$params = [
'Bucket' => getenv('BREF_LIVE_BUCKET'),
'Key' => $zipKey,
];
// Download the new zip only if it was modified
if (file_exists('/tmp/.bref-live-etag.txt')) {
$params['IfNoneMatch'] = file_get_contents('/tmp/.bref-live-etag.txt');
}
try {
$result = $s3->getObject($params);
file_put_contents('/tmp/.bref-live-etag.txt', $result->getEtag());
$fp = fopen('/tmp/.bref-live.zip', 'wb');
stream_copy_to_stream($result->getBody()->getContentAsResource(), $fp);
} catch (NoSuchKeyException $e) {
fwrite($stderr, "Bref Live Edit: No changes to apply\n");
return;
} catch (RedirectionException $e) {
if ($e->getResponse()->getStatusCode() !== 304) {
throw $e;
}
// We are already up to date!
fwrite($stderr, "Bref Live Edit: Up to date\n");
return;
}
$zip = new ZipArchive();
$zip->open('/tmp/.bref-live.zip');
// Restore previously modified paths
if (file_exists('/tmp/.bref-live-modified.json')) {
$previouslyModifiedPaths = file('/tmp/.bref-live-modified.json');
foreach ($previouslyModifiedPaths as $path) {
$path = trim($path);
// If the previously changed files are no longer in the zip, we need to restore the original version
if ($zip->locateName($path) === false) {
recursiveCopy($baseRoot . '/' . $path, $newRoot . '/' . $path);
}
}
}
// Extract new files from zip
$zip->extractTo($newRoot);
// Store modified paths
$modifiedPaths = [];
for ($i = 0; $i < $zip->numFiles; $i++){
$modifiedPaths[] = $zip->getNameIndex($i);
}
file_put_contents('/tmp/.bref-live-modified.json', implode(PHP_EOL, $modifiedPaths));
$zip->close();
}
}