Skip to content

Commit

Permalink
Store GitRevision CommitDate in native unix time
Browse files Browse the repository at this point in the history
Convert to local DateTime format when presenting to avoid
converting all timestamps when reading Git commits.

Cache timelimit for storing Git Body when parsing Git Commits
  • Loading branch information
gerhardol committed Jul 5, 2021
1 parent 2ba9fa5 commit 380f6ef
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 23 deletions.
17 changes: 16 additions & 1 deletion GitCommands/DateTimeUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,26 @@ public static class DateTimeUtils
/// <summary>
/// Midnight 1 January 1970.
/// </summary>
public static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

/// <summary>
/// Parse unix time string
/// </summary>
/// <param name="unixTime">Unix time string</param>
/// <returns>DateTime (local time)</returns>
public static DateTime ParseUnixTime(string unixTime)
{
return UnixEpoch.AddSeconds(long.Parse(unixTime)).ToLocalTime();
}

/// <summary>
/// Convert from DateTime to native Git time format (unix time)
/// </summary>
/// <param name="dateTime">DateTime</param>
/// <returns>Unix time (seconds since 1970)</returns>
public static long ToUnixTime(DateTime dateTime)
{
return (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds;
}
}
}
4 changes: 2 additions & 2 deletions GitCommands/Git/GitModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -938,8 +938,8 @@ public GitRevision GetRevision(ObjectId? objectId = null, bool shortFormat = fal
AuthorEmail = ReEncodeStringFromLossless(lines[4]),
Committer = ReEncodeStringFromLossless(lines[6]),
CommitterEmail = ReEncodeStringFromLossless(lines[7]),
AuthorDate = DateTimeUtils.ParseUnixTime(lines[5]),
CommitDate = DateTimeUtils.ParseUnixTime(lines[8]),
AuthorUnixTime = long.Parse(lines[5]),
CommitUnixTime = long.Parse(lines[8]),
MessageEncoding = lines[9]
};

Expand Down
15 changes: 8 additions & 7 deletions GitCommands/RevisionReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public sealed class RevisionReader : IDisposable
// This property is relatively expensive to call for every revision, so
// cache it for the duration of the loop.
var logOutputEncoding = module.LogOutputEncoding;
long sixMonths = new DateTimeOffset(DateTime.Now.ToUniversalTime() - TimeSpan.FromDays(30 * 6)).ToUnixTimeSeconds();

