Private/Add-Project.ps1

#
# Add-Project.ps1
#

function Add-Project {
    try {
        Clear-Variable devops_* -Scope Global
        ##Review
        Set-ToolVariables
        Set-ProjectVariables
        $message = "Adding PowerPlatform DevOps Project"
        $options = "Select an Existing Project", "Browse for a local Repository", "Create a new Project", "Clone an existing Repo", "Quit"
        do {
            $sel = Invoke-Menu -MenuTitle "---- $message ------" -MenuOptions $options
        } until ($sel -ge 0)

        try {
            switch ($sel) {
                '0' { Select-GitRepo }
                '1' { Get-GitRepo }
                '2' { Add-GitRepo }
                '3' { Clone-GitRepo }
                '4' { return }
            }               
        }
        catch {
            Write-Host $_
            pause
            return
        }
    }
    catch {
        Write-Host $_
        pause
        return
    }
    finally {
        $global:devops_configFile | ConvertTo-Json | Set-Content ("$env:APPDATA\Microsoft.PowerPlatform.DevOps\devopsConfig.json")
        if ($global:devops_projectFile) {
            $global:devops_projectFile.ProjectAdded = "True"
            $global:devops_projectFile | ConvertTo-Json | Set-Content ("$global:devops_projectLocation\$global:devops_gitRepo.json") 
        }
    }
}

function Add-GitRepo {
    do {
        $global:devops_gitRepo = Read-Host -Prompt "Please enter a Name for the Git Repository you wish to Create"
    }until ($global:devops_gitRepo -ne "")
    $global:devops_gitRepo = $global:devops_gitRepo.Replace(' ', '')
    if ($global:devops_configFile.Projects.Count -eq 0 -or !($global:devops_configFile.Projects.Name.Contains($global:devops_gitRepo))) {
        Copy-GitRepoFromTemplate
        pause
    }
    else {
        Write-Host "You already have a repo called $global:devops_gitRepo, please select a different name"
        $global:devops_gitRepo = ""
        Add-GitRepo
    }
}

function Copy-GitRepoFromTemplate {
    try {
        if ($global:devops_isDocker) {
            $path = Read-Host "Enter a folder to create a new git Repository for your Power Platform Project"
        }
        else {
            Write-Host "Select a folder to create a new git Repository for your Power Platform Project"
            $application = New-Object -ComObject Shell.Application
            $path = ($application.BrowseForFolder(0, 'Select a folder', 0)).Self.Path
    
        }
        $global:devops_projectLocation = "$path\$global:devops_gitRepo"        
        if (!(Test-Path -Path "$global:devops_projectLocation") -and !($null -eq $path)) {
            Write-Host "Creating Project Folder"
            New-Item -Path $path -Name $global:devops_gitRepo -ItemType Directory
            Copy-Item -Path (Join-Path $PSScriptRoot emptyProject.json) -Destination $global:devops_projectLocation\$global:devops_gitRepo.json
            $global:devops_projectConfigID = $global:devops_configFile.Projects.Count
            $newProject = @([ordered]@{ID = $global:devops_projectConfigID; Name = $global:devops_gitRepo; ProjectLocation = "$global:devops_projectLocation" })
            $global:devops_configFile.Projects += $newProject
            $global:devops_configFile | ConvertTo-Json | Set-Content ("$env:APPDATA\Microsoft.PowerPlatform.DevOps\devopsConfig.json")
            $global:devops_projectFile = Get-Content ("$global:devops_projectLocation\$global:devops_gitRepo.json") | ConvertFrom-Json
            $global:devops_projectFile.gitRepo = $global:devops_gitRepo
            $global:devops_projectFile | ConvertTo-Json | Set-Content ("$global:devops_projectLocation\$global:devops_gitRepo.json") 
            Set-ProjectVariables
            Set-Location -Path "$global:devops_projectLocation" 
              
    
            $message = "Setting up PowerPlatform.DevOps locally"
            Write-Host $message
    
            Remove-Item -Path (Join-Path $PSScriptRoot ..\FrameworkTemplate\node_modules) -Recurse -Force -ErrorAction Ignore  
            Copy-Item -Path (Join-Path $PSScriptRoot ..\FrameworkTemplate\*) -Destination $global:devops_projectLocation\ -Recurse -Force
        
            $message = "Confirming Git User Details"
            Write-Host $message
    
            $GitUser = git config --global user.name
            $GitEmail = git config --global user.email
    
            If ($null -eq $GitUser) {
                $GitUser = Read-Host "Enter your name (to use when committing changes to Git)"
                git config --global user.name $GitUser
            }
    
            If ($null -eq $GitEmail) {
                $GitEmail = Read-Host "Enter your email address (to use when committing changes to Git)"
                git config --global user.email $GitEmail
            }  

            Write-Host "Git User : " $GitUser
            Write-Host "Git Email : " $GitEmail
    
            Remove-Item .git -Recurse -Force -ErrorAction SilentlyContinue
    
            git init

            Write-Host "Rename PowerPlatformDevOps.sln to $global:devops_gitRepo.sln"
            Rename-Item -Path $global:devops_projectLocation\PowerPlatformDevOps.sln -NewName "$global:devops_gitRepo.sln"

            Write-Host "Rename dot files"
            Rename-Item -Path $global:devops_projectLocation\file.gitignore -NewName ".gitignore"
            Rename-Item -Path $global:devops_projectLocation\file.artifactignore -NewName ".artifactignore"
            Rename-Item -Path $global:devops_projectLocation\file.gitattributes -NewName ".gitattributes"
            Rename-Item -Path $global:devops_projectLocation\SolutionTemplate\file.eslintrc.json -NewName ".eslintrc.json"
            Rename-Item -Path $global:devops_projectLocation\SolutionTemplate\file.prettierrc.json -NewName ".prettierrc.json"

            git add -A 
            git commit -m "Initial Commit"
    
        }
        else {
            Write-Warning "The Path $global:devops_projectLocation already exists, please select a different path or project name"
            $continue = Read-Host -Prompt "Press [Enter] to Continue or [Q] to Quit"
            if (!$continue -eq 'Q') {
            }
        } 
    }
    catch {
        Write-Host $_
        $global:devops_projectFile.ProjectAdded = "Error"
        pause
    }
}


