Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
2e4127c
Catch specifc exception
VictoriousRaptor Jan 18, 2023
6efa9d1
Only expand environment var when path starts with %
VictoriousRaptor Jan 18, 2023
983f0aa
Use a static dictionary for environment vars
VictoriousRaptor Jan 18, 2023
009ee3d
Simplify environment variable detection
VictoriousRaptor Jan 19, 2023
52e7299
Change context and settings to non static
VictoriousRaptor Jan 19, 2023
51f5d8a
Add new constructor for EngineNotAvailableException
VictoriousRaptor Jan 19, 2023
383298a
Fix null subtitle when creating disk result
VictoriousRaptor Jan 19, 2023
a6b7c58
Fix subpath check
VictoriousRaptor Jan 19, 2023
2c36692
Use case-insensitve comparator for path
VictoriousRaptor Jan 19, 2023
3226889
Remove TranslateEnvironmentVariablePath
VictoriousRaptor Jan 19, 2023
ac92b93
Move IsSubPathOf to SharedCommands
VictoriousRaptor Jan 19, 2023
beb1449
Rename method and add option to allow equality
VictoriousRaptor Jan 19, 2023
b42fc54
Add test for PathContains()
VictoriousRaptor Jan 19, 2023
4bea50d
Add unit test for PathEqualityComparator
VictoriousRaptor Jan 19, 2023
03f062c
Fix build error
VictoriousRaptor Jan 19, 2023
fefb137
fix test format
jjw24 Jan 19, 2023
b77bfea
update test name
jjw24 Jan 19, 2023
768ed4f
Update wording
VictoriousRaptor Jan 20, 2023
504fb4a
Display environment vars in upper case
VictoriousRaptor Jan 20, 2023
4d267fe
Fix incorrect %homepath% parsing
VictoriousRaptor Jan 20, 2023
966d3e7
Fix environment variable expansion logic
VictoriousRaptor Jan 20, 2023
71a2f99
Set environment var dict in LoadEnvironmentStringPaths()
VictoriousRaptor Jan 20, 2023
b739bb4
Fix CI test failure
VictoriousRaptor Jan 20, 2023
f5cc792
Return empty when operation canceled
VictoriousRaptor Jan 21, 2023
babffe9
Disable unused import warning
VictoriousRaptor Jan 22, 2023
dd02ad3
Refactor
VictoriousRaptor Jan 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
#pragma warning disable IDE0005
using System.Windows;
#pragma warning restore IDE0005

namespace Flow.Launcher.Plugin.SharedCommands
{
Expand Down Expand Up @@ -206,22 +208,16 @@ public static bool IsLocationPathString(this string querySearchString)
///</summary>
public static string GetPreviousExistingDirectory(Func<string, bool> locationExists, string path)
{
var previousDirectoryPath = "";
var index = path.LastIndexOf('\\');
if (index > 0 && index < (path.Length - 1))
{
previousDirectoryPath = path.Substring(0, index + 1);
if (!locationExists(previousDirectoryPath))
{
return "";
}
string previousDirectoryPath = path.Substring(0, index + 1);
return locationExists(previousDirectoryPath) ? previousDirectoryPath : "";
}
else
{
return "";
}

return previousDirectoryPath;
}

///<summary>
Expand All @@ -241,5 +237,33 @@ public static string ReturnPreviousDirectoryIfIncompleteString(string path)

return path;
}

/// <summary>
/// Returns if <paramref name="parentPath"/> contains <paramref name="subPath"/>.
/// From https://stackoverflow.com/a/66877016
/// </summary>
/// <param name="parentPath">Parent path</param>
/// <param name="subPath">Sub path</param>
/// <param name="allowEqual">If <see langword="true"/>, when <paramref name="parentPath"/> and <paramref name="subPath"/> are equal, returns <see langword="true"/></param>
/// <returns></returns>
public static bool PathContains(string parentPath, string subPath, bool allowEqual = false)
{
var rel = Path.GetRelativePath(parentPath.EnsureTrailingSlash(), subPath);
return (rel != "." || allowEqual)
&& rel != ".."
&& !rel.StartsWith("../")
&& !rel.StartsWith(@"..\")
&& !Path.IsPathRooted(rel);
}

/// <summary>
/// Returns path ended with "\"
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string EnsureTrailingSlash(this string path)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, this will be helpful because through out explorer there are dup code to add trailing slash.

{
return path.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
}
}
}
53 changes: 53 additions & 0 deletions Flow.Launcher.Test/FilesFoldersTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using Flow.Launcher.Plugin.SharedCommands;
using NUnit.Framework;

namespace Flow.Launcher.Test
{
[TestFixture]

public class FilesFoldersTest
{
// Testcases from https://stackoverflow.com/a/31941905/20703207
// Disk
[TestCase(@"c:", @"c:\foo", true)]
[TestCase(@"c:\", @"c:\foo", true)]
// Slash
[TestCase(@"c:\foo\bar\", @"c:\foo\", false)]
[TestCase(@"c:\foo\bar", @"c:\foo\", false)]
[TestCase(@"c:\foo", @"c:\foo\bar", true)]
[TestCase(@"c:\foo\", @"c:\foo\bar", true)]
// File
[TestCase(@"c:\foo", @"c:\foo\a.txt", true)]
[TestCase(@"c:\foo", @"c:/foo/a.txt", true)]
[TestCase(@"c:\FOO\a.txt", @"c:\foo", false)]
[TestCase(@"c:\foo\a.txt", @"c:\foo\", false)]
[TestCase(@"c:\foobar\a.txt", @"c:\foo", false)]
[TestCase(@"c:\foobar\a.txt", @"c:\foo\", false)]
[TestCase(@"c:\foo\", @"c:\foo.txt", false)]
// Prefix
[TestCase(@"c:\foo", @"c:\foobar", false)]
[TestCase(@"C:\Program", @"C:\Program Files\", false)]
[TestCase(@"c:\foobar", @"c:\foo\a.txt", false)]
[TestCase(@"c:\foobar\", @"c:\foo\a.txt", false)]
// Edge case
[TestCase(@"c:\foo", @"c:\foo\..\bar\baz", false)]
[TestCase(@"c:\bar", @"c:\foo\..\bar\baz", true)]
[TestCase(@"c:\barr", @"c:\foo\..\bar\baz", false)]
// Equality
[TestCase(@"c:\foo", @"c:\foo", false)]
[TestCase(@"c:\foo\", @"c:\foo", false)]
[TestCase(@"c:\foo", @"c:\foo\", false)]
public void GivenTwoPaths_WhenCheckPathContains_ThenShouldBeExpectedResult(string parentPath, string path, bool expectedResult)
{
Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path));
}

[TestCase(@"c:\foo", @"c:\foo", true)]
[TestCase(@"c:\foo\", @"c:\foo", true)]
[TestCase(@"c:\foo", @"c:\foo\", true)]
public void GivenTwoPathsAreTheSame_WhenCheckPathContains_ThenShouldBeTrue(string parentPath, string path, bool expectedResult)
{
Assert.AreEqual(expectedResult, FilesFolders.PathContains(parentPath, path, true));
}
}
}
68 changes: 67 additions & 1 deletion Flow.Launcher.Test/Plugins/ExplorerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks;
using static Flow.Launcher.Plugin.Explorer.Search.SearchManager;

namespace Flow.Launcher.Test.Plugins
{
Expand Down Expand Up @@ -176,7 +178,7 @@ public void GivenQuery_WhenActionKeywordForFileContentSearchExists_ThenFileConte
var searchManager = new SearchManager(new Settings(), new PluginInitContext());

// When
var result = SearchManager.IsFileContentSearch(query.ActionKeyword);
var result = searchManager.IsFileContentSearch(query.ActionKeyword);

// Then
Assert.IsTrue(result,
Expand All @@ -193,6 +195,7 @@ public void GivenQuery_WhenActionKeywordForFileContentSearchExists_ThenFileConte
[TestCase(@"c:\>*", true)]
[TestCase(@"c:\>", true)]
[TestCase(@"c:\SomeLocation\SomeOtherLocation\>", true)]
[TestCase(@"c:\SomeLocation\SomeOtherLocation", true)]
public void WhenGivenQuerySearchString_ThenShouldIndicateIfIsLocationPathString(string querySearchString, bool expectedResult)
{
// When, Given
Expand Down Expand Up @@ -393,5 +396,68 @@ public void GivenQueryWithFileTypeResult_WhenGetAutoComplete_ThenResultShouldBeE
// Then
Assert.AreEqual(result, expectedResult);
}

[TestCase(@"c:\foo", @"c:\foo", true)]
[TestCase(@"C:\Foo\", @"c:\foo\", true)]
[TestCase(@"c:\foo", @"c:\foo\", false)]
public void GivenTwoPaths_WhenCompared_ThenShouldBeExpectedSameOrDifferent(string path1, string path2, bool expectedResult)
{
// Given
var comparator = PathEqualityComparator.Instance;
var result1 = new Result
{
Title = Path.GetFileName(path1),
SubTitle = path1
};
var result2 = new Result
{
Title = Path.GetFileName(path2),
SubTitle = path2
};

// When, Then
Assert.AreEqual(expectedResult, comparator.Equals(result1, result2));
}

[TestCase(@"c:\foo\", @"c:\foo\")]
[TestCase(@"C:\Foo\", @"c:\foo\")]
public void GivenTwoPaths_WhenComparedHasCode_ThenShouldBeSame(string path1, string path2)
{
// Given
var comparator = PathEqualityComparator.Instance;
var result1 = new Result
{
Title = Path.GetFileName(path1),
SubTitle = path1
};
var result2 = new Result
{
Title = Path.GetFileName(path2),
SubTitle = path2
};

var hash1 = comparator.GetHashCode(result1);
var hash2 = comparator.GetHashCode(result2);

// When, Then
Assert.IsTrue(hash1 == hash2);
}

[TestCase(@"%appdata%", true)]
[TestCase(@"%appdata%\123", true)]
[TestCase(@"c:\foo %appdata%\", false)]
[TestCase(@"c:\users\%USERNAME%\downloads", true)]
[TestCase(@"c:\downloads", false)]
[TestCase(@"%", false)]
[TestCase(@"%%", false)]
[TestCase(@"%bla%blabla%", false)]
public void GivenPath_WhenHavingEnvironmentVariableOrNot_ThenShouldBeExpected(string path, bool expectedResult)
{
// When
var result = EnvironmentVariables.HasEnvironmentVar(path);

// Then
Assert.AreEqual(result, expectedResult);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
using System;
using System.Threading.Tasks;
using System.Windows;
using Flow.Launcher.Plugin.Explorer.Search.IProvider;
using JetBrains.Annotations;

namespace Flow.Launcher.Plugin.Explorer.Exceptions;

Expand All @@ -20,7 +18,7 @@ public EngineNotAvailableException(
string engineName,
string resolution,
string message,
Func<ActionContext, ValueTask<bool>> action = null) : base(message)
Func<ActionContext, ValueTask<bool>>? action = null) : base(message)
{
EngineName = engineName;
Resolution = resolution;
Expand All @@ -40,6 +38,23 @@ public EngineNotAvailableException(
EngineName = engineName;
Resolution = resolution;
}

public EngineNotAvailableException(
string engineName,
string resolution,
string message,
string errorIconPath,
Func<ActionContext, ValueTask<bool>>? action = null) : base(message)
{
EngineName = engineName;
Resolution = resolution;
ErrorIcon = errorIconPath;
Action = action ?? (_ =>
{
Clipboard.SetDataObject(this.ToString());
return ValueTask.FromResult(true);
});
}

public override string ToString()
{
Expand Down
Loading