Skip to content

Commit 8d0f72b

Browse files
committed
Merge branch 'DBTOOLS-2082_fix_cache_clear' into 'master'
DBTOOLS-2082 fixed deleting non project files during update See merge request codekeeper/pgcodekeeper-core!279
2 parents b11148b + e548edc commit 8d0f72b

10 files changed

Lines changed: 122 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1515

1616
### Fixed
1717

18+
- Fixed full project update to clean only the project's own directories.
1819
- Fixed adding library objects to a project during export.
1920
- Fixed code generation for index when altering in CONCURRENTLY mode.
2021
- Fixed migration script generation when changing a generated column in PostgreSQL.

CHANGELOG.ru.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
### Исправлено
1717

18+
- Исправлено полное обновление проекта: очищаются только папки самого проекта.
1819
- Исправлено добавление объектов библиотек в проект при экспорте.
1920
- Исправлена генерация кода индекса при его изменении в режиме CONCURRENTLY.
2021
- Исправлена генерация скрипта миграции при изменении генерируемой колонки в PostgreSQL.

src/main/java/org/pgcodekeeper/core/database/api/project/IProjectUpdater.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,19 @@ public interface IProjectUpdater {
3434
* @param projectOnly whether to preserve overrides directory during update
3535
* @throws IOException if update operation fails
3636
*/
37-
void updateFull(boolean projectOnly) throws IOException;
37+
default void updateFull(boolean projectOnly) throws IOException {
38+
updateFull(projectOnly, null);
39+
}
40+
41+
/**
42+
* Performs full update of database project.
43+
* Completely regenerates project structure with optional overrides preservation.
44+
* Only the project's own working directories are cleaned.
45+
*
46+
* @param projectOnly whether to preserve overrides directory during update
47+
* @param previousWorkDirs the layout the project currently uses on disk, or {@code null}
48+
* to clean only the new layout's directories
49+
* @throws IOException if update operation fails
50+
*/
51+
void updateFull(boolean projectOnly, IWorkDirs previousWorkDirs) throws IOException;
3852
}

src/main/java/org/pgcodekeeper/core/database/api/project/IWorkDirs.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.io.IOException;
2323
import java.nio.file.Path;
24+
import java.util.List;
2425
import java.util.Map;
2526

2627
/**
@@ -80,4 +81,20 @@ public interface IWorkDirs {
8081
* @throws IOException if the configuration file cannot be written
8182
*/
8283
void saveAltDirs(Path projectPath) throws IOException;
84+
85+
/**
86+
* Returns the distinct top-level directory names of this layout, i.e. the
87+
* directories created directly under the project root.
88+
*
89+
* @return distinct top-level directory names of this layout
90+
*/
91+
default List<String> getTopLevelDirNames() {
92+
boolean split = isSplitBySchema();
93+
return getDirMapping().values().stream()
94+
.filter(rule -> !split || !rule.isSubElement())
95+
.map(rule -> rule.getDirName().split("/")[0])
96+
.filter(name -> !name.isBlank())
97+
.distinct()
98+
.toList();
99+
}
83100
}

src/main/java/org/pgcodekeeper/core/database/base/project/AbstractModelExporter.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,15 @@ public Path getRelativeFilePath(IStatement st) {
160160
return workDirs.getRelativeFilePath(st);
161161
}
162162

163+
/**
164+
* Returns the directory layout used by this exporter.
165+
*
166+
* @return the work directories layout
167+
*/
168+
public IWorkDirs getWorkDirs() {
169+
return workDirs;
170+
}
171+
163172
@Override
164173
public void exportFull() throws IOException {
165174
createOutDir();

src/main/java/org/pgcodekeeper/core/database/base/project/AbstractProjectUpdater.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package org.pgcodekeeper.core.database.base.project;
1717

1818
import org.pgcodekeeper.core.database.api.project.IProjectUpdater;
19+
import org.pgcodekeeper.core.database.api.project.IWorkDirs;
1920
import org.pgcodekeeper.core.database.api.schema.IDatabase;
2021
import org.pgcodekeeper.core.exception.PgCodeKeeperException;
2122
import org.pgcodekeeper.core.localizations.Messages;
@@ -32,7 +33,9 @@
3233
import java.nio.file.attribute.BasicFileAttributes;
3334
import java.util.ArrayList;
3435
import java.util.Collection;
36+
import java.util.LinkedHashSet;
3537
import java.util.List;
38+
import java.util.Set;
3639
import java.util.stream.Stream;
3740

3841
import static org.pgcodekeeper.core.database.base.loader.AbstractProjectLoader.OVERRIDES_DIR;
@@ -199,15 +202,16 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
199202
}
200203

