Bug 431392

Summary: CleanCommand does not clean file in sub-directory
Product: [Technology] JGit Reporter: Rüdiger Herrmann <ruediger.herrmann>
Component: JGitAssignee: Project Inbox <jgit.core-inbox>
Status: NEW --- QA Contact:
Severity: normal    
Priority: P3 CC: ned.twigg, robin.rosenberg, robin, ruediger.herrmann
Version: unspecifiedKeywords: helpwanted
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Rüdiger Herrmann CLA 2014-03-27 13:07:40 EDT
I found that the CleanCommand behaves differently than C Git clean when it comes to clean files located in sub-directories.
After executing the following shell commands within a repository, the 'file' is deleted as expected:
  mkdir folder
  cd folder
  touch file
  cd ..
  git clean -f folder/file
whereas, after running these lines:
  Set<String> paths = new HashSet<String>();
  paths.add( "folder/file" );
  git.clean().setPaths( paths ).call();
the file still exists. Am I missing someting here or is this a bug in JGit?

To easily reproduce the issue, here is a (failing) test case that fits into CleanCommandTest.
	@Test
	public void testCleanWithNestedPath() throws Exception {
		Set<String> paths = new TreeSet<String>();
		paths.add("sub-clean/File4.txt");

		Set<String> cleanedFiles = git.clean().setPaths(paths).call();

		assertTrue(cleanedFiles.contains("sub-clean/File4.txt"));
		assertFalse(new File(git.getRepository().getWorkTree(), "sub-clean/File4.txt").exists());
	}
Comment 1 Robin Rosenberg CLA 2014-03-29 10:48:03 EDT
try setCleanDirectories(true)

Maybe the docs needs updating
Comment 2 Rüdiger Herrmann CLA 2014-03-30 06:48:07 EDT
(In reply to Robin Rosenberg from comment #1)
> try setCleanDirectories(true)
Sorry, I forgot to mention that I tried that already. It doesn't make a difference.
Comment 3 Ned Twigg CLA 2019-04-25 01:57:12 EDT
I bumped into this too, spent a little time isolating it.  Here's one of the problems:

- I have a folder `build`, which is ignored
- I have a file `build.gradle`, which is untracked

If I do a clean, I would expect the untracked `build.gradle` to be deleted, but that does not happen.  That is because the code thinks that `build.gradle` is a file inside the `build` folder, because it uses `startsWith` as its check.  You could fix this with `startsWith(path + "/")` to fix the bug on this line:

https://github.com/eclipse/jgit/blob/0a15cb3a2bc14feec11baa1977567179ce3094bc/org.eclipse.jgit/src/org/eclipse/jgit/api/CleanCommand.java#L220

But the code has other bugs as well.  It seems to be making assumptions about what the output of the StatusCommand is, and I believe those assumptions no longer hold true today.

Here is a total re-implementation of the command which we use, it fixes a few bugs and simplifies the code quite a bit.  You can easily copy-paste it into your project and use it with stock JGit, no patching necessary

https://gist.github.com/nedtwigg/a5ce9dadc160a8ec2ac48deb55b4e4c6

Naturally, we would like to contribute it back upstream, but we'd rather use our limited upstreaming budget to get multiple worktree support merged, which seems to be bogged down in style nits:

https://git.eclipse.org/r/#/c/126281/