conan-recipes/utils/impl/debug_processors/symstore_processor.py

120 lines
4.0 KiB
Python

import os
import sys
import re
from pathlib import Path
from symstore import Store, cab
from impl.debug_processor import DebugProcessor, register_debug_processor
from impl.package_reference import PackageReference
from impl.config import directories
from impl.files import safe_rm_tree
from impl.artifactory import ArtifactoryInstance
class SymstoreProcessor(DebugProcessor):
entries = []
def __init__(self, skip_upload:bool):
self.skip_upload = skip_upload
def activate(self, directory:str=None):
if sys.platform != 'win32':
return False
symstore_url = os.environ.get('ARTIFACTORY_SYMBOLS_URL', None)
symstore_key = os.environ.get('ARTIFACTORY_SYMBOLS_KEY', os.environ.get('ARTIFACTORY_API_KEY', None))
if not symstore_url:
print('SymstoreProcessor not activated: ARTIFACTORY_SYMBOLS_URL is not set')
return False
if not symstore_key:
print('SymstoreProcessor not activated: ARTIFACTORY_SYMBOLS_KEY or ARTIFACTORY_API_KEY is not set')
return False
if directory:
self.symstore_dir = directory
else:
self.symstore_dir = os.path.join(directories.temp_dir, 'debug_processors', 'symstore')
if not os.path.exists(self.symstore_dir):
os.makedirs(self.symstore_dir)
_000admin = os.path.join(self.symstore_dir, '000Admin')
if not os.path.exists(_000admin):
os.makedirs(_000admin)
self.artifactory = ArtifactoryInstance(url=symstore_url, key=symstore_key)
for file in ('000Admin/lastid.txt', '000Admin/history.txt', '000Admin/server.txt'):
self.__download_file(file)
self.symstore = Store(self.symstore_dir)
print('SymstoreProcessor activated')
return True
def process(self, package_reference:PackageReference, source_dir: str, build_dir: str):
if package_reference.is_build_tool:
print(f'Skipping symstore upload for build tool {package_reference}')
return
transaction = self.symstore.new_transaction(package_reference.name, package_reference.version, None)
for path in Path(build_dir).rglob('*.pdb'):
if re.fullmatch(r'vc[0-9]+\.pdb', path.name):
continue
try:
entry = transaction.new_entry(path, cab.compress)
except Exception as e:
print(f'Failed to create symstore entry for {path}: {e}')
continue
if entry.exists():
continue
print(f'Adding {path} to symstore')
try:
transaction.add_entry(entry)
self.entries.append(entry)
except Exception as e:
print(f'Failed to add {path} to symstore: {e}')
if len(transaction.entries) > 0:
self.symstore.commit(transaction)
def finalize(self):
if self.skip_upload:
return
print(self.symstore.transactions.items())
for dir in os.listdir(self.symstore_dir):
if dir == '000Admin':
continue
for root, dirnames, filenames in os.walk(os.path.join(self.symstore_dir, dir)):
relative_root = os.path.relpath(root, self.symstore_dir).replace('\\', '/')
for filename in filenames:
self.__upload_file(f'{relative_root}/{filename}', os.path.join(root, filename))
safe_rm_tree(self.symstore_dir)
def discard(self):
print('Discarding symstore transaction')
safe_rm_tree(self.symstore_dir)
def __download_file(self, file:str):
self.artifactory.get_file(file, os.path.join(self.symstore_dir, file))
def __upload_file(self, file:str, path:str):
try:
print(f'Uploading {file} to remote symstore')
url = self.artifactory.upload_file(file, path)
except Exception as e:
print(f'Failed to upload {file} to remote symstore: {e}')
register_debug_processor('symstore', lambda skip_upload: SymstoreProcessor(skip_upload))