name: Initialise RepoRepository from Full Backup

args:
  -
    name: reporepository
    label: Repo repository
    placeholder: Urn or api id
    python_type: str
  -
    name: host
    label: Host instance
    placeholder: Urn or api id
    python_type: str
  -
    name: blob
    label: Backup blob
    placeholder: Urn or api id
    python_type: str

role:
  policies:
    - urn/api/policy/svnplace/Allow Everything
  parents:
    - urn/api/role/{user.username}/
    - urn/api/role/svnplace/Backup Restorer

jobs:
  restore:
    runs_on:
      host_instance: "{host}"
    mapped_repo: "{reporepository}"
    steps:
      -
        name: Restore
        python:  |
          blob = '{escape(blob)}'
          import os
          import subprocess
          import sys
          import xml.etree.ElementTree as ET
          from api_api import API

          repo = '{repo.urn}'
          repo_user = repo.rsplit('/',2)[1]
          repo_name = repo.rsplit('/',2)[2]
          repo_file = '/var/svnplace/process/repo'

          api = API('https://svnplace.com/api', ['~/.svnplace/config'])

          reporepo_desc = api.repos.describe_reporepository('{reporepository}')
          if reporepo_desc.state.name != 'Initialising':
              print(f'Reporepository in wrong state:{{reporepo_desc.state}')
              sys.exit(1)

          # confirm backup is an actual backup
          backup_desc = api.blobs.describe_blob(blob)
          backup_seal = api.blobs.describe_seal('urn/seal/user/svnplace/Backup - Full')
          if backup_seal.id not in backup_desc.seals:
              print('Blob not a full backup')
              sys.exit(1)
          
          # restore the backup files to the root directory

          r0 = subprocess.Popen(['blobcp', f'blob:{{backup_desc.fullpath}', '-'], stdout=subprocess.PIPE)
          r1 = subprocess.run(['tar', '--keep-old-files', '-xzf', '-', '-C', repo_file], stdin=r0.stdout)

          if r1.returncode:
              print('Backup failed: could not unpack backup')
              sys.exit(1)

          r0.wait()
          if r0.returncode:
              print('Backup failed: reading blob failed')
              sys.exit(1)

          backup_desc2 = api.blobs.describe_blob(blob)
          if backup_desc2.seal_tag != backup_desc.seal_tag:
              print('Backup failed: backup changed during restore')
              sys.exit(1)

          repo_desc = api.repos.describe_repo(repo)
          if repo_desc.seal in backup_desc2.seals:
              # backup is of this repo...
              # leave the UUID alone
              # leave the hooks in place
              pass
          else:
              # backup is of a different repo...
              
              # replace the uuid with a new one
              r = subprocess.run(['svnadmin', 'setuuid', repo_file])

              # clear all hooks
              for item in os.scandir(f'{{repo_file}/hooks/descriptions'):
                  if item.is_file():
                      os.remove(item.path)

          api.repos.modify_reporepository('{reporepository}', state='Ready')

          print('Restore complete')
