Skip to content
Merged
1 change: 1 addition & 0 deletions src/LogExpert.Configuration/LegacyPreferencesMigrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ private static void MigrateToV1 (Settings settings)
}
#pragma warning restore CS0618
}

}
55 changes: 35 additions & 20 deletions src/LogExpert.Core/Classes/Log/RolloverFilenameBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public class RolloverFilenameBuilder
#region Fields

private string _condContent;
private Group _condGroup;
private string _currentFileName;

private Group _dateGroup;
Expand All @@ -41,6 +40,7 @@ public class RolloverFilenameBuilder

private bool _hideZeroIndex;
private Group _indexGroup;
private Group _indexPartGroup;
private Regex _regex;

#endregion
Expand Down Expand Up @@ -89,7 +89,7 @@ public void SetFileName (string fileName)
Index = _indexGroup.Value.Length > 0 ? int.Parse(_indexGroup.Value) : 0;
}

_condGroup = match.Groups["cond"];
_indexPartGroup = match.Groups["indexPart"];
}
}

Expand All @@ -116,15 +116,15 @@ public string BuildFileName ()

Comment thread
Hirogen marked this conversation as resolved.
Resolved
if (_indexGroup != null && _indexGroup.Success)
{
fileName = fileName.Remove(_indexGroup.Index, _indexGroup.Length);
fileName = fileName.Remove(_indexPartGroup.Index, _indexPartGroup.Length);

if (!_hideZeroIndex || Index > 0)
{
var format = "D" + _indexGroup.Length;
fileName = fileName.Insert(_indexGroup.Index, Index.ToString(format));
fileName = fileName.Insert(_indexPartGroup.Index, Index.ToString(format));
if (_hideZeroIndex && _condContent != null)
{
fileName = fileName.Insert(_indexGroup.Index, _condContent);
fileName = fileName.Insert(_indexPartGroup.Index, _condContent);
}
}
}
Expand All @@ -141,14 +141,14 @@ public string BuildFileName ()
private void ParseFormatString (string formatString)
{
var fmt = EscapeNonvarRegions(formatString);
var datePos = formatString.IndexOf("$D(", StringComparison.Ordinal);
var datePos = fmt.IndexOf("$D(", StringComparison.Ordinal);

if (datePos != -1)
{
var endPos = formatString.IndexOf(')', datePos);
var endPos = fmt.IndexOf(')', datePos);
if (endPos != -1)
{
_dateTimeFormat = formatString.Substring(datePos + 3, endPos - datePos - 3)
_dateTimeFormat = fmt.Substring(datePos + 3, endPos - datePos - 3)
.ToUpperInvariant()
.Replace('D', 'd')
.Replace('Y', 'y');
Expand Down Expand Up @@ -176,12 +176,17 @@ private void ParseFormatString (string formatString)
}
}

fmt = fmt.Replace("*", ".*", StringComparison.Ordinal);
fmt = fmt.Replace("*", ".*?", StringComparison.Ordinal);
Comment thread
Hirogen marked this conversation as resolved.
Resolved
_hideZeroIndex = fmt.Contains("$J", StringComparison.Ordinal);
fmt = fmt.Replace("$I", "(?'index'[\\d]+)", StringComparison.Ordinal);
fmt = fmt.Replace("$J", "(?'index'[\\d]*)", StringComparison.Ordinal);

_regex = new Regex(fmt);
const string indexPattern = "(?'indexPart'(?'index'[\\d]+))";
const string hiddenZeroIndexPattern = "(?'indexPart'(?'index'[\\d]*))";
var conditionalIndexPattern = _condContent != null
? $"(?'indexPart'(?:{Regex.Escape(_condContent)}(?'index'[\\d]+)|(?'index')))"
: hiddenZeroIndexPattern;
fmt = fmt.Replace("$I", indexPattern, StringComparison.Ordinal);
fmt = fmt.Replace("$J", conditionalIndexPattern, StringComparison.Ordinal);

_regex = new Regex(fmt + @"\z");
Comment thread
Hirogen marked this conversation as resolved.
Resolved
}

private string EscapeNonvarRegions (string formatString)
Expand All @@ -199,17 +204,15 @@ private string EscapeNonvarRegions (string formatString)
case 0: // looking for $
if (fmt[i] == '$')
{
_ = result.Append(Regex.Escape(segment.ToString()));
segment = new StringBuilder();
AppendEscapedSegment(result, segment);
state = 1;
}

