Reading .git/config
is the fastest way of getting info on a repository and its dependencies.
The Spec
Let’s start by going through the spec from https://git-scm.com/docs/git-config#_syntax
An example config:
# Core variables
[core]
; Don't trust file modes
filemode = false
# Our diff algorithm
[branch "master"]
use = true
The basics:
The # and ; characters begin comments to the end of line, blank lines are ignored.
let isComment (line:string) = line.StartsWith(';') || line.StartsWith('#') || String.IsNullOrWhiteSpace(line)
The file consists of sections and variables. A section begins with the name of the section in square brackets and continues until the next section begins.
let isSectionHeader (line:string) = line.StartsWith("[") && line.EndsWith("]")
Sections can be further divided into subsections. To begin a subsection put its name in double quotes, separated by space from the section name, in the section header.
let splitSectionHeader (line:string) =
line.Split([|' '|], 2) |> Array.map(fun s -> s.Trim('[',']', ' ', '"'))
Construction
What we want is a seq of ConfigSection
type ConfigSection = { Name: string; Subsection: string; Values: Map<string,string> }
The file is sequence of lines, but when we encounter a section header, all subsequent lines under it have to be grouped into that section - till the next section header is encountered.
We can do that by carrying the section header with every line until we swap out to a new section header.
Seq.scan (fun (section, prev) line ->
if isSectionHeader line then
(line, line)
else
(section, line)
) ("", "")
So this is going to be our example up top:
("","")
("core", "core")
("core", "filemode = false")
Now if we do a Seq.groupBy fst
, we have our values grouped under our sections.
Here’s the whole implementation:
Last modified on 2019-09-24
Comments Disabled.