pyreposync 0.2.6__py3-none-any.whl → 0.2.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pyreposync/__init__.py CHANGED
@@ -269,6 +269,12 @@ class PyRepoSync:
269
269
  section, "allow_missing_packages", fallback=False
270
270
  ),
271
271
  treeinfo=self.config.get(section, "treeinfo", fallback=".treeinfo"),
272
+ basic_auth_user=self.config.get(
273
+ section, "basic_auth_user", fallback=None
274
+ ),
275
+ basic_auth_pass=self.config.get(
276
+ section, "basic_auth_pass", fallback=None
277
+ ),
272
278
  proxy=self.config.get("main", "proxy", fallback=None),
273
279
  client_cert=self.config.get(section, "sslclientcert", fallback=None),
274
280
  client_key=self.config.get(section, "sslclientkey", fallback=None),
@@ -283,6 +289,12 @@ class PyRepoSync:
283
289
  allow_missing_packages=self.config.getboolean(
284
290
  section, "allow_missing_packages", fallback=False
285
291
  ),
292
+ basic_auth_user=self.config.get(
293
+ section, "basic_auth_user", fallback=None
294
+ ),
295
+ basic_auth_pass=self.config.get(
296
+ section, "basic_auth_pass", fallback=None
297
+ ),
286
298
  proxy=self.config.get(section, "proxy", fallback=None),
287
299
  client_cert=self.config.get(section, "sslclientcert", fallback=None),
288
300
  client_key=self.config.get(section, "sslclientkey", fallback=None),
@@ -291,6 +303,7 @@ class PyRepoSync:
291
303
  components=self.config.get(section, "components").split(),
292
304
  binary_archs=self.config.get(section, "binary_archs").split(),
293
305
  )
306
+ return None
294
307
 
295
308
  def get_sections(self):
296
309
  sections = set()
pyreposync/downloader.py CHANGED
@@ -2,6 +2,7 @@ import hashlib
2
2
  import logging
3
3
  import os
4
4
  import requests
5
+ import requests.auth
5
6
  import requests.exceptions
6
7
  import shutil
7
8
  import tempfile
@@ -11,8 +12,20 @@ from pyreposync.exceptions import OSRepoSyncDownLoadError, OSRepoSyncHashError
11
12
 
12
13
 
13
14
  class Downloader(object):
14
- def __init__(self, proxy=None, client_cert=None, client_key=None, ca_cert=None):
15
+ def __init__(
16
+ self,
17
+ basic_auth_user=None,
18
+ basic_auth_pass=None,
19
+ proxy=None,
20
+ client_cert=None,
21
+ client_key=None,
22
+ ca_cert=None,
23
+ ):
15
24
  self.log = logging.getLogger("application")
25
+ if basic_auth_user and basic_auth_pass:
26
+ self._basic_auth = (basic_auth_user, basic_auth_pass)
27
+ else:
28
+ self._basic_auth = None
16
29
  if proxy:
17
30
  self._proxy = {"http": proxy, "https": proxy}
18
31
  else:
@@ -26,6 +39,10 @@ class Downloader(object):
26
39
  else:
27
40
  self._ca_cert = True
28
41
 
42
+ @property
43
+ def basic_auth(self):
44
+ return self._basic_auth
45
+
29
46
  @property
30
47
  def ca_cert(self):
31
48
  return self._ca_cert
@@ -54,13 +71,11 @@ class Downloader(object):
54
71
 
55
72
  with open(destination, "rb") as dest:
56
73
  hasher.update(dest.read())
57
- self.log.debug(f"expected hash: {hasher.hexdigest()}")
58
- self.log.debug(f"actual hash: {checksum}")
59
74
  if hasher.hexdigest() == checksum:
60
- self.log.debug(f"download valid: {destination}")
75
+ self.log.debug(f"download valid: {destination}, expected hash: {hasher.hexdigest()}, actual hash: {checksum}")
61
76
  else:
62
- self.log.error(f"download invalid: {destination}")
63
- raise OSRepoSyncHashError(f"download invalid: {destination}")
77
+ self.log.error(f"download invalid: {destination} expected hash: {hasher.hexdigest()}, actual hash: {checksum}")
78
+ raise OSRepoSyncHashError(f"download invalid: {destination} expected hash: {hasher.hexdigest()}, actual hash: {checksum}")
64
79
 
65
80
  def get(
66
81
  self,
@@ -71,11 +86,11 @@ class Downloader(object):
71
86
  replace=False,
72
87
  not_found_ok=False,
73
88
  ):
74
- self.log.info(f"downloading: {url}")
75
89
  if not replace:
76
90
  if os.path.isfile(destination):
77
- self.log.info("already there, not downloading")
91
+ self.log.debug(f"{url} already there, not downloading")
78
92
  return
93
+ self.log.info(f"{url} downloading")
79
94
  retries = 10
80
95
  while retries >= 0:
81
96
  try:
@@ -90,7 +105,7 @@ class Downloader(object):
90
105
  pass
91
106
  else:
92
107
  raise
93
- self.log.info(f"done downloading: {url}")
108
+ self.log.info(f"{url} download done")
94
109
  return
95
110
  except requests.exceptions.ConnectionError:
96
111
  self.log.error("could not fetch resource, retry in 10 seconds")
@@ -102,8 +117,8 @@ class Downloader(object):
102
117
  time.sleep(10)
103
118
  except OSRepoSyncDownLoadError:
104
119
  break
105
- self.log.error(f"could not download: {url}")
106
- raise OSRepoSyncDownLoadError(f"could not download: {url}")
120
+ self.log.error(f"{url} could not download")
121
+ raise OSRepoSyncDownLoadError(f"{url} could not download")
107
122
 
108
123
  def create_dir(self, destination):
109
124
  if not os.path.isdir(os.path.dirname(destination)):
@@ -123,7 +138,12 @@ class Downloader(object):
123
138
  ):
124
139
  self.create_dir(destination)
125
140
  r = requests.get(
126
- url, stream=True, proxies=self.proxy, cert=self.cert, verify=self.ca_cert
141
+ url,
142
+ auth=self.basic_auth,
143
+ stream=True,
144
+ proxies=self.proxy,
145
+ cert=self.cert,
146
+ verify=self.ca_cert,
127
147
  )
128
148
  if r.status_code == 200:
129
149
  with open(destination, "wb", 0) as dst:
pyreposync/sync_deb822.py CHANGED
@@ -1,8 +1,11 @@
1
1
  from shutil import copyfile
2
+ import threading
2
3
 
3
4
  import gzip
5
+ import lzma
4
6
  import os
5
7
 
8
+ from pyreposync import OSRepoSyncException
6
9
  from pyreposync.sync_generic import SyncGeneric
7
10
 
8
11
 
@@ -17,6 +20,8 @@ class SyncDeb822(SyncGeneric):
17
20
  components,
18
21
  binary_archs,
19
22
  allow_missing_packages,
23
+ basic_auth_user=None,
24
+ basic_auth_pass=None,
20
25
  proxy=None,
21
26
  client_cert=None,
22
27
  client_key=None,
@@ -28,6 +33,8 @@ class SyncDeb822(SyncGeneric):
28
33
  reponame=reponame,
29
34
  date=date,
30
35
  allow_missing_packages=allow_missing_packages,
36
+ basic_auth_user=basic_auth_user,
37
+ basic_auth_pass=basic_auth_pass,
31
38
  proxy=proxy,
32
39
  client_cert=client_cert,
33
40
  client_key=client_key,
@@ -51,15 +58,34 @@ class SyncDeb822(SyncGeneric):
51
58
  return self._components
52
59
 
53
60
  def _snap(self):
61
+ jobs = []
54
62
  for suite in self.suites:
55
- self.snap_suites(suite=suite)
63
+ job = threading.Thread(
64
+ name=f"{threading.current_thread().name}_{suite}",
65
+ target=self.snap_suites,
66
+ kwargs={"suite": suite},
67
+ )
68
+ job.start()
69
+ jobs.append(job)
70
+ for job in jobs:
71
+ job.join()
56
72
 
