Skip to content

Commit 52d7e9b

Browse files
committed
fix(sqlite): [UPD] treat db-name as file name under core/database
1 parent 77b7590 commit 52d7e9b

8 files changed

Lines changed: 70 additions & 47 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ evo install my-project --extras=sTask@main,sSeo # Install extras after setup (o
122122
- `--db-type`: Database type (`mysql`, `pgsql`, `sqlite`, or `sqlsrv`)
123123
- `--db-host`: Database host (default: `localhost`, not used for SQLite)
124124
- `--db-port`: Database port (defaults: 3306 for MySQL, 5432 for PostgreSQL, 1433 for SQL Server)
125-
- `--db-name`: Database name (for SQLite: path to database file, default: `core/database/database.sqlite`)
125+
- `--db-name`: Database name (for SQLite: database file name stored under `core/database/`, default: `database.sqlite`)
126126
- `--db-user`: Database user (not used for SQLite)
127127
- `--db-password`: Database password (not used for SQLite). If it contains shell special characters (e.g. `;`, `&`, `!`), quote it: `--db-password='p;ass'`.
128128
- `--admin-username`: Admin username
@@ -148,7 +148,7 @@ evo install demo \
148148
--cli \
149149
--branch=3.5.x \
150150
--db-type=sqlite \
151-
--db-name=core/database/database.sqlite \
151+
--db-name=database.sqlite \
152152
--admin-username=admin \
153153
--admin-email=admin@example.com \
154154
--admin-password=123456 \

internal/engine/install/engine.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,8 @@ func (e *Engine) Run(ctx context.Context, ch chan<- domain.Event, actions <-chan
509509
Active: true,
510510
ID: "db_sqlite_path",
511511
Kind: domain.QuestionInput,
512-
Prompt: "What is the path to your SQLite database file?",
513-
Default: defaultSQLiteDatabasePath(),
512+
Prompt: "What is the name of your SQLite database file?",
513+
Default: defaultSQLiteDatabaseName(),
514514
})
515515
if !ok {
516516
return
@@ -524,7 +524,7 @@ func (e *Engine) Run(ctx context.Context, ch chan<- domain.Event, actions <-chan
524524
Source: "install",
525525
Severity: domain.SeverityInfo,
526526
Payload: domain.LogPayload{
527-
Message: "Selected database path: " + dbName + ".",
527+
Message: "Selected database name: " + dbName + ".",
528528
},
529529
})
530530
default:
@@ -1763,8 +1763,8 @@ func defaultPort(dbType string) int {
17631763
}
17641764
}
17651765

