Skip to content

Commit

Permalink
Merge branch 'release/2.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
dazinator committed Mar 20, 2018
2 parents 8f8da1b + cea0b12 commit 02bac8e
Show file tree
Hide file tree
Showing 33 changed files with 583 additions and 295 deletions.
81 changes: 42 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,6 @@ The benchmarks use [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet)
```

## Parsing options.
By default, when your glob pattern is parsed, `DotNet.Glob` will only parse literal characters which are valid for path / directory names.
These are:

1. Any Letter or Digit
2. '.', ' ', '!', '#', '-', ';', '=', '@', '~', '_', ':' };

This is optimised for matching against paths / directory strings.
However starting in `1.6.4` you can override this behaviour so that you can match on arbitrary string containing other characters:

```
// Overide the default options globally for all matche:
GlobParseOptions.Default.AllowInvalidPathCharacters = true;
DotNet.Globbing.Glob.Parse("\"Stuff*").IsMatch("\"Stuff"); // true;
```

You can also just set this behaviour on a per match basis:

```
var globParseOptions = new GlobParseOptions() { AllowInvalidPathCharacters = true };
DotNet.Globbing.Glob.Parse("\"Stuff*", globParseOptions).IsMatch("\"Stuff"); // true;
```


# Build a glob fluently

You can also use the `GlobBuilder` class if you wish to build up a glob using a fluent syntax.
Expand Down Expand Up @@ -91,9 +66,50 @@ In addition, DotNet Glob also supports:
| `**` | matches any number of path / directory segments. When used must be the only contents of a segment. | /\*\*/some.\* | /foo/bar/bah/some.txt, /some.txt, or /foo/some.txt |


# Advanced Usages

## Parsing options.
By default, when your glob pattern is parsed, `DotNet.Glob` will only allow literals which are valid for path / directory names.
These are:

1. Any Letter (A-Z, a-z) or Digit
2. `.`, ` `, `!`, `#`, `-`, `;`, `=`, `@`, `~`, `_`, `:`

This is optimised for matching against paths / directory strings.
However, introduced in version `1.6.4`, you can override this behaviour so that you can include arbitrary characters in your literals. For example, here is a pattern that matches the literal `"Stuff`:

```csharp
// Overide the default options globally for all matche:
GlobParseOptions.Default.Parsing.AllowInvalidPathCharacters = true;
DotNet.Globbing.Glob.Parse("\"Stuff*").IsMatch("\"Stuff"); // true;
```

You can also just set these options on a per glob pattern basis:

```csharp
GlobOptions options = new GlobOptions();
options.Parsing.AllowInvalidPathCharacters = allowInvalidPathCharcters;
DotNet.Globbing.Glob.Parse("\"Stuff*", globParseOptions).IsMatch("\"Stuff"); // true;
```

## Case Sensitivity (Available as of version >= 2.0.0)

By default, evaluation is case-sensitive unless you specify otherwise.

```csharp
GlobOptions options = new GlobOptions();
options.Evaluation.CaseInsensitive = true;
DotNet.Globbing.Glob.Parse("foo*", globParseOptions).IsMatch("FOo"); // true;
```

Setting CaseInsensitive has an impact on:

- Letter Ranges. Any letter range (i.e '[A-Z]') will now match both lower or upper case characters.
- Character Lists. Any character list (i.e '[ABC]') will now match both lower or upper case characters.
- Literals. Any literal (i.e 'foo') will now match both lower or upper case characters i.e `FoO` will match `foO` etc.

# Advanced Usages

