-
Notifications
You must be signed in to change notification settings - Fork 0
/
Posh-GitMultiStatus.psm1
170 lines (155 loc) · 5.62 KB
/
Posh-GitMultiStatus.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
##############################################################################
#.SYNOPSIS
# Get a summary of the status of all the git repositories in the working directory.
#
#.DESCRIPTION
# The function will scan the working directory for git repositories and do an git remote update on them.
# It will then run "git fetch" and check the status of the local active branch and compare it to the remote so that it can
# inform if the branch is up-to-date, behind, ahead or divereged from the remote.
# The function will also display staged and unstaged files if they exist.
#
#.PARAMETER Path
# The path you want to scan for repositories, defualt is working directory.
#
#.PARAMETER Depth
# The recursive depth to scan for repositories, default is 0 (flat).
#
#.PARAMETER Push
# If set, the function will do a git push if the status is "Ahead".
# Be carefull as this automatically pushes commited changes to the remote!
#
#.PARAMETER Rebase
# If this paramter is set, the function will do a rebase where the status is "Behind".
#
#.PARAMETER NoFetch
# If set, the function will not fetch from remote, this is faster, but only compares from the last fetch.
#
#.LINK
# Https:\\github.com\user\matias\get-gitstatus
#
#.EXAMPLE
# Get-GitStatus
# This gets the status of the repositories in working directory.
#.EXAMPLE
# Get-GitStatus -Depth 1
# This gets the status of the repositories in working directory witha recursive depth of 1.
#.EXAMPLE
# Get-GitStatus -Rebase -Push
# This gets the status of the repositories in working directory, rebase and push them if they need it.
##############################################################################
function Get-GitMultiStatus
{
param(
[string]$Path = (Get-Location),
[int]$Depth = 0,
[switch]$NoFetch,
[switch]$Push,
[switch]$Rebase
)
# Get all repositories in the directory, assumes all of them have a .git folder
$repsoitories = Get-ChildItem -Directory -Path $Path -Depth $Depth | Where-Object {Test-Path ($_.FullName + "\.git")}
if ($repsoitories -eq $null)
{
Write-Host "No git repositories found"
}
# Get the string lenght for the longest basename, use for padding.
$maxpad_name = 5
$maxpad_branch = 5
foreach ($repository in $repsoitories) {
if ($repository.BaseName.length -gt $maxpad_name)
{
$maxpad_name = $repository.BaseName.length
}
$branch = git -C $repository.FullName name-rev --name-only HEAD 2> $null
$length = $branch.length
if ($length -gt $maxpad_branch)
{
$maxpad_branch = $length
}
}
# Iterate through each repo and get the status
foreach ($repository in $repsoitories)
{
if (-not $NoFetch)
{
git -C $repository.FullName fetch 2>&1 | out-null
}
$branch = git -C $repository.FullName name-rev --name-only HEAD 2> $null
$local = git -C $repository.FullName rev-parse --quiet "@" 2> $null
$remote = git -C $repository.FullName rev-parse --quiet "@{u}" 2> $null
$base = git -C $repository.FullName merge-base "@" "@{u}" 2> $null
if ($local -eq $remote)
{
$status = "Up-to-date"
WriteStatus -Status $status -Branch $branch
}
elseif ($local -eq $base)
{
$status = "Behind"
WriteStatus -Status $status -Branch $branch -Color "Red"
if ($Rebase)
{
git -C $repository.FullName rebase 2>&1 | out-null
$status = "Up-to-date"
WriteStatus -Status $status -Branch $branch -Update
}
}
elseif ($remote -eq $base)
{
$has_remote = -not [string]::IsNullOrEmpty(((git -C $repository.FullName branch -r) -match $branch ))
if ($has_remote)
{
$status = "Ahead"
WriteStatus -Status $status -Branch $branch -Color "Green"
if ($Push)
{
git -C $repository.FullName push --quiet 2>&1 | out-null
$status = "Up-to-date"
WriteStatus -Status $status -Branch $branch -Update
}
}
else
{
$status = "No remote"
WriteStatus -Status $status -Branch $branch -Color "DarkRed"
}
}
else
{
$status = "Diverged"
WriteStatus -Status $status -Branch $branch -Color "Yellow"
if ($Rebase)
{
git -C $repository.FullName rebase 2>&1 | out-null
$status = "Ahead"
WriteStatus -Status $status -Branch $branch -Color "Green" -Update
if ($Push)
{
git -C $repository.FullName push --quiet 2>&1 | out-null
$status = "Up-to-date"
WriteStatus -Status $status -Branch $branch -Update
}
}
}
Write-Host
git -C $repository.FullName status --short
}
}
function WriteStatus()
{
param(
[parameter(Mandatory=$true)]
[string]$Status,
[parameter(Mandatory=$true)]
[string]$Branch,
[switch]$Update,
[string]$Color = "White"
)
if ($Update){Write-Host "`r"-NoNewline}
else {Write-Host}
Write-Host "($branch)".PadRight($maxpad_branch +5) -NoNewline
Write-Host $repository.BaseName.padright($maxpad_name +5) -NoNewline
Write-Host " : " -NoNewline
Write-Host "$status".padright(10) -ForegroundColor $Color -NoNewline
}
export-modulemember -function Get-GitMultiStatus