name: Backup (full)

args:
  -
    name: backup.store
    label: Backup location
    placeholder: Path to blob directory
  -
    name: backup.pattern
    label: Backup names
    placeholder: The bit between the directory and _<ver>_full

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

jobs:

  do_backup:
    runs_on:
      host_instance: "{repo.primary.rootdirectory.instance.api_id}"
    mapped_repo: "{repo.primary.api_id}"
    steps:
      -
        name: Backup
        python:  |
          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'
          backup_file = os.path.abspath('./backup')

          def get_repo_version(repo):
              r = subprocess.run(['svn','info','--xml', 'FILE://'+repo], capture_output=True)
              if r.returncode != 0:
                    print(r.stdout)
                    print(r.stderr)
                    return None
              
              tree = ET.fromstring(r.stdout)
              return int(tree.find('entry').attrib['revision'])

          def backup_blob(ver):
              return '{backup.store}/{backup.pattern}_%(ver)d_full' % {{
                  'backups': '{backup.store}',
                  'username': repo_user,
                  'reponame': repo_name,
                  'ver': ver,
              }

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

          repo_desc = api.repos.describe_repo(repo)
          repo_ver = get_repo_version(repo_file)

          try:
              r = api.blobs.describe_blob('urn/blob/'+backup_blob(repo_ver))
          except FileNotFoundError:
              pass
          else:
              print(f'{{repo_user}/{{repo_name}@{{repo_ver} is already backed up - nothing to do') 
              sys.exit(0)

          print('Creating backup copy')

          r = subprocess.run(['svnadmin','hotcopy', repo_file, backup_file])
          if r.returncode != 0:
              print('Failed to complete backup')
              sys.exit(1)

          backup_ver = get_repo_version(backup_file)
          if backup_ver is None:
              print('Failed to read backup version')
              sys.exit(1)

          print(f'Archiving backup {{repo_user}/{{repo_name}@{{backup_ver}')

          r0 = subprocess.Popen(('tar', '--strip-components', '1', '-C', backup_file, '-cz', '.'), stdout=subprocess.PIPE)
          r1 = subprocess.run(['blobcp', '-s', repo_desc.seal.api_id, '-s', 'urn/seal/user/svnplace/Backup - Full', '-', 'blob:'+backup_blob(backup_ver)], stdin=r0.stdout)

          if r1.returncode:
              print('Backup failed')
              sys.exit(1)

          print('Backup complete')
