diff --git a/GitCommands/Git/Commands/GitCommandHelpers.cs b/GitCommands/Git/Commands/GitCommandHelpers.cs
index 478a056ce4d..c4b4164ba72 100644
--- a/GitCommands/Git/Commands/GitCommandHelpers.cs
+++ b/GitCommands/Git/Commands/GitCommandHelpers.cs
@@ -531,14 +531,16 @@ public static ArgumentString ApplyDiffPatchCmd(bool ignoreWhiteSpace, string pat
/// Only show what would be deleted.
/// Delete untracked directories too.
/// Limit to specific paths.
- public static ArgumentString CleanCmd(CleanMode mode, bool dryRun, bool directories, string? paths = null)
+ /// Exclude certain files.
+ public static ArgumentString CleanCmd(CleanMode mode, bool dryRun, bool directories, string? paths = null, string? excludes = null)
{
return new GitArgumentBuilder("clean")
{
mode,
{ directories, "-d" },
{ dryRun, "--dry-run", "-f" },
- paths
+ paths,
+ { !string.IsNullOrEmpty(excludes), excludes }
};
}
diff --git a/GitUI/CommandsDialogs/FormCleanupRepository.Designer.cs b/GitUI/CommandsDialogs/FormCleanupRepository.Designer.cs
index f739170c349..385a993681a 100644
--- a/GitUI/CommandsDialogs/FormCleanupRepository.Designer.cs
+++ b/GitUI/CommandsDialogs/FormCleanupRepository.Designer.cs
@@ -29,7 +29,7 @@ protected override void Dispose(bool disposing)
private void InitializeComponent()
{
Preview = new Button();
- AddPath = new Button();
+ AddInclusivePath = new Button();
Cleanup = new Button();
_NO_TRANSLATE_Close = new Button();
groupBox1 = new GroupBox();
@@ -39,9 +39,13 @@ private void InitializeComponent()
RemoveDirectories = new CheckBox();
PreviewOutput = new TextBox();
label1 = new Label();
- textBoxPaths = new TextBox();
- checkBoxPathFilter = new CheckBox();
- labelPathHint = new Label();
+ textBoxIncludePaths = new TextBox();
+ checkBoxIncludePathFilter = new CheckBox();
+ textBoxExcludePaths = new TextBox();
+ checkBoxExcludePathFilter = new CheckBox();
+ AddExclusivePath = new Button();
+ labelPathHintExclude = new Label();
+ labelPathHintInclude = new Label();
CleanSubmodules = new CheckBox();
groupBox1.SuspendLayout();
SuspendLayout();
@@ -51,35 +55,38 @@ private void InitializeComponent()
Preview.Anchor = AnchorStyles.Top | AnchorStyles.Right;
Preview.Image = Properties.Images.Preview;
Preview.ImageAlign = ContentAlignment.MiddleLeft;
- Preview.Location = new Point(50, 300);
+ Preview.Location = new Point(60, 529);
+ Preview.Margin = new Padding(4);
Preview.Name = "Preview";
- Preview.Size = new Size(120, 25);
- Preview.TabIndex = 0;
+ Preview.Size = new Size(150, 31);
+ Preview.TabIndex = 10;
Preview.Text = "Preview";
Preview.UseVisualStyleBackColor = true;
Preview.Click += Preview_Click;
//
- // AddPath
+ // AddInclusivePath
//
- AddPath.Anchor = AnchorStyles.Top | AnchorStyles.Right;
- AddPath.ImageAlign = ContentAlignment.MiddleLeft;
- AddPath.Location = new Point(302, 164);
- AddPath.Name = "AddPath";
- AddPath.Size = new Size(120, 25);
- AddPath.TabIndex = 0;
- AddPath.Text = "Add a path...";
- AddPath.UseVisualStyleBackColor = true;
- AddPath.Click += AddPath_Click;
+ AddInclusivePath.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+ AddInclusivePath.ImageAlign = ContentAlignment.MiddleLeft;
+ AddInclusivePath.Location = new Point(378, 203);
+ AddInclusivePath.Margin = new Padding(4);
+ AddInclusivePath.Name = "AddInclusivePath";
+ AddInclusivePath.Size = new Size(150, 31);
+ AddInclusivePath.TabIndex = 3;
+ AddInclusivePath.Text = "Add a path...";
+ AddInclusivePath.UseVisualStyleBackColor = true;
+ AddInclusivePath.Click += AddIncludePath_Click;
//
// Cleanup
//
Cleanup.Anchor = AnchorStyles.Top | AnchorStyles.Right;
Cleanup.Image = Properties.Images.CleanupRepo;
Cleanup.ImageAlign = ContentAlignment.MiddleLeft;
- Cleanup.Location = new Point(176, 300);
+ Cleanup.Location = new Point(218, 529);
+ Cleanup.Margin = new Padding(4);
Cleanup.Name = "Cleanup";
- Cleanup.Size = new Size(120, 25);
- Cleanup.TabIndex = 1;
+ Cleanup.Size = new Size(150, 31);
+ Cleanup.TabIndex = 11;
Cleanup.Text = "Cleanup";
Cleanup.UseVisualStyleBackColor = true;
Cleanup.Click += Cleanup_Click;
@@ -88,11 +95,12 @@ private void InitializeComponent()
//
_NO_TRANSLATE_Close.Anchor = AnchorStyles.Top | AnchorStyles.Right;
_NO_TRANSLATE_Close.DialogResult = DialogResult.OK;
- _NO_TRANSLATE_Close.Location = new Point(302, 300);
+ _NO_TRANSLATE_Close.Location = new Point(376, 529);
+ _NO_TRANSLATE_Close.Margin = new Padding(4);
_NO_TRANSLATE_Close.Name = "_NO_TRANSLATE_Close";
- _NO_TRANSLATE_Close.Size = new Size(120, 25);
- _NO_TRANSLATE_Close.TabIndex = 2;
- _NO_TRANSLATE_Close.Text = TranslatedStrings.Close;
+ _NO_TRANSLATE_Close.Size = new Size(150, 31);
+ _NO_TRANSLATE_Close.TabIndex = 12;
+ _NO_TRANSLATE_Close.Text = "Close";
_NO_TRANSLATE_Close.UseVisualStyleBackColor = true;
_NO_TRANSLATE_Close.Click += Close_Click;
//
@@ -102,19 +110,22 @@ private void InitializeComponent()
groupBox1.Controls.Add(RemoveIgnored);
groupBox1.Controls.Add(RemoveNonIgnored);
groupBox1.Controls.Add(RemoveAll);
- groupBox1.Location = new Point(12, 12);
+ groupBox1.Location = new Point(15, 15);
+ groupBox1.Margin = new Padding(4);
groupBox1.Name = "groupBox1";
- groupBox1.Size = new Size(410, 100);
- groupBox1.TabIndex = 3;
+ groupBox1.Padding = new Padding(4);
+ groupBox1.Size = new Size(512, 125);
+ groupBox1.TabIndex = 0;
groupBox1.TabStop = false;
groupBox1.Text = "Remove untracked files from working directory";
//
// RemoveIgnored
//
RemoveIgnored.AutoSize = true;
- RemoveIgnored.Location = new Point(7, 67);
+ RemoveIgnored.Location = new Point(9, 84);
+ RemoveIgnored.Margin = new Padding(4);
RemoveIgnored.Name = "RemoveIgnored";
- RemoveIgnored.Size = new Size(197, 17);
+ RemoveIgnored.Size = new Size(272, 24);
RemoveIgnored.TabIndex = 2;
RemoveIgnored.Text = "Remove only ignored untracked files";
RemoveIgnored.UseVisualStyleBackColor = true;
@@ -122,9 +133,10 @@ private void InitializeComponent()
// RemoveNonIgnored
//
RemoveNonIgnored.AutoSize = true;
- RemoveNonIgnored.Location = new Point(7, 43);
+ RemoveNonIgnored.Location = new Point(9, 54);
+ RemoveNonIgnored.Margin = new Padding(4);
RemoveNonIgnored.Name = "RemoveNonIgnored";
- RemoveNonIgnored.Size = new Size(218, 17);
+ RemoveNonIgnored.Size = new Size(303, 24);
RemoveNonIgnored.TabIndex = 1;
RemoveNonIgnored.Text = "Remove only non-ignored untracked files";
RemoveNonIgnored.UseVisualStyleBackColor = true;
@@ -133,9 +145,10 @@ private void InitializeComponent()
//
RemoveAll.AutoSize = true;
RemoveAll.Checked = true;
- RemoveAll.Location = new Point(7, 20);
+ RemoveAll.Location = new Point(9, 25);
+ RemoveAll.Margin = new Padding(4);
RemoveAll.Name = "RemoveAll";
- RemoveAll.Size = new Size(150, 17);
+ RemoveAll.Size = new Size(204, 24);
RemoveAll.TabIndex = 0;
RemoveAll.TabStop = true;
RemoveAll.Text = "Remove all untracked files";
@@ -146,84 +159,139 @@ private void InitializeComponent()
RemoveDirectories.AutoSize = true;
RemoveDirectories.Checked = true;
RemoveDirectories.CheckState = CheckState.Checked;
- RemoveDirectories.Location = new Point(19, 119);
+ RemoveDirectories.Location = new Point(24, 148);
+ RemoveDirectories.Margin = new Padding(4);
RemoveDirectories.Name = "RemoveDirectories";
- RemoveDirectories.Size = new Size(168, 17);
- RemoveDirectories.TabIndex = 4;
+ RemoveDirectories.Size = new Size(228, 24);
+ RemoveDirectories.TabIndex = 1;
RemoveDirectories.Text = "Remove untracked directories";
RemoveDirectories.UseVisualStyleBackColor = true;
//
// PreviewOutput
//
PreviewOutput.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
- PreviewOutput.Location = new Point(12, 353);
+ PreviewOutput.Location = new Point(17, 597);
+ PreviewOutput.Margin = new Padding(4);
PreviewOutput.Multiline = true;
PreviewOutput.Name = "PreviewOutput";
PreviewOutput.ScrollBars = ScrollBars.Both;
- PreviewOutput.Size = new Size(410, 87);
- PreviewOutput.TabIndex = 5;
+ PreviewOutput.Size = new Size(512, 117);
+ PreviewOutput.TabIndex = 14;
PreviewOutput.WordWrap = false;
//
// label1
//
label1.AutoSize = true;
- label1.Location = new Point(9, 335);
+ label1.Location = new Point(17, 573);
+ label1.Margin = new Padding(4, 0, 4, 0);
label1.Name = "label1";
- label1.Size = new Size(28, 13);
- label1.TabIndex = 6;
+ label1.Size = new Size(37, 20);
+ label1.TabIndex = 13;
label1.Text = "Log:";
//
- // textBoxPaths
- //
- textBoxPaths.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
- textBoxPaths.Location = new Point(48, 194);
- textBoxPaths.Multiline = true;
- textBoxPaths.Name = "textBoxPaths";
- textBoxPaths.ScrollBars = ScrollBars.Vertical;
- textBoxPaths.Size = new Size(374, 63);
- textBoxPaths.TabIndex = 1;
- //
- // checkBoxPathFilter
- //
- checkBoxPathFilter.AutoSize = true;
- checkBoxPathFilter.Location = new Point(19, 169);
- checkBoxPathFilter.Name = "checkBoxPathFilter";
- checkBoxPathFilter.Size = new Size(176, 17);
- checkBoxPathFilter.TabIndex = 0;
- checkBoxPathFilter.Text = "Affect the following path(s) only:";
- checkBoxPathFilter.UseVisualStyleBackColor = true;
- checkBoxPathFilter.CheckedChanged += checkBoxPathFilter_CheckedChanged;
- //
- // labelPathHint
- //
- labelPathHint.AutoSize = true;
- labelPathHint.Location = new Point(50, 261);
- labelPathHint.Name = "labelPathHint";
- labelPathHint.Size = new Size(92, 13);
- labelPathHint.TabIndex = 7;
- labelPathHint.Text = "(one path per line)";
+ // textBoxIncludePaths
+ //
+ textBoxIncludePaths.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ textBoxIncludePaths.Location = new Point(60, 240);
+ textBoxIncludePaths.Margin = new Padding(4);
+ textBoxIncludePaths.Multiline = true;
+ textBoxIncludePaths.Name = "textBoxIncludePaths";
+ textBoxIncludePaths.ScrollBars = ScrollBars.Vertical;
+ textBoxIncludePaths.Size = new Size(466, 78);
+ textBoxIncludePaths.TabIndex = 4;
+ //
+ // checkBoxIncludePathFilter
+ //
+ checkBoxIncludePathFilter.AutoSize = true;
+ checkBoxIncludePathFilter.Location = new Point(24, 209);
+ checkBoxIncludePathFilter.Margin = new Padding(4);
+ checkBoxIncludePathFilter.Name = "checkBoxIncludePathFilter";
+ checkBoxIncludePathFilter.Size = new Size(311, 24);
+ checkBoxIncludePathFilter.TabIndex = 2;
+ checkBoxIncludePathFilter.Text = "Affect the following directory path(s) only:";
+ checkBoxIncludePathFilter.UseVisualStyleBackColor = true;
+ checkBoxIncludePathFilter.CheckedChanged += checkBoxPathFilter_CheckedChanged;
+ //
+ // textBoxExcludePaths
+ //
+ textBoxExcludePaths.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
+ textBoxExcludePaths.Location = new Point(60, 391);
+ textBoxExcludePaths.Margin = new Padding(4);
+ textBoxExcludePaths.Multiline = true;
+ textBoxExcludePaths.Name = "textBoxExcludePaths";
+ textBoxExcludePaths.ScrollBars = ScrollBars.Vertical;
+ textBoxExcludePaths.Size = new Size(466, 78);
+ textBoxExcludePaths.TabIndex = 8;
+ //
+ // checkBoxExcludePathFilter
+ //
+ checkBoxExcludePathFilter.AutoSize = true;
+ checkBoxExcludePathFilter.Location = new Point(24, 360);
+ checkBoxExcludePathFilter.Margin = new Padding(4);
+ checkBoxExcludePathFilter.Name = "checkBoxExcludePathFilter";
+ checkBoxExcludePathFilter.Size = new Size(252, 24);
+ checkBoxExcludePathFilter.TabIndex = 6;
+ checkBoxExcludePathFilter.Text = "Exclude the following file path(s):";
+ checkBoxExcludePathFilter.UseVisualStyleBackColor = true;
+ checkBoxExcludePathFilter.CheckedChanged += checkBoxExcludePathFilter_CheckedChanged;
+ //
+ // AddExclusivePath
+ //
+ AddExclusivePath.Anchor = AnchorStyles.Top | AnchorStyles.Right;
+ AddExclusivePath.ImageAlign = ContentAlignment.MiddleLeft;
+ AddExclusivePath.Location = new Point(378, 354);
+ AddExclusivePath.Margin = new Padding(4);
+ AddExclusivePath.Name = "AddExclusivePath";
+ AddExclusivePath.Size = new Size(150, 31);
+ AddExclusivePath.TabIndex = 7;
+ AddExclusivePath.Text = "Add a path...";
+ AddExclusivePath.UseVisualStyleBackColor = true;
+ AddExclusivePath.Click += AddExcludePath_Click;
+ //
+ // labelPathHintExclude
+ //
+ labelPathHintExclude.AutoSize = true;
+ labelPathHintExclude.Location = new Point(62, 475);
+ labelPathHintExclude.Margin = new Padding(4, 0, 4, 0);
+ labelPathHintExclude.Name = "labelPathHintExclude";
+ labelPathHintExclude.Size = new Size(132, 20);
+ labelPathHintExclude.TabIndex = 9;
+ labelPathHintExclude.Text = "(one path per line)";
+ //
+ // labelPathHintInclude
+ //
+ labelPathHintInclude.AutoSize = true;
+ labelPathHintInclude.Location = new Point(62, 323);
+ labelPathHintInclude.Margin = new Padding(4, 0, 4, 0);
+ labelPathHintInclude.Name = "labelPathHintInclude";
+ labelPathHintInclude.Size = new Size(132, 20);
+ labelPathHintInclude.TabIndex = 5;
+ labelPathHintInclude.Text = "(one path per line)";
//
// CleanSubmodules
//
CleanSubmodules.AutoSize = true;
- CleanSubmodules.Location = new Point(19, 144);
+ CleanSubmodules.Location = new Point(24, 178);
CleanSubmodules.Name = "CleanSubmodules";
- CleanSubmodules.Size = new Size(183, 19);
+ CleanSubmodules.Size = new Size(225, 24);
CleanSubmodules.TabIndex = 8;
CleanSubmodules.Text = "Clean submodules recursively";
CleanSubmodules.UseVisualStyleBackColor = true;
//
// FormCleanupRepository
//
- AcceptButton = AddPath;
- AutoScaleDimensions = new SizeF(96F, 96F);
+ AcceptButton = AddInclusivePath;
+ AutoScaleDimensions = new SizeF(120F, 120F);
AutoScaleMode = AutoScaleMode.Dpi;
CancelButton = _NO_TRANSLATE_Close;
- ClientSize = new Size(434, 462);
- Controls.Add(CleanSubmodules);
- Controls.Add(labelPathHint);
- Controls.Add(textBoxPaths);
- Controls.Add(checkBoxPathFilter);
+ ClientSize = new Size(542, 727);
+ Controls.Add(labelPathHintInclude);
+ Controls.Add(labelPathHintExclude);
+ Controls.Add(textBoxExcludePaths);
+ Controls.Add(checkBoxExcludePathFilter);
+ Controls.Add(AddExclusivePath);
+ Controls.Add(textBoxIncludePaths);
+ Controls.Add(checkBoxIncludePathFilter);
Controls.Add(label1);
Controls.Add(PreviewOutput);
Controls.Add(RemoveDirectories);
@@ -231,10 +299,12 @@ private void InitializeComponent()
Controls.Add(_NO_TRANSLATE_Close);
Controls.Add(Cleanup);
Controls.Add(Preview);
- Controls.Add(AddPath);
+ Controls.Add(AddInclusivePath);
+ Controls.Add(CleanSubmodules);
+ Margin = new Padding(4);
MaximizeBox = false;
MinimizeBox = false;
- MinimumSize = new Size(450, 500);
+ MinimumSize = new Size(558, 738);
Name = "FormCleanupRepository";
StartPosition = FormStartPosition.CenterParent;
Text = "Clean working directory";
@@ -247,7 +317,7 @@ private void InitializeComponent()
#endregion
private Button Preview;
- private Button AddPath;
+ private Button AddInclusivePath;
private Button Cleanup;
private Button _NO_TRANSLATE_Close;
private GroupBox groupBox1;
@@ -257,9 +327,13 @@ private void InitializeComponent()
private CheckBox RemoveDirectories;
private TextBox PreviewOutput;
private Label label1;
- private TextBox textBoxPaths;
- private CheckBox checkBoxPathFilter;
- private Label labelPathHint;
+ private TextBox textBoxIncludePaths;
+ private CheckBox checkBoxIncludePathFilter;
+ private TextBox textBoxExcludePaths;
+ private CheckBox checkBoxExcludePathFilter;
+ private Button AddExclusivePath;
+ private Label labelPathHintExclude;
+ private Label labelPathHintInclude;
private CheckBox CleanSubmodules;
}
}
diff --git a/GitUI/CommandsDialogs/FormCleanupRepository.cs b/GitUI/CommandsDialogs/FormCleanupRepository.cs
index aebe5b5a1d8..749d0186dd7 100644
--- a/GitUI/CommandsDialogs/FormCleanupRepository.cs
+++ b/GitUI/CommandsDialogs/FormCleanupRepository.cs
@@ -1,6 +1,7 @@
using GitCommands;
using GitCommands.Git.Commands;
using GitCommands.Utils;
+using GitExtUtils;
using GitUI.HelperDialogs;
using ResourceManager;
@@ -24,56 +25,60 @@ public FormCleanupRepository(GitUICommands commands)
InitializeComponent();
InitializeComplete();
PreviewOutput.ReadOnly = true;
+
checkBoxPathFilter_CheckedChanged(this, EventArgs.Empty);
+ checkBoxExcludePathFilter_CheckedChanged(this, EventArgs.Empty);
}
public void SetPathArgument(string? path)
{
if (string.IsNullOrEmpty(path))
{
- checkBoxPathFilter.Checked = false;
- textBoxPaths.Text = "";
+ checkBoxExcludePathFilter.Checked = false;
+ textBoxExcludePaths.Text = "";
+
+ checkBoxIncludePathFilter.Checked = false;
+ textBoxIncludePaths.Text = "";
}
else
{
- checkBoxPathFilter.Checked = true;
- textBoxPaths.Text = path;
+ checkBoxExcludePathFilter.Checked = true;
+ textBoxExcludePaths.Text = path;
+
+ checkBoxIncludePathFilter.Checked = true;
+ textBoxIncludePaths.Text = path;
}
}
- private void Preview_Click(object sender, EventArgs e)
+ private void CleanUp(bool dryRun)
{
- string pathArgument = GetPathArgumentFromGui();
+ string includePathArgument = GetInclusivePathArgumentFromGui();
+ string excludePathArguments = GetExclusivePathArgumentFromGui();
CleanMode mode = GetCleanMode();
- var cleanUpCmd = GitCommandHelpers.CleanCmd(mode, dryRun: true, directories: RemoveDirectories.Checked, paths: pathArgument);
+ ArgumentString cleanUpCmd = GitCommandHelpers.CleanCmd(mode, dryRun, directories: RemoveDirectories.Checked,
+ paths: includePathArgument, excludes: excludePathArguments);
+
string cmdOutput = FormProcess.ReadDialog(this, arguments: cleanUpCmd, Module.WorkingDir, input: null, useDialogSettings: true);
PreviewOutput.Text = EnvUtils.ReplaceLinuxNewLinesDependingOnPlatform(cmdOutput);
if (CleanSubmodules.Checked)
{
- var cleanSubmodulesCmd = GitCommandHelpers.CleanSubmodules(mode, dryRun: true, directories: RemoveDirectories.Checked, paths: pathArgument);
+ ArgumentString cleanSubmodulesCmd = GitCommandHelpers.CleanSubmodules(mode, dryRun, directories: RemoveDirectories.Checked, paths: includePathArgument);
cmdOutput = FormProcess.ReadDialog(this, arguments: cleanSubmodulesCmd, Module.WorkingDir, input: null, useDialogSettings: true);
PreviewOutput.Text += EnvUtils.ReplaceLinuxNewLinesDependingOnPlatform(cmdOutput);
}
}
+ private void Preview_Click(object sender, EventArgs e)
+ {
+ CleanUp(dryRun: true);
+ }
+
private void Cleanup_Click(object sender, EventArgs e)
{
if (MessageBox.Show(this, _reallyCleanupQuestion.Text, _reallyCleanupQuestionCaption.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
{
- string pathArgument = GetPathArgumentFromGui();
- CleanMode mode = GetCleanMode();
- var cleanUpCmd = GitCommandHelpers.CleanCmd(mode, dryRun: false, directories: RemoveDirectories.Checked, paths: pathArgument);
-
- string cmdOutput = FormProcess.ReadDialog(this, arguments: cleanUpCmd, Module.WorkingDir, input: null, useDialogSettings: true);
- PreviewOutput.Text = EnvUtils.ReplaceLinuxNewLinesDependingOnPlatform(cmdOutput);
-
- if (CleanSubmodules.Checked)
- {
- var cleanSubmodulesCmd = GitCommandHelpers.CleanSubmodules(mode, dryRun: false, directories: RemoveDirectories.Checked, paths: pathArgument);
- cmdOutput = FormProcess.ReadDialog(this, arguments: cleanSubmodulesCmd, Module.WorkingDir, input: null, useDialogSettings: true);
- PreviewOutput.Text += EnvUtils.ReplaceLinuxNewLinesDependingOnPlatform(cmdOutput);
- }
+ CleanUp(dryRun: false);
}
}
@@ -97,9 +102,9 @@ private CleanMode GetCleanMode()
throw new NotSupportedException($"Unknown value for {nameof(CleanMode)}.");
}
- private string? GetPathArgumentFromGui()
+ private string? GetInclusivePathArgumentFromGui()
{
- if (!checkBoxPathFilter.Checked)
+ if (!checkBoxIncludePathFilter.Checked)
{
return null;
}
@@ -107,7 +112,21 @@ private CleanMode GetCleanMode()
// 1. get all lines from text box which are not empty
// 2. wrap lines with ""
// 3. join together with space as separator
- return string.Join(" ", textBoxPaths.Lines.Where(a => !string.IsNullOrEmpty(a)).Select(a => string.Format("\"{0}\"", a)));
+ return string.Join(" ", textBoxIncludePaths.Lines.Where(p => !string.IsNullOrEmpty(p)).Select(p => $"\"{p}\""));
+ }
+
+ private string? GetExclusivePathArgumentFromGui()
+ {
+ if (!checkBoxExcludePathFilter.Checked)
+ {
+ return null;
+ }
+
+ // 1. get all lines from text box which are not empty
+ // 2. Prepend lines with '--exclude='
+ // 3. Replace whitespace with '?' and convert to POSIX path
+ // 4. join together with space as separator
+ return string.Join(" ", textBoxExcludePaths.Lines.Where(p => !string.IsNullOrEmpty(p)).Select(p => $"--exclude={p.Replace(" ", "?")}".ToPosixPath()));
}
private void Close_Click(object sender, EventArgs e)
@@ -117,14 +136,42 @@ private void Close_Click(object sender, EventArgs e)
private void checkBoxPathFilter_CheckedChanged(object sender, EventArgs e)
{
- bool filterByPath = checkBoxPathFilter.Checked;
- textBoxPaths.Enabled = filterByPath;
- labelPathHint.Visible = filterByPath;
+ bool filterByPath = checkBoxIncludePathFilter.Checked;
+ textBoxIncludePaths.Enabled = filterByPath;
+ labelPathHintInclude.Visible = filterByPath;
+ }
+
+ private void checkBoxExcludePathFilter_CheckedChanged(object sender, EventArgs e)
+ {
+ bool filterByPath = checkBoxExcludePathFilter.Checked;
+ textBoxExcludePaths.Enabled = filterByPath;
+ labelPathHintExclude.Visible = filterByPath;
+ }
+
+ private void AddIncludePath_Click(object sender, EventArgs e)
+ {
+ string path = RequestUserFolderPath();
+
+ if (path is not null)
+ {
+ textBoxIncludePaths.Text += path;
+ }
+ }
+
+ private void AddExcludePath_Click(object sender, EventArgs e)
+ {
+ string path = RequestUserFilePath();
+
+ if (path is not null)
+ {
+ path = path.Replace(Module.WorkingDir, "");
+ textBoxExcludePaths.Text += path;
+ }
}
- private void AddPath_Click(object sender, EventArgs e)
+ private string? RequestUserFolderPath()
{
- FolderBrowserDialog dialog = new()
+ using FolderBrowserDialog dialog = new()
{
SelectedPath = Module.WorkingDir,
};
@@ -132,20 +179,51 @@ private void AddPath_Click(object sender, EventArgs e)
var result = dialog.ShowDialog(this);
string subFoldersToClean;
- if (result == DialogResult.OK
- && (subFoldersToClean = dialog.SelectedPath).StartsWith(Module.WorkingDir)
- && Directory.Exists(subFoldersToClean)
- && !subFoldersToClean.Equals(Module.WorkingDirGitDir.TrimEnd(Path.DirectorySeparatorChar)))
- {
- checkBoxPathFilter.Checked = true;
- textBoxPaths.Enabled = true;
- if (textBoxPaths.Text.Length != 0)
- {
- textBoxPaths.Text += Environment.NewLine;
- }
-
- textBoxPaths.Text += string.Join(Environment.NewLine, subFoldersToClean);
+ if (result != DialogResult.OK
+ || !(subFoldersToClean = dialog.SelectedPath).StartsWith(Module.WorkingDir)
+ || !Directory.Exists(subFoldersToClean)
+ || subFoldersToClean.Equals(Module.WorkingDirGitDir.TrimEnd(Path.DirectorySeparatorChar)))
+ {
+ return null;
}
+
+ checkBoxIncludePathFilter.Checked = true;
+ textBoxIncludePaths.Enabled = true;
+ if (textBoxIncludePaths.Text.Length != 0)
+ {
+ textBoxIncludePaths.Text += Environment.NewLine;
+ }
+
+ string userPath = string.Join(Environment.NewLine, subFoldersToClean);
+ return userPath;
+ }
+
+ private string? RequestUserFilePath()
+ {
+ using OpenFileDialog openFileDialog = new();
+
+ openFileDialog.InitialDirectory = Module.WorkingDir;
+ openFileDialog.RestoreDirectory = true;
+
+ var result = openFileDialog.ShowDialog(this);
+
+ string fileToExclude;
+ if (result != DialogResult.OK
+ || !(fileToExclude = openFileDialog.FileName).StartsWith(Module.WorkingDir))
+ {
+ return null;
+ }
+
+ checkBoxExcludePathFilter.Checked = true;
+ textBoxExcludePaths.Enabled = true;
+
+ if (textBoxExcludePaths.Text.Length != 0)
+ {
+ textBoxExcludePaths.Text += Environment.NewLine;
+ }
+
+ string userPath = string.Join(Environment.NewLine, fileToExclude);
+ return userPath;
}
}
}
diff --git a/GitUI/Translation/English.xlf b/GitUI/Translation/English.xlf
index 7600e9b9bbf..6f4326f272e 100644
--- a/GitUI/Translation/English.xlf
+++ b/GitUI/Translation/English.xlf
@@ -3240,7 +3240,11 @@ revision:
-
+
+
+
+
+
@@ -3280,8 +3284,12 @@ revision:
-
-
+
+
+
+
+
+
@@ -3292,7 +3300,11 @@ revision:
-
+
+
+
+
+
diff --git a/UnitTests/GitCommands.Tests/Git/Commands/GitCommandHelpersTest.cs b/UnitTests/GitCommands.Tests/Git/Commands/GitCommandHelpersTest.cs
index b6780069ef8..564cfda4c4c 100644
--- a/UnitTests/GitCommands.Tests/Git/Commands/GitCommandHelpersTest.cs
+++ b/UnitTests/GitCommands.Tests/Git/Commands/GitCommandHelpersTest.cs
@@ -499,15 +499,20 @@ public void RebaseCmd()
() => GitCommandHelpers.RebaseCmd("branch", false, false, false, false, false, false, from: "from", onto: null));
}
- [TestCase(CleanMode.OnlyNonIgnored, true, false, null, "clean --dry-run")]
- [TestCase(CleanMode.OnlyNonIgnored, false, false, null, "clean -f")]
- [TestCase(CleanMode.OnlyNonIgnored, false, true, null, "clean -d -f")]
- [TestCase(CleanMode.OnlyNonIgnored, false, false, "paths", "clean -f paths")]
- [TestCase(CleanMode.OnlyIgnored, false, false, null, "clean -X -f")]
- [TestCase(CleanMode.All, false, false, null, "clean -x -f")]
- public void CleanCmd(CleanMode mode, bool dryRun, bool directories, string paths, string expected)
- {
- Assert.AreEqual(expected, GitCommandHelpers.CleanCmd(mode, dryRun, directories, paths).Arguments);
+ [TestCase(CleanMode.OnlyNonIgnored, true, false, null, null, "clean --dry-run")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, null, null, "clean -f")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, true, null, null, "clean -d -f")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, "\"path1\"", null, "clean -f \"path1\"")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, "\"path1\"", "--exclude=excludes", "clean -f \"path1\" --exclude=excludes")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, null, "excludes", "clean -f excludes")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, "\"path1\" \"path2\"", null, "clean -f \"path1\" \"path2\"")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, "\"path1\" \"path2\"", "--exclude=exclude1 --exclude=exclude2", "clean -f \"path1\" \"path2\" --exclude=exclude1 --exclude=exclude2")]
+ [TestCase(CleanMode.OnlyNonIgnored, false, false, null, "--exclude=exclude1 --exclude=exclude2", "clean -f --exclude=exclude1 --exclude=exclude2")]
+ [TestCase(CleanMode.OnlyIgnored, false, false, null, null, "clean -X -f")]
+ [TestCase(CleanMode.All, false, false, null, null, "clean -x -f")]
+ public void CleanCmd(CleanMode mode, bool dryRun, bool directories, string paths, string excludes, string expected)
+ {
+ Assert.AreEqual(expected, GitCommandHelpers.CleanCmd(mode, dryRun, directories, paths, excludes).Arguments);
}
[TestCase(CleanMode.OnlyNonIgnored, true, false, null, "clean --dry-run")]
diff --git a/contributors.txt b/contributors.txt
index 4aa7c5ef0df..8814cdfece5 100644
--- a/contributors.txt
+++ b/contributors.txt
@@ -196,4 +196,5 @@ YYYY/MM/DD, github id, Full name, email
2023/05/31, SimonCropp, Simon Cropp, simon.cropp@gmail.com
2023/06/09, beiifeng, YiFei Wang, beiifeng@hotmail.com
2023/07/05, NatRavenhill, Nat Ravenhill, natalie.ravenhill(at)gmail.com
+2023/07/13, Scott Sumrall, ssumrall, snsumrall(at)gmail.com
2023/08/01, IlijaQ, Ilija Kujovic, ilijaqnet{at]gmail.com