Skip to content

Commit

Permalink
fix: windows escape symbols (#684)
Browse files Browse the repository at this point in the history
  • Loading branch information
katerina20 committed Jan 8, 2024
1 parent 1bedcde commit 09a79dc
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ private Map<String, java.io.File> getReviewedSourceFiles(String baseTemp, Projec
Utils.PATH_SEPARATOR +
project.getSourceLanguageId() + "-REV"
);
return Utils.unixPath(path);
return Utils.toUnixPath(path);
},
Function.identity()
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ public void act(Outputter out, ProjectProperties properties, ClientScreenshot cl
request.setBranchId(branch.getId());
}
if (nonNull(pathToSourceFile)) {
final String normalizedPath = Utils.unixPath(Utils.sepAtStart(pathToSourceFile));
final String normalizedPath = Utils.toUnixPath(Utils.sepAtStart(pathToSourceFile));
FileInfo fileInfo = project.getFileInfos().stream()
.filter(f -> normalizedPath.equals(f.getPath())).findFirst()
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), pathToSourceFile)));
request.setFileId(fileInfo.getId());
}
if (nonNull(directoryPath)) {
final String normalizedPath = Utils.unixPath(Utils.sepAtStart(directoryPath));
final String normalizedPath = Utils.toUnixPath(Utils.sepAtStart(directoryPath));
Directory directory = project.getDirectories().values().stream()
.filter(d -> normalizedPath.equals(d.getPath())).findFirst()
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.dir_not_exists"), directoryPath)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ public void act(Outputter out, ProjectProperties pb, ProjectClient client) {
List<LanguageProgress> progresses;

if (file != null) {
String filePath = Utils.unixPath(Utils.sepAtStart(file));
String filePath = Utils.toUnixPath(Utils.sepAtStart(file));
Long fileId = project.getFileInfos().stream()
.filter(f -> filePath.equals(f.getPath()))
.findFirst()
.orElseThrow(() -> new RuntimeException(String.format(RESOURCE_BUNDLE.getString("error.file_not_exists"), file)))
.getId();
progresses = client.getFileProgress(fileId);
} else if (directory != null) {
String directoryPath = Utils.unixPath(Utils.sepAtStart(directory));
String directoryPath = Utils.toUnixPath(Utils.sepAtStart(directory));
Long directoryId = project.getDirectories().values().stream()
.filter(d -> directoryPath.equals(d.getPath()))
.findFirst()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ public static Stream<File> getFiles(String basePath, String sourcePattern, List<
public static List<String> filterProjectFiles(
List<String> filePaths, String sourcePattern, List<String> ignorePatterns, boolean preserveHierarchy, PlaceholderUtil placeholderUtil
) {
filePaths = filePaths.stream().map((Utils.isWindows() ? Utils::windowsPath : Utils::unixPath)).map(Utils::noSepAtStart).collect(Collectors.toList());
sourcePattern = Utils.noSepAtStart(Utils.isWindows() ? Utils.windowsPath(sourcePattern) : Utils.unixPath(sourcePattern));
filePaths = filePaths.stream().map((Utils.isWindows() ? Utils::toWindowsPath : Utils::toUnixPath)).map(Utils::noSepAtStart).collect(Collectors.toList());
sourcePattern = Utils.noSepAtStart(Utils.isWindows() ? Utils.toWindowsPath(sourcePattern) : Utils.toUnixPath(sourcePattern));
ignorePatterns = (ignorePatterns != null)
? ignorePatterns.stream().map((Utils.isWindows() ? Utils::windowsPath : Utils::unixPath)).map(Utils::noSepAtStart).collect(Collectors.toList()) : Collections.emptyList();
? ignorePatterns.stream().map((Utils.isWindows() ? Utils::toWindowsPath : Utils::toUnixPath)).map(Utils::noSepAtStart).collect(Collectors.toList()) : Collections.emptyList();

Predicate<String> sourcePredicate;
Predicate<String> ignorePredicate;
Expand Down
30 changes: 20 additions & 10 deletions src/main/java/com/crowdin/cli/utils/PlaceholderUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import java.util.Set;
import java.util.stream.Collectors;

import static com.crowdin.cli.utils.Utils.isWindows;

public class PlaceholderUtil {

public static final String PLACEHOLDER_ANDROID_CODE = "%android_code%";
Expand Down Expand Up @@ -51,13 +53,16 @@ public class PlaceholderUtil {
private static final String SET_CLOSE_BRACKET = "]";
public static final String ROUND_BRACKET_OPEN = "(";
public static final String ROUND_BRACKET_CLOSE = ")";
public static final String ESCAPE_ROUND_BRACKET_OPEN = "\\(";
public static final String ESCAPE_ROUND_BRACKET_CLOSE = "\\)";
private static final String ESCAPE_DOT = "\\.";
public static final String ESCAPE_ROUND_BRACKET_OPEN = isWindows() ? "^(" : "\\(";
public static final String ESCAPE_ROUND_BRACKET_CLOSE = isWindows() ? "^)" : "\\)";
private static final String ESCAPE_DOT = isWindows() ? "^." : "\\.";
private static final String ESCAPE_DOT_REGEX = "\\.";
private static final String ESCAPE_DOT_PLACEHOLDER = "{ESCAPE_DOT}";
private static final String ESCAPE_QUESTION = "\\?";
private static final String ESCAPE_QUESTION = isWindows() ? "^?" : "\\?";
private static final String ESCAPE_QUESTION_REGEX = "\\?";
private static final String ESCAPE_QUESTION_PLACEHOLDER = "{ESCAPE_QUESTION_MARK}";
private static final String ESCAPE_ASTERISK = "\\*";
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_TO = "(.+" + Utils.PATH_SEPARATOR_REGEX + ")?";
Expand Down Expand Up @@ -228,13 +233,13 @@ public List<String> formatForRegex(List<String> toFormat, boolean onProjectLangs
}

public static String formatSourcePatternForRegex(String toFormat) {
if(Utils.isWindows()){
if (isWindows()) {
toFormat = toFormat
.replace("\\", "\\\\");
.replace("\\", "\\\\");
}
toFormat = toFormat
.replace(ESCAPE_DOT, ESCAPE_DOT_PLACEHOLDER)
.replace(DOT, ESCAPE_DOT)
.replace(DOT, ESCAPE_DOT_REGEX)
.replace(ESCAPE_DOT_PLACEHOLDER, ESCAPE_DOT)

.replace(ESCAPE_QUESTION, ESCAPE_QUESTION_PLACEHOLDER)
Expand All @@ -252,10 +257,15 @@ public static String formatSourcePatternForRegex(String toFormat) {

toFormat = toFormat
.replace(ROUND_BRACKET_OPEN, ESCAPE_ROUND_BRACKET_OPEN)

.replace(ROUND_BRACKET_CLOSE, ESCAPE_ROUND_BRACKET_CLOSE)

.replace(ESCAPE_ASTERISK_REPLACEMENT_FROM, ESCAPE_ASTERISK_REPLACEMENT_TO);

if (isWindows()) {
toFormat = toFormat
.replace(ESCAPE_ASTERISK, ESCAPE_ASTERISK_REGEX)
.replace(ESCAPE_DOT, ESCAPE_DOT_REGEX)
.replace(ESCAPE_QUESTION, ESCAPE_QUESTION_REGEX);
}
return toFormat
.replace(PLACEHOLDER_FILE_EXTENSION, "[^/]+")
.replace(PLACEHOLDER_FILE_NAME, "[^/]+")
Expand Down
11 changes: 8 additions & 3 deletions src/main/java/com/crowdin/cli/utils/Utils.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,16 @@ public static String buildUserAgent() {
System.getProperty("os.version"));
}

public static String unixPath(String path) {
return (path != null) ? path.replaceAll("[\\\\/]+", "/") : null;
public static String toUnixPath(String path) {
if (path == null) {
return null;
}
return isWindows()
? path.replaceAll("[\\\\/]+", "/")
: path.replaceAll("\\\\{2,}", "/").replaceAll("/+", "/");
}

public static String windowsPath(String path) {
public static String toWindowsPath(String path) {
return (path != null) ? path.replaceAll("[\\\\/]+", "\\\\") : null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,90 @@ public void testFilterProjectFiles_dest() {
assertThat(actual, containsInAnyOrder(expected));
}

@ParameterizedTest
@MethodSource
@DisabledOnOs({OS.LINUX, OS.MAC})
public void testFilterProjectFiles_escapeSymbols_windows(List<String> filePaths, String sourcePattern, List<String> expected) {
List<String> actual = SourcesUtils.filterProjectFiles(
filePaths, sourcePattern, Collections.emptyList(), true, PlaceholderUtilBuilder.STANDART.build(""));
assertEquals(expected.size(), actual.size());
assertThat(actual, containsInAnyOrder(expected.toArray()));
}

static Stream<Arguments> testFilterProjectFiles_escapeSymbols_windows() {
String file1 = "here\\file-1.po";
String file1Symbol = "here\\file?1.po";
String file2 = "here\\file-2.po";
String file2Symbol = "here\\file*2.po";
String file3 = "here\\file-3.po";
String file3Symbol = "here\\file.3.po";
List<String> allFiles = Arrays.asList(file1, file1Symbol, file2, file2Symbol, file3, file3Symbol);
return Stream.of(
arguments(
allFiles,
"here\\file^?1.po",
Arrays.asList(file1Symbol)
),
arguments(
allFiles,
"here\\file^*2.po",
Arrays.asList(file2Symbol)
),
arguments(
allFiles,
"here\\file^.3.po",
Arrays.asList(file3Symbol)
),
arguments(
allFiles,
"here\\*.po",
allFiles
)
);
}

@ParameterizedTest
@MethodSource
@DisabledOnOs(OS.WINDOWS)
public void testFilterProjectFiles_escapeSymbols_unix(List<String> filePaths, String sourcePattern, List<String> expected) {
List<String> actual = SourcesUtils.filterProjectFiles(
filePaths, sourcePattern, Collections.emptyList(), true, PlaceholderUtilBuilder.STANDART.build(""));
assertEquals(expected.size(), actual.size());
assertThat(actual, containsInAnyOrder(expected.toArray()));
}

static Stream<Arguments> testFilterProjectFiles_escapeSymbols_unix() {
String file1 = "here/file-1.po";
String file1Symbol = "here/file?1.po";
String file2 = "here/file-2.po";
String file2Symbol = "here/file*2.po";
String file3 = "here/file-3.po";
String file3Symbol = "here/file.3.po";
List<String> allFiles = Arrays.asList(file1, file1Symbol, file2, file2Symbol, file3, file3Symbol);
return Stream.of(
arguments(
allFiles,
"here/file\\?1.po",
Arrays.asList(file1Symbol)
),
arguments(
allFiles,
"here/file\\*2.po",
Arrays.asList(file2Symbol)
),
arguments(
allFiles,
"here/file\\.3.po",
Arrays.asList(file3Symbol)
),
arguments(
allFiles,
"here/*.po",
allFiles
)
);
}

@ParameterizedTest
@MethodSource
public void testContainsParameter(String sourcePattern, boolean expected) {
Expand Down
15 changes: 12 additions & 3 deletions src/test/java/com/crowdin/cli/utils/UtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.Optional;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -36,13 +38,20 @@ public void testBuildUserAgent() {
}

@Test
public void testUnixPath() {
assertEquals("/path/to/file", Utils.unixPath("\\path\\to\\file"));
@DisabledOnOs({OS.LINUX, OS.MAC})
public void testUnixPath_windows() {
assertEquals("/path/to/file", Utils.toUnixPath("\\path\\to\\\\file"));
}

@Test
@DisabledOnOs(OS.WINDOWS)
public void testUnixPath_unix() {
assertEquals("/path/to/file", Utils.toUnixPath("/path/to\\\\file"));
}

@Test
public void testWindowsPath() {
assertEquals("\\path\\to\\file", Utils.windowsPath("/path/to/file"));
assertEquals("\\path\\to\\file", Utils.toWindowsPath("/path/to/file"));
}

@Test
Expand Down

0 comments on commit 09a79dc

Please sign in to comment.