I have received a tremendous amount of interest in my recent articles on creating a git sizing tool using PowerShell. Many of you were savvy enough to realize the journey I was describing was just as important as the destination. With that in mind, I decided to revisit another PowerShell and git-related project that I wrote about last year. I created a PowerShell function to write an object version of your git configuration. That function, which originated as a script, is nothing more than a fancy wrapper around a command like git config --global --list. Except that instead of dealing with text I have objects in the pipeline. Anyway, based on some things I learned in the last article and some of the techniques I used, I decided to revisit the code and update it.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
Adding a Custom Type
The essence of the PowerShell function is to run a git config command and parse the structured data into an object. The previous function wrote a generic custom object to the pipeline. But I decided to take advantage of the technique where I can define the typename with the object.
foreach ($line in $data) { $split = $line.split("=") #split the first element again to get the category and name $sub = $split[0].split(".") [PSCustomObject]@{ PSTypeName = 'gitConfig' Scope = $scope Category = $sub[0] Name = $sub[1] Setting = $split[1] Username = $env:username Computername = $env:COMPUTERNAME } } #foreach line
Each line from the git configuration will be turned into a custom object of the type 'gitConfig'. While I was at it, I decided to include additional parameters for the username and computername. Even though the intent is to run the command locally, if the data is serialized or saved to a file it might be helpful to know where it originated. As you build your own PowerShell tools you always need to be thinking about how the results might be used and even where they might be consumed.
Extending the gitConfig Type
So now I have a custom object with its own type name. By default I'll get all properties. But I don't really want that. By default I don't need to see the Username and Computername properties. The solution, as I did last time, is to define a default property set using Update-TypeData.
Update-TypeData -TypeName 'gitConfig' -DefaultDisplayPropertySet 'Scope', 'Category', 'Name', 'Setting' -force
The additional properties are there if I need them.
Since I created my custom object to be more PowerShell-like it may lose some of its 'git-ness'. For example, in the custom object I am using property names like Category and Setting. But in the git world, these parts of the configuration file are probably more likely referred to as Section and Value. One thing I can do to make the result more git-friendly, is to create alias properties for Category and Setting.
Update-TypeData -TypeName 'gitConfig' -MemberType AliasProperty -MemberName 'Value' -Value 'Setting' -force Update-TypeData -TypeName 'gitConfig' -MemberType AliasProperty -MemberName 'Section' -Value 'Category' -force
Even the the default display won't use the aliases, although it certainly could, if the user knows the aliases exist they can use them.
I also added a custom type extension to show the git version.
Update-TypeData -TypeName 'gitConfig' -MemberType ScriptProperty -MemberName gitVersion -value {git --version} -force
Get-Member displays all of these properties.
The PowerShell Code
I've posted this version of the script on GitHub.
If you look just before the Parameter declaration, you can see that I am defining the output type with my custom type name. If you enclose it in braces like [gitConfig] PowerShell might try to look for a registered type and complain. Use a string. This is all for documentation purposes anyway. I'm also defining an alias, ggc, as part of the function. That way I don't have to include code to run Set-Alias or New-Alias.
The other item I want to point out is the use of an internal and private "helper" function. This function does not use a standard Verb-Noun name because it is not exposed to the user. This is a block of code that can be called depending on the parameter set. What I don't want are two copies of chunks of code. Not only does that make the code a bit more unwieldy I have to maintain the code in to places. Modularizing with a private function simplifies the process, and if I were building a Pester test, would also be easier to test.
Getting Git Config the PowerShell Way
Once I've dot sourced the ps1 file, I have a new command that lets me view my git configuration in any number of ways.
I realize that you can still use the git command line tool to display much of the same information. But when I have this turned into PowerShell, then I can build additional tooling around it like this:
#dot source the required function . C:\scripts\Get-Gitconfig.ps1 $data = Get-GitConfig -Scope Global,System $frags = @("<H1>Git Configuration</H1>") $frags+= $data[0] | Select-object "Computername","Username"| ConvertTo-Html -Fragment $data | Group-Object -Property Scope | ForEach-Object { $frags += "<H2>$($_.name.toupper())</H2>" $frags+= $_.group | Sort-Object Category | Select-Object -Property Category,Name,Setting | ConvertTo-Html -Fragment } $head = @" <Title> git Configuration</Title> <style> body { background-color:#FFFFFF; font-family:Monospace; font-size:10pt; } td, th { border:0px solid black; border-collapse:collapse; white-space:pre; font-size:12pt; } th { color:white; background-color:black; } table, tr, td, th { padding: 0px; margin: 0px ;white-space:pre; } tr:nth-child(odd) {background-color: lightgray} table { margin-left:10px; } h2 { font-family:Tahoma; } </style> "@ ConvertTo-Html -Body $frags -Head $head -PostContent "<h4>$($data[0].gitversion)</h4>"| Out-File mygit.html -Encoding ascii
This will create an html report of my git configuration. If you have git installed, you should be able to run it as well.
I hope found found this journey informative. Although the best way to learn is by doing. I hope you'll grab my code, open them up your scripting editor and see how they work. Give them a spin. Tweak them to see what happens. Have fun. That's how you learn.