75 lines
3.0 KiB
Python
75 lines
3.0 KiB
Python
|
|
import hashlib
|
|
import os
|
|
|
|
from odrive.api_client import ApiClient
|
|
from odrive.crypto import b64encode
|
|
|
|
class PrivateReleaseApi():
|
|
BASE_URL = '/releases'
|
|
|
|
@staticmethod
|
|
def get_content_key(path: str, commit_hash: str):
|
|
commit_hash_bytes = bytes.fromhex(commit_hash)
|
|
|
|
def _get_file_names(path: str, prefix: list):
|
|
with os.scandir(os.path.join(path, *prefix)) as it:
|
|
for entry in it:
|
|
if entry.is_file():
|
|
yield os.path.join(*prefix, entry.name)
|
|
else:
|
|
yield from _get_file_names(path, prefix + [entry.name])
|
|
filenames = sorted(_get_file_names(path, []))
|
|
|
|
dir_hasher = hashlib.sha256()
|
|
|
|
for filename in filenames:
|
|
with open(os.path.join(path, filename), 'rb') as fp:
|
|
content = fp.read()
|
|
|
|
# Calculate commit-invariant hash of the file content
|
|
# This means that if a new compile differs only by embedded commit hash,
|
|
# it is considered equal.
|
|
patched_content = content.replace(commit_hash_bytes, bytes(len(commit_hash_bytes)))
|
|
file_hasher = hashlib.sha256()
|
|
file_hasher.update(patched_content)
|
|
|
|
dir_hasher.update(filename.encode('utf-8'))
|
|
dir_hasher.update(file_hasher.digest())
|
|
|
|
return dir_hasher.digest()
|
|
|
|
def __init__(self, api_client: 'ApiClient'):
|
|
self._api_client = api_client
|
|
|
|
async def get_manifest(self, release_type: str, content_key: bytes):
|
|
outputs = await self._api_client.call('GET', PrivateReleaseApi.BASE_URL + '/' + release_type + '/manifest', inputs={
|
|
'content_key': b64encode(content_key),
|
|
})
|
|
return outputs
|
|
|
|
async def register_content(self, release_type: str, content_key: bytes, indicated_commit: str):
|
|
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/content', inputs={
|
|
'content_key': b64encode(content_key),
|
|
'indicated_commit': indicated_commit,
|
|
})
|
|
return outputs['created']
|
|
|
|
async def register_version(self, release_type: str, version: str, content_key: bytes, **qualifiers):
|
|
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/version', inputs={
|
|
'version': version,
|
|
'content_key': b64encode(content_key),
|
|
**qualifiers
|
|
})
|
|
return outputs['created']
|
|
|
|
async def append_to_channel(self, release_type: str, channel: str, version: str):
|
|
outputs = await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/channel', inputs={
|
|
'channel': channel,
|
|
'version': version,
|
|
})
|
|
return outputs['published']
|
|
|
|
async def refresh_routes(self, release_type: str):
|
|
await self._api_client.call('PUT', PrivateReleaseApi.BASE_URL + '/' + release_type + '/refresh-routes')
|