1766-
func defaultSQLiteDatabasePath() string {
1767-
return filepath.ToSlash(filepath.Join("core", "database", "database.sqlite"))
1766+
func defaultSQLiteDatabaseName() string {
1767+
return "database.sqlite"
17681768
}
17691769

17701770
func dbDriverLabel(dbType string) string {
@@ -1854,7 +1854,10 @@ try {
18541854
$pass = $cfg["password"] ?? "";
18551855
$timeout = [\PDO::ATTR_TIMEOUT => 5];
18561856
if ($type === "sqlite") {
1857-
if ($name === "") { echo json_encode(["ok"=>false,"error"=>"SQLite database path is required."]); exit(0); }
1857+
if ($name === "") { echo json_encode(["ok"=>false,"error"=>"SQLite database name is required."]); exit(0); }
1858+
if ($name !== ":memory:" && !str_starts_with($name, "file:") && !preg_match('/^(\/|[A-Za-z]:[\\\\\\/])/', $name)) {
1859+
$name = "core/database/" . basename(str_replace("\\", "/", $name));
1860+
}
18581861
new \PDO("sqlite:".$name, null, null, $timeout);
18591862
echo json_encode(["ok"=>true]); exit(0);
18601863
}

internal/ui/view.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ var logValuePrefixes = []string{
523523
"Selected database name:",
524524
"Selected database user:",
525525
"Selected database password:",
526-
"Selected database path:",
526+
"Selected database name:",
527527
"Your Admin username:",
528528
"Your Admin email:",
529529
"Your Admin password:",

src/Commands/InstallCommand.php

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -391,20 +391,20 @@ protected function askDatabaseHost(): string
391391
/**
392392
* Ask for database name.
393393
*
394-
* @param string|null $type Database type (for SQLite, asks for file path)
394+
* @param string|null $type Database type (for SQLite, asks for file name)
395395
*/
396396
protected function askDatabaseName(?string $type = null): string
397397
{
398398
if ($type === 'sqlite') {
399-
$defaultPath = $this->defaultSqliteDatabasePath();
399+
$defaultName = $this->defaultSqliteDatabaseName();
400400
$answer = $this->tui->ask(
401-
'What is the path to your SQLite database file?',
402-
$defaultPath
401+
'What is the name of your SQLite database file?',
402+
$defaultName
403403
);
404404

405-
$this->tui->replaceLastLogs('<fg=green>✔</> Selected database path: ' . $answer . '.', 2);
405+
$this->tui->replaceLastLogs('<fg=green>✔</> Selected database name: ' . $answer . '.', 2);
406406

407-
return $this->normalizeSqliteDatabasePath($answer ?: $defaultPath);
407+
return $this->normalizeSqliteDatabaseName($answer ?: $defaultName);
408408
}
409409

410410
$answer = $this->tui->ask(
@@ -491,8 +491,8 @@ protected function testDatabaseConnection(array $config): bool
491491
if ($type === 'sqlite') {
492492
// SQLite: Connect directly to the database file
493493
if (empty($config['name'])) {
494-
$this->tui->replaceLastLogs('<fg=red>✗</> Database connection failed: SQLite database path is required.', 2);
495-
$this->lastDatabaseConnectionError = 'SQLite database path is required.';
494+
$this->tui->replaceLastLogs('<fg=red>✗</> Database connection failed: SQLite database name is required.', 2);
495+
$this->lastDatabaseConnectionError = 'SQLite database name is required.';
496496
return false;
497497
}
498498
$this->createConnection($config);
@@ -2682,7 +2682,7 @@ protected function assertDatabaseReadyForPackageDiscovery(string $projectPath, a
26822682

26832683
if ($type === 'sqlite') {
26842684
if ($dbName === '') {
2685-
throw new \RuntimeException('SQLite database path is empty.');
2685+
throw new \RuntimeException('SQLite database name is empty.');
26862686
}
26872687
if ($dbName !== ':memory:' && !str_starts_with($dbName, 'file:') && !is_file($dbName)) {
26882688
throw new \RuntimeException("SQLite database file not found: {$dbName}");
@@ -3324,7 +3324,7 @@ protected function getDatabaseConfigForOperations(string $projectPath, array $db
33243324
return $dbConfig;
33253325
}
33263326

3327-
$name = $this->normalizeSqliteDatabasePath((string) ($dbConfig['name'] ?? ''));
3327+
$name = $this->resolveSqliteDatabasePath((string) ($dbConfig['name'] ?? ''));
33283328
$dbConfig['name'] = $name;
33293329
if ($name === '' || $name === ':memory:' || str_starts_with($name, 'file:')) {
33303330
return $dbConfig;
@@ -3340,16 +3340,16 @@ protected function getDatabaseConfigForOperations(string $projectPath, array $db
33403340
return $dbConfig;
33413341
}
33423342

3343-
protected function defaultSqliteDatabasePath(): string
3343+
protected function defaultSqliteDatabaseName(): string
33443344
{
3345-
return 'core/database/database.sqlite';
3345+
return 'database.sqlite';
33463346
}
33473347

3348-
protected function normalizeSqliteDatabasePath(string $path): string
3348+
protected function resolveSqliteDatabasePath(string $path): string
33493349
{
33503350
$path = trim($path);
33513351
if ($path === '') {
3352-
return $this->defaultSqliteDatabasePath();
3352+
return 'core/database/' . $this->defaultSqliteDatabaseName();
33533353
}
33543354

33553355
if ($path === ':memory:' || str_starts_with($path, 'file:')) {
@@ -3360,18 +3360,22 @@ protected function normalizeSqliteDatabasePath(string $path): string
33603360
return $path;
33613361
}
33623362

3363-
$normalized = str_replace('\\', '/', $path);
3364-
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
3365-
$normalized = ltrim($normalized, '/');
3366-
if ($normalized === '') {
3367-
return $this->defaultSqliteDatabasePath();
3368-
}
3363+
return 'core/database/' . $this->normalizeSqliteDatabaseName($path);
3364+
}
33693365

3370-
if (!str_contains($normalized, '/')) {
3371-
return 'core/database/' . $normalized;
3366+
protected function normalizeSqliteDatabaseName(string $name): string
3367+
{
3368+
$name = trim($name);
3369+
if ($name === '') {
3370+
return $this->defaultSqliteDatabaseName();
33723371
}
33733372

3374-
return $normalized;
3373+
$normalized = str_replace('\\', '/', $name);
3374+
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
3375+
$normalized = trim($normalized, '/');
3376+
$basename = basename($normalized);
3377+
3378+
return ($basename !== '' && $basename !== '.') ? $basename : $this->defaultSqliteDatabaseName();
33753379
}
33763380

33773381
/**

src/Concerns/ConfiguresDatabase.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,16 +270,13 @@ protected function normalizeRelativeSqliteDatabasePath(string $path): string
270270
{
271271
$normalized = trim(str_replace('\\', '/', $path));
272272
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
273-
$normalized = ltrim($normalized, '/');
274-
if ($normalized === '') {
273+
$normalized = trim($normalized, '/');
274+
$basename = basename($normalized);
275+
if ($basename === '' || $basename === '.') {
275276
return $this->defaultSqliteDatabasePath();
276277
}
277278

278-
if (!str_contains($normalized, '/')) {
279-
return 'core/database/' . $normalized;
280-
}
281-
282-
return $normalized;
279+
return 'core/database/' . $basename;
283280
}
284281

285282
protected function isAbsolutePath(string $path): bool

src/Process/CreatesDatabaseConfig.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,13 @@ protected function normalizeSqliteDatabasePath(string $path): string
149149

150150
$normalized = str_replace('\\', '/', $path);
151151
$normalized = preg_replace('#^(?:\./)+#', '', $normalized) ?? $normalized;
152-
$normalized = ltrim($normalized, '/');
153-
if ($normalized === '') {
152+
$normalized = trim($normalized, '/');
153+
$basename = basename($normalized);
154+
if ($basename === '' || $basename === '.') {
154155
return 'core/database/database.sqlite';
155156
}
156157

157-
if (!str_contains($normalized, '/')) {
158-
return 'core/database/' . $normalized;
159-
}
160-
161-
return $normalized;
158+
return 'core/database/' . $basename;
162159
}
163160

164161
protected function isAbsolutePath(string $path): bool

tests/Unit/CreatesDatabaseConfigTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public function testGenerateConfigContentForPostgreSQL(): void
7373
$this->assertStringContainsString("'engine' => env('DB_ENGINE', '')", $content);
7474
}
7575

76-
public function testGenerateConfigContentForSqliteUsesCoreDatabaseDefaultPath(): void
76+
public function testGenerateConfigContentForSqliteStoresFileInsideCoreDatabase(): void
7777
{
7878
$reflection = new \ReflectionClass($this->processor);
7979
$method = $reflection->getMethod('generateConfigContent');

tests/Unit/InstallCommandAdminDirectoryTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,28 @@ public function testWriteCoreCustomEnvWritesSqlitePathInsideCoreDatabase(): void
121121
$this->removeTempDir($projectPath);
122122
}
123123

124+
public function testWriteCoreCustomEnvStoresOnlySqliteFileNameInsideCoreDatabase(): void
125+
{
126+
$cmd = $this->makeCommand();
127+
128+
$projectPath = $this->makeTempProjectDir();
129+
@mkdir($projectPath . '/core/custom', 0755, true);
130+
131+
$cmd->writeCoreCustomEnvPublic($projectPath, [
132+
'database' => [
133+
'type' => 'sqlite',
134+
'name' => 'nested/custom.sqlite',
135+
'prefix' => 'evo_',
136+
],
137+
]);
138+
139+
$env = (string) file_get_contents($projectPath . '/core/custom/.env');
140+
$expected = 'DB_DATABASE="' . $projectPath . '/core/database/custom.sqlite"' . "\n";
141+
$this->assertStringContainsString($expected, $env);
142+
143+
$this->removeTempDir($projectPath);
144+
}
145+
124146
public function testApplyManagerDirectoryRenamesManagerFolder(): void
125147
{
126148
$cmd = $this->makeCommand();

0 commit comments

Comments
 (0)