Skip to content

Commit

Permalink
Merge pull request #175 from StartAutomating/ugit-ufix
Browse files Browse the repository at this point in the history
ugit 0.4
  • Loading branch information
StartAutomating authored May 14, 2023
2 parents 14267d5 + 5d472ad commit 4ac0a77
Show file tree
Hide file tree
Showing 16 changed files with 464 additions and 47 deletions.
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: [StartAutomating]
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 0.4:

* Adding Sponsorship! (#174)
* RealGit / GitReal will opt-out of ugit (#173)
* Added git.commit.info.psuh (#111)
* Fixing directory piping (#172)
* Git Clone allows absolute paths (#169, thanks @corbob)
* Fixing Git Log -Statistics (#171)
* Not Mapping Partial Dynamic Parameters (#168)

--

## 0.3.9:

* Adding ugit demo (Fixes #163)
Expand Down
6 changes: 3 additions & 3 deletions Extensions/Git.Clone.UGit.Extension.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ end {


if ($dest) {
$destPath = Join-Path $pwd $dest
$destPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($dest)
$gitUrl = $gitArgument | Where-Object { $_ -like '*.git' -and $_ -as [uri]}
[PSCustomObject]@{
PSTypeName = 'git.clone'
GitRoot = $destPath
Directory = Get-Item -Path $destPath
GitRoot = "$destPath"
Directory = Get-Item -LiteralPath $destPath
GitUrl = $gitUrl
}
} else {
Expand Down
4 changes: 0 additions & 4 deletions Extensions/Git.Help.All.UGit.Extension.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,3 @@ process {
Category = $category
}
}

end {

}
10 changes: 4 additions & 6 deletions Extensions/Git.Log.Input.UGit.Extension.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,6 @@ foreach ($dashToDoubleDash in 'after', 'before', 'author') {
}
}

foreach ($dashToDoubleDashSwitch in 'Statistics') {
if ($PSBoundParameters[$dashToDoubleDash]) {
"--$dashToDoubleDashSwitch"
}
}

if ($CurrentBranch) {
$headbranch = git remote | git remote show | Select-Object -ExpandProperty HeadBranch
$currentBranchName = git branch | Where-Object IsCurrentBranch
Expand Down Expand Up @@ -119,4 +113,8 @@ if ($SearchString) {
if ($SearchPattern) {
"-G"
$SearchPattern
}

if ($Statistics) {
'--stat'
}
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
<a href='https://www.powershellgallery.com/packages/ugit/'>
<img src='https://img.shields.io/powershellgallery/dt/ugit' />
</a>
<br/>
<a href='https://github.com/sponsors/StartAutomating'>❤️</a>
<a href='https://github.com/StartAutomating/ugit/stargazers'>⭐</a>
</div>

Updated Git: A powerful PowerShell wrapper for git that lets you extend git, automate multiple repos, and output git as objects.

ugit (Updated Git) is a powerful PowerShell module for git that lets you: output git as objects, automate multiple repos, and extend git.

## What is ugit?

Expand Down Expand Up @@ -470,4 +472,9 @@ ugit also allows you to extend the input for git.



## What uses ugit?

ugit is part of the core of [GitLogger](https://gitlogger.com/).

GitLogger uses ugit to turn logs into objects and then provides standardized metrics and a way to query your logs.

11 changes: 9 additions & 2 deletions README.ps1.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
<a href='https://www.powershellgallery.com/packages/ugit/'>
<img src='https://img.shields.io/powershellgallery/dt/ugit' />
</a>
<br/>
<a href='https://github.com/sponsors/StartAutomating'>❤️</a>
<a href='https://github.com/StartAutomating/ugit/stargazers'>⭐</a>
</div>

Updated Git: A powerful PowerShell wrapper for git that lets you extend git, automate multiple repos, and output git as objects.

ugit (Updated Git) is a powerful PowerShell module for git that lets you: output git as objects, automate multiple repos, and extend git.

## What is ugit?

Expand Down Expand Up @@ -127,3 +129,8 @@ ugit also allows you to extend the input for git.
}
~~~

## What uses ugit?

ugit is part of the core of [GitLogger](https://gitlogger.com/).

GitLogger uses ugit to turn logs into objects and then provides standardized metrics and a way to query your logs.
3 changes: 3 additions & 0 deletions Types/git.commit.info/Push.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Push-Location $this.GitRoot
git push @args
Pop-Location
122 changes: 96 additions & 26 deletions Use-Git.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
.NOTES
Use-Git will generate two events before git runs. They will have the source identifiers of "Use-Git" and "Use-Git $GitArgument"
#>
[Alias('git')]
[Alias('git','realgit','gitreal')]
[CmdletBinding(PositionalBinding=$false,SupportsShouldProcess,ConfirmImpact='Low')]
param(
# Any arguments passed to git. All positional arguments will automatically be passed to -GitArgument.
Expand All @@ -53,9 +53,11 @@
)

dynamicParam {
# To get dynamic parameters, we need to look at our invocation
$myInv = $MyInvocation

$callstackPeek = @(Get-PSCallStack)[1]
# and peek up the callstack.
$callstackPeek = @(Get-PSCallStack)[-1]
$callingContext =
if ($callstackPeek.InvocationInfo.MyCommand.ScriptBlock) {
@($callstackPeek.InvocationInfo.MyCommand.ScriptBlock.Ast.FindAll({
Expand All @@ -66,27 +68,80 @@
},$true))[0]
}

# This will give us something to validate against, so we don't get dynamic parameters for everything
$ToValidate =
if (-not $callingContext -and
$callstackPeek.Command -like 'TabExpansion*' -and
$callstackPeek.InvocationInfo.BoundParameters.InputScript
) {
$callstackPeek.InvocationInfo.BoundParameters.InputScript.ToString()
} else {
}
elseif ($callingContext) {
$callingContext.CommandElements -join ' '
}
elseif ($myInv.Line) {
$myInv.Line.Substring($myInv.OffsetInLine - 1)
}

# If there's nothing to validate, there are no dynamic parameters.
if (-not $ToValidate) { return }

# Get dynamic parameters that are valid for this command
$dynamicParameterSplat = [Ordered]@{
CommandName='Use-Git'
ValidateInput=$ToValidate
DynamicParameter=$true
DynamicParameterSetName='__AllParameterSets'
NoMandatoryDynamicParameter=$true
}
$myDynamicParameters = Get-UGitExtension @dynamicParameterSplat
if (-not $myDynamicParameters) { return }

# Here's where things get a little tricky.
# we want to make as much muscle memory work as possible, so we don't wany any dynamic parameter that is not "fully" mapped.
# So we need to walk over each command element.

if (-not ($callingContext -or ($callstackPeek.Command -like 'TabExpansion*'))) {
# (bonus points - within Pester, we cannot callstack peek effectively, and need to use the invocation line)
# Therefore, when testing dynamic parameters, assign to a variable (because parenthesis and pipes may make this an invalid ScriptBlock)
$callingContext = try {
[scriptblock]::Create($ToValidate).Ast.EndBlock.Statements[0].PipelineElements[0]
} catch { $null}
}
Get-UGitExtension @dynamicParameterSplat
foreach ($commandElement in $callingContext.CommandElements) {
if (-not $commandElement.parameterName) { continue } # that is a Powershell parameter
foreach ($dynamicParam in @($myDynamicParameters.Values)) {
if (
(
# If it started with this name
$dynamicParam.Name.StartsWith($commandElement.parameterName, 'CurrentCultureIgnoreCase') -and
# but was not the full parameter name, we'll remove it
$dynamicParam.Name -ne $commandElement.parameterName
) -or # otherwise
(
# If the dynamic parameter had aliases
$dynamicParam.Attributes.AliasNames -and
$(foreach ($aliasName in $dynamicParam.Attributes.AliasNames) {
if (-not $aliasName) { continue }
# and any of those aliases starts with the parameter name
if ($aliasName.StartsWith($commandElement.parameterName, 'CurrentCultureIgnoreCase') -and
# and is not the full parameter name
$aliasName -ne $commandElement.parameterName) {
# we also want to remove it
$true; break
}
})
)
) {
$null = $myDynamicParameters.Remove($dynamicParam.Name)
}
}
}
$myDynamicParameters
}

begin {
$myInv = $MyInvocation
if (-not $script:CachedGitCmd) { # If we haven't cahced the git command
# go get it.
$script:CachedGitCmd = $ExecutionContext.SessionState.InvokeCommand.GetCommand('git', 'Application')
Expand Down Expand Up @@ -117,21 +172,22 @@
$gitArgsArray.AddRange($GitArgument)
}

foreach ($commandElement in $callingContext.CommandElements) {
if ($commandElement.parameterName -in 'd', 'v', 'c') {
:nextCommandElement foreach ($commandElement in $callingContext.CommandElements) {
if (-not $commandElement.parameterName) { $argumentNumber++; continue }
$paramName = $commandElement.parameterName
if ($paramName -in 'd', 'c', 'v') {
# Insert the argument into the list
$gitArgsArray.Insert(
$argumentNumber - 1, # ( don't forget to subtract one, because the command is an element)
$argumentNumber - 1, # ( don't forget to subtract one, because the command name is an element)
$commandElement.Extent.ToString()
)
if ($commandElement.parameterName -in 'd', 'c', 'v') {
if ($commandElement.parameterName -eq 'c') {
$ConfirmPreference = 'none' # so set confirm preference to none
}
$VerbosePreference = 'silentlyContinue'
$DebugPreference = 'silentlyContinue'
if ($paramName -eq 'c') {
$ConfirmPreference = 'none' # so set confirm preference to none
}
$VerbosePreference = 'silentlyContinue'
$DebugPreference = 'silentlyContinue'
}

$argumentNumber++
}

Expand Down Expand Up @@ -166,6 +222,8 @@
return # we're done.
}

$pipedInDirectories = $false

$inputObject =
@(foreach ($in in $AllInputObjects) {
if ($in -is [IO.FileInfo]) { # If the input is a file
Expand All @@ -184,11 +242,13 @@
$in.Fullname # and adding this file name.
}
} elseif ($in -is [IO.DirectoryInfo]) {
$pipedInDirectories = $true
$directories += Get-Item -LiteralPath $in.Fullname # If the input was a directory, keep track of it.
} else {
# Otherwise, see if it was a path and it was a directory
if ((Test-Path $in -ErrorAction SilentlyContinue) -and
(Get-Item $in -ErrorAction SilentlyContinue) -is [IO.DirectoryInfo]) {
$pipedInDirectories = $true
$directories += Get-Item $in
} else {

Expand Down Expand Up @@ -267,8 +327,10 @@

# Walk over each input for each directory
:nextInput foreach ($inObject in $InputDirectories[$dir]) {
# Continue if there was no input and we were not the first step of the pipeline.
if (-not $inObject -and $myInv.PipelinePosition -gt 1) { continue }
# Continue if there was no input and we were not the first step of the pipeline that was not a directory.
if (-not $inObject -and (
$myInv.PipelinePosition -gt 1
) -and -not $pipedInDirectories) { continue }

$AllGitArgs = @(@($GitArgument) + $inObject) # Then we collect the combined arguments

Expand Down Expand Up @@ -344,30 +406,38 @@
Write-Progress -PercentComplete $percentageComplete -Status "git $allGitArgs " -Activity "$($dir) " -Id $progId
}

# If -WhatIf was passed, $WhatIfPreference will be true.
if ($WhatIfPreference) {
# If that's the case, return the command line we would execute.
"git $AllGitArgs"
}

# If we have indicated we do not care about -Confirmation, don't prompt
# otherwise, if we have indicated we do not want to -Confirm, don't prompt.
elseif (($ConfirmPreference -eq 'None' -and (-not $paramCopy.Confirm)) -or
$PSCmdlet.ShouldProcess("$pwd : git $allGitArgs") # otherwise, as for confirmation to run.
$PSCmdlet.ShouldProcess("$pwd : git $allGitArgs") # otherwise, prompt for confirmation to run.
) {
$eventSourceIds = @("Use-Git","Use-Git $allGitArgs")
$messageData = @{
GitRoot = "$pwd"
$messageData = [Ordered]@{
GitCommand = @(@("git") + $AllGitArgs) -join ' '
}
GitRoot = "$pwd"
}

$null =
foreach ($sourceIdentifier in $eventSourceIds) {
New-Event -SourceIdentifier $sourceIdentifier -MessageData $messageData
}
& $script:CachedGitCmd @AllGitArgs *>&1 | # Then we run git, combining all streams into output.
# then pipe to Out-Git, which will
Out-Git @OutGitParams # output git as objects.

# These objects are decorated for the PowerShell Extended Type System.
# This makes them easy to extend and customize their display.
# If Out-Git finds one or more extensions to run, these can parse the output.
if ($myInv.InvocationName -in 'realgit', 'gitreal') {
& $script:CachedGitCmd @AllGitArgs *>&1
} else {
& $script:CachedGitCmd @AllGitArgs *>&1 | # Then we run git, combining all streams into output.
# then pipe to Out-Git, which will
Out-Git @OutGitParams # output git as objects.

# These objects are decorated for the PowerShell Extended Type System.
# This makes them easy to extend and customize their display.
# If Out-Git finds one or more extensions to run, these can parse the output.
}
}

}
Expand Down
12 changes: 12 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 0.4:

* Adding Sponsorship! (#174)
* RealGit / GitReal will opt-out of ugit (#173)
* Added git.commit.info.psuh (#111)
* Fixing directory piping (#172)
* Git Clone allows absolute paths (#169, thanks @corbob)
* Fixing Git Log -Statistics (#171)
* Not Mapping Partial Dynamic Parameters (#168)

--

## 0.3.9:

* Adding ugit demo (Fixes #163)
Expand Down
14 changes: 12 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
<a href='https://www.powershellgallery.com/packages/ugit/'>
<img src='https://img.shields.io/powershellgallery/dt/ugit' />
</a>
<br/>
<a href='https://github.com/sponsors/StartAutomating'>❤️</a>
<a href='https://github.com/StartAutomating/ugit/stargazers'>⭐</a>
</div>

Updated Git: A powerful PowerShell wrapper for git that lets you extend git, automate multiple repos, and output git as objects.

ugit (Updated Git) is a powerful PowerShell module for git that lets you: output git as objects, automate multiple repos, and extend git.

## What is ugit?

Expand Down Expand Up @@ -467,3 +469,11 @@ ugit also allows you to extend the input for git.


* [Git Log Input](Git.Log.Input-Extension.md)



## What uses ugit?

ugit is part of the core of [GitLogger](https://gitlogger.com/).

GitLogger uses ugit to turn logs into objects and then provides standardized metrics and a way to query your logs.
Loading

0 comments on commit 4ac0a77

Please sign in to comment.