Repository: Senth/minecraft-mod-manager

Issue:
Mod is already installed - Can't reinstall mod after manually deleting it
When you install a mod via the mod manager and then delete it from the folder and try to install it again via the manager it says the mod is already installed.

I had thinked about an uninstall command line to delete the mod from the database as a possible solution.

Comments:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d15922..b16295c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [1.0.4] - ???
+
+### Fixed
+
+- Reinstalling a mod after deleting it manually #33
+
 ## [1.0.3] - 2021-04-25
 
 ### Fixed
diff --git a/minecraft_mod_manager/gateways/sqlite.py b/minecraft_mod_manager/gateways/sqlite.py
index 7305020..04d8c82 100644
--- a/minecraft_mod_manager/gateways/sqlite.py
+++ b/minecraft_mod_manager/gateways/sqlite.py
@@ -2,12 +2,11 @@ import sqlite3
 from os import path
 from typing import Dict, List
 
-from ..gateways.sqlite_upgrader import SqliteUpgrader
-
 from ..config import config
 from ..core.entities.mod import Mod
 from ..core.entities.sites import Sites
 from ..core.errors.mod_already_exists import ModAlreadyExists
+from ..gateways.sqlite_upgrader import SqliteUpgrader
 from ..utils.logger import LogColors, Logger
 from .sqlite_upgrader import _Column
 
@@ -105,15 +104,18 @@ class Sqlite:
             )
         return mods
 
-    def exists(self, id: str) -> bool:
-        self._cursor.execute(f"SELECT 1 FROM mod WHERE {_Column.c_id}=?", [id])
+    def exists(self, id: str, filter_active: bool = True) -> bool:
+        extra_filter = ""
+        if filter_active:
+            extra_filter = f"AND {_Column.c_active}=1"
+        self._cursor.execute(f"SELECT 1 FROM mod WHERE {_Column.c_id}=? {extra_filter}", [id])
         return bool(self._cursor.fetchone())
 
     def update_mod(self, mod: Mod):
         if config.pretend:
             return
 
-        if self.exists(mod.id):
+        if self.exists(mod.id, filter_active=False):
             self._connection.execute(
                 "UPDATE mod SET "
                 + f"{_Column.c_site}=?, "


Test patch:
diff --git a/minecraft_mod_manager/gateways/sqlite_test.py b/minecraft_mod_manager/gateways/sqlite_test.py
index f8f3325..28ec7af 100644
--- a/minecraft_mod_manager/gateways/sqlite_test.py
+++ b/minecraft_mod_manager/gateways/sqlite_test.py
@@ -3,11 +3,11 @@ import sqlite3
 from typing import Any, List, Tuple, Union
 
 import pytest
-from ..core.entities.sites import Sites
-from ..core.errors.mod_already_exists import ModAlreadyExists
 
 from ..config import config
 from ..core.entities.mod import Mod
+from ..core.entities.sites import Sites
+from ..core.errors.mod_already_exists import ModAlreadyExists
 from ..gateways.sqlite import Sqlite
 
 db_file = f".{config.app_name}.db"
@@ -148,6 +148,30 @@ def test_exists_when_exists(mod: Mod, sqlite: Sqlite, db: sqlite3.Connection):
     assert result
 
 
+def test_does_not_exist_when_set_as_inactive(mod: Mod, sqlite: Sqlite, db: sqlite3.Connection):
+    db.execute(
+        "INSERT INTO mod (id, site, site_id, site_slug, upload_time, active) VALUES (?, ?, ?, ?, ?, 0)",
+        [mod.id, mod.site.value, mod.site_id, mod.site_slug, mod.upload_time],
+    )
+    db.commit()
+
+    result = sqlite.exists(mod.id)
+
+    assert not result
+
+
+def test_exists_when_set_as_inactive_but_not_filtering(mod: Mod, sqlite: Sqlite, db: sqlite3.Connection):
+    db.execute(
+        "INSERT INTO mod (id, site, site_id, site_slug, upload_time, active) VALUES (?, ?, ?, ?, ?, 0)",
+        [mod.id, mod.site.value, mod.site_id, mod.site_slug, mod.upload_time],
+    )
+    db.commit()
+
+    result = sqlite.exists(mod.id, filter_active=False)
+
+    assert result
+
+
 def test_exists_when_doesnt_exists(sqlite: Sqlite):
     result = sqlite.exists("id")