201204
@Override
202-
public void updateFull(boolean projectOnly) throws IOException {
205+
public void updateFull(boolean projectOnly, IWorkDirs previousWorkDirs) throws IOException {
203206
LOG.info(Messages.ProjectUpdater_log_start_full_update);
204207
boolean caughtProcessingEx = false;
205208
try (TempDir tmp = new TempDir(dirExport, "tmp-export")) { //$NON-NLS-1$
206209
Path dirTmp = tmp.get();
207210

208211
try {
209-
safeCleanProjectDir(dirTmp);
210-
createModelExporter(dirExport, dbNew, encoding).exportFull();
212+
AbstractModelExporter exporter = createModelExporter(dirExport, dbNew, encoding);
213+
safeCleanProjectDir(dirTmp, exporter.getWorkDirs(), previousWorkDirs);
214+
exporter.exportFull();
211215
if (projectOnly) {
212216
restoreFolder(dirTmp, OVERRIDES_DIR);
213217
}
@@ -227,8 +231,13 @@ public void updateFull(boolean projectOnly) throws IOException {
227231
}
228232
}
229233

230-
private void safeCleanProjectDir(Path dirTmp) throws IOException {
231-
for (String subdirName : listProjectDirs(dirExport, dirTmp)) {
234+
private void safeCleanProjectDir(Path dirTmp, IWorkDirs workDirs, IWorkDirs previousWorkDirs) throws IOException {
235+
Set<String> ownedDirs = new LinkedHashSet<>(workDirs.getTopLevelDirNames());
236+
if (previousWorkDirs != null) {
237+
ownedDirs.addAll(previousWorkDirs.getTopLevelDirNames());
238+
}
239+
ownedDirs.add(OVERRIDES_DIR);
240+
for (String subdirName : ownedDirs) {
232241
moveFolder(dirTmp, subdirName);
233242
}
234243
}
@@ -246,12 +255,15 @@ private void restoreProjectDir(Path dirTmp) throws IOException {
246255
}
247256
}
248257

249-
private static List<String> listProjectDirs(Path dir, Path exclude) throws IOException {
258+
private List<String> listProjectDirs(Path dir, Path exclude) throws IOException {
250259
try (Stream<Path> stream = Files.list(dir)) {
251260
List<String> result = new ArrayList<>();
252261
for (Path path : Utils.streamIterator(stream)) {
253-
if (Files.isDirectory(path) && !path.equals(exclude)) {
254-
result.add(path.getFileName().toString());
262+
String name = path.getFileName().toString();
263+
if (Files.isDirectory(path)
264+
&& !path.equals(exclude)
265+
&& !name.startsWith(".")) {
266+
result.add(name);
255267
}
256268
}
257269
return result;

src/test/java/org/pgcodekeeper/core/api/PgCodeKeeperApiTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@
1919
import static org.junit.jupiter.api.Assertions.assertTrue;
2020
import java.io.IOException;
2121
import java.nio.file.*;
22+
import java.util.List;
2223
import org.junit.jupiter.api.BeforeEach;
2324
import org.junit.jupiter.api.Test;
2425
import org.junit.jupiter.api.io.TempDir;
2526
import org.junit.jupiter.params.ParameterizedTest;
2627
import org.junit.jupiter.params.provider.CsvSource;
2728
import org.junit.jupiter.params.provider.ValueSource;
2829
import org.pgcodekeeper.core.TestUtils;
30+
import org.pgcodekeeper.core.database.api.schema.IDatabase;
31+
import org.pgcodekeeper.core.database.base.project.AbstractWorkDirs;
2932
import org.pgcodekeeper.core.database.pg.PgDatabaseProvider;
33+
import org.pgcodekeeper.core.database.pg.project.PgWorkDirs;
3034
import org.pgcodekeeper.core.settings.CoreSettings;
3135
import org.pgcodekeeper.core.settings.DiffSettings;
3236

@@ -172,6 +176,34 @@ void updateProjectWithIgnoreListTest(@TempDir Path tempDir) throws IOException,
172176
TestUtils.assertErrors(diffSettings.getErrors());
173177
}
174178

179+
@Test
180+
void fullUpdatePreservesMetadataDirsTest(@TempDir Path tempDir) throws IOException, InterruptedException {
181+
Path settingsDir = tempDir.resolve(".settings");
182+
Files.createDirectories(settingsDir);
183+
184+
IDatabase newDb = provider.getDumpLoader(getFilePath("test_export.sql"), diffSettings).loadAndAnalyze();
185+
provider.getProjectUpdater(newDb, null, List.of(), tempDir, false, new CoreSettings()).updateFull(true);
186+
187+
assertTrue(Files.exists(settingsDir));
188+
TestUtils.assertErrors(diffSettings.getErrors());
189+
}
190+
191+
@Test
192+
void fullUpdateCleansRenamedDirsAndKeepsForeignTest(@TempDir Path tempDir)
193+
throws IOException, InterruptedException {
194+
Files.createDirectories(tempDir.resolve("MIGRATION"));
195+
Files.createDirectories(tempDir.resolve("SCHEMA"));
196+
Files.writeString(tempDir.resolve(AbstractWorkDirs.ALT_DIRS_FILENAME), "SCHEMA=DB\n");
197+
198+
IDatabase newDb = provider.getDumpLoader(getFilePath("test_export.sql"), diffSettings).loadAndAnalyze();
199+
provider.getProjectUpdater(newDb, null, List.of(), tempDir, false, new CoreSettings())
200+
.updateFull(true, new PgWorkDirs());
201+
202+
assertTrue(Files.exists(tempDir.resolve("MIGRATION")));
203+
assertFalse(Files.exists(tempDir.resolve("SCHEMA")));
204+
TestUtils.assertErrors(diffSettings.getErrors());
205+
}
206+
175207
private void setupUpdateProjectStructure(Path tempDir) throws IOException {
176208
Path publicDir = tempDir.resolve(PUBLIC_DIRECTORY);
177209
Path tablesDir = tempDir.resolve(TABLES_DIRECTORY);

src/test/java/org/pgcodekeeper/core/database/ch/project/ChWorkDirsTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import java.nio.file.Files;
2424
import java.nio.file.Path;
25+
import java.util.List;
2526

2627
final class ChWorkDirsTest {
2728

@@ -50,4 +51,12 @@ void testLoadsAltDirsFromPropertiesFile(@TempDir Path tempDir) throws Exception
5051
Assertions.assertEquals("VIEW", workDirs.getDirMapping().get("VIEW").getDirName());
5152
Assertions.assertFalse(workDirs.isSplitBySchema());
5253
}
54+
55+
@Test
56+
void testTopDirNames() {
57+
var workDirs = new ChWorkDirs();
58+
var expected = List.of("DATABASE", "FUNCTION", "USER", "POLICY", "ROLE");
59+
var actual = workDirs.getTopLevelDirNames();
60+
Assertions.assertEquals(expected, actual);
61+
}
5362
}

src/test/java/org/pgcodekeeper/core/database/ms/project/MsWorkDirsTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import java.nio.file.Files;
2424
import java.nio.file.Path;
25+
import java.util.List;
2526

2627
final class MsWorkDirsTest {
2728

@@ -51,4 +52,12 @@ void testLoadsAltDirsFromPropertiesFile(@TempDir Path tempDir) throws Exception
5152
Assertions.assertEquals("Views", workDirs.getDirMapping().get("VIEW").getDirName());
5253
Assertions.assertTrue(workDirs.isSplitBySchema());
5354
}
55+
56+
@Test
57+
void testTopDirNames() {
58+
var workDirs = new MsWorkDirs();
59+
var expected = List.of("Security", "Assemblies", "Types", "Tables", "Views", "Sequences", "Functions", "Stored Procedures");
60+
var actual = workDirs.getTopLevelDirNames();
61+
Assertions.assertEquals(expected, actual);
62+
}
5463
}

src/test/java/org/pgcodekeeper/core/database/pg/project/PgWorkDirsTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import java.nio.file.Files;
2929
import java.nio.file.Path;
30+
import java.util.List;
3031
import java.util.Properties;
3132

3233
final class PgWorkDirsTest {
@@ -134,4 +135,12 @@ void testSaveDefaultAltDirs(@TempDir Path tempDir) throws Exception {
134135
boolean exists = Files.isRegularFile(tempDir.resolve(AbstractWorkDirs.ALT_DIRS_FILENAME));
135136
Assertions.assertFalse(exists);
136137
}
138+
139+
@Test
140+
void testTopDirNames() {
141+
var workDirs = new PgWorkDirs();
142+
var expected = List.of("SCHEMA", "EXTENSION", "EVENT_TRIGGER", "USER_MAPPING", "CAST", "SERVER", "FDW");
143+
var actual = workDirs.getTopLevelDirNames();
144+
Assertions.assertEquals(expected, actual);
145+
}
137146
}

0 commit comments

Comments
 (0)