Public/Git/Update-GitRepositories.ps1

function Update-GitRepositories {
    <#
    .SYNOPSIS
        Updates all Git repositories in immediate subdirectories by performing a git pull operation.
 
    .DESCRIPTION
        This function searches for all immediate subdirectories containing a .git folder in the specified root directory
        (or the current directory by default), and performs a simple git pull operation in each one.
 
    .PARAMETER RootDirectory
        The root directory containing the Git repositories to update. Defaults to the current directory.
 
    .EXAMPLE
        Update-GitRepositories
        Updates all Git repositories in the immediate subdirectories of the current directory.
 
    .EXAMPLE
        Update-GitRepositories -RootDirectory "C:\Projects"
        Updates all Git repositories in the immediate subdirectories of the C:\Projects directory.
 
    .NOTES
        Requires Git to be installed and available in your PATH.
 
        Author: Michiel VH
 
    .LINK
        https://git-scm.com/docs/git-pull
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$false, Position=0)]
        [string]$RootDirectory = (Get-Location)
    )

    # Save the original location to return to it at the end
    $originalLocation = Get-Location
    
    try {
        # Ensure the root directory exists
        if (-not (Test-Path -Path $RootDirectory)) {
            Write-Error "The specified root directory '$RootDirectory' does not exist."
            return
        }

        # Set location to the root directory
        Set-Location -Path $RootDirectory

        # Find all Git repositories (directories that contain a .git subfolder)
        # Simple approach to just search one level down - include hidden items with -Hidden
        $dirs = Get-ChildItem -Path $RootDirectory -Directory
        $gitDirs = @()
        
        foreach ($dir in $dirs) {
            # Look specifically for hidden .git directories
            $gitFolder = Get-ChildItem -Path $dir.FullName -Directory -Hidden -Filter ".git" -ErrorAction SilentlyContinue
            if ($gitFolder) {
                $gitDirs += $gitFolder
            }
        }

        Write-Host "Found $($gitDirs.Count) Git repositories to update." -ForegroundColor Cyan
        
        # Initialize progress bar
        $progressParams = @{
            Activity = "Updating Git Repositories"
            Status = "Starting updates..."
            PercentComplete = 0
        }
        Write-Progress @progressParams
        
        # Process each repository
        $currentRepo = 0
        $totalRepos = $gitDirs.Count
        
        foreach ($gitDir in $gitDirs) {
            $currentRepo++
            $repoPath = $gitDir.Parent.FullName
            $repoName = $gitDir.Parent.Name
            
            # Update progress bar
            $progressParams.Status = "Processing $currentRepo of $totalRepos - $repoName"
            $progressParams.PercentComplete = ($currentRepo / $totalRepos) * 100
            Write-Progress @progressParams

            Write-Host "`nUpdating repository: $repoName [$currentRepo/$totalRepos]" -ForegroundColor Yellow
            Write-Host "Repository path: $repoPath" -ForegroundColor Gray

            # Navigate to the repository
            Set-Location -Path $repoPath

            try {
                # Simple git pull operation
                Write-Host "Running git pull..." -ForegroundColor Gray
                
                # Perform git pull
                $pullResult = git pull 2>&1
                
                # Show the result
                if ($LASTEXITCODE -eq 0) {
                    Write-Host "Success" -ForegroundColor Green
                    
                    # Format the output in a more structured way
                    if ($pullResult -match "Already up to date") {
                        Write-Host " Status: Already up to date" -ForegroundColor Cyan
                    } else {
                        Write-Host " Status: Changes pulled successfully" -ForegroundColor Cyan
                        
                        # Parse and display changes in a structured format
                        $changes = $pullResult -split "`n" | Where-Object { $_ -match "\s+\d+\s+\w+\(\+\)" -or $_ -match "\s+\d+\s+files?\s+changed" -or $_ -match "^\s+(create mode|rename|delete mode)" }
                        
                        if ($changes) {
                            Write-Host " Changes:" -ForegroundColor Cyan
                            foreach ($change in $changes) {
                                Write-Host " $($change.Trim())" -ForegroundColor White
                            }
                        }
                    }
                } else {
                    Write-Host "Failed: $pullResult" -ForegroundColor Red
                }
            } catch {
                Write-Host "Error updating repository $repoName : $($_.Exception.Message)" -ForegroundColor Red
            }
        }
    } catch {
        Write-Host "Error: $_" -ForegroundColor Red
    } finally {
        # Complete the progress bar
        Write-Progress -Activity "Updating Git Repositories" -Completed
        
        # Return to the original location
        Set-Location -Path $originalLocation
    }
}