diff options
author | Thomas Wolf <twolf@apache.org> | 2022-07-30 00:27:49 +0200 |
---|---|---|
committer | Thomas Wolf <twolf@apache.org> | 2022-08-03 07:42:27 +0200 |
commit | 8184683f7e8d0e62bb70ff27af92dcc2d7332939 (patch) | |
tree | ea2bbcb361f919369ce49efa22680e06f299c418 /org.eclipse.jgit/src/org/eclipse/jgit | |
parent | 59e8bec6e7705a89b5d0b9c6ac004b323ffa16b0 (diff) | |
download | jgit-8184683f7e8d0e62bb70ff27af92dcc2d7332939.tar.gz jgit-8184683f7e8d0e62bb70ff27af92dcc2d7332939.zip |
CleanCommand: fix prefix matching
String.startsWith() is not a valid test for file path prefixes:
directory "a" is _not_ a prefix of a file "ab", only of "a/b".
Add a proper Paths.isEqualOrPrefix() method and use it in CleanCommand.
Bug: 580478
Change-Id: I6863e6ba94a8ffba6561835cc57044a0945d2770
Signed-off-by: Thomas Wolf <twolf@apache.org>
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java | 32 | ||||
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/util/Paths.java | 35 |
2 files changed, 49 insertions, 18 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java index 69272b7547..36ca97d694 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java @@ -25,6 +25,7 @@ import org.eclipse.jgit.events.WorkingTreeModifiedEvent; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; +import org.eclipse.jgit.util.Paths; /** * Remove untracked files from the working tree @@ -91,15 +92,16 @@ public class CleanCommand extends GitCommand<Set<String>> { Set<String> notIgnoredDirs = filterIgnorePaths(untrackedDirs, status.getIgnoredNotInIndex(), false); - for (String file : notIgnoredFiles) + for (String file : notIgnoredFiles) { if (paths.isEmpty() || paths.contains(file)) { files = cleanPath(file, files); } - - for (String dir : notIgnoredDirs) + } + for (String dir : notIgnoredDirs) { if (paths.isEmpty() || paths.contains(dir)) { files = cleanPath(dir, files); } + } } catch (IOException e) { throw new JGitInternalException(e.getMessage(), e); } finally { @@ -142,14 +144,14 @@ public class CleanCommand extends GitCommand<Set<String>> { FileUtils.delete(curFile, FileUtils.RECURSIVE | FileUtils.SKIP_MISSING); } - inFiles.add(path + "/"); //$NON-NLS-1$ + inFiles.add(path + '/'); } } else { if (!dryRun) { FileUtils.delete(curFile, FileUtils.RECURSIVE | FileUtils.SKIP_MISSING); } - inFiles.add(path + "/"); //$NON-NLS-1$ + inFiles.add(path + '/'); } } } else { @@ -166,14 +168,16 @@ public class CleanCommand extends GitCommand<Set<String>> { Set<String> ignoredNotInIndex, boolean exact) { if (ignore) { Set<String> filtered = new TreeSet<>(inputPaths); - for (String path : inputPaths) - for (String ignored : ignoredNotInIndex) + for (String path : inputPaths) { + for (String ignored : ignoredNotInIndex) { if ((exact && path.equals(ignored)) - || (!exact && path.startsWith(ignored))) { + || (!exact + && Paths.isEqualOrPrefix(ignored, path))) { filtered.remove(path); break; } - + } + } return filtered; } return inputPaths; @@ -182,14 +186,14 @@ public class CleanCommand extends GitCommand<Set<String>> { private Set<String> filterFolders(Set<String> untracked, Set<String> untrackedFolders) { Set<String> filtered = new TreeSet<>(untracked); - for (String file : untracked) - for (String folder : untrackedFolders) - if (file.startsWith(folder)) { + for (String file : untracked) { + for (String folder : untrackedFolders) { + if (Paths.isEqualOrPrefix(folder, file)) { filtered.remove(file); break; } - - + } + } return filtered; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/Paths.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/Paths.java index 5a39f95b2b..ae13ef7f3c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/Paths.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/Paths.java @@ -18,7 +18,8 @@ import static org.eclipse.jgit.lib.FileMode.TYPE_TREE; * * @since 4.2 */ -public class Paths { +public final class Paths { + /** * Remove trailing {@code '/'} if present. * @@ -43,6 +44,33 @@ public class Paths { } /** + * Determines whether a git path {@code folder} is a prefix of another git + * path {@code path}, or the same as {@code path}. An empty {@code folder} + * is <em>not</em> not considered a prefix and matches only if {@code path} + * is also empty. + * + * @param folder + * a git path for a directory, without trailing slash + * @param path + * a git path + * @return {@code true} if {@code folder} is a directory prefix of + * {@code path}, or is equal to {@code path}, {@code false} + * otherwise + * @since 6.3 + */ + public static boolean isEqualOrPrefix(String folder, String path) { + if (folder.isEmpty()) { + return path.isEmpty(); + } + boolean isPrefix = path.startsWith(folder); + if (isPrefix) { + int length = folder.length(); + return path.length() == length || path.charAt(length) == '/'; + } + return false; + } + + /** * Compare two paths according to Git path sort ordering rules. * * @param aPath @@ -63,9 +91,8 @@ public class Paths { * @param bMode * mode of the second file. Trees are sorted as though * {@code bPath[bEnd] == '/'}, even if bEnd does not exist. - * @return <0 if {@code aPath} sorts before {@code bPath}; - * 0 if the paths are the same; - * >0 if {@code aPath} sorts after {@code bPath}. + * @return <0 if {@code aPath} sorts before {@code bPath}; 0 if the paths + * are the same; >0 if {@code aPath} sorts after {@code bPath}. */ public static int compare(byte[] aPath, int aPos, int aEnd, int aMode, byte[] bPath, int bPos, int bEnd, int bMode) { |