parent
86c956d783
commit
a68c059aff
@ -0,0 +1,93 @@ |
||||
namespace git_guts |
||||
|
||||
open System |
||||
open System.IO |
||||
open System.Text.RegularExpressions |
||||
open Spectre.Console |
||||
|
||||
// -------------------------------------------------------------------- |
||||
|
||||
type LogEntry = |
||||
{ |
||||
entryType: string option |
||||
prevRef: string option |
||||
nextRef: string option |
||||
userName: string |
||||
userEmail: string |
||||
tstamp: int * string // epoch timestamp + timezone |
||||
msg: string option |
||||
} |
||||
|
||||
member this.dumpLogEntry = |
||||
AnsiConsole.Markup( "[cyan]{0}[/]", |
||||
if this.entryType.IsSome then this.entryType.Value else "(no type)" |
||||
) |
||||
if this.msg.IsSome then |
||||
printf ": %s" this.msg.Value |
||||
printfn "" |
||||
let dt = parseTimestamp ( fst this.tstamp ) |
||||
let tstamp = sprintf "%s %s" (dt.ToString "yyyy-MM-dd HH:mm:ss") (snd this.tstamp) |
||||
printfn "%s (%s) %s" this.userName this.userEmail tstamp |
||||
if this.prevRef.IsSome then |
||||
AnsiConsole.Markup( "{0} ", objNameStr this.prevRef.Value ) |
||||
printf "->" |
||||
if this.nextRef.IsSome then |
||||
AnsiConsole.Markup( " {0}", objNameStr this.nextRef.Value ) |
||||
printfn "" |
||||
|
||||
// -------------------------------------------------------------------- |
||||
|
||||
[<AutoOpen>] |
||||
module Logs = |
||||
|
||||
let private _findLogFiles repoDir = seq { |
||||
// find log files in the specified repo |
||||
let dname = Path.Join( repoDir, "/.git/logs" ) |
||||
if Directory.Exists( dname ) then |
||||
let prefix = dname + Path.DirectorySeparatorChar.ToString() |
||||
for fname in Directory.GetFiles( dname, "*", SearchOption.AllDirectories ) do |
||||
if not ( fname.StartsWith( prefix ) ) then |
||||
failwithf "Unexpected log filename: %s" fname |
||||
let ref = fname.Substring( prefix.Length ) |
||||
yield ref, fname |
||||
} |
||||
|
||||
let private _readLogFile fname = seq { |
||||
let regex = Regex( @"^([0-9a-f]{40}) ([0-9a-f]{40}) (.+?) \<(.+?)\> (\d+) ([+-]\d{4})(\s+[^:]+)?" ) |
||||
for line in File.ReadLines( fname ) do |
||||
let line2 = line.Trim() |
||||
let matches = regex.Matches( line2 ) |
||||
if matches.Count <> 1 then |
||||
failwithf "Couldn't parse log line: %s" line2 |
||||
let groups = matches.[0].Groups |
||||
let prevRef, nextRef = groups.[1].Value, groups.[2].Value |
||||
let userName, userEmail = groups.[3].Value, groups.[4].Value |
||||
let tstamp, tzone = groups.[5].Value, groups.[6].Value |
||||
let entryType = if groups.[7].Success then Some( groups.[7].Value.Trim() ) else None |
||||
let msg = |
||||
if groups.[0].Length < line2.Length then |
||||
Some ( line2.Substring( groups.[0].Length + 2 ) ) |
||||
else |
||||
None |
||||
let checkRef ref = |
||||
if ref = "0000000000000000000000000000000000000000" then None else Some ref |
||||
yield { |
||||
entryType = entryType |
||||
prevRef = checkRef prevRef; nextRef = checkRef nextRef |
||||
userName = userName; userEmail = userEmail |
||||
tstamp = ( int(tstamp), tzone ) |
||||
msg = msg |
||||
} |
||||
} |
||||
|
||||
let dumpLogs repoDir = |
||||
|
||||
// dump the log files (sorted, for stable output) |
||||
_findLogFiles repoDir |> Seq.sortBy ( fun f -> fst f ) |> Seq.iteri ( fun logNo (ref, fname) -> |
||||
if logNo > 0 then |
||||
printfn "" |
||||
AnsiConsole.MarkupLine( makeHeader ref "" ) |
||||
for entry in _readLogFile fname do |
||||
printfn "" |
||||
entry.dumpLogEntry |
||||
) |
@ -0,0 +1,38 @@ |
||||
namespace tests |
||||
|
||||
open System |
||||
open System.IO |
||||
open Microsoft.VisualStudio.TestTools.UnitTesting |
||||
|
||||
open git_guts |
||||
|
||||
// -------------------------------------------------------------------- |
||||
|
||||
[<TestClass>] |
||||
type TestLogs () = |
||||
|
||||
[<TestInitialize>] |
||||
member this.init () = |
||||
// prepare to run a test |
||||
disableSpectreCapabilities |
||||
|
||||
[<TestMethod>] |
||||
member this.TestDumpLogs () = |
||||
|
||||
let doTest zipFname = |
||||
|
||||
// set up the test repo |
||||
use gitTestRepo = new GitTestRepo( zipFname ) |
||||
|
||||
// dump the logs |
||||
using ( new CaptureStdout() ) ( fun cap -> |
||||
dumpLogs gitTestRepo.repoDir |
||||
let expectedFname = |
||||
let fname = Path.GetFileNameWithoutExtension( zipFname ) + ".logs.txt" |
||||
Path.Combine( __SOURCE_DIRECTORY__, "fixtures", fname ) |
||||
cap.checkOutput expectedFname |
||||
) |
||||
// run the tests |
||||
doTest "empty.zip" |
||||
doTest "simple.zip" |
||||
doTest "full2.zip" |
@ -0,0 +1,57 @@ |
||||
--- HEAD ----------------------------------------------------------------------- |
||||
|
||||
commit (initial): Added a file with spaces in its path. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:36:07 +0000 |
||||
-> de483a0a2160dc698967033f2c351208e6da9066 |
||||
|
||||
commit: Added a binary file. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:36:31 +0000 |
||||
de483a0a2160dc698967033f2c351208e6da9066 -> 89bac892dbe3bc028ec2c361d836791f446ffc11 |
||||
|
||||
commit: Added an empty file. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:36:46 +0000 |
||||
89bac892dbe3bc028ec2c361d836791f446ffc11 -> fb407a730e3730eb07698f7ced84b596fe7fb7bd |
||||
|
||||
commit: Added a file with Unicode (日本) in its name and content. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:37:10 +0000 |
||||
fb407a730e3730eb07698f7ced84b596fe7fb7bd -> 30c84cc603759f82470a119c5b5348001ab13500 |
||||
|
||||
checkout: moving from master to a-branch |
||||
Taka (tutorial@git-guts) 2021-12-29 03:52:26 +0000 |
||||
30c84cc603759f82470a119c5b5348001ab13500 -> de483a0a2160dc698967033f2c351208e6da9066 |
||||
|
||||
commit: Changed the greeting. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:53:14 +0000 |
||||
de483a0a2160dc698967033f2c351208e6da9066 -> 06d4e9c2beb2c23a955bdb213d02ac63e15e3318 |
||||
|
||||
checkout: moving from a-branch to master |
||||
Taka (tutorial@git-guts) 2021-12-29 03:54:11 +0000 |
||||
06d4e9c2beb2c23a955bdb213d02ac63e15e3318 -> 30c84cc603759f82470a119c5b5348001ab13500 |
||||
|
||||
--- refs/heads/a-branch -------------------------------------------------------- |
||||
|
||||
branch: Created from de483a0a2160dc698967033f2c351208e6da9066 |
||||
Taka (tutorial@git-guts) 2021-12-29 03:52:26 +0000 |
||||
-> de483a0a2160dc698967033f2c351208e6da9066 |
||||
|
||||
commit: Changed the greeting. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:53:14 +0000 |
||||
de483a0a2160dc698967033f2c351208e6da9066 -> 06d4e9c2beb2c23a955bdb213d02ac63e15e3318 |
||||
|
||||
--- refs/heads/master ---------------------------------------------------------- |
||||
|
||||
commit (initial): Added a file with spaces in its path. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:36:07 +0000 |
||||
-> de483a0a2160dc698967033f2c351208e6da9066 |
||||
|
||||
commit: Added a binary file. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:36:31 +0000 |
||||
de483a0a2160dc698967033f2c351208e6da9066 -> 89bac892dbe3bc028ec2c361d836791f446ffc11 |
||||
|
||||
commit: Added an empty file. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:36:46 +0000 |
||||
89bac892dbe3bc028ec2c361d836791f446ffc11 -> fb407a730e3730eb07698f7ced84b596fe7fb7bd |
||||
|
||||
commit: Added a file with Unicode (日本) in its name and content. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:37:10 +0000 |
||||
fb407a730e3730eb07698f7ced84b596fe7fb7bd -> 30c84cc603759f82470a119c5b5348001ab13500 |
@ -0,0 +1,19 @@ |
||||
--- HEAD ----------------------------------------------------------------------- |
||||
|
||||
commit (initial): Added a greeting. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:19:03 +0000 |
||||
-> 2cccb4accf4fffcf9f6487a32b16750dfe298cc7 |
||||
|
||||
commit: Added 2 files in a sub-directory. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:19:33 +0000 |
||||
2cccb4accf4fffcf9f6487a32b16750dfe298cc7 -> 828139d586d32cbe03dc4b32cfefe42e678a3f2e |
||||
|
||||
--- refs/heads/master ---------------------------------------------------------- |
||||
|
||||
commit (initial): Added a greeting. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:19:03 +0000 |
||||
-> 2cccb4accf4fffcf9f6487a32b16750dfe298cc7 |
||||
|
||||
commit: Added 2 files in a sub-directory. |
||||
Taka (tutorial@git-guts) 2021-12-29 03:19:33 +0000 |
||||
2cccb4accf4fffcf9f6487a32b16750dfe298cc7 -> 828139d586d32cbe03dc4b32cfefe42e678a3f2e |
Loading…
Reference in new issue