_ = segment.Append(fmt[i]);
break;
case 1: // the char behind $
_ = segment.Append(fmt[i]);
_ = result.Append(segment);
segment = new StringBuilder();
AppendSegment(result, segment);
state = 2;
break;
case 2: // checking if ( or other char
Expand All @@ -229,18 +232,30 @@ private string EscapeNonvarRegions (string formatString)
_ = segment.Append(fmt[i]);
if (fmt[i] == ')')
{
_ = result.Append(segment);
segment = new StringBuilder();
AppendSegment(result, segment);
state = 0;
}

break;
}
}

AppendEscapedSegment(result, segment);
fmt = result.ToString().Replace('\xFFFD', '*');
return fmt;
}

private static void AppendEscapedSegment (StringBuilder result, StringBuilder segment)
{
_ = result.Append(Regex.Escape(segment.ToString()));
_ = segment.Clear();
}

private static void AppendSegment (StringBuilder result, StringBuilder segment)
{
_ = result.Append(segment);
_ = segment.Clear();
}

#endregion
}
}
12 changes: 8 additions & 4 deletions src/LogExpert.Resources/Resources.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1680,12 +1680,16 @@ Ein ausgewähltes Tool erscheint in der Iconbar. Alle anderen verfügbaren Tools
<value>Muster syntax:

* = alle Zeichen (wildcard)
$D(&amp;lt;date&amp;gt;) = Datumsmuster
$D(&lt;date&gt;) = Datumsmuster
$I = Dateiindexnummer
$J = Dateiindexnummer, versteckt wenn 09
$J(&amp;lt;prefix&amp;gt;) = Wie $J, jedoch wird ein &amp;lt;prefix&amp;gt; hinzugefügt when es nicht 0 ist
$J = Dateiindexnummer, versteckt wenn null
$J(&lt;prefix&gt;) = Wie $J, jedoch wird ein &lt;prefix&gt; hinzugefügt wenn es nicht 0 ist

&amp;lt;date&amp;gt;:
Beispiele:
*$J(.) → app.log, app.log.1, app.log.2
*$J(.).log → app.log, app.1.log, app.2.log

&lt;date&gt;:
DD = Tag
MM = Monat
YY[YY] = Jahr
Expand Down
10 changes: 7 additions & 3 deletions src/LogExpert.Resources/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1743,12 +1743,16 @@ Checked tools will appear in the icon bar. All other tools are available in the
<value>Pattern syntax:

* = any characters (wildcard)
$D(&amp;lt;date&amp;gt;) = Date pattern
$D(&lt;date&gt;) = Date pattern
$I = File index number
$J = File index number, hidden when zero
$J(&amp;lt;prefix&amp;gt;) = Like $J, but adding &amp;lt;prefix&amp;gt; when non-zero
$J(&lt;prefix&gt;) = Like $J, but adding &lt;prefix&gt; when non-zero

&amp;lt;date&amp;gt;:
Examples:
*$J(.) → app.log, app.log.1, app.log.2
*$J(.).log → app.log, app.1.log, app.2.log

&lt;date&gt;:
DD = day
MM = month
YY[YY] = year
Expand Down
4 changes: 4 additions & 0 deletions src/LogExpert.Resources/Resources.zh-CN.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1554,6 +1554,10 @@ $I = 文件索引编号
$J = 文件索引编号,为零时隐藏
$J(&lt;前缀&gt;) = 类似 $J,但在非零时添加 &lt;前缀&gt;

示例:
*$J(.) → app.log, app.log.1, app.log.2
*$J(.).log → app.log, app.1.log, app.2.log

