2023-05-01 20:00:32 +09:00
|
|
|
import configparser
|
|
|
|
import os
|
|
|
|
from typing import Final
|
|
|
|
|
2023-07-19 21:47:47 +09:00
|
|
|
import validators # type: ignore
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
from mdrsclient.exceptions import IllegalArgumentException
|
2023-05-10 14:46:08 +09:00
|
|
|
from mdrsclient.settings import CONFIG_DIRNAME
|
2023-05-23 11:48:09 +09:00
|
|
|
from mdrsclient.utils import FileLock
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
|
|
|
|
class ConfigFile:
|
|
|
|
OPTION_URL: Final[str] = "url"
|
2023-05-10 14:46:08 +09:00
|
|
|
CONFIG_FILENAME: Final[str] = "config.ini"
|
2023-05-01 20:00:32 +09:00
|
|
|
remote: str
|
2023-05-10 14:46:08 +09:00
|
|
|
__serial: int
|
|
|
|
__config_dirname: str
|
|
|
|
__config_path: str
|
|
|
|
__config: configparser.ConfigParser
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
def __init__(self, remote: str) -> None:
|
|
|
|
self.remote = remote
|
2023-05-10 14:46:08 +09:00
|
|
|
self.__serial = -1
|
|
|
|
self.__config_dirname = CONFIG_DIRNAME
|
|
|
|
self.__config_path = os.path.join(CONFIG_DIRNAME, self.CONFIG_FILENAME)
|
|
|
|
self.__config = configparser.ConfigParser()
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
def list(self) -> list[tuple[str, str]]:
|
|
|
|
ret: list[tuple[str, str]] = []
|
|
|
|
self.__load()
|
2023-05-10 14:46:08 +09:00
|
|
|
for remote in self.__config.sections():
|
|
|
|
url = self.__config.get(remote, self.OPTION_URL)
|
2023-05-01 20:00:32 +09:00
|
|
|
ret.append((remote, url))
|
|
|
|
return ret
|
|
|
|
|
|
|
|
@property
|
|
|
|
def url(self) -> str | None:
|
|
|
|
if not self.__exists(self.remote):
|
|
|
|
return None
|
2023-05-10 14:46:08 +09:00
|
|
|
return self.__config.get(self.remote, self.OPTION_URL)
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
@url.setter
|
|
|
|
def url(self, url: str) -> None:
|
|
|
|
if not validators.url(url): # type: ignore
|
|
|
|
raise IllegalArgumentException("malformed URI sequence")
|
|
|
|
self.__load()
|
2023-05-10 14:46:08 +09:00
|
|
|
if self.__config.has_section(self.remote):
|
|
|
|
self.__config.remove_section(self.remote)
|
|
|
|
self.__config.add_section(self.remote)
|
|
|
|
self.__config.set(self.remote, self.OPTION_URL, url)
|
2023-05-01 20:00:32 +09:00
|
|
|
self.__save()
|
|
|
|
|
|
|
|
@url.deleter
|
|
|
|
def url(self) -> None:
|
|
|
|
if self.__exists(self.remote):
|
2023-05-10 14:46:08 +09:00
|
|
|
self.__config.remove_section(self.remote)
|
2023-05-01 20:00:32 +09:00
|
|
|
self.__save()
|
|
|
|
|
|
|
|
def __exists(self, section: str) -> bool:
|
|
|
|
self.__load()
|
2023-05-10 14:46:08 +09:00
|
|
|
return self.__config.has_option(section, self.OPTION_URL)
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
def __load(self) -> None:
|
2023-05-10 14:46:08 +09:00
|
|
|
if os.path.isfile(self.__config_path):
|
|
|
|
stat = os.stat(self.__config_path)
|
2023-05-01 20:00:32 +09:00
|
|
|
serial = hash(stat)
|
2023-05-10 14:46:08 +09:00
|
|
|
if self.__serial != serial:
|
|
|
|
self.__config.read(self.__config_path, encoding="utf8")
|
|
|
|
self.__serial = serial
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
def __save(self) -> None:
|
|
|
|
self.__ensure_cache_dir()
|
2023-05-10 14:46:08 +09:00
|
|
|
with open(self.__config_path, "w") as f:
|
2023-05-23 11:48:09 +09:00
|
|
|
FileLock.lock(f)
|
2023-05-10 14:46:08 +09:00
|
|
|
self.__config.write(f)
|
2023-05-23 11:48:09 +09:00
|
|
|
FileLock.unlock(f)
|
2023-05-10 14:46:08 +09:00
|
|
|
os.chmod(self.__config_path, 0o600)
|
2023-05-01 20:00:32 +09:00
|
|
|
|
|
|
|
def __ensure_cache_dir(self) -> None:
|
2023-05-10 14:46:08 +09:00
|
|
|
if not os.path.exists(self.__config_dirname):
|
|
|
|
os.makedirs(self.__config_dirname)
|
2023-05-01 20:00:32 +09:00
|
|
|
# ensure directory is secure.
|
2023-05-10 14:46:08 +09:00
|
|
|
os.chmod(self.__config_dirname, 0o700)
|