Je kunt niet meer dan 25 onderwerpen selecteren Onderwerpen moeten beginnen met een letter of nummer, kunnen streepjes bevatten ('-') en kunnen maximaal 35 tekens lang zijn.
calculate-utils-3-update/pym/update/profile.py

260 regels
8.4 KiB

Dit bestand bevat dubbelzinnige Unicode karakters!

Dit bestand bevat dubbelzinnige Unicode karakters die verward kunnen worden met andere karakters in uw huidige taal. Als je het opzettelijk en legitiem gebruikt, kun je deze waarschuwing veilig negeren. Gebruik de Escape knop om deze karakters te markeren.

# -*- coding: utf-8 -*-
# Copyright 2014-2016 Mir Calculate. http://www.calculate-linux.org
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from os import path
import shutil
from calculate.lib.utils.files import (listDirectory, readFile, readLinesFile,
makeDirectory, removeDir)
from calculate.lib.utils.git import Git
from update import UpdateError
from calculate.lib.cl_lang import setLocalTranslate, _
setLocalTranslate('cl_update3', sys.modules[__name__])
DEFAULT_BRANCH = Git.Reference.Master
class RepositoryStorageInterface(object):
def __iter__(self):
raise StopIteration
def get_profiles(self, url, branch=DEFAULT_BRANCH):
return []
def get_repository(self, url, branch=DEFAULT_BRANCH):
return None
class RepositoryStorage(RepositoryStorageInterface):
directory = '/tmp'
def __init__(self, directory):
self.directory = directory
makeDirectory(directory)
def __iter__(self):
git = Git()
for dn in listDirectory(self.directory, onlyDir=True, fullPath=True):
if git.is_git(dn):
yield ProfileRepository(path.basename(dn), self)
def get_profiles(self, url, branch=DEFAULT_BRANCH):
return []
def get_repository(self, url, branch=DEFAULT_BRANCH):
return None
class ProfileStorage(RepositoryStorage):
def get_profiles(self, url, branch=DEFAULT_BRANCH):
rep = self.get_repository(url, branch)
if rep:
return rep.get_profiles()
return None
def get_repository(self, url, branch=DEFAULT_BRANCH):
return None
class LocalStorage(ProfileStorage):
"""
Локальное хранилище репозиториев, при запросе по урлу смотрит, доступные
репозитории если находит подходящий - возвращает его профили
"""
def get_repository(self, url, branch=DEFAULT_BRANCH):
for rep in self:
if rep.is_like(url, branch):
return rep
class CacheStorage(ProfileStorage):
"""
Хранилище репозиториев, при запросе по урлу смотрит, доступные
репозитории если находит подходящий - возвращает его профили,
если не находит - скачивает и возвращает профили
"""
def get_repository(self, url, branch=DEFAULT_BRANCH):
for rep in self:
if rep.is_like(url, branch):
return rep
else:
return ProfileRepository.clone(url, self, branch)
class RepositoryStorageSet(RepositoryStorageInterface):
"""
Набор хранилищ репозиториев
"""
def __init__(self, *storages):
self.storages = storages
def get_profiles(self, url, branch=DEFAULT_BRANCH):
"""
Получить профили из указанного репозитория
"""
for storage in self.storages:
profiles = storage.get_profiles(url, branch)
if profiles is not None:
return profiles
return None
def __iter__(self):
for storage in self.storages:
for rep in storage:
yield rep
def get_repository(self, url, branch=DEFAULT_BRANCH):
"""
Получить репозиторий по параметрам
"""
for rep in self:
if rep.is_like(url, branch):
return rep
return None
def is_local(self, url, branch=DEFAULT_BRANCH):
"""
Проверить является ли репозиторий с указанными параметрами
локальным
"""
rep = self.get_repository(url, branch)
if rep and isinstance(rep.storage, LocalStorage):
return True
return False
def __repr__(self):
return "Repository set"
class Profile(object):
"""
Профиль репозитория
"""
available_arch = ["amd64", "x86"]
def __init__(self, repository, profile, arch):
self.repository = repository
self.profile = profile
self.arch = arch
@property
def path(self):
return path.join(self.repository.directory,"profiles", self.profile)
@classmethod
def from_string(cls, repository, s):
parts = filter(None, s.split())
if len(parts) == 3 and parts[0] in cls.available_arch:
return Profile(repository, parts[1], parts[0])
return None
def __repr__(self):
return "<Profile (%s) %s:%s from %s>" % (self.arch,
self.repository.repo_name,
self.profile,
self.repository.directory)
class ProfileRepository(object):
"""
Репозиторий либо скачивается, либо берется из кэша
"""
def __init__(self, name, storage):
self._storage = storage
self.name = name
@property
def storage(self):
return self._storage
@storage.setter
def storage(self, storage):
if storage.directory != self._storage.directory:
newpath = path.join(storage.directory, self.name)
if self.directory == newpath:
return
try:
if path.exists(newpath):
removeDir(newpath)
shutil.move(self.directory, newpath)
self._storage = storage
except OSError as e:
raise UpdateError(_("Failed to move the profile: %s") %
str(e))
@classmethod
def clone(cls, url, storage, branch=DEFAULT_BRANCH):
name = path.basename(url)
if name.endswith(".git"):
name = name[:-4]
git = Git()
rpath = path.join(storage.directory, name)
if path.exists(rpath):
removeDir(rpath)
git.cloneRepository(url, rpath, branch)
pr = cls(name, storage)
repo_name = pr.repo_name
if name != repo_name:
rpath_new = path.join(storage.directory, repo_name)
if path.exists(rpath_new):
removeDir(rpath_new)
shutil.move(rpath, rpath_new)
pr = cls(repo_name, storage)
return pr
@property
def repo_name(self):
return readFile(path.join(self.directory,
"profiles/repo_name")).strip()
def is_like(self, url, branch=DEFAULT_BRANCH):
if self.url == url and (branch is None or self.branch == branch):
return True
return False
@property
def directory(self):
"""
Получить локальную директорию на данные репозитория
"""
return path.join(self.storage.directory, self.name)
@property
def url(self):
git = Git()
return git.get_url(self.directory, "origin")
@property
def branch(self):
git = Git()
return git.getBranch(self.directory)
def sync(self):
"""
Синхронизировать репозиторий
"""
git = Git()
if not git.pullRepository(self.directory, quiet_error=True):
git.resetRepository(self.directory, to_origin=True)
git.pullRepository(self.directory, quiet_error=True)
def get_profiles(self):
"""
Получить список профилей репозитория
"""
profiles_desc = path.join(self.directory, "profiles/profiles.desc")
return filter(None, (Profile.from_string(self, line)
for line in readLinesFile(profiles_desc)))
def __repr__(self):
return "<ProfileRepository %s url=%s>" % (self.directory, self.url)