Skip to content

Commit 673a2dc

Browse files
authored
Merge pull request #57 from ralphschindler/feature-gzip-and-external-load
Feature: support creating and loading gzip snapshots
2 parents 473232a + d2c4f35 commit 673a2dc

File tree

11 files changed

+101
-15
lines changed

11 files changed

+101
-15
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ return [
8282
* The directory where temporary files will be stored.
8383
*/
8484
'temporary_directory_path' => storage_path('app/laravel-db-snapshots/temp'),
85+
86+
/*
87+
* Create dump files that are gzipped
88+
*/
89+
'compress' => false,
8590
];
8691
```
8792

@@ -100,6 +105,13 @@ Giving your snapshot a name is optional. If you don't pass a name the current da
100105
php artisan snapshot:create
101106
```
102107

108+
When creating snapshots, you can optionally create compressed snapshots. To do this either pass the `--compress` option on the command line, or set the `db-snapshots.compress` configuration option to `true`:
109+
110+
```bash
111+
# Creates a snapshot named my-compressed-dump.sql.gz
112+
php artisan snapshot:create my-compressed-dump --compress
113+
```
114+
103115
After you've made some changes to the database you can create another snapshot:
104116

105117
```bash

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@
1919
"php": "^7.0",
2020
"illuminate/support": "^5.4.30",
2121
"league/flysystem": "^1.0.41",
22-
"spatie/db-dumper": "^2.7",
22+
"spatie/db-dumper": "^2.11",
2323
"spatie/laravel-migrate-fresh": "^1.4.1",
2424
"spatie/temporary-directory": "^1.1"
2525
},
2626
"require-dev": {
2727
"mockery/mockery": "^0.9.8",
2828
"orchestra/testbench": "^3.4.10",
29-
"phpunit/phpunit": "^6.2 || ^7.0"
29+
"phpunit/phpunit": "^6.5 || ^7.0"
3030
},
3131
"autoload": {
3232
"psr-4": {

config/db-snapshots.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@
1717
* The directory where temporary files will be stored.
1818
*/
1919
'temporary_directory_path' => storage_path('app/laravel-db-snapshots/temp'),
20+
21+
/*
22+
* Create dump files that are gzipped
23+
*/
24+
'compress' => false,
2025
];

src/Commands/Create.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22

33
namespace Spatie\DbSnapshots\Commands;
44

5-
use DB;
65
use Carbon\Carbon;
76
use Illuminate\Console\Command;
87
use Spatie\DbSnapshots\Helpers\Format;
98
use Spatie\DbSnapshots\SnapshotFactory;
109

1110
class Create extends Command
1211
{
13-
protected $signature = 'snapshot:create {name?} {--connection=}';
12+
protected $signature = 'snapshot:create {name?} {--connection=} {--compress}';
1413

1514
protected $description = 'Create a new snapshot.';
1615

@@ -24,10 +23,13 @@ public function handle()
2423

2524
$snapshotName = $this->argument('name') ?: Carbon::now()->format('Y-m-d_H-i-s');
2625

26+
$compress = $this->option('compress', null);
27+
2728
$snapshot = app(SnapshotFactory::class)->create(
2829
$snapshotName,
2930
config('db-snapshots.disk'),
30-
$connectionName
31+
$connectionName,
32+
($compress !== null) ? $compress : (bool) config('db-snapshots.compress', false)
3133
);
3234

3335
$size = Format::humanReadableSize($snapshot->size());

src/Snapshot.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,22 @@ class Snapshot
2222
/** @var string */
2323
public $name;
2424

25+
/** @var string */
26+
public $compressionExtension = null;
27+
2528
public function __construct(Disk $disk, string $fileName)
2629
{
2730
$this->disk = $disk;
2831

2932
$this->fileName = $fileName;
3033

34+
$pathinfo = pathinfo($fileName);
35+
36+
if ($pathinfo['extension'] === 'gz') {
37+
$this->compressionExtension = $pathinfo['extension'];
38+
$fileName = $pathinfo['filename'];
39+
}
40+
3141
$this->name = pathinfo($fileName, PATHINFO_FILENAME);
3242
}
3343

@@ -43,6 +53,10 @@ public function load(string $connectionName = null)
4353

4454
$dbDumpContents = $this->disk->get($this->fileName);
4555

56+
if ($this->compressionExtension === 'gz') {
57+
$dbDumpContents = gzdecode($dbDumpContents);
58+
}
59+
4660
DB::connection($connectionName)->unprepared($dbDumpContents);
4761

4862
event(new LoadedSnapshot($this));

src/SnapshotFactory.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Illuminate\Contracts\Filesystem\Factory;
77
use Illuminate\Filesystem\FilesystemAdapter;
88
use Spatie\DbSnapshots\Events\CreatedSnapshot;
9+
use Spatie\DbDumper\Compressors\GzipCompressor;
910
use Spatie\DbSnapshots\Events\CreatingSnapshot;
1011
use Spatie\TemporaryDirectory\TemporaryDirectory;
1112
use Spatie\DbSnapshots\Exceptions\CannotCreateDisk;
@@ -25,20 +26,24 @@ public function __construct(DbDumperFactory $dumperFactory, Factory $filesystemF
2526
$this->filesystemFactory = $filesystemFactory;
2627
}
2728

28-
public function create(string $snapshotName, string $diskName, string $connectionName): Snapshot
29+
public function create(string $snapshotName, string $diskName, string $connectionName, bool $compress = false): Snapshot
2930
{
3031
$disk = $this->getDisk($diskName);
3132

3233
$fileName = $snapshotName.'.sql';
3334
$fileName = pathinfo($fileName, PATHINFO_BASENAME);
3435

36+
if ($compress) {
37+
$fileName .= '.gz';
38+
}
39+
3540
event(new CreatingSnapshot(
3641
$fileName,
3742
$disk,
3843
$connectionName
3944
));
4045

41-
$this->createDump($connectionName, $fileName, $disk);
46+
$this->createDump($connectionName, $fileName, $disk, $compress);
4247

4348
$snapshot = new Snapshot($disk, $fileName);
4449

@@ -63,13 +68,19 @@ protected function getDbDumper(string $connectionName): DbDumper
6368
return $factory::createForConnection($connectionName);
6469
}
6570

66-
protected function createDump(string $connectionName, string $fileName, FilesystemAdapter $disk)
71+
protected function createDump(string $connectionName, string $fileName, FilesystemAdapter $disk, bool $compress = false)
6772
{
6873
$directory = (new TemporaryDirectory(config('db-snapshots.temporary_directory_path')))->create();
6974

7075
$dumpPath = $directory->path($fileName);
7176

72-
$this->getDbDumper($connectionName)->dumpToFile($dumpPath);
77+
$dbDumper = $this->getDbDumper($connectionName);
78+
79+
if ($compress) {
80+
$dbDumper->useCompressor(new GzipCompressor());
81+
}
82+
83+
$dbDumper->dumpToFile($dumpPath);
7384

7485
$file = fopen($dumpPath, 'r');
7586

src/SnapshotRepository.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public function getAll(): Collection
1919
{
2020
return collect($this->disk->allFiles())
2121
->filter(function (string $fileName) {
22+
$pathinfo = pathinfo($fileName);
23+
24+
if ($pathinfo['extension'] === 'gz') {
25+
$fileName = $pathinfo['filename'];
26+
}
27+
2228
return pathinfo($fileName, PATHINFO_EXTENSION) === 'sql';
2329
})
2430
->map(function (string $fileName) {

tests/Commands/CreateTest.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,26 @@ public function it_can_create_a_snapshot_without_a_specific_name()
1515

1616
$fileName = Carbon::now()->format('Y-m-d_H-i-s').'.sql';
1717

18-
$this->assertFileOnDiskContains($fileName, 'CREATE TABLE "models"');
18+
$this->assertFileOnDiskPassesRegex($fileName, '/CREATE TABLE(?: IF NOT EXISTS){0,1} "models"/');
1919
}
2020

2121
/** @test */
2222
public function it_can_create_a_snapshot_with_specific_name()
2323
{
2424
Artisan::call('snapshot:create', ['name' => 'test']);
2525

26-
$this->assertFileOnDiskContains('test.sql', 'CREATE TABLE "models"');
26+
$this->assertFileOnDiskPassesRegex('test.sql', '/CREATE TABLE(?: IF NOT EXISTS){0,1} "models"/');
27+
}
28+
29+
/** @test */
30+
public function it_can_create_a_compressed_snapshot()
31+
{
32+
Artisan::call('snapshot:create', ['--compress' => true]);
33+
34+
$fileName = Carbon::now()->format('Y-m-d_H-i-s').'.sql.gz';
35+
36+
$this->disk->assertExists($fileName);
37+
38+
$this->assertNotEmpty(gzdecode($this->disk->get($fileName)));
2739
}
2840
}

tests/Commands/LoadTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ public function it_can_load_a_snapshot_with_connection_option()
5858
$this->assertSnapshotLoaded('snapshot2');
5959
}
6060

61+
/** @test */
62+
public function it_can_load_a_compressed_snapshot()
63+
{
64+
$this->assertSnapshotNotLoaded('snapshot4');
65+
66+
Artisan::call('snapshot:load', ['name' => 'snapshot4']);
67+
68+
$this->assertSnapshotLoaded('snapshot4');
69+
}
70+
6171
protected function assertSnapshotLoaded($snapshotName)
6272
{
6373
$this->assertEquals(

tests/SnapshotRepositoryTest.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function it_can_load_snapshots_from_a_disk()
2222
{
2323
$snapshots = $this->repository->getAll();
2424

25-
$this->assertCount(3, $snapshots);
25+
$this->assertCount(4, $snapshots);
2626

2727
$this->assertInstanceOf(Snapshot::class, $snapshots->first());
2828
}
@@ -32,6 +32,18 @@ public function it_can_get_a_snapshot_by_name()
3232
{
3333
$this->assertInstanceOf(Snapshot::class, $this->repository->findByName('snapshot2'));
3434

35-
$this->assertNull($this->repository->findByName('snapshot4'));
35+
$this->assertNull($this->repository->findByName('snapshot5'));
36+
}
37+
38+
/** @test */
39+
public function it_can_find_gz_compressed_snapshots()
40+
{
41+
$snapshot = $this->repository->findByName('snapshot4');
42+
43+
$this->assertInstanceOf(Snapshot::class, $snapshot);
44+
45+
$this->assertEquals('gz', $snapshot->compressionExtension);
46+
47+
$this->assertNull($this->repository->findByName('snapshot5'));
3648
}
3749
}

0 commit comments

Comments
 (0)