function Select-GitRepo {
    try {
        if ($global:devops_configFile.Projects.Count -gt 0) {
            [array]$options = "Go Back"
            $options += $global:devops_configFile.Projects | ForEach-Object { "$($_.Name)" }

            do {
                $thesel = Invoke-Menu -MenuTitle "---- Please Select your Project ------" -MenuOptions $options
                $sel = $thesel - 1
                $selectedRepo = $global:devops_configFile.Projects[$sel].Name
                $global:devops_projectConfigID = $sel
            } until ($selectedRepo -ne "")
            if ($thesel -eq 0) {
                return
            }
            if (($global:devops_configFile.Projects[$sel].PSobject.Properties.Name -contains "ProjectLocation")) {
                $global:devops_projectFile = Get-Content ("$($global:devops_configFile.Projects[$global:devops_projectConfigID].ProjectLocation)\$selectedRepo.json") | ConvertFrom-Json  
                $global:devops_projectLocation = $global:devops_configFile.Projects[$global:devops_projectConfigID].ProjectLocation
                $global:devops_gitRepo = $selectedRepo  
                
                Set-Location  $global:devops_projectLocation

                if ($global:devops_projectFile.DevOpsProduct -eq "Azure Devops") {
                    try {
                        Get-AzureAccounts("Azure DevOps")
                        Write-Host "Pulling latest version from Repo"
                        #Get Access Token
                        Write-Host "Getting Updated Access Token"
                        $azureDevopsResourceId = "499b84ac-1321-427f-aa17-267ca6975798"
                        $token = az account get-access-token --resource $azureDevopsResourceId | ConvertFrom-Json
                        if (!$token) {
                            Get-AzureAccounts("Azure DevOps")
                            $token = az account get-access-token --resource $azureDevopsResourceId | ConvertFrom-Json
                        }
                        $authValue = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":" + $token.accessToken)) 
                        $env:AZURE_DEVOPS_EXT_PAT = $token.accessToken   
    
                        $REPO_URL = git remote get-url origin
                        Write-Host "git URL is $REPO_URL"
    
                        git config http.$REPO_URL.extraHeader "Authorization:Basic $authValue"
                        Write-Host "Updated Auth Token"
                        git pull   
    
                    }
                    catch {
                        Write-Host $_
                        pause
                    } 
    
                }
                
                Update-ProjectFile 
                Update-ArtifactIgnore 
                Set-ProjectVariables

                # if ($global:devops_BaseBranch) {
                # $currentBranch = git branch --show-current
                # $merge = Read-Host -Prompt "Would you like to merge changes from $global:devops_BaseBranch into this branch ($currentBranch) ? [Y/N]"
                # if ($merge.ToUpper() -eq "Y") {
    
                # Write-Host "Merging any updates from $global:devops_BaseBranch"
                # git checkout $global:devops_BaseBranch
                # git pull

                # git checkout -

                # git merge $global:devops_BaseBranch
                    
                # }
                # }
            }
            else {
                Write-Host "Not Implemented" 
            }
         
        }
        else {
            Write-Host "You don't have any Projects set up, please Add a new one or Clone an existing Repo"
            pause
        }  
    }
    catch {
        Write-Error $_
        $global:devops_projectFile.ProjectAdded = "Error"
        pause
    }
}

