refactor: streamline certain string operations (#1540)

This commit is contained in:
Nathan Baulch
2025-07-07 19:36:41 +10:00
committed by GitHub
parent f7b2063e8d
commit 5c9d96fe7a
23 changed files with 74 additions and 125 deletions

View File

@@ -695,7 +695,7 @@ namespace SourceGit
}
var name = sb.ToString();
if (name.Contains('#', StringComparison.Ordinal))
if (name.Contains('#'))
{
if (!name.Equals("fonts:Inter#Inter", StringComparison.Ordinal) &&
!name.Equals("fonts:SourceGit#JetBrains Mono", StringComparison.Ordinal))

View File

@@ -50,7 +50,7 @@ namespace SourceGit.Commands
private void ParseLine(string line)
{
if (line.Contains('\0', StringComparison.Ordinal))
if (line.Contains('\0'))
{
_result.IsBinary = true;
_result.LineInfos.Clear();

View File

@@ -31,13 +31,9 @@ namespace SourceGit.Commands
var lines = output.StdOut.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries);
foreach (var line in lines)
{
var idx = line.IndexOf('=', StringComparison.Ordinal);
if (idx != -1)
{
var key = line.Substring(0, idx).Trim();
var val = line.Substring(idx + 1).Trim();
rs[key] = val;
}
var parts = line.Split('=', 2);
if (parts.Length == 2)
rs[parts[0]] = parts[1];
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -39,20 +40,10 @@ namespace SourceGit.Commands
public async Task<Models.DiffResult> ReadAsync()
{
var rs = await ReadToEndAsync().ConfigureAwait(false);
var start = 0;
var end = rs.StdOut.IndexOf('\n', start);
while (end > 0)
{
var line = rs.StdOut.Substring(start, end - start);
var sr = new StringReader(rs.StdOut);
while (sr.ReadLine() is { } line)
ParseLine(line);
start = end + 1;
end = rs.StdOut.IndexOf('\n', start);
}
if (start < rs.StdOut.Length)
ParseLine(rs.StdOut.Substring(start));
if (_result.IsBinary || _result.IsLFS || _result.TextDiff.Lines.Count == 0)
{
_result.TextDiff = null;

View File

@@ -80,12 +80,12 @@ namespace SourceGit.Commands
else if (refName.StartsWith(PREFIX_REMOTE, StringComparison.Ordinal))
{
var name = refName.Substring(PREFIX_REMOTE.Length);
var shortNameIdx = name.IndexOf('/', StringComparison.Ordinal);
if (shortNameIdx < 0)
var nameParts = name.Split('/', 2);
if (nameParts.Length != 2)
return null;
branch.Remote = name.Substring(0, shortNameIdx);
branch.Name = name.Substring(branch.Remote.Length + 1);
branch.Remote = nameParts[0];
branch.Name = nameParts[1];
branch.IsLocal = false;
}
else

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@@ -25,18 +26,9 @@ namespace SourceGit.Commands
var rs = await ReadToEndAsync().ConfigureAwait(false);
if (rs.IsSuccess)
{
var start = 0;
var end = rs.StdOut.IndexOf('\0', start);
while (end > 0)
{
var line = rs.StdOut.Substring(start, end - start);
var sr = new StringReader(rs.StdOut);
while (sr.ReadLine() is { } line)
Parse(outs, line);
start = end + 1;
end = rs.StdOut.IndexOf('\0', start);
}
if (start < rs.StdOut.Length)
Parse(outs, rs.StdOut.Substring(start));
}
return outs;

View File

@@ -1,4 +1,4 @@
using System;
using System.IO;
using System.Threading.Tasks;
namespace SourceGit.Commands
@@ -19,17 +19,9 @@ namespace SourceGit.Commands
if (!rs.IsSuccess)
return statistics;
var start = 0;
var end = rs.StdOut.IndexOf('\n', start);
while (end > 0)
{
ParseLine(statistics, rs.StdOut.Substring(start, end - start));
start = end + 1;
end = rs.StdOut.IndexOf('\n', start);
}
if (start < rs.StdOut.Length)
ParseLine(statistics, rs.StdOut.Substring(start));
var sr = new StringReader(rs.StdOut);
while (sr.ReadLine() is { } line)
ParseLine(statistics, line);
statistics.Complete();
return statistics;
@@ -37,13 +29,9 @@ namespace SourceGit.Commands
private void ParseLine(Models.Statistics statistics, string line)
{
var dateEndIdx = line.IndexOf('$', StringComparison.Ordinal);
if (dateEndIdx == -1)
return;
var dateStr = line.AsSpan(0, dateEndIdx);
if (double.TryParse(dateStr, out var date))
statistics.AddCommit(line.Substring(dateEndIdx + 1), date);
var parts = line.Split('$', 2);
if (parts.Length == 2 && double.TryParse(parts[0], out var date))
statistics.AddCommit(parts[1], date);
}
}
}

View File

@@ -1,6 +1,4 @@
using System;
namespace SourceGit.Models
namespace SourceGit.Models
{
public enum ChangeViewMode
{
@@ -64,20 +62,13 @@ namespace SourceGit.Models
if (index == ChangeState.Renamed || workTree == ChangeState.Renamed)
{
var idx = Path.IndexOf('\t', StringComparison.Ordinal);
if (idx >= 0)
var parts = Path.Split('\t', 2);
if (parts.Length < 2)
parts = Path.Split(" -> ", 2);
if (parts.Length == 2)
{
OriginalPath = Path.Substring(0, idx);
Path = Path.Substring(idx + 1);
}
else
{
idx = Path.IndexOf(" -> ", StringComparison.Ordinal);
if (idx > 0)
{
OriginalPath = Path.Substring(0, idx);
Path = Path.Substring(idx + 4);
}
OriginalPath = parts[0];
Path = parts[1];
}
}

View File

@@ -32,17 +32,17 @@ namespace SourceGit.Models
buffer = REG_COT().Replace(buffer, "");
var startIdx = buffer.IndexOf('<', StringComparison.Ordinal);
var startIdx = buffer.IndexOf('<');
if (startIdx >= 0)
{
if (startIdx > 0)
OnReceive(buffer.Substring(0, startIdx));
var endIdx = buffer.IndexOf(">", startIdx + 1, StringComparison.Ordinal);
var endIdx = buffer.IndexOf('>', startIdx + 1);
if (endIdx <= startIdx)
{
if (buffer.Length - startIdx <= 15)
_thinkTail.Append(buffer.Substring(startIdx));
_thinkTail.Append(buffer.AsSpan(startIdx));
else
OnReceive(buffer.Substring(startIdx));
}
@@ -50,7 +50,7 @@ namespace SourceGit.Models
{
var tag = buffer.Substring(startIdx + 1, endIdx - startIdx - 1);
if (_thinkTags.Contains(tag))
_thinkTail.Append(buffer.Substring(startIdx));
_thinkTail.Append(buffer.AsSpan(startIdx));
else
OnReceive(buffer.Substring(startIdx));
}

View File

@@ -15,8 +15,7 @@ namespace SourceGit.Models
{
get
{
var idx = Message.IndexOf('\n', StringComparison.Ordinal);
return idx > 0 ? Message.Substring(0, idx).Trim() : Message;
return Message.Split('\n', 2)[0].Trim();
}
}

View File

@@ -199,7 +199,7 @@ namespace SourceGit.Models
public void AddCommit(string author, double timestamp)
{
var emailIdx = author.IndexOf('±', StringComparison.Ordinal);
var emailIdx = author.IndexOf('±');
var email = author.Substring(emailIdx + 1).ToLower(CultureInfo.CurrentCulture);
if (!_users.TryGetValue(email, out var user))
{

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Concurrent;
namespace SourceGit.Models
{
@@ -17,10 +16,12 @@ namespace SourceGit.Models
public User(string data)
{
var nameEndIdx = data.IndexOf('±', StringComparison.Ordinal);
var parts = data.Split('±', 2);
if (parts.Length < 2)
parts = [string.Empty, data];
Name = nameEndIdx > 0 ? data.Substring(0, nameEndIdx) : string.Empty;
Email = data.Substring(nameEndIdx + 1);
Name = parts[0];
Email = parts[1];
_hash = data.GetHashCode();
}

View File

@@ -151,7 +151,7 @@ namespace SourceGit.ViewModels
{
var time = branch.CommitterDate;
var fullpath = $"{prefix}/{branch.Name}";
var sepIdx = branch.Name.IndexOf('/', StringComparison.Ordinal);
var sepIdx = branch.Name.IndexOf('/');
if (sepIdx == -1 || branch.IsDetachedHead)
{
roots.Add(new BranchTreeNode()

View File

@@ -55,7 +55,7 @@ namespace SourceGit.ViewModels
foreach (var c in changes)
{
var sepIdx = c.Path.IndexOf('/', StringComparison.Ordinal);
var sepIdx = c.Path.IndexOf('/');
if (sepIdx == -1)
{
nodes.Add(new ChangeTreeNode(c, 0));

View File

@@ -232,7 +232,7 @@ namespace SourceGit.ViewModels
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, file);
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.Substring(0, 10)}{fileExt}");
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_commit.SHA.AsSpan(0, 10)}{fileExt}");
await Commands.SaveRevisionFile
.RunAsync(_repo.FullPath, _commit.SHA, file, tmpFile)

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -60,7 +61,7 @@ namespace SourceGit.ViewModels
var fullPath = Native.OS.GetAbsPath(_repo.FullPath, _file);
var fileName = Path.GetFileNameWithoutExtension(fullPath) ?? "";
var fileExt = Path.GetExtension(fullPath) ?? "";
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_revision.SHA.Substring(0, 10)}{fileExt}");
var tmpFile = Path.Combine(Path.GetTempPath(), $"{fileName}~{_revision.SHA.AsSpan(0, 10)}{fileExt}");
await Commands.SaveRevisionFile
.RunAsync(_repo.FullPath, _revision.SHA, _file, tmpFile)

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
@@ -52,11 +51,8 @@ namespace SourceGit.ViewModels
if (SetProperty(ref _fullMessage, value))
{
var normalized = value.ReplaceLineEndings("\n");
var idx = normalized.IndexOf("\n\n", StringComparison.Ordinal);
if (idx > 0)
Subject = normalized.Substring(0, idx).ReplaceLineEndings(" ");
else
Subject = value.ReplaceLineEndings(" ");
var parts = normalized.Split("\n\n", 2);
Subject = parts[0].ReplaceLineEndings(" ");
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace SourceGit.ViewModels
{
@@ -31,7 +32,7 @@ namespace SourceGit.ViewModels
public override async Task<bool> Sure()
{
_repo.SetWatcherEnabled(false);
ProgressDescription = $"Push {Revision.SHA.Substring(0, 10)} -> {RemoteBranch.FriendlyName} ...";
ProgressDescription = $"Push {Revision.SHA.AsSpan(0, 10)} -> {RemoteBranch.FriendlyName} ...";
var log = _repo.CreateLog("Push Revision");
Use(log);

View File

@@ -59,7 +59,7 @@ namespace SourceGit.ViewModels
foreach (var module in submodules)
{
var sepIdx = module.Path.IndexOf('/', StringComparison.Ordinal);
var sepIdx = module.Path.IndexOf('/');
if (sepIdx == -1)
{
nodes.Add(new SubmoduleTreeNode(module, 0));

View File

@@ -70,7 +70,7 @@ namespace SourceGit.ViewModels
foreach (var tag in tags)
{
var sepIdx = tag.Name.IndexOf('/', StringComparison.Ordinal);
var sepIdx = tag.Name.IndexOf('/');
if (sepIdx == -1)
{
nodes.Add(new TagTreeNode(tag, 0));

View File

@@ -774,7 +774,7 @@ namespace SourceGit.ViewModels
}
else
{
var isRooted = change.Path.IndexOf('/', StringComparison.Ordinal) <= 0;
var isRooted = change.Path.IndexOf('/') <= 0;
var singleFile = new MenuItem();
singleFile.Header = App.Text("WorkingCopy.AddToGitIgnore.SingleFile");
singleFile.Click += (_, e) =>
@@ -1653,8 +1653,7 @@ namespace SourceGit.ViewModels
for (int i = 0; i < historiesCount; i++)
{
var message = _repo.Settings.CommitMessages[i].Trim().ReplaceLineEndings("\n");
var subjectEndIdx = message.IndexOf('\n');
var subject = subjectEndIdx > 0 ? message.Substring(0, subjectEndIdx) : message;
var subject = message.Split('\n', 2)[0];
var item = new MenuItem();
item.Header = new CommitMessageRecord(subject);
item.Icon = App.CreateMenuIcon("Icons.Histories");

View File

@@ -19,15 +19,15 @@ namespace SourceGit.Views
_shouldExitApp = true;
var content = File.ReadAllText(file).ReplaceLineEndings("\n").Trim();
var firstLineEnd = content.IndexOf('\n', StringComparison.Ordinal);
if (firstLineEnd == -1)
var parts = content.Split('\n', 2);
if (parts.Length != 2)
{
Editor.SubjectEditor.Text = content;
}
else
{
Editor.SubjectEditor.Text = content.Substring(0, firstLineEnd);
Editor.DescriptionEditor.Text = content.Substring(firstLineEnd + 1).Trim();
Editor.SubjectEditor.Text = parts[0];
Editor.DescriptionEditor.Text = parts[1];
}
}
@@ -36,15 +36,15 @@ namespace SourceGit.Views
_onSave = onSave;
_shouldExitApp = false;
var firstLineEnd = msg.IndexOf('\n', StringComparison.Ordinal);
if (firstLineEnd == -1)
var parts = msg.Split('\n', 2);
if (parts.Length != 2)
{
Editor.SubjectEditor.Text = msg;
}
else
{
Editor.SubjectEditor.Text = msg.Substring(0, firstLineEnd);
Editor.DescriptionEditor.Text = msg.Substring(firstLineEnd + 1).Trim();
Editor.SubjectEditor.Text = parts[0];
Editor.DescriptionEditor.Text = parts[1];
}
}

View File

@@ -105,17 +105,11 @@ namespace SourceGit.Views
{
_changingWay = TextChangeWay.FromSource;
var normalized = Text.ReplaceLineEndings("\n");
var subjectEnd = normalized.IndexOf("\n\n", StringComparison.Ordinal);
if (subjectEnd == -1)
{
SetCurrentValue(SubjectProperty, normalized.ReplaceLineEndings(" "));
SetCurrentValue(DescriptionProperty, string.Empty);
}
else
{
SetCurrentValue(SubjectProperty, normalized.Substring(0, subjectEnd).ReplaceLineEndings(" "));
SetCurrentValue(DescriptionProperty, normalized.Substring(subjectEnd + 2));
}
var parts = normalized.Split("\n\n", 2);
if (parts.Length != 2)
parts = [normalized, string.Empty];
SetCurrentValue(SubjectProperty, parts[0].ReplaceLineEndings(" "));
SetCurrentValue(DescriptionProperty, parts[1]);
_changingWay = TextChangeWay.None;
}
else if ((change.Property == SubjectProperty || change.Property == DescriptionProperty) && _changingWay == TextChangeWay.None)
@@ -145,17 +139,17 @@ namespace SourceGit.Views
if (SubjectEditor.CaretIndex == Subject.Length)
{
var idx = text.IndexOf('\n');
if (idx == -1)
var parts = text.Split('\n', 2);
if (parts.Length != 2)
{
SubjectEditor.Paste(text);
}
else
{
SubjectEditor.Paste(text.Substring(0, idx));
SubjectEditor.Paste(parts[0]);
DescriptionEditor.Focus();
DescriptionEditor.CaretIndex = 0;
DescriptionEditor.Paste(text.Substring(idx + 1).Trim());
DescriptionEditor.Paste(parts[1].Trim());
}
}
else