## Match Generation
Given a glob, you can generate random matches, or non matches, for that glob.
Expand All @@ -117,16 +133,3 @@ For example, given the glob pattern `/f?o/bar/**/*.txt` you could generate match
}
```


## Match Analysis

The `IsMatch` method just returns you a boolean. If you require more in-depth information about the match including which tokens were matched, or failed to match, you can do this:

```
MatchInfo match = glob.Match(somestring);
```

You can then inspect the `MatchInfo` which holds all of those useful details.

15 changes: 10 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
version: 1.0.{build}
skip_tags: true
image: Visual Studio 2017
install:
- choco install gitversion.portable -pre -y
before_build:
- ps: gitversion /l console /output buildserver
build:
verbosity: minimal
verbosity: detailed
environment:
NuGetOrgApiKey:
secure: u8JpW5kkti8pMi+ra2QcXTJPhkHCA8pkKSiiZOJbcS/vFVHNvF3W8qw1Fy2If6a7
PUBLIC_NUGET_FEED_NAME: nuget.org
PUBLIC_NUGET_FEED_SOURCE: https://www.nuget.org/
BENCHMARKS: on
build_script:
- cmd: ./build.cmd
- cmd: dotnet restore ./src/DotNetGlob.sln --disable-parallel
- cmd: dotnet build ./src/DotNetGlob.sln --disable-parallel
- cmd: dotnet pack ./src/DotNetGlob.sln --output ../../artifacts/
test: off
artifacts:
- path: ./artifacts/*
- path: ./**/*Artifacts/**/*.*
- path: ./artifacts/*
46 changes: 17 additions & 29 deletions build.cake
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
//////////////////////////////////////////////////////////////////////
// TOOLS
//////////////////////////////////////////////////////////////////////
#tool "nuget:?package=GitVersion.CommandLine&version=4.0.0-beta0012"
#tool "nuget:https://ci.appveyor.com/nuget/gitversion-8nigugxjftrw?package=GitVersion.CommandLine&version=4.0.0-pullrequest1269-1542"
#tool "nuget:?package=GitReleaseNotes&version=0.7.0"
#addin "nuget:?package=Cake.Git&version=0.15.0"
#addin "nuget:?package=Cake.ExtendedNuGet&version=1.0.0.24"
#addin "nuget:?package=NuGet.Core&version=2.14.0"
#addin "nuget:?package=MagicChunks&version=1.2.0.58"


//////////////////////////////////////////////////////////////////////
Expand All @@ -20,7 +17,6 @@ var configuration = Argument("configuration", "Release");
///////////////////////////////////////////////////////////////////////////////
var artifactsDir = "./artifacts";
var projectName = "DotNet.Glob";
var globalAssemblyFile = "./src/GlobalAssemblyInfo.cs";
var projectToPackage = $"./src/{projectName}";
var repoBranchName = "master";
var benchMarksEnabled = EnvironmentVariable("BENCHMARKS") == "on";
Expand Down Expand Up @@ -54,8 +50,7 @@ Teardown(context =>
Task("__Default")
.IsDependentOn("__SetAppVeyorBuildNumber")
.IsDependentOn("__Clean")
.IsDependentOn("__Restore")
.IsDependentOn("__UpdateAssemblyVersionInformation")
.IsDependentOn("__Restore")
.IsDependentOn("__Build")
.IsDependentOn("__Test")
.IsDependentOn("__Benchmarks")
Expand Down Expand Up @@ -90,28 +85,26 @@ Task("__SetAppVeyorBuildNumber")
});

Task("__Restore")
.Does(() => DotNetCoreRestore(solutionPath));

Task("__UpdateAssemblyVersionInformation")
.WithCriteria(isContinuousIntegrationBuild)
.Does(() =>
.Does(() =>
{
GitVersion(new GitVersionSettings {
UpdateAssemblyInfo = true,
UpdateAssemblyInfoFilePath = globalAssemblyFile
});

Information("AssemblyVersion -> {0}", gitVersionInfo.AssemblySemVer);
Information("AssemblyFileVersion -> {0}", $"{gitVersionInfo.MajorMinorPatch}.0");
Information("AssemblyInformationalVersion -> {0}", gitVersionInfo.InformationalVersion);
});
var settings = new DotNetCoreRestoreSettings
{
// ArgumentCustomization = args => args.Append("/p:PackageVersion=" + nugetVersion),
DisableParallel = true
};

DotNetCoreRestore(solutionPath, settings);

});

Task("__Build")
.Does(() =>
{
DotNetCoreBuild(solutionPath, new DotNetCoreBuildSettings
{
Configuration = configuration
Configuration = configuration,
ArgumentCustomization = args => args.Append("--disable-parallel"),
Verbosity = Cake.Common.Tools.DotNetCore.DotNetCoreVerbosity.Detailed
});
});

Expand Down Expand Up @@ -165,7 +158,7 @@ Task("__Pack")
var versionarg = "/p:PackageVersion=" + nugetVersion;
var settings = new DotNetCorePackSettings
{
Configuration = "Release",
Configuration = configuration,
OutputDirectory = $"{artifactsDir}",
ArgumentCustomization = args=>args.Append(versionarg)
};
Expand All @@ -175,12 +168,7 @@ Task("__Pack")

Task("__GenerateReleaseNotes")
.Does(() =>
{
var settings = new DotNetCorePackSettings
{
Configuration = "Release",
OutputDirectory = $"{artifactsDir}"
};
{

GitReleaseNotes($"{artifactsDir}/ReleaseNotes.md", new GitReleaseNotesSettings {
WorkingDirectory = ".",
Expand Down
14 changes: 1 addition & 13 deletions src/DotNet.Glob.Benchmarks/DotNetGlobBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,7 @@ public bool IsMatch_False()
result ^= _glob.IsMatch(testString);
}
return result;
}

[Benchmark]
public List<MatchInfo> Match()
{
var results = new List<MatchInfo>(NumberOfMatches);
for (int i = 0; i < NumberOfMatches; i++)
{
var testString = _testMatchingStringsList[i];
results.Add(_glob.Match(testString));
}
return results;
}
}

}
}
2 changes: 1 addition & 1 deletion src/DotNet.Glob.Benchmarks/Utils/GlobToRegexFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void IGlobTokenVisitor.Visit(CharacterListToken token)
{
_stringBuilder.Append('^');
}
_stringBuilder.Append(Regex.Escape(new string(token.Characters.ToArray())));
_stringBuilder.Append(Regex.Escape(new string(token.Characters)));
_stringBuilder.Append(']');

}
Expand Down
19 changes: 10 additions & 9 deletions src/DotNet.Glob.Tests/FormatterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ public void Can_Format_Glob_Pattern()
// build the following glob pattern using tokens:
// /foo?\\*[abc][!1-3].txt

var glob = new Globbing.Glob(new PathSeperatorToken('/'),
new LiteralToken("foo"),
new AnyCharacterToken(),
new PathSeperatorToken('\\'),
new WildcardToken(),
new CharacterListToken(new char[] { 'a', 'b', 'c' }, false),
new WildcardDirectoryToken(new PathSeperatorToken('/'), new PathSeperatorToken('/')),
new NumberRangeToken('1', '3', true),
new LiteralToken(".txt"));
var glob = new Globbing.Glob(
new PathSeperatorToken('/'),
new LiteralToken("foo"),
new AnyCharacterToken(),
new PathSeperatorToken('\\'),
new WildcardToken(),
new CharacterListToken(new char[] { 'a', 'b', 'c' }, false),
new WildcardDirectoryToken(new PathSeperatorToken('/'), new PathSeperatorToken('/')),
new NumberRangeToken('1', '3', true),
new LiteralToken(".txt"));

// now format the glob.
var sut = new GlobTokenFormatter();
Expand Down
41 changes: 31 additions & 10 deletions src/DotNet.Glob.Tests/GlobTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ public class GlobTests
[InlineData("C:\\name\\**", false, "C:\\name.ext", "C:\\name_longer.ext")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/29
[InlineData("Bumpy/**/AssemblyInfo.cs", false, "Bumpy.Test/Properties/AssemblyInfo.cs")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/33
[InlineData("C:\\sources\\x-y 1\\BIN\\DEBUG\\COMPILE\\**\\MSVC*120.DLL", false, "C:\\sources\\x-y 1\\BIN\\DEBUG\\COMPILE\\ANTLR3.RUNTIME.DLL")] // Attempted repro for https://github.com/dazinator/DotNet.Glob/issues/37
[InlineData("literal1", false, "LITERAL1")] // Regression tests for https://github.com/dazinator/DotNet.Glob/issues/41
[InlineData("*ral*", false, "LITERAL1")] // Regression tests for https://github.com/dazinator/DotNet.Glob/issues/41
[InlineData("[list]s", false, "LS", "iS", "Is")] // Regression tests for https://github.com/dazinator/DotNet.Glob/issues/41
[InlineData("range/[a-b][C-D]", false, "range/ac", "range/Ad", "range/BD")] // Regression tests for https://github.com/dazinator/DotNet.Glob/issues/41
public void Does_Not_Match(string pattern, bool allowInvalidPathCharcters, params string[] testStrings)
{
GlobParseOptions options = new GlobParseOptions() { AllowInvalidPathCharacters = allowInvalidPathCharcters };
GlobOptions options = new GlobOptions();
options.Parsing.AllowInvalidPathCharacters = allowInvalidPathCharcters;

var glob = Globbing.Glob.Parse(pattern, options);
foreach (var testString in testStrings)
{
Expand Down Expand Up @@ -59,12 +65,14 @@ public void Does_Not_Match(string pattern, bool allowInvalidPathCharcters, param
[InlineData("Stuff, *", "Stuff, x")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/31
[InlineData("\"Stuff*", "\"Stuff")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/32
[InlineData("path/**/somefile.txt", "path//somefile.txt")]
[InlineData("**/app*.js", "dist/app.js", "dist/app.a72ka8234.js")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/34
[InlineData("**/app*.js", "dist/app.js", "dist/app.a72ka8234.js")] // Regression Test for https://github.com/dazinator/DotNet.Glob/issues/34#
public void IsMatch(string pattern, params string[] testStrings)
{

GlobParseOptions.Default.AllowInvalidPathCharacters = true;
var glob = Globbing.Glob.Parse(pattern);
GlobOptions options = new GlobOptions();
options.Parsing.AllowInvalidPathCharacters = true;

var glob = Globbing.Glob.Parse(pattern, options);
foreach (var testString in testStrings)
{
var match = glob.IsMatch(testString);
Expand All @@ -73,6 +81,25 @@ public void IsMatch(string pattern, params string[] testStrings)
}
}

// Regression tests for https://github.com/dazinator/DotNet.Glob/issues/41
[Theory]
[InlineData("literal1", "LITERAL1", "literal1")]
[InlineData("*ral*", "LITERAL1", "literal1")]
[InlineData("[list]s", "LS", "ls", "iS", "Is")]
[InlineData("range/[a-b][C-D]", "range/ac", "range/Ad", "range/bC", "range/BD")]
public void IsMatchCaseInsensitive(string pattern, params string[] testStrings)
{
GlobOptions options = new GlobOptions();
options.Parsing.AllowInvalidPathCharacters = true;
options.Evaluation.CaseInsensitive = true;

var glob = Globbing.Glob.Parse(pattern, options);
foreach (var testString in testStrings)
{
var match = glob.IsMatch(testString);
Assert.True(match);
}
}

[Fact]
public void To_String_Returns_Pattern()
Expand All @@ -82,11 +109,5 @@ public void To_String_Returns_Pattern()
var resultPattern = glob.ToString();
Assert.Equal(pattern, resultPattern);
}






}
}
18 changes: 13 additions & 5 deletions src/DotNet.Glob/DotNet.Glob.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,24 @@
<TargetFrameworks>netstandard1.1;net45;net46;net4</TargetFrameworks>
<AssemblyName>DotNet.Glob</AssemblyName>
<OutputType>Library</OutputType>
<PackageId>DotNet.Glob</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<PackageId>DotNet.Glob</PackageId>
<PackageProjectUrl>https://github.com/dazinator/DotNet.Glob</PackageProjectUrl>
<Description>A fast globbing library for .NET applications, including .net core. Doesn't use Regex.</Description>
<Authors>Darrell Tunnell &lt;darrell.tunnell@googlemail.com&gt;</Authors>
<PackageLicenseUrl>https://github.com/dazinator/DotNet.Glob/blob/master/LICENSE</PackageLicenseUrl>
<PackageTags>glob;globbing;dotnet;pattern;match</PackageTags>
<PackageReleaseNotes>This is a hotfix release to support tilde characters (~), thanks goes to @ming4883</PackageReleaseNotes>
<PackageReleaseNotes>New features and fixes. See README in Github Repo.</PackageReleaseNotes>
<RootNamespace>DotNet.Glob</RootNamespace>
</PropertyGroup>

<PropertyGroup Condition=" '$(TargetFramework)' == 'net4' ">
<DefineConstants>NET40</DefineConstants>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="GitVersionTask" Version="4.0.0-pullrequest1269-1542">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions src/DotNet.Glob/Evaluation/AnyCharacterTokenEvaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public AnyCharacterTokenEvaluator(AnyCharacterToken token)
{
_token = token;
}

public bool IsMatch(string allChars, int currentPosition, out int newPosition)
{
newPosition = currentPosition + 1;
Expand Down
Loading

0 comments on commit 02bac8e

Please sign in to comment.