function Get-GitRepo {
    try {
        if (!(Test-Path $env:APPDATA\Microsoft.PowerPlatform.DevOps)) {
            New-Item -Path $env:APPDATA\Microsoft.PowerPlatform.Devops -ItemType Directory
        }

        if ($global:devops_isDocker) {
            $path = Read-Host "Please enter the location of your Existing Project"
        }
        else {
            $application = New-Object -ComObject Shell.Application
            $path = ($application.BrowseForFolder(0, "Select the location of your Existing Project", 0)).Self.Path           
        }

        $repoFinder = $path -split "\\"
        $selectedRepo = $repoFinder[$repoFinder.Count - 1]
        Write-Host $selectedRepo
        Write-Host $path\$selectedRepo.json
    
        if ((Test-Path -Path "$path\$selectedRepo.json")) {
            $global:devops_projectLocation = "$path"

            $global:devops_projectConfigID = $global:devops_configFile.Projects.Count
            $newProject = [ordered]@{ID = $global:devops_projectConfigID; Name = $selectedRepo; ProjectLocation = $global:devops_projectLocation }
            $global:devops_configFile.Projects += $newProject
            $global:devops_configFile | ConvertTo-Json | Set-Content ("$env:APPDATA\Microsoft.PowerPlatform.DevOps\devopsConfig.json")
            $global:devops_projectFile = Get-Content ("$path\$selectedRepo.json") | ConvertFrom-Json
            Update-ProjectFile
            Set-ProjectVariables
            Set-Location  $global:devops_projectLocation
        }
        else {
            Write-Host "$path is not a valid Project Location, please Add a new one or Clone an existing Repo"
            pause
        }    
    }
    catch {
        Write-Error $_
        $global:devops_projectFile.ProjectAdded = "Error"
    }
}

function Clone-GitRepo {
    try {
        $regEx = '(http[s]?|[s]?ftp[s]?)(:\/\/)([^\s,]+)'

        do {
            $repoURL = Read-Host "Please enter the git clone URL"
        } until ($repoURL -ne "" -and $repoURL -match $regEx)  

        if ($global:devops_isDocker) {
            $path = Read-Host "Please enter the local path to Clone to"
        }
        else {
            $application = New-Object -ComObject Shell.Application
            $path = ($application.BrowseForFolder(0, "Select a folder to Clone your $selectedRepo Repo to", 0)).Self.Path    
        }

        $repoFinder = $repoURL -split "/"
        $selectedRepo = $repoFinder[$repoFinder.Count - 1].Replace('.git', '')
        $global:devops_gitRepo = $selectedRepo
        Write-Host $selectedRepo

        Write-host $path
        Write-Host $repoURL

        $message = "Confirming Git User Details"
        Write-Host $message

        $GitUser = git config --global user.name
        $GitEmail = git config --global user.email

        If ($null -eq $GitUser) {
            $GitUser = Read-Host "Enter your name (to use when committing changes to Git)"
            git config --global user.name $GitUser
        }

        If ($null -eq $GitEmail) {
            $GitEmail = Read-Host "Enter your email address (to use when committing changes to Git)"
            git config --global user.email $GitEmail
        }  

        Write-Host "Git User : " $GitUser
        Write-Host "Git Email : " $GitEmail

        $isADO = $repoURL.Contains("azure.com") -or $repoURL.Contains("visualstudio.com")

        if ($isADO) {
            Get-AzureAccounts("Azure DevOps")
            az account set --subscription $global:devops_selectedSubscription
            #Get Access Token
            $azureDevopsResourceId = "499b84ac-1321-427f-aa17-267ca6975798"
            $token = az account get-access-token --resource $azureDevopsResourceId | ConvertFrom-Json
            $authValue = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":" + $token.accessToken))  

            . git -c http.$repoURL.extraHeader="Authorization: Basic $authValue" clone $repoURL $path\$global:devops_gitRepo    

        }
        else {
            . git clone $repoURL $path\$global:devops_gitRepo
        }
    
        $global:devops_projectLocation = "$path\$global:devops_gitRepo"
        Write-Host "Change path to " $global:devops_projectLocation

        Set-Location $global:devops_projectLocation

        if (!(Test-Path -Path "$global:devops_projectLocation\$selectedRepo.json")) {
            Copy-Item -Path (Join-Path $PSScriptRoot emptyProject.json) -Destination $global:devops_projectLocation\$selectedRepo.json
            $global:devops_projectFile = Get-Content ("$global:devops_projectLocation\$selectedRepo.json") | ConvertFrom-Json
            Update-ProjectFile
            $global:devops_projectFile.gitRepo = $global:devops_gitRepo
            #$global:devops_projectFile.selectedSubscriptionName = $global:devops_selectedSubscriptionName
            #$global:devops_projectFile.selectedSubscription = $global:devops_selectedSubscription
            $global:devops_projectFile | ConvertTo-Json | Set-Content ("$global:devops_projectLocation\$global:devops_gitRepo.json")  
            Set-ProjectVariables          
        }
        $global:devops_projectConfigID = $global:devops_configFile.Projects.Count
        $newProject = [ordered]@{ID = $global:devops_projectConfigID; Name = $selectedRepo; ProjectLocation = $global:devops_projectLocation }
        $global:devops_configFile.Projects += $newProject
        $global:devops_configFile | ConvertTo-Json | Set-Content ("$env:APPDATA\Microsoft.PowerPlatform.DevOps\devopsConfig.json")
        $global:devops_projectFile = Get-Content ("$global:devops_projectLocation\$global:devops_gitRepo.json") | ConvertFrom-Json
        Update-ProjectFile
        Set-ProjectVariables

        git config http.$repoURL.extraHeader "Authorization:Basic $authValue"

        pause    
    }
    catch {
        Write-Error $_
        $global:devops_projectFile.ProjectAdded = "Error"
        pause
    }
}