Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

<#
.SYNOPSIS
This Powershell script will update the hooks for ONE Repo an all servers
 
.DESCRIPTION
        This Powershell script will update the hooks for ONE Repo an all servers
    from the current machine.

        It will
                Locate the Repo Master
        Determine the Replica machines (Slaves)
        This will give a complete list of machines to replicate hooks scripts

        Determine the source of the hooks scripts
            If the Master instance of the Repo has a 'specialhooks' marker file then
            the hooks in the Master Repo will be replicated to all slaves

            If the Master does not have the 'specialhooks' marker then
            then global hooks will be copied from the current machine


        For each slave it will:
            Locate the Machine path to Slave Repo
            Copy appropriate hook files to the Repo
            Propagate the specialhooks file
        
        Global Hook files are found in the Repostitory root and are *.cmd

.PARAMETER  Repo
Name of the Repo to create

.PARAMETER TestMode
If present then no copy operations will be done
        
.EXAMPLE
UpdateRepoHooks.ps1 -Repo myRepo
 
.NOTES
Uses a number of cmdlets provided by VisualSVN.
 
#>
#

Param
(
    [ parameter (Mandatory=$true,
                     HelpMessage="Enter the name of the Repository")]
    [string] $Repo,
    [switch] $TestMode
)


#
#   Get information on a named repo on the named Computer
function GetRepoInfo( $repoName, $ComputerName )
{
    $repoData = Get-CimInstance -Namespace "root\VisualSVN" -ClassName VisualSVN_Repository -ComputerName $ComputerName | Where { $_.Name -eq $repoName } 
    Return $RepoData
}

#
#   Get information on the current SVN server on the named Computer
#
function GetSvnInfo($ComputerName)
{
    $repoData = Get-CimInstance -Namespace "root\VisualSVN" -ClassName VisualSVN_Service -ComputerName $ComputerName
    Return $RepoData
}

#
# Convert Absolute Path to UNC on a named computer
#
Function AbsToUnc( $ComputerName, $absPath )
{
    return '\\' + $ComputerName + '\' + $absPath.Replace(":","$")
}

# Init Data
$ALLSERVERS = @()

#
# Locate the Repo Master
# Examine current machine and determine data about the repo
#
$repoData = GetRepoInfo $Repo $env:COMPUTERNAME
If ($repoData -eq $null )
{
    Write-Error "The repo ($REPO) does not exist on the local machine" -Category InvalidArgument
    Return
}
#Write-Host 'RepoData:' , ($repoData | Format-List | Out-String)
$CURMASTER = $repoData.MasterServer
If (! $CURMASTER) { $CURMASTER = $env:COMPUTERNAME }
Write-Host "Current Master:", $CURMASTER
$CURMASTER = $CURMASTER.ToUpper()
$ALLSERVERS += $CURMASTER

 #
# Examine the repo on the Master
#
$RepoData =  Get-SvnRepositoryReplication $REPO -CimSession $CURMASTER
#Write-Host ($RepoData | Format-List | Out-String)
$RepoData.Replicators | ForEach-Object {
    $name = $_ -match '\w+\\(\w+)'
    If ( $name )
    {
        $ALLSERVERS += $matches[1].ToUpper()
    }
    else
    {
        Write-Error "Replicator data in unexepcted form: $_" -Category InvalidData
        Return;
    }
}
Write-Host "All Servers:", $ALLSERVERS

#
# Determine the root of the Repositores on this computer
#     This will be the source for the Hook Scripts
#
$SvnInfo = GetSvnInfo $env:COMPUTERNAME
if ($SvnInfo -eq $null)
{
    Write-Error 'Cannot get VisualSVN info'
    Exit
}

# Validate the Repo Root
$repoRoot = $SvnInfo.RepositoriesRoot
If (!(Test-Path $repoRoot)) 
{
    Write-Error 'RepositoriesRoot - Does not exist'
    Exit
}
Write-Host "Local Repo Root: ", $repoRoot

#
# Examine the 'Master' repo
#     Determine if it contains a specialhooks marker
#
$masterRepo = GetRepoInfo $Repo $CURMASTER
$masterHookPathUnc = AbsToUnc $CURMASTER  ($masterRepo.Path  + '\hooks')
$specialHooks = Test-Path ($masterHookPathUnc + '\specialhooks')
Write-Host 'Master Hooks: ', $masterHookPathUnc
Write-Host 'Special Hooks: ', $specialHooks


#
# Process each Machine in the set
#
$ALLSERVERS | ForEach-Object {
    Write-Host "Processing: ", $_

    #
    # If the Master Repo had specialhooks, then copy the Master repo Hooks
    # Otherwise copy the global hooks
    #
    If ($specialHooks)
    {
        If ( $_ -eq $CURMASTER )
        {
            Return
        }
        $HookSrc = $masterHookPathUnc
    }
    else
    {
        $HookSrc = $repoRoot
    }

    #
    # Get target Repo Information
    #     Want the path to the hooks directory
    #
    $targetRepo = GetRepoInfo $Repo $_
    $hookPath = $targetRepo.Path  + '\hooks'
    $hookPathUnc = AbsToUnc $_  $hookPath


    #
    # Copy files to Remote Computer
    #
    Write-Host "Hooks Found", $hookPathUnc
    $HookFileCount = 0

    Get-ChildItem $HookSrc -Filter '*.cmd' | ForEach-Object {
        $srcFile = $_.Name
        If ( ! $TestMode )
        {
            Copy-Item $_.FullName -Destination $hookPathUnc 
        }
        $HookFileCount++
    }
    Write-Host ("{0,20} : {1}" -f $Repo, "Hooks copied: $HookFileCount")
    
    #
    # Propagate specialhook information
    #
    If ( ! $TestMode )
        {
        If ($specialHooks)
        {
            Write-Host ("{0,20} : {1}" -f $Repo, "Copy specialhooks")
            Copy-Item ($HookSrc + '\specialhooks') -Destination $hookPathUnc 
        }
        else
        {
            Remove-Item ($hookPathUnc + '\specialhooks') -ErrorAction SilentlyContinue
        }
    }   
}