From aa99d5e55d1150bb91003b165b812ef7bc5eae7d Mon Sep 17 00:00:00 2001 From: Kateryna Oblakevych Date: Tue, 19 Mar 2024 09:31:01 +0200 Subject: [PATCH] fix: double asterisks in paths (#733) --- .../crowdin/cli/utils/PlaceholderUtil.java | 10 +++--- .../actions/DownloadSourcesActionTest.java | 36 +++++++++++++++++++ .../cli/utils/PlaceholderUtilTest.java | 7 ++++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/crowdin/cli/utils/PlaceholderUtil.java b/src/main/java/com/crowdin/cli/utils/PlaceholderUtil.java index 9257f9d55..e5cdabb80 100644 --- a/src/main/java/com/crowdin/cli/utils/PlaceholderUtil.java +++ b/src/main/java/com/crowdin/cli/utils/PlaceholderUtil.java @@ -64,7 +64,7 @@ public class PlaceholderUtil { private static final String ESCAPE_ASTERISK = isWindows() ? "^*" : "\\*"; private static final String ESCAPE_ASTERISK_REGEX = "\\*"; private static final String ESCAPE_ASTERISK_PLACEHOLDER = "{ESCAPE_ASTERISK}"; - private static final String ESCAPE_ASTERISK_REPLACEMENT_FROM = ".+" + Utils.PATH_SEPARATOR; + private static final String ESCAPE_ASTERISK_REPLACEMENT_FROM = ".+" + Utils.PATH_SEPARATOR_REGEX; private static final String ESCAPE_ASTERISK_REPLACEMENT_TO = "(.+" + Utils.PATH_SEPARATOR_REGEX + ")?"; private List supportedLanguages; @@ -193,10 +193,12 @@ public String replaceFileDependentPlaceholders(String toFormat, File file) { toFormat = toFormat.replace("/", File.separator); if (toFormat.contains("**")) { - String prefix = StringUtils.substringBefore(toFormat, "**"); - prefix = prefix.length() > 1 && file.getPath().contains(prefix) ? StringUtils.substringBefore(fileParent, Utils.noSepAtStart(prefix)) : ""; + String prefixFormat = StringUtils.substringBefore(toFormat, "**"); + String postfix = Utils.getParentDirectory(StringUtils.substringAfter(toFormat, "**")); + String prefix = prefixFormat.length() > 1 && file.getPath().contains(prefixFormat) ? StringUtils.substringBefore(fileParent, Utils.noSepAtStart(prefixFormat)) : ""; String doubleAsterisks = - StringUtils.removeStart(Utils.noSepAtStart(StringUtils.removeStart(fileParent, prefix)), Utils.noSepAtEnd(Utils.noSepAtStart(StringUtils.substringBefore(toFormat, "**")))); + StringUtils.removeStart(Utils.noSepAtStart(StringUtils.removeStart(fileParent, prefix)), Utils.noSepAtEnd(Utils.noSepAtStart(prefixFormat))); + doubleAsterisks = postfix.length() > 1 ? StringUtils.removeEnd(doubleAsterisks, Utils.noSepAtEnd(postfix)) : doubleAsterisks; toFormat = toFormat.replace("**", doubleAsterisks); } diff --git a/src/test/java/com/crowdin/cli/commands/actions/DownloadSourcesActionTest.java b/src/test/java/com/crowdin/cli/commands/actions/DownloadSourcesActionTest.java index a37d0ed45..3958af3e9 100644 --- a/src/test/java/com/crowdin/cli/commands/actions/DownloadSourcesActionTest.java +++ b/src/test/java/com/crowdin/cli/commands/actions/DownloadSourcesActionTest.java @@ -83,6 +83,42 @@ public void testDest() throws IOException { verifyNoMoreInteractions(files); } + @Test + public void testDest_doubleAsterisks() throws IOException { + PropertiesWithFiles pb = NewPropertiesWithFilesUtilBuilder + .minimalBuiltPropertiesBean( + Utils.normalizePath("/values/**/res/strings.xml"), Utils.normalizePath("/values/**/%two_letters_code%/%original_file_name%"), + null, Utils.normalizePath("/common/**/%original_file_name%")) + .setBasePath(project.getBasePath()) + .setPreserveHierarchy(true) + .build(); + + ProjectClient client = mock(ProjectClient.class); + when(client.downloadFullProject(null)) + .thenReturn(ProjectBuilder.emptyProject(Long.parseLong(pb.getProjectId())) + .addDirectory("common", 201L, null, null) + .addDirectory("values", 202L, 201L, null) + .addDirectory("first", 203L, 202L, null) + .addDirectory("second", 204L, 203L, null) + .addFile("strings.xml", "gettext", 101L, 204L, null, Utils.normalizePath("/values/first/second/%two_letters_code%/%original_file_name%")).build()); + URL urlMock = MockitoUtils.getMockUrl(getClass()); + when(client.downloadFile(eq(101L))) + .thenReturn(urlMock); + + FilesInterface files = mock(FilesInterface.class); + + NewAction action = + new DownloadSourcesAction(files, false, false, null, true, false, false); + action.act(Outputter.getDefault(), pb, client); + + verify(client).downloadFullProject(null); + verify(client).downloadFile(eq(101L)); + verifyNoMoreInteractions(client); + + verify(files).writeToFile(eq(Utils.joinPaths(project.getBasePath(), "values/first/second/res/strings.xml")), any()); + verifyNoMoreInteractions(files); + } + @Test public void testDestAndUnaryAsterisk() throws IOException { PropertiesWithFiles pb = NewPropertiesWithFilesUtilBuilder diff --git a/src/test/java/com/crowdin/cli/utils/PlaceholderUtilTest.java b/src/test/java/com/crowdin/cli/utils/PlaceholderUtilTest.java index 164eb3c2d..400b985fd 100644 --- a/src/test/java/com/crowdin/cli/utils/PlaceholderUtilTest.java +++ b/src/test/java/com/crowdin/cli/utils/PlaceholderUtilTest.java @@ -66,6 +66,13 @@ static Stream testMainFunctionality() { new File[] {new File("resources/messages.xml")}, Utils.normalizePath("/**/%two_letters_code%_%original_file_name%"), new String[] {Utils.normalizePath("resources/en_messages.xml")} + ), + arguments(// How to treat double asterisks in the middle + new Language[] {LanguageBuilder.ENG.build()}, + new Language[] {LanguageBuilder.ENG.build()}, + new File[] {new File("resources/main/settings/default/messages.xml")}, + Utils.normalizePath("app/**/default/%two_letters_code%_%original_file_name%"), + new String[] {Utils.normalizePath("app/resources/main/settings/default/en_messages.xml")} ) ); }