&lt;日期&gt;:
DD = 日
MM = 月
Expand Down
6 changes: 6 additions & 0 deletions src/LogExpert.Tests/LogExpert.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@
<Content Include="TestData\app.log.1">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestData\app.1.log">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="TestData\app.2.log">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Update="TestData\organizations-1000.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
29 changes: 28 additions & 1 deletion src/LogExpert.Tests/RollingNameTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ public void TestFilename1(string expectedResult, string formatString)
[TestCase("engine.log", "engine1.log","engine$J.log")]
[TestCase("engine1.log", "engine2.log","engine$J.log")]
[TestCase("engine.log", "engine.log.1","*$J(.)")]
[TestCase("engine.log", "engine.1.log", "*$J(.).log")]
[TestCase("engine.log.1", "engine.log.2", "*$J(.)")]
[TestCase("engine.1.log", "engine.2.log", "*$J(.).log")]
[TestCase("engine1.log", "engine2.log", "*$I.log")]
[TestCase("engine_2010-06-12.1.log", "engine_2010-06-12.2.log", "*$D(yyyy-MM-dd)$J(.).log")]
[TestCase("engine_2010-06-12.log", "engine_2010-06-12.log.1", "*$D(yyyy-MM-dd).log$J(.)")]
Comment thread
Hirogen marked this conversation as resolved.
Resolved
Comment thread
Hirogen marked this conversation as resolved.
Resolved
public void TestFilenameAnd1(string fileName, string expectedResult, string formatString)
{
Expand All @@ -45,6 +50,7 @@ public void TestFilenameAnd1(string fileName, string expectedResult, string form
[Test]
[TestCase("engine.log", "engine.log.2","*$J(.)")]
[TestCase("engine.log", "engine.log.2","*.log$J(.)")]
[TestCase("engine.log", "engine.2.log", "*$J(.).log")]
public void TestFilenameAnd2(string fileName, string expectedResult, string formatString)
{
RolloverFilenameBuilder fnb = new(formatString);
Expand All @@ -54,6 +60,27 @@ public void TestFilenameAnd2(string fileName, string expectedResult, string form
Assert.That(name, Is.EqualTo(expectedResult));
}

[Test]
public void TestFilenameDateAfterRegexMetacharacter ()
{
RolloverFilenameBuilder fnb = new("app.$D(yyyy-MM-dd).log");
fnb.SetFileName("app.2010-06-12.log");

fnb.IncrementDate();

Assert.That(fnb.BuildFileName(), Is.EqualTo("app.2010-06-13.log"));
}

[Test]
public void BuildFileName_FullPathWithNonWildcardMask_IncrementsIndex ()
{
RolloverFilenameBuilder fnb = new("engine$J.log");
fnb.SetFileName(@"C:\logs\engine1.log");

fnb.Index += 1;

Assert.That(fnb.BuildFileName(), Is.EqualTo(@"C:\logs\engine2.log"));
}

[Test]
[TestCase("engine1.log", "engine.log","engine$J.log")]
Expand All @@ -65,4 +92,4 @@ public void TestFilenameMinus1(string fileName, string expectedResult, string fo
var name = fnb.BuildFileName();
Assert.That(name, Is.EqualTo("engine.log"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,24 @@ public void SingleFileCtor_MultiFileTrue_ExpandsRollover ()
});
}

[Test]
public void SingleFileCtor_MultiFileTrue_LoadsIndexBeforeExtension ()
{
var options = new MultiFileOptions { FormatPattern = "*$J(.).log" };
Comment thread
Hirogen marked this conversation as resolved.
Resolved
File.Copy(Path.Combine(_testDataDirectory, "app.1.log"), Path.Combine(_testDirectory, "app.1.log"));
File.Copy(Path.Combine(_testDataDirectory, "app.2.log"), Path.Combine(_testDirectory, "app.2.log"));
using var reader = CreateSingleFileReader(multiFile: true, options);

reader.ReadFiles();

Assert.Multiple(() =>
{
Assert.That(reader.IsMultiFile, Is.True);
Assert.That(reader.GetLogFileInfoList().Select(file => Path.GetFileName(file.FullName)),
Is.EqualTo(new[] { "app.2.log", "app.1.log", "app.log" }));
});
}

[Test]
public void MultiFileCtor_AlwaysMultiFile ()
{
Expand All @@ -91,15 +109,15 @@ public void MultiFileCtor_AlwaysMultiFile ()
});
}

private LogfileReader CreateSingleFileReader (bool multiFile)
private LogfileReader CreateSingleFileReader (bool multiFile, MultiFileOptions? options = null)
{
return new LogfileReader(
_logFile,
new EncodingOptions { Encoding = Encoding.UTF8 },
Comment thread
Hirogen marked this conversation as resolved.
Resolved
multiFile,
bufferCount: 40,
linesPerBuffer: 50,
new MultiFileOptions(),
options ?? new MultiFileOptions(),
ReaderType.System,
PluginRegistry.PluginRegistry.Instance,
maximumLineLength: 500,
Expand Down
1 change: 1 addition & 0 deletions src/LogExpert.Tests/TestData/app.1.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app.1.log
1 change: 1 addition & 0 deletions src/LogExpert.Tests/TestData/app.2.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app.2.log

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions src/LogExpert.UI/Dialogs/MultiFileMaskDialog.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading