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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
#!/usr/bin/python
from __future__ import unicode_literals
import os
import sys
import shutil
import tempfile
import xml.etree.ElementTree as ET # Python 2.5
from layman.constants import MOUNT_TYPES
from layman.compatibility import fileopen
from layman.overlays.source import OverlaySource, require_supported
from layman.utils import path
from layman.version import VERSION
from sslfetch.connections import Connector
USERAGENT = "Layman-" + VERSION
class ArchiveOverlay(OverlaySource):
type = 'Archive'
type_key = 'archive'
def __init__(self, parent, config, _location, ignore = 0):
super(ArchiveOverlay, self).__init__(parent,
config, _location, ignore)
self.clean_archive = config['clean_archive']
self.output = config['output']
self.proxies = config.proxies
self.branch = self.parent.branch
self.mount_me = bool(self.type in MOUNT_TYPES)
def _fetch(self, base, archive_url, dest_dir):
'''
Fetches overlay source archive.
@params base: string of directory base for installed overlays.
@params archive_url: string of URL where archive is located.
@params dest_dir: string of destination of extracted archive.
@rtype tuple (str of package location, bool to clean_archive)
'''
ext = self.get_extension()
if 'file://' not in archive_url:
# set up ssl-fetch output map
connector_output = {
'info': self.output.debug,
'error': self.output.error,
'kwargs-info': {'level': 5},
'kwargs-debug': {'level': 2},
'kwargs-error': {'level': None},
}
fetcher = Connector(connector_output, self.proxies, USERAGENT)
success, archive, timestamp = fetcher.fetch_content(archive_url)
pkg = path([base, self.parent.name + ext])
try:
with fileopen(pkg, 'w+b') as out_file:
out_file.write(archive)
except Exception as error:
raise Exception('Failed to store archive package in '\
'%(pkg)s\nError was: %(error)s'\
% ({'pkg': pkg, 'error': error}))
else:
self.clean_archive = False
pkg = archive_url.replace('file://', '')
return pkg
def _add_unchecked(self, base):
def try_to_wipe(folder):
if not os.path.exists(folder):
return
try:
self.output.info('Deleting directory %(dir)s'\
% ({'dir': folder}), 2)
shutil.rmtree(folder)
except Exception as error:
raise Exception('Failed to remove unneccessary archive '\
'structure %(dir)s\nError was: %(err)s'\
% ({'dir': folder, 'err': error}))
final_path = path([base, self.parent.name])
try:
if not self.mount_me:
temp_path = tempfile.mkdtemp(dir=base)
else:
temp_path = final_path
if not os.path.exists(temp_path):
os.mkdir(temp_path)
else:
if os.path.ismount(temp_path):
self.config['mounts'].umount([self.parent.name],
dest=temp_path,
sync=True)
pkg = self._fetch(base=base, archive_url=self.src,
dest_dir=temp_path)
result = self.post_fetch(pkg, temp_path)
if self.clean_archive:
os.unlink(pkg)
except Exception as error:
try_to_wipe(temp_path)
raise error
if result == 0 and not self.mount_me:
if self.branch:
source = temp_path + os.path.sep + self.branch
else:
source = temp_path
if os.path.exists(source):
if os.path.exists(final_path):
self.delete(base)
try:
os.rename(source, final_path)
except Exception as error:
raise Exception('Failed to rename archive subdirectory '\
'%(src)s to %(path)s\nError was: %(err)s'\
% ({'src': source, 'path': final_path, 'err': error}))
os.chmod(final_path, 0o755)
else:
raise Exception('The given path (branch setting in the xml)\n'\
' %(src)s does not exist in this archive package!'\
% ({'src': source}))
if not self.mount_me:
try_to_wipe(temp_path)
return result
def add(self, base):
'''
Add overlay.
@params base: string location where overlays are installed.
@rtype bool
'''
if not self.supported():
return 1
target = path([base, self.parent.name])
if os.path.exists(target):
raise Exception('Directory %(dir)s already exists. Will not '\
'overwrite its contents!' % ({'dir': target}))
return self.postsync(
self._add_unchecked(base),
cwd=target)
def sync(self, base):
'''
Sync overlay.
@params base: string location where overlays are installed.
@rtype bool
'''
if not self.supported():
return 1
target = path([base, self.parent.name])
return self.postsync(
self._add_unchecked(base),
cwd=target)
def supported(self):
'''
Determines if overlay type is supported.
@rtype bool
'''
return self.is_supported()
|