-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathconfig_handler.py
More file actions
130 lines (107 loc) · 4.46 KB
/
config_handler.py
File metadata and controls
130 lines (107 loc) · 4.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""Configuration file handling utilities."""
import os
import logging
import re
from typing import Dict, Any, Optional
import constants
logger = logging.getLogger(__name__)
def modify_config_file(config_path: str, setting: str, new_value: str) -> bool:
"""
Modifies a specific setting in the bluestacks.conf file.
"""
if not os.path.isfile(config_path):
logger.error(f"Config file not found: {config_path}")
raise FileNotFoundError(f"Config file not found: {config_path}")
logger.debug(
f"Attempting to modify setting '{setting}' to '{new_value}' in {config_path}"
)
new_line_content = f'{setting}="{new_value}"'
lines = []
try:
with open(config_path, "r", encoding="utf-8") as file:
lines = file.readlines()
except Exception as e:
logger.exception(f"Error reading configuration file {config_path}")
raise IOError(f"Error reading configuration file {config_path}: {e}") from e
updated_lines = []
setting_found_and_updated = False
changed = False
setting_pattern = re.compile(r"^\s*" + re.escape(setting) + r"\s*=")
for line in lines:
stripped_line = line.strip()
if setting_pattern.match(stripped_line):
if stripped_line != new_line_content:
logger.info(
f"Updating setting '{setting}'. Old line: '{stripped_line}', New line: '{new_line_content}'"
)
updated_lines.append(new_line_content + "\n")
changed = True
else:
updated_lines.append(line)
setting_found_and_updated = True
else:
updated_lines.append(line)
if not setting_found_and_updated:
logger.info(
f"Setting '{setting}' not found. Appending with value '{new_value}'."
)
if updated_lines and not updated_lines[-1].endswith("\n"):
updated_lines[-1] += "\n"
updated_lines.append(new_line_content + "\n")
changed = True
if changed:
try:
with open(config_path, "w", encoding="utf-8") as file:
file.writelines(updated_lines)
logger.debug(f"Successfully wrote changes to {config_path}")
except Exception as e:
logger.exception(f"Error writing updated configuration file {config_path}")
raise IOError(
f"Error writing updated configuration file {config_path}: {e}"
) from e
return changed
def get_complete_root_statuses(config_path: str) -> Dict[str, Any]:
"""
Reads a config file and returns all instance root statuses AND the global rooting feature status.
Args:
config_path: Path to the bluestacks.conf file.
Returns:
A dictionary like: {'global_status': bool, 'instance_statuses': {name: bool}}
"""
instance_statuses: Dict[str, bool] = {}
global_status: bool = False
if not os.path.isfile(config_path):
logger.warning(
f"Config file not found for reading root statuses: {config_path}"
)
return {"global_status": False, "instance_statuses": {}}
# FIX: Regex for both instance-specific and global root keys
instance_pattern = re.compile(
r"^"
+ re.escape(constants.INSTANCE_PREFIX)
+ r"([^.]+)"
+ re.escape(constants.ENABLE_ROOT_KEY)
+ r'\s*=\s*"([^"]*)"',
re.IGNORECASE,
)
global_pattern = re.compile(
r"^" + re.escape(constants.FEATURE_ROOTING_KEY) + r'\s*=\s*"1"', re.IGNORECASE
)
try:
with open(config_path, "r", encoding="utf-8") as file:
for line in file:
stripped_line = line.strip()
# Check for global key
if global_pattern.match(stripped_line):
global_status = True
logger.debug(f"Found global root status in {config_path}: Enabled")
# Check for instance key
match = instance_pattern.match(stripped_line)
if match:
instance_name, value = match.group(1), match.group(2)
is_enabled = value == "1"
instance_statuses[instance_name] = is_enabled
except Exception:
logger.exception(f"Error reading config file {config_path} for root statuses.")
return {"global_status": False, "instance_statuses": {}}
return {"global_status": global_status, "instance_statuses": instance_statuses}