| 240 | |
| 241 | |
| 242 | class CacheConfig: |
| 243 | def __init__(self, repository, path=None): |
| 244 | self.repository = repository |
| 245 | self.path = cache_dir(repository, path) |
| 246 | logger.debug("Using %s as cache", self.path) |
| 247 | self.config_path = self.path / "config" |
| 248 | |
| 249 | def __enter__(self): |
| 250 | self.open() |
| 251 | return self |
| 252 | |
| 253 | def __exit__(self, exc_type, exc_val, exc_tb): |
| 254 | self.close() |
| 255 | |
| 256 | def exists(self): |
| 257 | return self.config_path.exists() |
| 258 | |
| 259 | def create(self): |
| 260 | assert not self.exists() |
| 261 | config = configparser.ConfigParser(interpolation=None) |
| 262 | config.add_section("cache") |
| 263 | config.set("cache", "version", "1") |
| 264 | config.set("cache", "repository", self.repository.id_str) |
| 265 | config.set("cache", "manifest", "") |
| 266 | config.add_section("integrity") |
| 267 | config.set("integrity", "manifest", "") |
| 268 | with SaveFile(self.config_path) as fd: |
| 269 | config.write(fd) |
| 270 | |
| 271 | def open(self): |
| 272 | self.load() |
| 273 | |
| 274 | def load(self): |
| 275 | self._config = configparser.ConfigParser(interpolation=None) |
| 276 | with self.config_path.open() as fd: |
| 277 | self._config.read_file(fd) |
| 278 | self._check_upgrade(self.config_path) |
| 279 | self.id = self._config.get("cache", "repository") |
| 280 | self.manifest_id = hex_to_bin(self._config.get("cache", "manifest")) |
| 281 | self.ignored_features = set(parse_stringified_list(self._config.get("cache", "ignored_features", fallback=""))) |
| 282 | self.mandatory_features = set( |
| 283 | parse_stringified_list(self._config.get("cache", "mandatory_features", fallback="")) |
| 284 | ) |
| 285 | try: |
| 286 | self.integrity = dict(self._config.items("integrity")) |
| 287 | if self._config.get("cache", "manifest") != self.integrity.pop("manifest"): |
| 288 | # The cache config file is updated (parsed with ConfigParser, the state of the ConfigParser |
| 289 | # is modified and then written out.), not re-created. |
| 290 | # Thus, older versions will leave our [integrity] section alone, making the section's data invalid. |
| 291 | # Therefore, we also add the manifest ID to this section and |
| 292 | # can discern whether an older version interfered by comparing the manifest IDs of this section |
| 293 | # and the main [cache] section. |
| 294 | self.integrity = {} |
| 295 | logger.warning("Cache integrity data not available: old Borg version modified the cache.") |
| 296 | except configparser.NoSectionError: |
| 297 | logger.debug("Cache integrity: No integrity data found (files, chunks). Cache is from old version.") |
| 298 | self.integrity = {} |
| 299 | |