Daha Fazla Git PowerShell Aracı Oluşturma


PowerShell kullanarak git boyutlandırma aracı oluşturmaya ilişkin son makalelerime büyük ilgi gördüm. Birçoğunuz anlattığım yolculuğun varış noktası kadar önemli olduğunu anlayacak kadar bilgiliydiniz. Bunu aklımda tutarak geçen yıl hakkında yazdığım PowerShell ve git ile ilgili başka bir projeyi tekrar gözden geçirmeye karar verdim. Git yapılandırmanızın nesne sürümünü yazmak için bir PowerShell işlevi oluşturdum. Bir komut dosyası olarak ortaya çıkan bu işlev, git config -global -list gibi bir komutun etrafındaki süslü bir sarmalayıcıdan başka bir şey değildir. Bunun dışında metinle uğraşmak yerine boru hattında nesnelerim var. Her neyse, son makaleden öğrendiğim bazı bilgilere ve kullandığım bazı tekniklere dayanarak kodu tekrar gözden geçirip güncellemeye karar verdim.

Özel Tür Ekleme

PowerShell işlevinin özü, bir git config komutunu çalıştırmak ve yapılandırılmış verileri bir nesneye ayrıştırmaktır. Önceki işlev, ardışık düzene genel bir özel nesne yazıyordu. Ancak yazı tipi adını nesneyle tanımlayabildiğim teknikten yararlanmaya karar verdim.

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

Git yapılandırmasındaki her satır 'gitConfig' türünde özel bir nesneye dönüştürülecektir. Bunu yaparken kullanıcı adı ve bilgisayar adı için ek parametreler eklemeye karar verdim. Amaç, komutu yerel olarak çalıştırmak olsa da, veriler serileştirilmişse veya bir dosyaya kaydedilmişse, bunun nereden geldiğini bilmek faydalı olabilir. Kendi PowerShell araçlarınızı oluştururken her zaman sonuçların nasıl kullanılabileceğini ve hatta nerede tüketilebileceğini düşünmeniz gerekir.

gitConfig Türünü genişletme

Artık kendi tür adına sahip özel bir nesnem var. Varsayılan olarak tüm özellikleri alacağım. Ama bunu gerçekten istemiyorum. Varsayılan olarak Kullanıcı Adı ve Bilgisayar Adı özelliklerini görmem gerekmiyor. Çözüm, geçen sefer yaptığım gibi, Update-TypeData'yı kullanarak varsayılan bir özellik seti tanımlamaktır.

Update-TypeData -TypeName 'gitConfig' -DefaultDisplayPropertySet 'Scope', 'Category', 'Name', 'Setting' -force

İhtiyacım olursa ek özellikler orada.

Özel nesnemi daha çok PowerShell'e benzeyecek şekilde oluşturduğumdan beri 'git-ness'inin bir kısmını kaybedebilir. Örneğin, özel nesnede Kategori ve Ayar gibi özellik adlarını kullanıyorum. Ancak git dünyasında, yapılandırma dosyasının bu bölümlerine muhtemelen Bölüm ve Değer adı verilir. Sonucu daha git dostu hale getirmek için yapabileceğim şeylerden biri Kategori ve Ayar için takma ad özellikleri oluşturmaktır.

Update-TypeData -TypeName 'gitConfig' -MemberType AliasProperty -MemberName 'Value' -Value 'Setting' -force
Update-TypeData -TypeName 'gitConfig' -MemberType AliasProperty -MemberName 'Section' -Value 'Category' -force

Varsayılan ekran bile takma adları kullanmaz; ancak kesinlikle kullanabilir; kullanıcı takma adların mevcut olduğunu biliyorsa bunları kullanabilir.

Git sürümünü göstermek için özel bir tür uzantısı da ekledim.

Update-TypeData -TypeName 'gitConfig' -MemberType ScriptProperty -MemberName gitVersion -value {git --version} -force

Get-Member bu özelliklerin tümünü görüntüler.

PowerShell Kodu