57
73
  def snap_suites(self, suite):
58
74
  self.log.info(f"creating snapshot for suite {suite}")
59
75
  self.snap_release(suite=suite)
60
76
  self.snap_release_files(suite=suite)
61
- for arch in self.binary_archs:
62
- self.snap_package_binary_files(suite=suite, arch=arch)
77
+ jobs = []
78
+ for component in self.components:
79
+ for arch in self.binary_archs:
80
+ job = threading.Thread(
81
+ name=f"{threading.current_thread().name}_{component}_{arch}",
82
+ target=self.snap_package_binary_files,
83
+ kwargs={"suite": suite, "component": component, "arch": arch},
84
+ )
85
+ job.start()
86
+ jobs.append(job)
87
+ for job in jobs:
88
+ job.join()
63
89
  self.log.info(f"creating snapshot for suite {suite}, done")
64
90
 
65
91
  def snap_release(self, suite):
@@ -95,11 +121,11 @@ class SyncDeb822(SyncGeneric):
95
121
  pass
96
122
  self.log.info(f"creating snapshot for suite {suite} release files, done")
97
123
 
98
- def snap_package_binary_files(self, suite, arch):
124
+ def snap_package_binary_files(self, suite, component, arch):
99
125
  self.log.info(
100
- f"creating snapshot for suite {suite} arch {arch} package binary files"
126
+ f"creating snapshot for suite {suite} component {component} arch {arch} package binary files"
101
127
  )
102
- packages = self.binary_files_sha256(suite=suite, component="main", arch=arch)
128
+ packages = self.binary_files_sha256(suite=suite, component=component, arch=arch)
103
129
  src_path = f"{self.destination}/sync/{self.reponame}"
104
130
  dst_path = f"{self.destination}/snap/{self.reponame}/{self.date}"
105
131
  for filename, sha256_dict in packages.items():
@@ -116,16 +142,35 @@ class SyncDeb822(SyncGeneric):
116
142
 
117
143
  def sync(self):
118
144
  self.log.info("starting thread")
145
+ jobs = []
119
146
  for suite in self.suites:
120
- self.sync_suites(suite=suite)
147
+ job = threading.Thread(
148
+ name=f"{threading.current_thread().name}_{suite}",
149
+ target=self.sync_suites,
150
+ kwargs={"suite": suite},
151
+ )
152
+ job.start()
153
+ jobs.append(job)
154
+ for job in jobs:
155
+ job.join()
121
156
  self.log.info("shutdown thread complete")
122
157
 
123
158
  def sync_suites(self, suite):
124
159
  self.log.info(f"syncing suite {suite}")
125
160
  self.sync_release(suite=suite)
126
161
  self.sync_release_files(suite=suite)
127
- for arch in self.binary_archs:
128
- self.sync_package_binary_files(suite=suite, arch=arch)
162
+ jobs = []
163
+ for component in self.components:
164
+ for arch in self.binary_archs:
165
+ job = threading.Thread(
166
+ name=f"{threading.current_thread().name}_{component}_{arch}",
167
+ target=self.sync_package_binary_files,
168
+ kwargs={"suite": suite, "component": component, "arch": arch},
169
+ )
170
+ job.start()
171
+ jobs.append(job)
172
+ for job in jobs:
173
+ job.join()
129
174
  self.log.info(f"syncing suite {suite}, done")
130
175
 
131
176
  def sync_release(self, suite):
@@ -142,9 +187,9 @@ class SyncDeb822(SyncGeneric):
142
187
  )
143
188
  self.log.info(f"syncing suite {suite} release files, done")
144
189
 
145
- def sync_package_binary_files(self, suite, arch):
190
+ def sync_package_binary_files(self, suite, component, arch):
146
191
  self.log.info(f"syncing suite {suite} arch {arch} package binary files")
147
- packages = self.binary_files_sha256(suite=suite, component="main", arch=arch)
192
+ packages = self.binary_files_sha256(suite=suite, component=component, arch=arch)
148
193
  base_path = f"{self.destination}/sync/{self.reponame}"
