Skip to content

Commit

Permalink
Move dates earlier to avoid encoding them
Browse files Browse the repository at this point in the history
  • Loading branch information
drewnoakes committed May 27, 2018
1 parent dc14146 commit 47003ca
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 61 deletions.
37 changes: 1 addition & 36 deletions GitCommands/DateTimeUtils.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Text.RegularExpressions;

namespace GitCommands
{
Expand All @@ -8,45 +7,11 @@ public static class DateTimeUtils
/// <summary>
/// Midnight 1 January 1970.
/// </summary>
private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static bool TryParseUnixTime(string unixTime, out DateTime result)
{
if (long.TryParse(unixTime, out var seconds))
{
result = UnixEpoch.AddSeconds(seconds).ToLocalTime();
return true;
}

result = default;
return false;
}
public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static DateTime ParseUnixTime(string unixTime)
{
return UnixEpoch.AddSeconds(long.Parse(unixTime)).ToLocalTime();
}

public static DateTime ParseUnixTime(string s, Capture capture) => ParseUnixTime(s, capture.Index, capture.Length);

public static DateTime ParseUnixTime(string s, int index, int count)
{
long unixTime = 0;

while (count-- > 0)
{
var c = s[index++];
var i = c - '0';

if (i < 0 || i > 9)
{
throw new FormatException("Invalid character in unix time string.");
}

unixTime = (unixTime * 10) + i;
}

return UnixEpoch.AddTicks(unixTime * TimeSpan.TicksPerSecond).ToLocalTime();
}
}
}
77 changes: 52 additions & 25 deletions GitCommands/RevisionGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,12 @@ public sealed class RevisionGraph : IDisposable
^
([^\n]+)\n # 1 authorname
([^\n]+)\n # 2 authoremail
(\d+)\n # 3 authordate
([^\n]+)\n # 4 committername
([^\n]+)\n # 5 committeremail
(\d+)\n # 6 commitdate
([^\n]*)\n # 7 encoding
(.+) # 8 subject
([^\n]+)\n # 3 committername
([^\n]+)\n # 4 committeremail
([^\n]*)\n # 5 encoding
(.+) # 6 subject
(\n+
((.|\n)*) # 10 body
((.|\n)*) # 8 body
)?
$
",
Expand Down Expand Up @@ -123,12 +121,12 @@ private async Task ExecuteAsync()
/* Hash */ "%H" +
/* Tree */ "%T" +
/* Parents */ "%P%n" +
/* Author Date */ "%at%n" +
/* Commit Date */ "%ct%n" +
/* Author Name */ "%aN%n" +
/* Author Email */ "%aE%n" +
/* Author Date */ "%at%n" +
/* Committer Name */ "%cN%n" +
/* Committer Email */ "%cE%n" +
/* Commit Date */ "%ct%n" +
/* Commit message encoding */ "%e%n" + // there is a bug: git does not recode commit message when format is given
/* Commit Body */ "%B";

Expand Down Expand Up @@ -238,34 +236,63 @@ private void ProcessLogItem(ArraySegment<byte> logItemBytes, StringPool stringPo
return;
}

var array = logItemBytes.Array;

var parentIds = new List<ObjectId>(capacity: 1);
var parentIdOffset = ObjectId.Sha1CharCount * 2;
var offset = logItemBytes.Offset + (ObjectId.Sha1CharCount * 2);
var lastOffset = logItemBytes.Offset + logItemBytes.Count;

while (parentIdOffset < logItemBytes.Count - 1)
while (true)
{
var b = logItemBytes.Array[logItemBytes.Offset + parentIdOffset];
if (offset >= lastOffset - 21)
{
return;
}

var b = array[offset];

if (b == '\n')
{
parentIdOffset++;
offset++;
break;
}

if (b == ' ')
{
parentIdOffset++;
offset++;
}

if (!ObjectId.TryParseAsciiHexBytes(logItemBytes, parentIdOffset, out var parentId))
if (!ObjectId.TryParseAsciiHexBytes(array, offset, out var parentId))
{
// TODO log this parse problem
return;
}

parentIds.Add(parentId);
parentIdOffset += ObjectId.Sha1CharCount;
offset += ObjectId.Sha1CharCount;
}

var authorDate = ParseUnixDateTime();
var commitDate = ParseUnixDateTime();

DateTime ParseUnixDateTime()
{
long unixTime = 0;

while (true)
{
var c = array[offset++];

if (c == '\n')
{
return DateTimeUtils.UnixEpoch.AddTicks(unixTime * TimeSpan.TicksPerSecond).ToLocalTime();
}

unixTime = (unixTime * 10) + (c - '0');
}
}

var s = _module.LogOutputEncoding.GetString(logItemBytes.Array, logItemBytes.Offset + parentIdOffset, logItemBytes.Count - parentIdOffset);
var s = _module.LogOutputEncoding.GetString(array, offset, lastOffset - offset);

var match = _commitRegex.Match(s);

Expand All @@ -275,7 +302,7 @@ private void ProcessLogItem(ArraySegment<byte> logItemBytes, StringPool stringPo
return;
}

var encoding = stringPool.Intern(s, match.Groups[7 /*encoding*/]);
var encodingName = stringPool.Intern(s, match.Groups[5 /*encoding*/]);

var revision = new GitRevision(null)
{
Expand All @@ -289,13 +316,13 @@ private void ProcessLogItem(ArraySegment<byte> logItemBytes, StringPool stringPo

Author = stringPool.Intern(s, match.Groups[1 /*authorname*/]),
AuthorEmail = stringPool.Intern(s, match.Groups[2 /*authoremail*/]),
AuthorDate = DateTimeUtils.ParseUnixTime(s, match.Groups[3 /*authordate*/]),
Committer = stringPool.Intern(s, match.Groups[4 /*committername*/]),
CommitterEmail = stringPool.Intern(s, match.Groups[5 /*committeremail*/]),
CommitDate = DateTimeUtils.ParseUnixTime(s, match.Groups[6 /*commitdate*/]),
MessageEncoding = encoding,
Subject = _module.ReEncodeCommitMessage(match.Groups[8 /*subject*/].Value, encoding),
Body = _module.ReEncodeCommitMessage(match.Groups[10 /*body*/].Value, encoding)
AuthorDate = authorDate,
Committer = stringPool.Intern(s, match.Groups[3 /*committername*/]),
CommitterEmail = stringPool.Intern(s, match.Groups[4 /*committeremail*/]),
CommitDate = commitDate,
MessageEncoding = encodingName,
Subject = _module.ReEncodeCommitMessage(match.Groups[6 /*subject*/].Value, encodingName),
Body = _module.ReEncodeCommitMessage(match.Groups[8 /*body*/].Value, encodingName)
};

revision.HasMultiLineMessage = !string.IsNullOrWhiteSpace(revision.Body);
Expand Down

0 comments on commit 47003ca

Please sign in to comment.