Komut dosyasının bu sürümünü GitHub'da yayınladım.

Get-GitConfig.ps1:

#requires -version 5.1

Function Get-GitConfig {

 <#
.SYNOPSIS
    Get git configuration settings
.DESCRIPTION
    Git stores configurations settings in a simple text file format. Fortunately, this file is structured and predictable. This command will process git configuration information into PowerShell friendly output.
.PARAMETER Scope
    Possible values are Global,Local or System
.PARAMETER Path
    Enter the path to a .gitconfig file. You can use shell paths like ~\.gitconfig
.EXAMPLE
PS C:\> Get-GitConfig

Scope  Category  Name         Setting
-----  --------  ----         -------
global filter    lfs          git-lfs clean -- %f
global filter    lfs          git-lfs smudge -- %f
global filter    lfs          true
global user      name         Art Deco
global user      email        artd@company.com
global gui       recentrepo   C:/Scripts/Gen2Tools
global gui       recentrepo   C:/Scripts/PSVirtualBox
global gui       recentrepo   C:/Scripts/FormatFunctions
global core      editor       powershell_ise.exe
global core      autocrlf     true
global core      excludesfile ~/.gitignore
global push      default      simple
global color     ui           true
global alias     logd         log --oneline --graph --decorate
global alias     last         log -1 HEAD
global alias     pushdev      !git checkout master && git merge dev && git push && git checkout dev
global alias     st           status
global alias     fp           !git fetch && git pull
global merge     tool         kdiff3
global mergetool kdiff3       'C:/Program Files/KDiff3/kdiff3.exe' $BASE $LOCAL $REMOTE -o $MERGED

Getting global configuration settings

.EXAMPLE
PS C:\> Get-GitConfig -scope system | where category -eq 'filter'

Scope  Category Name Setting
-----  -------- ---- -------
system filter   lfs  git-lfs clean -- %f
system filter   lfs  git-lfs smudge -- %f
system filter   lfs  git-lfs filter-process
system filter   lfs  true

Get system configuration and only git filters.
.EXAMPLE
PS S:\PSScriptTools> Get-GitConfig local

Scope Category Name                    Setting
----- -------- ----                    -------
local core     repositoryformatversion 0
local core     filemode                false
local core     bare                    false
local core     logallrefupdates        true
local core     symlinks                false
local core     ignorecase              true
local remote   origin                  https://github.com/jdhitsolutions/PSScriptTools.git
local remote   origin                  +refs/heads/*:refs/remotes/origin/*
local branch   master                  origin
local branch   master                  refs/heads/master

Get the git configuration from a local repository.

.EXAMPLE
PS C:\> Get-GitConfig -path ~\.gitconfig | format-table -groupby category -property Name,Setting

Get settings from a configuration file and present in a grouped, formatted table.

.INPUTS
    none
.OUTPUTS
    [gitConfig]
.NOTES
    The command assumes you have git installed. Otherwise, why would you be using this?

    Learn more about PowerShell: http://jdhitsolutions.com/blog/essential-powershell-resources/

    Last updated: 1 February, 2019
.LINK
    git
#>

    [CmdletBinding(DefaultParameterSetName = "default")]
    [OutputType("gitConfig")]
    [Alias("ggc")]

    Param (
        [Parameter(Position = 0, ParameterSetName = "default")]
        [ValidateSet("Global", "System", "Local")]
        [string[]]$Scope = "Global",
        [Parameter(ParameterSetName = "file")]
        #the path to a .gitconfig file which must be specified if scope if File
        [ValidateScript( {Test-Path $_})]
        [Alias("config")]
        [string]$Path
    )

    Begin {
        Write-Verbose "Starting $($myinvocation.MyCommand)"
        if ($path) {
            #convert path value to a complete file system path
            $Path = Convert-Path -Path $path
        }

        #internal helper function
        function _process {
            [cmdletbinding()]
            Param(
                [scriptblock]$scriptblock,
                [string]$Scope
            )

            Write-Verbose "Invoking $($scriptblock.tostring())"
            #invoke the scriptblock and save the text output
            $data = Invoke-Command -scriptblock $scriptblock

            #split each line of the config on the = sign
            #and add to the hashtable
            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
        } # _process
    } #begin

    Process {

        if ($PSCmdlet.ParameterSetName -eq 'file') {
            Write-Verbose "Getting config from $path"
            $get = [scriptblock]::Create("git config --file $path --list")
            #call the helper function
            _process -scriptblock $get -scope "File"
        }
        else {
            foreach ($item in $Scope) {
                Write-Verbose "Getting $item config"
                #the git command is case sensitive so make the scope lower case
                $item = $item.tolower()

                #create a scriptblock to run git config
                $get = [scriptblock]::Create("git config --$item --list")

                #call the helper function
                _process -scriptblock $get -Scope $item
            } #foreach scope
        } #else
    } #process

    End {
        Write-Verbose "Ending $($myinvocation.MyCommand)"
    } #end

} #end Get-GitConfig

#define a default set of properties to the custom gitConfig type
Update-TypeData -TypeName 'gitConfig' -DefaultDisplayPropertySet 'Scope', 'Category', 'Name', 'Setting' -force
#define some alias properties that might be more 'git-like'
Update-TypeData -TypeName 'gitConfig' -MemberType AliasProperty -MemberName 'Value' -Value 'Setting' -force
Update-TypeData -TypeName 'gitConfig' -MemberType AliasProperty -MemberName 'Section' -Value 'Category' -force
#add a custom property
Update-TypeData -TypeName 'gitConfig' -MemberType ScriptProperty -MemberName gitVersion -value {git --version} -force

Parametre bildiriminin hemen öncesine bakarsanız, çıktı tipini özel tip adımla tanımladığımı görebilirsiniz. Bunu [gitConfig] gibi parantez içine alırsanız PowerShell kayıtlı bir tür arayıp şikayette bulunmaya çalışabilir. Bir dize kullanın. Zaten bunların hepsi belgeleme amaçlıdır. Ayrıca işlevin bir parçası olarak ggc takma adını da tanımlıyorum. Bu şekilde Set-Alias veya New-Alias'ı çalıştırmak için kod eklemem gerekmiyor.

Dikkat çekmek istediğim diğer husus ise dahili ve özel bir “yardımcı” fonksiyonunun kullanılmasıdır. Bu işlev, kullanıcıya gösterilmediğinden standart bir Fiil-İsim adı kullanmaz. Bu, parametre setine bağlı olarak çağrılabilen bir kod bloğudur. İstemediğim şey kod parçalarının iki kopyası. Bu sadece kodu biraz daha kullanışsız hale getirmekle kalmıyor, aynı zamanda kodu belirli yerlerde tutmam gerekiyor. Özel bir işlevle modülerleştirme süreci basitleştirir ve eğer bir Pester testi oluşturuyor olsaydım test edilmesi de daha kolay olurdu.

Git Config'i PowerShell Yoluyla Alma

PS1 dosyasına nokta kaynak sağladıktan sonra git yapılandırmamı çeşitli şekillerde görüntülememe olanak tanıyan yeni bir komutum var.

Aynı bilgilerin çoğunu görüntülemek için hala git komut satırı aracını kullanabileceğinizin farkındayım. Ancak bunu PowerShell'e dönüştürdüğümde, bunun etrafında şu şekilde ek araçlar oluşturabilirim:

#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

Bu, git yapılandırmamın bir html raporunu oluşturacaktır. Git'i yüklediyseniz, onu da çalıştırabilmeniz gerekir.

Umarım bu yolculuğu bilgilendirici bulmuşumdur. Her ne kadar öğrenmenin en iyi yolu yaparak olsa da. Umarım kodumu alırsınız, bunları komut dosyası düzenleyicinizde açarsınız ve nasıl çalıştıklarını görürsünüz. Onlara bir şans ver. Ne olacağını görmek için onları değiştirin. İyi eğlenceler. Bu şekilde öğrenirsiniz.

İlgili makaleler