149
194
  base_url = f"{self.base_url}"
150
195
  for filename, sha256_dict in packages.items():
@@ -158,12 +203,26 @@ class SyncDeb822(SyncGeneric):
158
203
  self.log.info(f"syncing suite {suite} arch {arch} package binary files, done")
159
204
 
160
205
  def binary_files_sha256(self, suite, component, arch):
161
- packages_gz_file = f"{self.destination}/sync/{self.reponame}/dists/{suite}/{component}/binary-{arch}/Packages.gz"
206
+ packages_file = f"{self.destination}/sync/{self.reponame}/dists/{suite}/{component}/binary-{arch}/Packages."
207
+ if os.path.isfile(f"{packages_file}gz"):
208
+ comp = gzip
209
+ packages_file += "gz"
210
+ elif os.path.isfile(f"{packages_file}xz"):
211
+ comp = lzma
212
+ packages_file += "xz"
213
+ else:
214
+ self.log.error(
215
+ f"no Packages.gz or Packages.xz file found for suite {suite}, component {component}, arch {arch}"
216
+ )
217
+ raise OSRepoSyncException(
218
+ f"no Packages.gz or Packages.xz file found for suite {suite}, component {component}, arch {arch}"
219
+ )
220
+
162
221
  packages = dict()
163
222
  sha256 = None
164
223
  filename = None
165
224
  size = None
166
- with gzip.open(packages_gz_file, "rb") as source:
225
+ with comp.open(packages_file, "rb") as source:
167
226
  for line in source:
168
227
  line = line.decode("utf-8")
169
228
  if line.startswith("SHA256: "):
@@ -14,6 +14,8 @@ class SyncGeneric:
14
14
  reponame,
15
15
  date,
16
16
  allow_missing_packages,
17
+ basic_auth_user=None,
18
+ basic_auth_pass=None,
17
19
  proxy=None,
18
20
  client_cert=None,
19
21
  client_key=None,
@@ -25,7 +27,12 @@ class SyncGeneric:
25
27
  self._destination = destination
26
28
  self._reponame = reponame
27
29
  self.downloader = Downloader(
28
- proxy=proxy, client_cert=client_cert, client_key=client_key, ca_cert=ca_cert
30
+ basic_auth_user=basic_auth_user,
31
+ basic_auth_pass=basic_auth_pass,
32
+ proxy=proxy,
33
+ client_cert=client_cert,
34
+ client_key=client_key,
35
+ ca_cert=ca_cert,
29
36
  )
30
37
  self.log = logging.getLogger("application")
31
38
 
pyreposync/sync_rpm.py CHANGED
@@ -24,6 +24,8 @@ class SyncRPM(SyncGeneric):
24
24
  date,
25
25
  treeinfo,
26
26
  allow_missing_packages,
27
+ basic_auth_user=None,
28
+ basic_auth_pass=None,
27
29
  proxy=None,
28
30
  client_cert=None,
29
31
  client_key=None,
@@ -35,6 +37,8 @@ class SyncRPM(SyncGeneric):
35
37
  reponame=reponame,
36
38
  date=date,
37
39
  allow_missing_packages=allow_missing_packages,
40
+ basic_auth_user=basic_auth_user,
41
+ basic_auth_pass=basic_auth_pass,
38
42
  proxy=proxy,
39
43
  client_cert=client_cert,
40
44
  client_key=client_key,
@@ -248,14 +252,15 @@ class SyncRPM(SyncGeneric):
248
252
  def snap_treeinfo(self):
249
253
  self.log.info("copy treeinfo")
250
254
  try:
251
- dst = f"{self.destination}/snap/{self.reponame}/{self.destination}/{self.treeinfo}"
255
+ dst = f"{self.destination}/snap/{self.reponame}/{self.date}/{self.treeinfo}"
252
256
  src = f"{self.destination}/sync/{self.reponame}/{self.treeinfo}"
253
257
  copyfile(src, dst)
254
258
  except (OSError, FileNotFoundError) as err:
