Extensions/Git.Pull.UGit.Extension.ps1
<# .SYNOPSIS git pull extension .DESCRIPTION Returns git pull as objects. .EXAMPLE git pull #> [Management.Automation.Cmdlet("Out", "Git")] [ValidatePattern("^git pull")] [OutputType('git.pull.fastforward', 'git.pull.nochange')] param( [Parameter(ValueFromPipeline)] [string] $GitOut ) begin { $pullLines = @() } process { $pullLines += $gitOut } end { if ($pullLines -match 'Already up to date.') { [PSCustomObject]@{UpToDate=$true;GitRoot=$GitRoot;PSTypeName='git.pull.no.update'} } elseif ($pullLines -match '^Fast-forward$' -or $pullLines -match "'(?<strategy>[^']+)'\s{1}strategy\.$") { $gitPullOut = if ($pullLines -match '^Fast-forward$') { @{PSTypeName='git.pull.fastforward';GitRoot=$gitRoot;Changes=@();NewFiles=@()} } else { foreach ($pl in $pullLines) { if ($pl -match "'(?<strategy>[^']+)'\s{1}strategy\.$") { @{ PSTypeName="git.pull.strategy"; Strategy=$matches.strategy; GitRoot=$gitRoot; Changes=@(); NewFiles=@() } break } } } foreach ($pl in $pullLines) { if ($pl -match '^From http') { $null, $gitPullOut.GitUrl = $pl -split ' ' } if ($pl -match '\[new tag\]\S+(?<t>\S+)') { if (-not $gitPullOut.NewTags) { $gitPullOut.NewTags = @() } $gitPullOut.NewTags += $matches.t } elseif ($pl -match '\s+(?<o>[0-9a-f]+)\.\.(?<n>[0-9a-f]+)\s+(?<dest>\S+)\s+->\s+(?<src>\S+)') { $gitPullOut.SourceBranch = $matches.src $gitPullOut.DestinationBranch = $matches.dest } if ($pl -match '^Updating (?<o>[0-9a-f]+)\.\.(?<n>[0-9a-f]+)') { $gitPullOut.LastCommitHash = $matches.o $gitPullOut.CommitHash = $matches.n } elseif ($pl -match '^\s\d+') # If the line starts with a space and digits { # It's the summary. Split it on commas and remove most of the rest of the text. foreach ($linePart in $pl -split ',' -replace '[\s\w\(\)-[\d]]') { if ($linePart.Contains('+')) { # If the part contains +, it's insertions. $gitPullout.Insertions = $linePart -replace '\+' -as [int] } elseif ($linePart.Contains('-')) { # If the part contains -, it's deletions. $gitPullout.Deletions = $linePart -replace '\-' -as [int] } else { # Otherwise, its the file change count. $gitPullout.FilesChanged = $linePart -as [int] } } } elseif ($pl -match 'create\smode\s(?<mode>\d+)\s(?<FilePath>\S+)') { $gitPullOut.NewFiles += $matches.FilePath } if ($pl -like ' *|*') { $nameOfFile, $fileChanges = $pl -split '\|' $nameOfFile = $nameOfFile -replace '^\s+' -replace '\s+$' $match = [Regex]::Match($fileChanges, "(?<c>\d+)\s(?<i>\+{0,})(?<d>\-{0,})") $linesChanged = $match.Groups["c"].Value -as [int] $linesInserted = $match.Groups["i"].Length $linesDeleted = $match.Groups["d"].Length $gitPullOut.Changes += [PSCustomObject][Ordered]@{ FilePath = $nameOfFile LinesChanged = $linesChanged LinesInserted = $linesInserted LinesDeleted = $linesDeleted } } } $gitPullOut.NewFiles = @(foreach ($nf in $gitPullOut.NewFiles) { try { Get-Item (Join-Path $gitPullOut.GitRoot $nf ) -ErrorAction SilentlyContinue } catch { $null } }) $gitPullOut.GitOutputLines = $pullLines [PSCustomObject]$gitPullOut } else { $pullLines } } |