(store: Store)
| 59 | |
| 60 | |
| 61 | def _gc(store: Store) -> int: |
| 62 | with store.exclusive_lock(), store.connect() as db: |
| 63 | store._create_configs_table(db) |
| 64 | |
| 65 | repos = db.execute('SELECT repo, ref, path FROM repos').fetchall() |
| 66 | all_repos = {(repo, ref): path for repo, ref, path in repos} |
| 67 | unused_repos = set(all_repos) |
| 68 | |
| 69 | configs_rows = db.execute('SELECT path FROM configs').fetchall() |
| 70 | configs = [path for path, in configs_rows] |
| 71 | |
| 72 | dead_configs = [] |
| 73 | for config_path in configs: |
| 74 | try: |
| 75 | config = load_config(config_path) |
| 76 | except InvalidConfigError: |
| 77 | dead_configs.append(config_path) |
| 78 | continue |
| 79 | else: |
| 80 | for repo in config['repos']: |
| 81 | _mark_used_repos(store, all_repos, unused_repos, repo) |
| 82 | |
| 83 | paths = [(path,) for path in dead_configs] |
| 84 | db.executemany('DELETE FROM configs WHERE path = ?', paths) |
| 85 | |
| 86 | db.executemany( |
| 87 | 'DELETE FROM repos WHERE repo = ? and ref = ?', |
| 88 | sorted(unused_repos), |
| 89 | ) |
| 90 | for k in unused_repos: |
| 91 | rmtree(all_repos[k]) |
| 92 | |
| 93 | return len(unused_repos) |
| 94 | |
| 95 | |
| 96 | def gc(store: Store) -> int: |
no test coverage detected