255
259
  self.log.error(f"could not copy {self.treeinfo}: {err}")
260
+ self.log.error(dst)
256
261
  for location, hash_algo, hash_sum in self.treeinfo_files():
257
262
  dst = (
258
- f"{self.destination}/snap/{self.reponame}/{self.destination}/{location}"
263
+ f"{self.destination}/snap/{self.reponame}/{self.date}/{location}"
259
264
  )
260
265
  src = f"{self.destination}/sync/{self.reponame}/{location}"
261
266
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreposync
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: rpm and deb822 repository sync tool
5
5
  Project-URL: Source, https://github.com/schlitzered/pyreposync
6
6
  Author-email: "Stephan.Schultchen" <sschultchen@gmail.com>
@@ -0,0 +1,11 @@
1
+ pyreposync/__init__.py,sha256=fHirsBBkEk806RJwVKQZHgujQZRk13YnokX-8rp_QJE,17117
2
+ pyreposync/downloader.py,sha256=rEv9lOg2X1VwCtADO63-yceZAZCeSJOBIGbyRsEnKQU,5275
3
+ pyreposync/exceptions.py,sha256=IlnvhNaffQQ6geOgrjCciNFVbFpNcycH4ijSuMTbrGA,169
4
+ pyreposync/sync_deb822.py,sha256=7Cuzg-1pC8WDiFTxw-qH26VsfzOEY9IxfZztGfLkdKg,10513
5
+ pyreposync/sync_generic.py,sha256=qe-ERp8O2kCnhOuToSZWhdQzGY7aYb7G7nUxuKD3lxY,5880
6
+ pyreposync/sync_rpm.py,sha256=bl1mVX8LZt5AF33o-oVsmaNwzC9teLN-quQMkQrwyUk,11781
7
+ pyreposync-0.2.8.dist-info/METADATA,sha256=4ZJYmZtU02e0YaE1-awb39qUPIwAqKwl2fdhiyGfimY,1591
8
+ pyreposync-0.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ pyreposync-0.2.8.dist-info/entry_points.txt,sha256=9LsBDWOF3O6_3ONP3Lc-4v1MTt5ay0Xv-TMcFbOIt2s,47
10
+ pyreposync-0.2.8.dist-info/licenses/LICENSE.txt,sha256=lwnJoIo7uwc0h6y6gC_RYqJkvjplViV3Ad6u7pQM4Bw,1084
11
+ pyreposync-0.2.8.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- pyreposync/__init__.py,sha256=hhsb3ZqssxKAcSZ_rEiG_2XjgbRK1SveMtL_sI9pMnI,16577
2
- pyreposync/downloader.py,sha256=828bIMCctd1X6I1w91-XHytQ1M5fmxkEw0YDKd5nvAY,4764
3
- pyreposync/exceptions.py,sha256=IlnvhNaffQQ6geOgrjCciNFVbFpNcycH4ijSuMTbrGA,169
4
- pyreposync/sync_deb822.py,sha256=XkIZfYfgshYFwdk1oL8TsysUge2_6iPiz5zOmKNaZRk,8367
5
- pyreposync/sync_generic.py,sha256=wN5hPcIacvQiMQoajcf7WSbiBGqxI86CYwfVnq1fR38,5693
6
- pyreposync/sync_rpm.py,sha256=1yf2-lQShKyY3CI_FW1i0tyWQ0sg69iBUn-4iWfoevk,11613
7
- pyreposync-0.2.6.dist-info/METADATA,sha256=_iKcUStZxLy2goNOQgaIMgRE3CzmG34iDz-nXKN51Jw,1591
8
- pyreposync-0.2.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- pyreposync-0.2.6.dist-info/entry_points.txt,sha256=9LsBDWOF3O6_3ONP3Lc-4v1MTt5ay0Xv-TMcFbOIt2s,47
10
- pyreposync-0.2.6.dist-info/licenses/LICENSE.txt,sha256=lwnJoIo7uwc0h6y6gC_RYqJkvjplViV3Ad6u7pQM4Bw,1084
11
- pyreposync-0.2.6.dist-info/RECORD,,