1
|
1 |
|
from plugin.core.environment import Environment |
2
|
1 |
|
from plugin.core.libraries.constants import CONTENTS_PATH |
3
|
1 |
|
from plugin.core.libraries.helpers import StorageHelper, SystemHelper |
4
|
|
|
|
5
|
1 |
|
import filecmp |
6
|
1 |
|
import logging |
7
|
1 |
|
import os |
8
|
|
|
|
9
|
1 |
|
log = logging.getLogger(__name__) |
10
|
|
|
|
11
|
|
|
|
12
|
1 |
|
class CacheManager(object): |
13
|
1 |
|
@classmethod |
14
|
|
|
def sync(cls): |
15
|
|
|
"""Synchronize native libraries cache, adding/updating/removing items to match bundled libraries. |
16
|
|
|
|
17
|
|
|
:rtype: str |
18
|
|
|
""" |
19
|
|
|
|
20
|
|
|
source, destination = cls.get_paths() |
|
|
|
|
21
|
|
|
|
22
|
|
|
# Compare directories, discover tasks |
23
|
|
|
changes = filecmp.dircmp(source, destination) |
24
|
|
|
tasks = cls.discover(changes) |
25
|
|
|
|
26
|
|
|
# Execute tasks |
27
|
|
|
if tasks and not cls.execute(source, destination, tasks): |
28
|
|
|
return None |
29
|
|
|
|
30
|
|
|
return os.path.join(Environment.path.plugin_data, 'Libraries') |
31
|
|
|
|
32
|
1 |
|
@classmethod |
33
|
1 |
|
def discover(cls, changes, base_path='', tasks=None): |
34
|
|
|
""""Discover actions required to update the cache. |
35
|
|
|
|
36
|
|
|
:param changes: Changes between bundle + cache directories |
37
|
|
|
:type changes: filecmp.dircmp |
38
|
|
|
|
39
|
|
|
:param base_path: Current directory of changes |
40
|
|
|
:type base_path: str |
41
|
|
|
|
42
|
|
|
:param tasks: Current tasks |
43
|
|
|
:type tasks: list or None |
44
|
|
|
|
45
|
|
|
:rtype: list |
46
|
|
|
""" |
47
|
|
|
if tasks is None: |
48
|
|
|
tasks = [] |
49
|
|
|
|
50
|
|
|
def process(action, names): |
51
|
|
|
for name in names: |
52
|
|
|
tasks.append((action, os.path.join(base_path, name))) |
53
|
|
|
|
54
|
|
|
# Create tasks from `changes` |
55
|
|
|
process('add', changes.left_only) |
56
|
|
|
process('delete', changes.right_only) |
57
|
|
|
process('update', changes.diff_files) |
58
|
|
|
|
59
|
|
|
# Process sub directories |
60
|
|
|
for name, child in changes.subdirs.items(): |
61
|
|
|
cls.discover(child, os.path.join(base_path, name), tasks) |
62
|
|
|
|
63
|
|
|
# Tasks retrieved |
64
|
|
|
return tasks |
65
|
|
|
|
66
|
1 |
|
@classmethod |
67
|
|
|
def execute(cls, source, destination, tasks): |
68
|
|
|
"""Execute tasks on directories |
69
|
|
|
|
70
|
|
|
:param source: Native libraries source directory |
71
|
|
|
:type source: str |
72
|
|
|
|
73
|
|
|
:param destination: Native libraries cache directory |
74
|
|
|
:type destination: str |
75
|
|
|
|
76
|
|
|
:param tasks: Tasks to execute |
77
|
|
|
:type tasks: list |
78
|
|
|
|
79
|
|
|
:rtype: bool |
80
|
|
|
""" |
81
|
|
|
success = True |
82
|
|
|
|
83
|
|
|
for action, path in tasks: |
84
|
|
|
if action in ['add', 'update']: |
85
|
|
|
action_success = StorageHelper.copy(os.path.join(source, path), os.path.join(destination, path)) |
86
|
|
|
elif action == 'delete': |
87
|
|
|
action_success = StorageHelper.delete(os.path.join(destination, path)) |
88
|
|
|
else: |
89
|
|
|
log.warn('Unknown task: %r - %r', action, path) |
90
|
|
|
action_success = False |
91
|
|
|
|
92
|
|
|
if not action_success: |
93
|
|
|
success = False |
94
|
|
|
|
95
|
|
|
return success |
96
|
|
|
|
97
|
1 |
|
@staticmethod |
98
|
|
|
def get_paths(): |
99
|
|
|
"""Retrieve system-specific native libraries source + destination path |
100
|
|
|
|
101
|
|
|
:rtype: (str, str) |
102
|
|
|
""" |
103
|
|
|
# Retrieve system details |
104
|
|
|
system = SystemHelper.name() |
105
|
|
|
architecture = SystemHelper.architecture() |
106
|
|
|
|
107
|
|
|
if not architecture: |
108
|
|
|
return |
109
|
|
|
|
110
|
|
|
# Build source path |
111
|
|
|
source = os.path.join(CONTENTS_PATH, 'Libraries', system, architecture) |
112
|
|
|
|
113
|
|
|
# Ensure `source` directory exists |
114
|
|
|
if not os.path.exists(source): |
115
|
|
|
log.error('Unable to find native libraries for platform (name: %r, architecture: %r)', system, architecture) |
116
|
|
|
return None |
117
|
|
|
|
118
|
|
|
# Build path for native dependencies |
119
|
|
|
destination = os.path.join(Environment.path.plugin_data, 'Libraries', system, architecture) |
120
|
|
|
|
121
|
|
|
# Ensure `destination` directory has been created |
122
|
|
|
StorageHelper.create_directories(destination) |
123
|
|
|
|
124
|
|
|
return source, destination |
125
|
|
|
|