using (var process = module.GitCommandRunner.RunDetached(arguments, redirectOutput: true, outputEncoding: GitModule.LosslessEncoding))
{
Expand All @@ -141,7 +142,7 @@ public sealed class RevisionReader : IDisposable
// We keep full multiline message bodies within the last six months.
// Commits earlier than that have their properties set to null and the
// memory will be GCd.
if (DateTime.Now - revision.AuthorDate > TimeSpan.FromDays(30 * 6))
if (sixMonths > revision.AuthorUnixTime)
{
revision.Body = null;
}
Expand Down Expand Up @@ -340,10 +341,10 @@ int CountParents(int baseOffset)
#region Timestamps

// Lines 2 and 3 are timestamps, as decimal ASCII seconds since the unix epoch, each terminated by `\n`
var authorDate = ParseUnixDateTime();
var commitDate = ParseUnixDateTime();
var authorUnixTime = ParseUnixDateTime();
var commitUnixTime = ParseUnixDateTime();

DateTime ParseUnixDateTime()
long ParseUnixDateTime()
{
long unixTime = 0;

Expand All @@ -353,7 +354,7 @@ DateTime ParseUnixDateTime()

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

unixTime = (unixTime * 10) + (c - '0');
Expand Down Expand Up @@ -435,10 +436,10 @@ DateTime ParseUnixDateTime()
TreeGuid = treeId,
Author = author,
AuthorEmail = authorEmail,
AuthorDate = authorDate,
AuthorUnixTime = authorUnixTime,
Committer = committer,
CommitterEmail = committerEmail,
CommitDate = commitDate,
CommitUnixTime = commitUnixTime,
MessageEncoding = encodingName,
Subject = subject,
Body = body,
Expand Down
8 changes: 4 additions & 4 deletions GitUI/UserControls/RevisionGrid/RevisionGridControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,10 +1046,10 @@ void AddArtificialRevisions(ObjectId filteredCurrentCheckout)
GitRevision workTreeRev = new(ObjectId.WorkTreeId)
{
Author = userName,
AuthorDate = DateTime.MaxValue,
AuthorUnixTime = 0,
AuthorEmail = userEmail,
Committer = userName,
CommitDate = DateTime.MaxValue,
CommitUnixTime = 0,
CommitterEmail = userEmail,
Subject = ResourceManager.TranslatedStrings.Workspace,
ParentIds = new[] { ObjectId.IndexId },
Expand All @@ -1061,10 +1061,10 @@ void AddArtificialRevisions(ObjectId filteredCurrentCheckout)
GitRevision indexRev = new(ObjectId.IndexId)
{
Author = userName,
AuthorDate = DateTime.MaxValue,
AuthorUnixTime = 0,
AuthorEmail = userEmail,
Committer = userName,
CommitDate = DateTime.MaxValue,
CommitUnixTime = 0,
CommitterEmail = userEmail,
Subject = ResourceManager.TranslatedStrings.Index,
ParentIds = new[] { filteredCurrentCheckout },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,15 @@ public void Should_should_show_info_for_multiple_commits()
{
Author = "Author1",
AuthorEmail = "author1@foo.bla",
AuthorDate = new DateTime(2018, 10, 23, 11, 34, 21),
AuthorUnixTime = DateTimeUtils.ToUnixTime(new DateTime(2018, 10, 23, 11, 34, 21)),
};
GitRevision rev2 = new(ObjectId.Random())
{
Author = "Author2",
AuthorEmail = "author2@foo.bla",
Committer = "Committer2",
CommitterEmail = "committer2@foo.bar",
CommitDate = new DateTime(2018, 10, 23, 11, 34, 21),
CommitUnixTime = DateTimeUtils.ToUnixTime(new DateTime(2018, 10, 23, 11, 34, 21)),
};
GitRevision rev3 = new(ObjectId.Random())
{
Expand Down
11 changes: 9 additions & 2 deletions Plugins/GitUIPluginInterfaces/GitRevision.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,17 @@ public GitRevision(ObjectId objectId)

public string? Author { get; set; }
public string? AuthorEmail { get; set; }
public DateTime AuthorDate { get; set; }

// Git native datetime format
public long AuthorUnixTime { get; set; }
public DateTime AuthorDate => FromUnixTimeSeconds(AuthorUnixTime);
public string? Committer { get; set; }
public string? CommitterEmail { get; set; }
public DateTime CommitDate { get; set; }
public long CommitUnixTime { get; set; }
public DateTime CommitDate => FromUnixTimeSeconds(CommitUnixTime);

private static DateTime FromUnixTimeSeconds(long unixTime)
=> unixTime == 0 ? DateTime.MaxValue : DateTimeOffset.FromUnixTimeSeconds(unixTime).LocalDateTime;

public BuildInfo? BuildStatus
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void Setup()
GitRevision = new GitRevision(ObjectId.WorkTreeId)
{
Author = "John Doe",
AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Body = "WIP: fixing bugs"
}
Expand All @@ -112,7 +112,7 @@ public void Setup()
GitRevision = new GitRevision(realCommitObjectId)
{
Author = "John Doe",
AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "fix: bugs",
Body = "fix: bugs\r\n\r\nall bugs fixed"
Expand All @@ -124,7 +124,7 @@ public void Setup()
GitRevision = new GitRevision(mergeCommitObjectId)
{
Author = "John Doe",
AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "merge remote tracking branch upstream/branch",
Body = "merge commit's subject here will not be parsed\r\n\r\nmerge commit's body might list details and/or conflicts...",
Expand All @@ -137,7 +137,7 @@ public void Setup()
GitRevision = new GitRevision(undetectedMergeCommitObjectId)
{
Author = "John Doe",
AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "special merge",
Body = "merge commit's subject here will not be parsed\r\n\r\nmerge commit's body might list details and/or conflicts...",
Expand All @@ -150,7 +150,7 @@ public void Setup()
GitRevision = new GitRevision(innerCommitObjectId)
{
Author = "John Doe",
AuthorDate = DateTime.Parse("2010-03-24 13:37:12"),
AuthorUnixTime = DateTimeUtils.ToUnixTime(DateTime.Parse("2010-03-24 13:37:12")),
AuthorEmail = "j.doe@some.email.dotcom",
Subject = "fix: further bugs",
Body = "fix: further bugs"
Expand Down

0 comments on commit 380f6ef

Please sign in to comment.