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>
This commit is contained in:
parent
59e8bec6e7
commit
8184683f7e
|
@ -301,4 +301,25 @@ public void testFilesShouldBeCleanedInSubSubFolders()
|
|||
writeTrashFile("this_is/not_ok/more/subdirs/file.txt", "2");
|
||||
git.clean().setCleanDirectories(true).setIgnore(false).call();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefix() throws Exception {
|
||||
File a = writeTrashFile("a.txt", "a");
|
||||
File b = writeTrashFile("a/a.txt", "sub a");
|
||||
File dir = b.getParentFile();
|
||||
git.clean().call();
|
||||
assertFalse(a.exists());
|
||||
assertTrue(dir.exists());
|
||||
assertTrue(b.exists());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixWithDir() throws Exception {
|
||||
File a = writeTrashFile("a.txt", "a");
|
||||
File b = writeTrashFile("a/a.txt", "sub a");
|
||||
File dir = b.getParentFile();
|
||||
git.clean().setCleanDirectories(true).call();
|
||||
assertFalse(a.exists());
|
||||
assertFalse(dir.exists());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
import static org.eclipse.jgit.util.Paths.compare;
|
||||
import static org.eclipse.jgit.util.Paths.compareSameName;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
|
@ -31,6 +33,23 @@ public void testStripTrailingSeparator() {
|
|||
assertEquals("a/boo", Paths.stripTrailingSeparator("a/boo///"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrefix() {
|
||||
assertTrue(Paths.isEqualOrPrefix("a", "a"));
|
||||
assertTrue(Paths.isEqualOrPrefix("a", "a/b"));
|
||||
assertTrue(Paths.isEqualOrPrefix("a", "a/a.txt"));
|
||||
assertFalse(Paths.isEqualOrPrefix("a", "ab"));
|
||||
assertFalse(Paths.isEqualOrPrefix("a", "a.txt"));
|
||||
assertFalse(Paths.isEqualOrPrefix("a", "b/a.txt"));
|
||||
assertFalse(Paths.isEqualOrPrefix("a", "b/a"));
|
||||
assertFalse(Paths.isEqualOrPrefix("a", "ab/a.txt"));
|
||||
assertFalse(Paths.isEqualOrPrefix("", "a"));
|
||||
assertTrue(Paths.isEqualOrPrefix("", ""));
|
||||
assertTrue(Paths.isEqualOrPrefix("a/b", "a/b"));
|
||||
assertTrue(Paths.isEqualOrPrefix("a/b", "a/b/c"));
|
||||
assertFalse(Paths.isEqualOrPrefix("a/b", "a/bc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathCompare() {
|
||||
byte[] a = Constants.encode("afoo/bar.c");
|
||||
|
|
|
@ -83,4 +83,11 @@
|
|||
</message_arguments>
|
||||
</filter>
|
||||
</resource>
|
||||
<resource path="src/org/eclipse/jgit/util/Paths.java" type="org.eclipse.jgit.util.Paths">
|
||||
<filter id="337768515">
|
||||
<message_arguments>
|
||||
<message_argument value="org.eclipse.jgit.util.Paths"/>
|
||||
</message_arguments>
|
||||
</filter>
|
||||
</resource>
|
||||
</component>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
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 Set<String> call() throws NoWorkTreeException, GitAPIException {
|
|||
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 @@ private Set<String> cleanPath(String path, Set<String> inFiles)
|
|||
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 @@ private Set<String> filterIgnorePaths(Set<String> inputPaths,
|
|||
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 @@ private Set<String> filterIgnorePaths(Set<String> inputPaths,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public class Paths {
|
||||
public final class Paths {
|
||||
|
||||
/**
|
||||
* Remove trailing {@code '/'} if present.
|
||||
*
|
||||
|
@ -42,6 +43,33 @@ public static String stripTrailingSeparator(String path) {
|
|||
return path.substring(0, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
@ -63,9 +91,8 @@ public static String stripTrailingSeparator(String path) {
|
|||
* @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) {
|
||||
|
|
Loading…
Reference in New Issue