You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hop.apache.org by ha...@apache.org on 2026/08/06 20:13:00 UTC
(hop) branch main updated: add git clean #7774 (#7805)
This is an automated email from the ASF dual-hosted git repository.
hansva pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 3e3a58d405 add git clean #7774 (#7805)
3e3a58d405 is described below
commit 3e3a58d405b24b857e1f3969863f4d9bf51c9603
Author: Bart Maertens <ba...@know.bi>
AuthorDate: Thu Aug 6 22:12:54 2026 +0200
add git clean #7774 (#7805)
---
.../main/java/org/apache/hop/git/GitGuiPlugin.java | 222 ++++++++++++++++-----
.../main/java/org/apache/hop/git/model/UIGit.java | 26 ++-
.../hop/git/messages/messages_en_US.properties | 12 +-
.../java/org/apache/hop/git/model/UIGitTest.java | 51 +++++
4 files changed, 262 insertions(+), 49 deletions(-)
diff --git a/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java b/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
index 4aac3ca64d..ff9626580e 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/GitGuiPlugin.java
@@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Predicate;
import lombok.Getter;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
@@ -71,6 +72,7 @@ import org.apache.hop.ui.hopgui.perspective.explorer.IExplorerRootChangedListene
import org.apache.hop.ui.hopgui.perspective.explorer.IExplorerSelectionListener;
import org.apache.hop.ui.util.EnvironmentUtils;
import org.apache.hop.workflow.WorkflowMeta;
+import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
@@ -105,6 +107,7 @@ public class GitGuiPlugin
public static final String TOOLBAR_ITEM_GIT_INFO = "ExplorerPerspective-Toolbar-20100-GitInfo";
public static final String TOOLBAR_ITEM_ADD = "ExplorerPerspective-Toolbar-20200-Add";
public static final String TOOLBAR_ITEM_REVERT = "ExplorerPerspective-Toolbar-20300-Revert";
+ public static final String TOOLBAR_ITEM_CLEAN = "ExplorerPerspective-Toolbar-20400-Clean";
public static final String TOOLBAR_ITEM_COMMIT = "ExplorerPerspective-Toolbar-21000-Commit";
public static final String CONTEXT_MENU_GIT_INFO =
@@ -112,6 +115,8 @@ public class GitGuiPlugin
public static final String CONTEXT_MENU_GIT_ADD = "ExplorerPerspective-ContextMenu-20100-GitAdd";
public static final String CONTEXT_MENU_GIT_REVERT =
"ExplorerPerspective-ContextMenu-20200-GitRevert";
+ public static final String CONTEXT_MENU_GIT_CLEAN =
+ "ExplorerPerspective-ContextMenu-20300-GitClean";
public static final String CONTEXT_MENU_GIT_COMMIT =
"ExplorerPerspective-ContextMenu-21000-GitCommit";
@@ -403,6 +408,7 @@ public class GitGuiPlugin
// Refresh the tree, change colors...
//
ExplorerPerspective.getInstance().refresh();
+ enableButtons();
} catch (Exception e) {
new ErrorDialog(
HopGui.getInstance().getShell(),
@@ -465,56 +471,19 @@ public class GitGuiPlugin
}
// New files (untracked or added) are only unstaged by the revert, they stay on disk.
- // Removing those takes an explicit git clean, see below.
+ // Removing those is what "Git Clean" is for.
//
- Set<String> newPaths = git.getNewRevertPathFiles(relativePath);
-
for (String filePath : selectedPaths) {
git.revertPath(filePath);
}
- // When a folder was selected and new files were unstaged, ask if we should also
- // remove those files with git clean (yes/no)
- //
- boolean isFolder = false;
- try {
- isFolder = HopVfs.getFileObject(explorerFile.getFilename()).isFolder();
- } catch (Exception ignored) {
- // not a folder
- }
- List<String> pathsToClean = selectedPaths.stream().filter(newPaths::contains).toList();
- if (isFolder && !pathsToClean.isEmpty()) {
- MessageBox cleanBox =
- new MessageBox(
- HopGui.getInstance().getShell(), SWT.YES | SWT.NO | SWT.ICON_QUESTION);
- cleanBox.setText(
- BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.CleanConfirm.Header"));
- cleanBox.setMessage(
- BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.CleanConfirm.Message"));
- if (cleanBox.open() == SWT.YES) {
- try {
- git.cleanPaths(pathsToClean);
- } catch (Exception cleanEx) {
- LogChannel.UI.logError("Git clean failed for " + relativePath, cleanEx);
- }
- }
- }
-
// Close the tabs of the files which are no longer on disk, reload the others
//
List<String> filenamesToClose = new ArrayList<>();
List<String> filenamesToReload = new ArrayList<>();
for (String filePath : selectedPaths) {
- File file = new File(git.getDirectory(), filePath);
- String fullFilename;
- try {
- FileObject fileObj = HopVfs.getFileObject(file.getAbsolutePath());
- fullFilename =
- fileObj.exists() ? HopVfs.getFilename(fileObj) : file.getAbsolutePath();
- } catch (Exception ignored) {
- fullFilename = file.getAbsolutePath();
- }
- if (file.exists()) {
+ String fullFilename = getOpenFilename(filePath);
+ if (new File(git.getDirectory(), filePath).exists()) {
filenamesToReload.add(fullFilename);
} else {
filenamesToClose.add(fullFilename);
@@ -550,6 +519,122 @@ public class GitGuiPlugin
enableButtons();
}
+ @GuiMenuElement(
+ root = ExplorerPerspective.GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ parentId = ExplorerPerspective.GUI_PLUGIN_CONTEXT_MENU_PARENT_ID,
+ id = CONTEXT_MENU_GIT_CLEAN,
+ label = "i18n::GitGuiPlugin.Menu.Clean.Text",
+ image = "git-delete.svg")
+ @GuiToolbarElement(
+ root = ExplorerPerspective.GUI_PLUGIN_TOOLBAR_PARENT_ID,
+ id = TOOLBAR_ITEM_CLEAN,
+ toolTip = "i18n::GitGuiPlugin.Toolbar.Clean.Tooltip",
+ image = "git-delete.svg")
+ public void gitClean() {
+ try {
+ ExplorerFile explorerFile = getSelectedFile();
+ if (git == null || explorerFile == null) {
+ return;
+ }
+ String relativePath = calculateRelativePath(git.getDirectory(), explorerFile);
+ if (relativePath == null) {
+ return;
+ }
+ List<String> untrackedFiles = git.getUntrackedPathFiles(relativePath);
+ if (untrackedFiles.isEmpty()) {
+ MessageBox box =
+ new MessageBox(HopGui.getInstance().getShell(), SWT.OK | SWT.ICON_INFORMATION);
+ box.setText(BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.NoFilesToClean.Header"));
+ box.setMessage(BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.NoFilesToClean.Message"));
+ box.open();
+ } else {
+ String[] files = untrackedFiles.toArray(new String[0]);
+ int[] selectedIndexes = new int[files.length];
+ for (int i = 0; i < files.length; i++) {
+ selectedIndexes[i] = i;
+ }
+ EnterSelectionDialog selectionDialog =
+ new EnterSelectionDialog(
+ HopGui.getInstance().getShell(),
+ files,
+ BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.CleanFiles.Header"),
+ BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.CleanFiles.Message"));
+ selectionDialog.setMulti(true);
+ // Select all files by default
+ //
+ selectionDialog.setSelectedNrs(selectedIndexes);
+ String selection = selectionDialog.open();
+ if (selection != null) {
+ List<String> pathsToClean = new ArrayList<>();
+ for (int selectedNr : selectionDialog.getSelectionIndeces()) {
+ pathsToClean.add(files[selectedNr]);
+ }
+
+ // Look up the filenames of the open tabs before the files are gone
+ //
+ Map<String, String> filenames = new HashMap<>();
+ for (String filePath : pathsToClean) {
+ filenames.put(filePath, getOpenFilename(filePath));
+ }
+
+ git.cleanPaths(pathsToClean);
+
+ // Close the tabs of the files which were deleted
+ //
+ List<String> filenamesToClose = new ArrayList<>();
+ for (String filePath : pathsToClean) {
+ if (!new File(git.getDirectory(), filePath).exists()) {
+ filenamesToClose.add(filenames.get(filePath));
+ }
+ }
+ ExplorerPerspective.getInstance().closeTabsForFilenames(filenamesToClose);
+
+ // Show confirmation message once after all files have been deleted
+ MessageBox box =
+ new MessageBox(HopGui.getInstance().getShell(), SWT.OK | SWT.ICON_INFORMATION);
+ box.setText(BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.FilesCleaned.Header"));
+ box.setMessage(BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.FilesCleaned.Message"));
+ box.open();
+ }
+ }
+ } catch (Exception e) {
+ new ErrorDialog(
+ HopGui.getInstance().getShell(),
+ BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.CleanError.Header"),
+ BaseMessages.getString(PKG, "GitGuiPlugin.Dialog.CleanError.Message"),
+ e);
+ }
+
+ // Refresh the git history, file explorer tree, change colors...
+ //
+ // TODO: To remove when git perspective work on web
+ if (EnvironmentUtils.getInstance().isWeb()) {
+ ExplorerPerspective.getInstance().refresh();
+ } else {
+ GitPerspective.getInstance().refresh(true);
+ }
+ enableButtons();
+ }
+
+ /**
+ * Calculate the filename an open editor tab uses for a file in the repository.
+ *
+ * @param relativePath The path of the file, relative to the repository root
+ * @return The filename to match open tabs with
+ */
+ private String getOpenFilename(String relativePath) {
+ File file = new File(git.getDirectory(), relativePath);
+ try {
+ FileObject fileObject = HopVfs.getFileObject(file.getAbsolutePath());
+ if (fileObject.exists()) {
+ return HopVfs.getFilename(fileObject);
+ }
+ } catch (Exception ignored) {
+ // Fall back to the absolute filename below
+ }
+ return file.getAbsolutePath();
+ }
+
@GuiMenuElement(
root = ID_CONTEXT_MENU_GIT,
parentId = ID_CONTEXT_MENU_GIT,
@@ -845,6 +930,8 @@ public class GitGuiPlugin
@Override
public void beforeRefresh() {
refreshChangedFiles();
+ // The git state of the files determines which operations are available
+ enableButtons();
}
@Override
@@ -857,21 +944,64 @@ public class GitGuiPlugin
boolean isGit = git != null;
boolean isSelected = isGit && getSelectedFile() != null;
+ // Only offer the git operations which make sense for what is selected:
+ //
+ // - Add stages what isn't staged yet
+ // - Commit needs any change at all, staged or not
+ // - Revert restores files from HEAD and unstages new files, so it needs something which isn't
+ // simply untracked
+ // - Clean deletes untracked files, so it needs the opposite of revert
+ //
+ boolean canAdd = isSelected && selectionContains(file -> !file.isStaged());
+ boolean canCommit = isSelected && selectionContains(file -> true);
+ boolean canRevert = isSelected && selectionContains(file -> !isUntracked(file));
+ boolean canClean = isSelected && selectionContains(GitGuiPlugin::isUntracked);
+
GuiToolbarWidgets toolBarWidgets = ExplorerPerspective.getInstance().getToolBarWidgets();
toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_GIT_INFO, isGit);
- toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_ADD, isSelected);
- toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_REVERT, isSelected);
- toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_COMMIT, isSelected);
+ toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_ADD, canAdd);
+ toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_REVERT, canRevert);
+ toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_CLEAN, canClean);
+ toolBarWidgets.enableToolbarItem(TOOLBAR_ITEM_COMMIT, canCommit);
GuiMenuWidgets menuWidgets = ExplorerPerspective.getInstance().getMenuWidgets();
menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_INFO, isGit);
- menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_ADD, isSelected);
- menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_COMMIT, isSelected);
- menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_REVERT, isSelected);
+ menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_ADD, canAdd);
+ menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_COMMIT, canCommit);
+ menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_REVERT, canRevert);
+ menuWidgets.enableMenuItem(CONTEXT_MENU_GIT_CLEAN, canClean);
HopGui.getInstance().getStatusToolbarWidgets().enableToolbarItem(ID_TOOLBAR_ITEM_GIT, isGit);
}
+ /** An untracked file: git doesn't know about it, so only a clean can remove it. */
+ private static boolean isUntracked(UIFile file) {
+ return file.getChangeType() == ChangeType.ADD && !file.isStaged();
+ }
+
+ /**
+ * Check the changed files of the selected file or folder against a condition. For a folder all
+ * the changed files below it are taken into account.
+ *
+ * @param condition The condition to check
+ * @return true if at least one changed file in the selection matches the condition
+ */
+ private boolean selectionContains(Predicate<UIFile> condition) {
+ ExplorerFile explorerFile = getSelectedFile();
+ if (explorerFile == null || changedFiles == null) {
+ return false;
+ }
+ String selectedPath = getAbsoluteFilename(explorerFile.getFilename());
+ for (Map.Entry<String, UIFile> entry : changedFiles.entrySet()) {
+ String path = entry.getKey();
+ if ((path.equals(selectedPath) || path.startsWith(selectedPath + "/"))
+ && condition.test(entry.getValue())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* If we have a git project we can take a look and see if a file is changed.
*
diff --git a/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java b/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
index e97965ebab..1423571820 100644
--- a/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
+++ b/plugins/misc/git/src/main/java/org/apache/hop/git/model/UIGit.java
@@ -444,6 +444,8 @@ public class UIGit extends VCS {
}
status.getUntracked().forEach(name -> files.add(new UIFile(name, ChangeType.ADD, false)));
status.getConflicting().forEach(name -> files.add(new UIFile(name, ChangeType.MODIFY, false)));
+ // Changed in the working tree but not staged: "git add" is what stages these
+ status.getModified().forEach(name -> files.add(new UIFile(name, ChangeType.MODIFY, false)));
status.getMissing().forEach(name -> files.add(new UIFile(name, ChangeType.DELETE, false)));
return files;
}
@@ -457,9 +459,9 @@ public class UIGit extends VCS {
e.printStackTrace();
return files;
}
+ // Only what is in the index: working tree changes are reported by getUnstagedFiles()
status.getAdded().forEach(name -> files.add(new UIFile(name, ChangeType.ADD, true)));
status.getChanged().forEach(name -> files.add(new UIFile(name, ChangeType.MODIFY, true)));
- status.getModified().forEach(name -> files.add(new UIFile(name, ChangeType.MODIFY, true)));
status.getRemoved().forEach(name -> files.add(new UIFile(name, ChangeType.DELETE, true)));
return files;
}
@@ -998,6 +1000,28 @@ public class UIGit extends VCS {
}
}
+ /**
+ * Get the untracked files under the given path: the files a git clean would remove. Ignored files
+ * are not part of this list, git clean leaves those alone as well.
+ *
+ * @param path The path to clean (relative to the repository root)
+ * @return The untracked files, sorted by name
+ */
+ public List<String> getUntrackedPathFiles(String path) throws HopException {
+ try {
+ String normalizedPath = normalizePathForJGit(path);
+ StatusCommand statusCommand = git.status();
+ if (normalizedPath != null && !".".equals(normalizedPath)) {
+ statusCommand = statusCommand.addPath(normalizedPath);
+ }
+ List<String> files = new ArrayList<>(statusCommand.call().getUntracked());
+ Collections.sort(files);
+ return files;
+ } catch (Exception e) {
+ throw new HopException("Git: error getting untracked files for '" + path + "'", e);
+ }
+ }
+
/**
* Get the subset of revert-path files which are new: untracked or added but not in HEAD. Revert
* only unstages these and leaves them on disk; removing them takes an explicit git clean. For all
diff --git a/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties b/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
index 28d564f06b..ddebb027d4 100644
--- a/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
+++ b/plugins/misc/git/src/main/resources/org/apache/hop/git/messages/messages_en_US.properties
@@ -42,10 +42,18 @@ GitGuiPlugin.Dialog.CherryPickCommitRepositoryIsNotClean.Message=Please clean yo
GitGuiPlugin.Dialog.CherryPickCommitConflicts.Message=There were conflicts while cherry-picking commit ''{0}''\n\n{1}
GitGuiPlugin.Dialog.CommitError.Header=Commit Error
GitGuiPlugin.Dialog.CommitError.Message=There was an error doing a git commit
+GitGuiPlugin.Dialog.CleanError.Header=Clean Error
+GitGuiPlugin.Dialog.CleanError.Message=There was an error doing a git clean
+GitGuiPlugin.Dialog.CleanFiles.Header=Select files to delete
+GitGuiPlugin.Dialog.CleanFiles.Message=These files are not tracked by git. Please select the files to delete from disk.
+GitGuiPlugin.Dialog.FilesCleaned.Header=Files Deleted
+GitGuiPlugin.Dialog.FilesCleaned.Message=The selected untracked files were deleted
GitGuiPlugin.Dialog.FilesReverted.Header=Files Reverted
GitGuiPlugin.Dialog.FilesReverted.Message=Files Reverted
GitGuiPlugin.Dialog.MergeBranchError.Header=Error merging branch
GitGuiPlugin.Dialog.MergeBranchError.Message=Error merging branch
+GitGuiPlugin.Dialog.NoFilesToClean.Header=No Files to Delete
+GitGuiPlugin.Dialog.NoFilesToClean.Message=Sorry, there are no untracked files to delete
GitGuiPlugin.Dialog.NoFilesToCommit.Header=No Files to Commit
GitGuiPlugin.Dialog.NoFilesToCommit.Message=Sorry, there are no files to commit
GitGuiPlugin.Dialog.NoFilesToRevert.Header=No Files to Revert
@@ -76,8 +84,6 @@ GitGuiPlugin.Dialog.Tag.CreateTag.Header=Create a Tag
GitGuiPlugin.Dialog.Tag.CreateTag.Message=Enter the name of the new tag
GitGuiPlugin.Dialog.Tag.DeleteTagConfirmation.Header=Delete a Tag
GitGuiPlugin.Dialog.Tag.DeleteTagConfirmation.Message=Are you sure you want to delete tag ''{0}'' ?
-GitGuiPlugin.Dialog.CleanConfirm.Header=Git Clean
-GitGuiPlugin.Dialog.CleanConfirm.Message=The new files were unstaged and are still on disk. Should we also run git clean to remove them?
GitGuiPlugin.Dialog.SelectFilesToCommit.Header=Commit Message
GitGuiPlugin.Dialog.SelectFilesToCommit.Message=Please enter a commit message:
GitGuiPlugin.Dialog.StageFiles.Header=Select files to commit
@@ -96,6 +102,7 @@ GitGuiPlugin.Menu.Branch.Rename.Text=Rename branch...
GitGuiPlugin.Menu.Commit.Text=Git Commit
GitGuiPlugin.Menu.Info.Text=Git Info
GitGuiPlugin.Menu.Revert.Text=Git Revert
+GitGuiPlugin.Menu.Clean.Text=Git Clean
GitGuiPlugin.Menu.Restore.Text=Git Restore
GitGuiPlugin.Menu.ShowDiff.Text=Show diff
GitGuiPlugin.Project.Label=Git Project
@@ -107,6 +114,7 @@ GitGuiPlugin.Toolbar.Fetch.Tooltip=Fetch
GitGuiPlugin.Toolbar.Pull.Tooltip=Git Pull
GitGuiPlugin.Toolbar.Push.Tooltip=Git Push
GitGuiPlugin.Toolbar.Revert.Tooltip=Git revert file to the last committed version (HEAD)
+GitGuiPlugin.Toolbar.Clean.Tooltip=Git clean: delete untracked files from disk
GitCommitPerspective.Description=Git commit perspective
GitCommitPerspective.Name=Git commit
diff --git a/plugins/misc/git/src/test/java/org/apache/hop/git/model/UIGitTest.java b/plugins/misc/git/src/test/java/org/apache/hop/git/model/UIGitTest.java
index da33524cd8..670baccdba 100644
--- a/plugins/misc/git/src/test/java/org/apache/hop/git/model/UIGitTest.java
+++ b/plugins/misc/git/src/test/java/org/apache/hop/git/model/UIGitTest.java
@@ -533,6 +533,57 @@ public class UIGitTest extends RepositoryTestCase {
assertTrue(newFiles.contains("folder/Added.txt"));
}
+ @Test
+ public void testModifiedFilesAreUnstagedUntilTheyAreAdded() throws Exception {
+ File file = writeTrashFile("Test.txt", "Hello world");
+ git.add().addFilepattern("Test.txt").call();
+ git.commit().setMessage("initial commit").call();
+
+ // A change in the working tree is not staged, only "git add" stages it
+ FileUtils.writeStringToFile(file, "Change", StandardCharsets.UTF_8);
+
+ List<UIFile> unstaged = uiGit.getUnstagedFiles();
+ assertEquals(1, unstaged.size());
+ assertEquals("Test.txt", unstaged.get(0).getName());
+ assertEquals(ChangeType.MODIFY, unstaged.get(0).getChangeType());
+ assertFalse(unstaged.get(0).isStaged());
+ assertTrue(uiGit.getStagedFiles().isEmpty());
+
+ uiGit.add("Test.txt");
+
+ List<UIFile> staged = uiGit.getStagedFiles();
+ assertEquals(1, staged.size());
+ assertEquals("Test.txt", staged.get(0).getName());
+ assertEquals(ChangeType.MODIFY, staged.get(0).getChangeType());
+ assertTrue(staged.get(0).isStaged());
+ assertTrue(uiGit.getUnstagedFiles().isEmpty());
+ }
+
+ @Test
+ public void testGetUntrackedPathFiles() throws Exception {
+ File tracked = writeTrashFile("folder/Tracked.txt", "Hello world");
+ writeTrashFile("folder/Ignored.txt", "Ignored");
+ writeTrashFile(".gitignore", "Ignored.txt");
+ git.add().addFilepattern("folder/Tracked.txt").addFilepattern(".gitignore").call();
+ git.commit().setMessage("initial commit").call();
+
+ FileUtils.writeStringToFile(tracked, "Change", StandardCharsets.UTF_8);
+ writeTrashFile("folder/Untracked.txt", "Untracked");
+ writeTrashFile("folder/Added.txt", "Added");
+ git.add().addFilepattern("folder/Added.txt").call();
+ writeTrashFile("outside/Other.txt", "Outside the folder");
+
+ // Only the untracked file: not the tracked, added, ignored or out of scope ones
+ assertEquals(List.of("folder/Untracked.txt"), uiGit.getUntrackedPathFiles("folder"));
+
+ // A single file works as well, as does the whole repository
+ assertEquals(
+ List.of("folder/Untracked.txt"), uiGit.getUntrackedPathFiles("folder/Untracked.txt"));
+ assertTrue(uiGit.getUntrackedPathFiles("folder/Tracked.txt").isEmpty());
+ assertEquals(
+ List.of("folder/Untracked.txt", "outside/Other.txt"), uiGit.getUntrackedPathFiles(null));
+ }
+
@Test
public void testCleanPathsOnlyRemovesUntrackedFiles() throws Exception {
File tracked = writeTrashFile("folder/Tracked.txt", "Hello world");