|
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
|
|
|
|