ScriptCollection 3.5.151__py3-none-any.whl → 3.5.153__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.
- ScriptCollection/Executables.py +14 -2
- ScriptCollection/GeneralUtilities.py +18 -4
- ScriptCollection/ImageUpdater.py +146 -12
- ScriptCollection/SCLog.py +3 -8
- ScriptCollection/ScriptCollectionCore.py +27 -1
- ScriptCollection/TasksForCommonProjectStructure.py +86 -64
- {scriptcollection-3.5.151.dist-info → scriptcollection-3.5.153.dist-info}/METADATA +4 -4
- scriptcollection-3.5.153.dist-info/RECORD +17 -0
- {scriptcollection-3.5.151.dist-info → scriptcollection-3.5.153.dist-info}/entry_points.txt +1 -0
- scriptcollection-3.5.151.dist-info/RECORD +0 -17
- {scriptcollection-3.5.151.dist-info → scriptcollection-3.5.153.dist-info}/WHEEL +0 -0
- {scriptcollection-3.5.151.dist-info → scriptcollection-3.5.153.dist-info}/top_level.txt +0 -0
ScriptCollection/Executables.py
CHANGED
@@ -715,11 +715,14 @@ def UpdateImagesInDockerComposeFile() -> int:
|
|
715
715
|
iu: ImageUpdater = ImageUpdater()
|
716
716
|
parser = argparse.ArgumentParser()
|
717
717
|
parser.add_argument('-f', '--file', required=False, default=None)
|
718
|
-
|
718
|
+
parser.add_argument('-v', '--versionecholon', required=False, default=VersionEcholon.Newest.name, dest="Possible values are: " + ", ".join([e.name for e in VersionEcholon]))
|
719
|
+
parser.add_argument("-s", "--servicename", required=True, default=None)
|
720
|
+
parser.add_argument("-u", "--updatertype", required=True, default=None)
|
719
721
|
args = parser.parse_args()
|
720
722
|
if args.file is None:
|
721
723
|
args.file = os.path.join(os.getcwd(), "docker-compose.yml")
|
722
|
-
|
724
|
+
versionecholonTyped = VersionEcholon[args.versionecholon]
|
725
|
+
iu.update_services_in_docker_compose_file(args.file, [args.servicename], versionecholonTyped, args.updatertype)
|
723
726
|
return 0
|
724
727
|
|
725
728
|
|
@@ -748,3 +751,12 @@ def GenerateTaskfileFromWorkspacefile() -> int:
|
|
748
751
|
t = TasksForCommonProjectStructure()
|
749
752
|
t.generate_tasksfile_from_workspace_file(args.repositoryfolder)
|
750
753
|
return 0
|
754
|
+
|
755
|
+
|
756
|
+
def UpdateTimestampInFile() -> int:
|
757
|
+
parser = argparse.ArgumentParser(description="Update the timestamp in a comment in a file")
|
758
|
+
parser.add_argument('-f', '--file', required=True)
|
759
|
+
args = parser.parse_args()
|
760
|
+
sc = ScriptCollectionCore()
|
761
|
+
sc.update_timestamp_in_file(args.file)
|
762
|
+
return 0
|
@@ -35,6 +35,7 @@ class VersionEcholon(Enum):
|
|
35
35
|
|
36
36
|
class GeneralUtilities:
|
37
37
|
|
38
|
+
__datetime_format_with_offset: str = "%Y-%m-%d %H:%M:%S %z"
|
38
39
|
__datetime_format: str = "%Y-%m-%dT%H:%M:%S"
|
39
40
|
__date_format: str = "%Y-%m-%d"
|
40
41
|
|
@@ -133,6 +134,11 @@ class GeneralUtilities:
|
|
133
134
|
value = datetime(year=value.year, month=value.month, day=value.day, hour=value.hour, minute=value.minute, second=value.second)
|
134
135
|
return value.strftime(GeneralUtilities.__datetime_format) # returns "2022-10-06T19:26:01" for example
|
135
136
|
|
137
|
+
@staticmethod
|
138
|
+
@check_arguments
|
139
|
+
def datetime_to_string_with_timezone(value: datetime) -> str:
|
140
|
+
return value.strftime(GeneralUtilities.__datetime_format_with_offset) # returns "2025-08-21 15:30:00 +0200" for example
|
141
|
+
|
136
142
|
@staticmethod
|
137
143
|
@check_arguments
|
138
144
|
def string_to_date(value: str) -> date:
|
@@ -352,13 +358,21 @@ class GeneralUtilities:
|
|
352
358
|
|
353
359
|
@staticmethod
|
354
360
|
@check_arguments
|
355
|
-
def datetime_to_string_for_logfile_name(datetime_object: datetime) -> str:
|
356
|
-
|
361
|
+
def datetime_to_string_for_logfile_name(datetime_object: datetime, add_timezone_info_to_log: bool = True) -> str:
|
362
|
+
base_pattern: str = "%Y-%m-%d_%H-%M-%S"
|
363
|
+
if add_timezone_info_to_log:
|
364
|
+
return datetime_object.strftime(f'{base_pattern}_%z')
|
365
|
+
else:
|
366
|
+
return datetime_object.strftime(base_pattern)
|
357
367
|
|
358
368
|
@staticmethod
|
359
369
|
@check_arguments
|
360
|
-
def datetime_to_string_for_logfile_entry(datetime_object: datetime) -> str:
|
361
|
-
|
370
|
+
def datetime_to_string_for_logfile_entry(datetime_object: datetime, add_timezone_info_to_log: bool = True) -> str:
|
371
|
+
base_pattern: str = "%Y-%m-%d %H:%M:%S"
|
372
|
+
if add_timezone_info_to_log:
|
373
|
+
return datetime_object.strftime(f'{base_pattern} %z')
|
374
|
+
else:
|
375
|
+
return datetime_object.strftime(base_pattern)
|
362
376
|
|
363
377
|
@staticmethod
|
364
378
|
@check_arguments
|
ScriptCollection/ImageUpdater.py
CHANGED
@@ -132,6 +132,11 @@ class ConcreteImageUpdater:
|
|
132
132
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
133
133
|
raise NotImplementedError
|
134
134
|
|
135
|
+
@abstractmethod
|
136
|
+
@GeneralUtilities.check_arguments
|
137
|
+
def get_name(self, image: str, tag: str) -> str:
|
138
|
+
raise NotImplementedError
|
139
|
+
|
135
140
|
|
136
141
|
class ConcreteImageUpdaterForNginx(ConcreteImageUpdater):
|
137
142
|
|
@@ -154,6 +159,11 @@ class ConcreteImageUpdaterForNginx(ConcreteImageUpdater):
|
|
154
159
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
155
160
|
return ve.parse(tag)
|
156
161
|
|
162
|
+
@abstractmethod
|
163
|
+
@GeneralUtilities.check_arguments
|
164
|
+
def get_name(self, image: str, tag: str) -> str:
|
165
|
+
return "Nginx"
|
166
|
+
|
157
167
|
|
158
168
|
class ConcreteImageUpdaterForWordpress(ConcreteImageUpdater):
|
159
169
|
|
@@ -176,6 +186,11 @@ class ConcreteImageUpdaterForWordpress(ConcreteImageUpdater):
|
|
176
186
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
177
187
|
return ve.parse(tag)
|
178
188
|
|
189
|
+
@abstractmethod
|
190
|
+
@GeneralUtilities.check_arguments
|
191
|
+
def get_name(self, image: str, tag: str) -> str:
|
192
|
+
return "Wordpress"
|
193
|
+
|
179
194
|
|
180
195
|
class ConcreteImageUpdaterForGitLab(ConcreteImageUpdater):
|
181
196
|
|
@@ -195,6 +210,11 @@ class ConcreteImageUpdaterForGitLab(ConcreteImageUpdater):
|
|
195
210
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
196
211
|
raise NotImplementedError
|
197
212
|
|
213
|
+
@abstractmethod
|
214
|
+
@GeneralUtilities.check_arguments
|
215
|
+
def get_name(self, image: str, tag: str) -> str:
|
216
|
+
return "GitLab"
|
217
|
+
|
198
218
|
|
199
219
|
class ConcreteImageUpdaterForRegistry(ConcreteImageUpdater):
|
200
220
|
|
@@ -218,6 +238,11 @@ class ConcreteImageUpdaterForRegistry(ConcreteImageUpdater):
|
|
218
238
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
219
239
|
return ve.parse(tag)
|
220
240
|
|
241
|
+
@abstractmethod
|
242
|
+
@GeneralUtilities.check_arguments
|
243
|
+
def get_name(self, image: str, tag: str) -> str:
|
244
|
+
return "Registry"
|
245
|
+
|
221
246
|
|
222
247
|
class ConcreteImageUpdaterForPrometheus(ConcreteImageUpdater):
|
223
248
|
|
@@ -240,6 +265,11 @@ class ConcreteImageUpdaterForPrometheus(ConcreteImageUpdater):
|
|
240
265
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
241
266
|
return ve.parse(tag[1:])
|
242
267
|
|
268
|
+
@abstractmethod
|
269
|
+
@GeneralUtilities.check_arguments
|
270
|
+
def get_name(self, image: str, tag: str) -> str:
|
271
|
+
return "Prometheus"
|
272
|
+
|
243
273
|
|
244
274
|
class ConcreteImageUpdaterForPrometheusBlackboxExporter(ConcreteImageUpdater):
|
245
275
|
|
@@ -262,6 +292,11 @@ class ConcreteImageUpdaterForPrometheusBlackboxExporter(ConcreteImageUpdater):
|
|
262
292
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
263
293
|
return ve.parse(tag[1:])
|
264
294
|
|
295
|
+
@abstractmethod
|
296
|
+
@GeneralUtilities.check_arguments
|
297
|
+
def get_name(self, image: str, tag: str) -> str:
|
298
|
+
return "PrometheusBlackboxExporter"
|
299
|
+
|
265
300
|
|
266
301
|
class ConcreteImageUpdaterForPrometheusNginxExporter(ConcreteImageUpdater):
|
267
302
|
|
@@ -284,6 +319,11 @@ class ConcreteImageUpdaterForPrometheusNginxExporter(ConcreteImageUpdater):
|
|
284
319
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
285
320
|
return ve.parse(tag[1:])
|
286
321
|
|
322
|
+
@abstractmethod
|
323
|
+
@GeneralUtilities.check_arguments
|
324
|
+
def get_name(self, image: str, tag: str) -> str:
|
325
|
+
return "NginxPrometheusExporter"
|
326
|
+
|
287
327
|
|
288
328
|
class ConcreteImageUpdaterForPrometheusNodeExporter(ConcreteImageUpdater):
|
289
329
|
|
@@ -306,6 +346,11 @@ class ConcreteImageUpdaterForPrometheusNodeExporter(ConcreteImageUpdater):
|
|
306
346
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
307
347
|
return ve.parse(tag[1:])
|
308
348
|
|
349
|
+
@abstractmethod
|
350
|
+
@GeneralUtilities.check_arguments
|
351
|
+
def get_name(self, image: str, tag: str) -> str:
|
352
|
+
return "PrometheusNodeExporter"
|
353
|
+
|
309
354
|
|
310
355
|
class ConcreteImageUpdaterForKeycloak(ConcreteImageUpdater):
|
311
356
|
|
@@ -325,6 +370,11 @@ class ConcreteImageUpdaterForKeycloak(ConcreteImageUpdater):
|
|
325
370
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
326
371
|
raise NotImplementedError
|
327
372
|
|
373
|
+
@abstractmethod
|
374
|
+
@GeneralUtilities.check_arguments
|
375
|
+
def get_name(self, image: str, tag: str) -> str:
|
376
|
+
return "KeyCloak"
|
377
|
+
|
328
378
|
|
329
379
|
class ConcreteImageUpdaterForMariaDB(ConcreteImageUpdater):
|
330
380
|
|
@@ -347,6 +397,11 @@ class ConcreteImageUpdaterForMariaDB(ConcreteImageUpdater):
|
|
347
397
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
348
398
|
return ve.parse(tag)
|
349
399
|
|
400
|
+
@abstractmethod
|
401
|
+
@GeneralUtilities.check_arguments
|
402
|
+
def get_name(self, image: str, tag: str) -> str:
|
403
|
+
return "MariaDB"
|
404
|
+
|
350
405
|
|
351
406
|
class ConcreteImageUpdaterForPostgreSQL(ConcreteImageUpdater):
|
352
407
|
|
@@ -369,6 +424,11 @@ class ConcreteImageUpdaterForPostgreSQL(ConcreteImageUpdater):
|
|
369
424
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
370
425
|
return ve.parse(tag+".0")
|
371
426
|
|
427
|
+
@abstractmethod
|
428
|
+
@GeneralUtilities.check_arguments
|
429
|
+
def get_name(self, image: str, tag: str) -> str:
|
430
|
+
return "PostgreSQL"
|
431
|
+
|
372
432
|
|
373
433
|
class ConcreteImageUpdaterForAdminer(ConcreteImageUpdater):
|
374
434
|
|
@@ -391,6 +451,65 @@ class ConcreteImageUpdaterForAdminer(ConcreteImageUpdater):
|
|
391
451
|
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
392
452
|
return ve.parse(tag)
|
393
453
|
|
454
|
+
@abstractmethod
|
455
|
+
@GeneralUtilities.check_arguments
|
456
|
+
def get_name(self, image: str, tag: str) -> str:
|
457
|
+
return "Adminer"
|
458
|
+
|
459
|
+
|
460
|
+
class ConcreteImageUpdaterForGeneric(ConcreteImageUpdater):
|
461
|
+
|
462
|
+
@GeneralUtilities.check_arguments
|
463
|
+
def version_to_tag(self, version: Version) -> str:
|
464
|
+
return f"{version.major}.{version.minor}.{version.micro}"
|
465
|
+
|
466
|
+
@GeneralUtilities.check_arguments
|
467
|
+
def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
|
468
|
+
versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^\\d+\\.\\d+\\.\\d+$", 999)
|
469
|
+
newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
|
470
|
+
result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
|
471
|
+
return result
|
472
|
+
|
473
|
+
@GeneralUtilities.check_arguments
|
474
|
+
def get_supported_images(self) -> list[str]:
|
475
|
+
return [".*"]
|
476
|
+
|
477
|
+
@GeneralUtilities.check_arguments
|
478
|
+
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
479
|
+
return ve.parse(tag)
|
480
|
+
|
481
|
+
@abstractmethod
|
482
|
+
@GeneralUtilities.check_arguments
|
483
|
+
def get_name(self, image: str, tag: str) -> str:
|
484
|
+
return "Generic"
|
485
|
+
|
486
|
+
|
487
|
+
class ConcreteImageUpdaterForGenericV(ConcreteImageUpdater):
|
488
|
+
|
489
|
+
@GeneralUtilities.check_arguments
|
490
|
+
def version_to_tag(self, version: Version) -> str:
|
491
|
+
return f"v{version.major}.{version.minor}.{version.micro}"
|
492
|
+
|
493
|
+
@GeneralUtilities.check_arguments
|
494
|
+
def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> Version:
|
495
|
+
versions = ImageUpdaterHelper.get_versions_in_docker_hub(image, ".", "^v\\d+\\.\\d+\\.\\d+$", 999)
|
496
|
+
newer_versions = ImageUpdaterHelper.filter_for_newer_versions(current_version, versions)
|
497
|
+
result = ImageUpdaterHelper.filter_considering_echolon(newer_versions, current_version, version_echolon)
|
498
|
+
return result
|
499
|
+
|
500
|
+
@GeneralUtilities.check_arguments
|
501
|
+
def get_supported_images(self) -> list[str]:
|
502
|
+
return [".*"]
|
503
|
+
|
504
|
+
@GeneralUtilities.check_arguments
|
505
|
+
def get_version_from_tag(self, image: str, tag: str) -> Version:
|
506
|
+
return ve.parse(tag[1:])
|
507
|
+
|
508
|
+
@abstractmethod
|
509
|
+
@GeneralUtilities.check_arguments
|
510
|
+
def get_name(self, image: str, tag: str) -> str:
|
511
|
+
return "GenericV"
|
512
|
+
|
394
513
|
|
395
514
|
class ImageUpdater:
|
396
515
|
|
@@ -434,16 +553,16 @@ class ImageUpdater:
|
|
434
553
|
return newer_version_available
|
435
554
|
|
436
555
|
@GeneralUtilities.check_arguments
|
437
|
-
def update_all_services_in_docker_compose_file(self, dockercompose_file: str, version_echolon: VersionEcholon, except_services: list[str] = []):
|
556
|
+
def update_all_services_in_docker_compose_file(self, dockercompose_file: str, version_echolon: VersionEcholon, except_services: list[str] = [], updatertype: str = None):
|
438
557
|
all_services = self.get_services_from_docker_compose_file(dockercompose_file)
|
439
558
|
services_to_update = [service for service in all_services if service not in except_services]
|
440
|
-
self.update_services_in_docker_compose_file(dockercompose_file, services_to_update, version_echolon)
|
559
|
+
self.update_services_in_docker_compose_file(dockercompose_file, services_to_update, version_echolon, updatertype)
|
441
560
|
|
442
561
|
@GeneralUtilities.check_arguments
|
443
|
-
def update_services_in_docker_compose_file(self, dockercompose_file: str, service_names: list[str], version_echolon: VersionEcholon):
|
562
|
+
def update_services_in_docker_compose_file(self, dockercompose_file: str, service_names: list[str], version_echolon: VersionEcholon, updatertype: str = None):
|
444
563
|
for service_name in service_names:
|
445
564
|
if self.service_has_image_information(dockercompose_file, service_name):
|
446
|
-
self.update_service_in_docker_compose_file(dockercompose_file, service_name, version_echolon)
|
565
|
+
self.update_service_in_docker_compose_file(dockercompose_file, service_name, version_echolon, updatertype)
|
447
566
|
|
448
567
|
@GeneralUtilities.check_arguments
|
449
568
|
def service_has_image_information(self, dockercompose_file: str, service_name: str) -> bool:
|
@@ -454,9 +573,9 @@ class ImageUpdater:
|
|
454
573
|
return image is not None
|
455
574
|
|
456
575
|
@GeneralUtilities.check_arguments
|
457
|
-
def update_service_in_docker_compose_file(self, dockercompose_file: str, service_name: str, version_echolon: VersionEcholon):
|
576
|
+
def update_service_in_docker_compose_file(self, dockercompose_file: str, service_name: str, version_echolon: VersionEcholon, updatertype: str = None):
|
458
577
|
imagename, existing_tag, existing_version = self.get_current_version_of_service_from_docker_compose_file(dockercompose_file, service_name) # pylint:disable=unused-variable
|
459
|
-
result = self.get_latest_version_of_image(imagename, version_echolon, existing_version)
|
578
|
+
result = self.get_latest_version_of_image(imagename, version_echolon, existing_version, updatertype)
|
460
579
|
newest_version = result[0]
|
461
580
|
newest_tag = result[1]
|
462
581
|
# TODO write info to console if there is a newwer version available if versionecoholon==latest would have been chosen
|
@@ -495,20 +614,35 @@ class ImageUpdater:
|
|
495
614
|
raise ValueError(f"Service '{service_name}' in '{dockercompose_file}'")
|
496
615
|
|
497
616
|
@GeneralUtilities.check_arguments
|
498
|
-
def __get_updater_for_image(self, image: str) ->
|
617
|
+
def __get_updater_for_image(self, image: str) -> ConcreteImageUpdater:
|
499
618
|
for updater in self.updater:
|
500
|
-
|
501
|
-
|
619
|
+
for supported_image_regex in updater.get_supported_images():
|
620
|
+
r = re.compile("^"+supported_image_regex+"$")
|
621
|
+
if r.match(supported_image_regex):
|
622
|
+
return updater
|
502
623
|
raise ValueError(f"No updater available for image '{image}'")
|
503
624
|
|
625
|
+
@GeneralUtilities.check_arguments
|
626
|
+
def __get_updater_by_name(self, updater_name: str) -> ConcreteImageUpdater:
|
627
|
+
for updater in self.updater:
|
628
|
+
if updater.get_name() == updater_name:
|
629
|
+
return updater
|
630
|
+
raise ValueError(f"No updater available with name '{updater_name}'")
|
631
|
+
|
504
632
|
@GeneralUtilities.check_arguments
|
505
633
|
def get_docker_version_from_tag(self, image: str, tag: str) -> Version:
|
506
|
-
updater:
|
634
|
+
updater: ConcreteImageUpdater = self.__get_updater_for_image(image)
|
507
635
|
return updater.get_version_from_tag(image, tag)
|
508
636
|
|
509
637
|
@GeneralUtilities.check_arguments
|
510
|
-
def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version) -> tuple[Version, str]:
|
511
|
-
|
638
|
+
def get_latest_version_of_image(self, image: str, version_echolon: VersionEcholon, current_version: Version, updatertype: str = None) -> tuple[Version, str]:
|
639
|
+
|
640
|
+
updater: ConcreteImageUpdater = None
|
641
|
+
if updatertype is None:
|
642
|
+
self.__get_updater_for_image(image)
|
643
|
+
else:
|
644
|
+
self.__get_updater_by_name(updatertype)
|
645
|
+
|
512
646
|
newest_version: Version = updater.get_latest_version_of_image(image, version_echolon, current_version)
|
513
647
|
newest_tag: str = updater.version_to_tag(newest_version)
|
514
648
|
return (newest_version, newest_tag)
|
ScriptCollection/SCLog.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
from enum import Enum
|
3
|
-
from datetime import datetime
|
3
|
+
from datetime import datetime
|
4
4
|
from .GeneralUtilities import GeneralUtilities
|
5
5
|
|
6
6
|
|
@@ -22,7 +22,6 @@ class SCLog:
|
|
22
22
|
add_overhead_to_console: bool
|
23
23
|
add_overhead_to_logfile: bool
|
24
24
|
print_as_color: bool
|
25
|
-
zone_of_time: timezone = None
|
26
25
|
|
27
26
|
def __init__(self, log_file: str = None, loglevel: LogLevel = None, print_as_color: bool = True):
|
28
27
|
self.log_file = log_file
|
@@ -69,13 +68,9 @@ class SCLog:
|
|
69
68
|
if loglevel == LogLevel.Diagnostic:
|
70
69
|
part3 = f"Diagnostic: {message}"
|
71
70
|
|
72
|
-
moment: datetime =
|
73
|
-
if self.zone_of_time is None:
|
74
|
-
moment = datetime.now()
|
75
|
-
else:
|
76
|
-
moment = datetime.now(self.zone_of_time)
|
71
|
+
moment: datetime = datetime.now(datetime.now().astimezone().tzinfo)
|
77
72
|
|
78
|
-
part1 = f"[{GeneralUtilities.datetime_to_string_for_logfile_entry(moment)}] ["
|
73
|
+
part1 = f"[{GeneralUtilities.datetime_to_string_for_logfile_entry(moment, True)}] ["
|
79
74
|
if loglevel == LogLevel.Information:
|
80
75
|
part2 = f"Information"
|
81
76
|
elif loglevel == LogLevel.Error:
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import traceback
|
1
2
|
from datetime import timedelta, datetime
|
2
3
|
import json
|
3
4
|
import binascii
|
@@ -34,7 +35,7 @@ from .ProgramRunnerPopen import ProgramRunnerPopen
|
|
34
35
|
from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
|
35
36
|
from .SCLog import SCLog, LogLevel
|
36
37
|
|
37
|
-
version = "3.5.
|
38
|
+
version = "3.5.153"
|
38
39
|
__version__ = version
|
39
40
|
|
40
41
|
|
@@ -2436,3 +2437,28 @@ OCR-content:
|
|
2436
2437
|
if has_staged_changes:
|
2437
2438
|
changed_ocr_file_relative_path = os.path.relpath(changed_ocr_file, folder)
|
2438
2439
|
self.run_program_argsasarray("git", ["add", changed_ocr_file_relative_path], folder)
|
2440
|
+
|
2441
|
+
@GeneralUtilities.check_arguments
|
2442
|
+
def update_timestamp_in_file(self, target_file: str) -> None:
|
2443
|
+
lines = GeneralUtilities.read_lines_from_file(target_file)
|
2444
|
+
new_lines = []
|
2445
|
+
prefix: str = "# last update: "
|
2446
|
+
for line in lines:
|
2447
|
+
if line.startswith(prefix):
|
2448
|
+
new_lines.append(prefix+GeneralUtilities.datetime_to_string_with_timezone(datetime.now()))
|
2449
|
+
else:
|
2450
|
+
new_lines.append(line)
|
2451
|
+
GeneralUtilities.write_lines_to_file(target_file, new_lines)
|
2452
|
+
|
2453
|
+
def do_and_log_task(self,name_of_task:str,task):
|
2454
|
+
try:
|
2455
|
+
self.log.log(f"Start {name_of_task}", LogLevel.Information)
|
2456
|
+
result= task()
|
2457
|
+
if result is None:
|
2458
|
+
result=0
|
2459
|
+
return result
|
2460
|
+
except Exception as e:
|
2461
|
+
self.log.log_exception(f"Error while {name_of_task}.", e, traceback)
|
2462
|
+
return 1
|
2463
|
+
finally:
|
2464
|
+
self.log.log(f"Finished {name_of_task}.", LogLevel.Information)
|
@@ -240,10 +240,9 @@ class TasksForCommonProjectStructure:
|
|
240
240
|
@GeneralUtilities.check_arguments
|
241
241
|
def copy_source_files_to_output_directory(self, buildscript_file: str) -> None:
|
242
242
|
GeneralUtilities.write_message_to_stdout("Copy sourcecode...")
|
243
|
-
sc = ScriptCollectionCore()
|
244
243
|
folder = os.path.dirname(os.path.realpath(buildscript_file))
|
245
244
|
codeunit_folder = GeneralUtilities.resolve_relative_path("../..", folder)
|
246
|
-
result =
|
245
|
+
result = self.__sc.run_program_argsasarray("git", ["ls-tree", "-r", "HEAD", "--name-only"], codeunit_folder)
|
247
246
|
files = [f for f in result[1].split('\n') if len(f) > 0]
|
248
247
|
for file in files:
|
249
248
|
full_source_file = os.path.join(codeunit_folder, file)
|
@@ -271,7 +270,6 @@ class TasksForCommonProjectStructure:
|
|
271
270
|
}
|
272
271
|
for target in targets:
|
273
272
|
GeneralUtilities.write_message_to_stdout(f"Build package {package_name} for target {target_names[target]}...")
|
274
|
-
sc = ScriptCollectionCore()
|
275
273
|
self.run_with_epew("flutter", f"build {target}", src_folder, verbosity)
|
276
274
|
if target == "web":
|
277
275
|
web_relase_folder = os.path.join(src_folder, "build/web")
|
@@ -300,7 +298,7 @@ class TasksForCommonProjectStructure:
|
|
300
298
|
GeneralUtilities.ensure_directory_does_not_exist(apk_folder)
|
301
299
|
GeneralUtilities.ensure_directory_exists(apk_folder)
|
302
300
|
apks_file = f"{apk_folder}/{codeunit_name}.apks"
|
303
|
-
|
301
|
+
self.__sc.run_program("java", f"-jar {bundletool} build-apks --bundle={aab_file} --output={apks_file} --mode=universal", aab_relase_folder, verbosity)
|
304
302
|
with zipfile.ZipFile(apks_file, "r") as zip_ref:
|
305
303
|
zip_ref.extract("universal.apk", apk_folder)
|
306
304
|
GeneralUtilities.ensure_file_does_not_exist(apks_file)
|
@@ -485,7 +483,7 @@ class TasksForCommonProjectStructure:
|
|
485
483
|
self.write_version_to_codeunit_file(codeunit_file, current_version)
|
486
484
|
|
487
485
|
@GeneralUtilities.check_arguments
|
488
|
-
def t4_transform(self, commontasks_script_file_of_current_file: str, verbosity: int,ignore_git_ignored_files:bool=True):
|
486
|
+
def t4_transform(self, commontasks_script_file_of_current_file: str, verbosity: int, ignore_git_ignored_files: bool = True):
|
489
487
|
codeunit_folder = GeneralUtilities.resolve_relative_path("../..", commontasks_script_file_of_current_file)
|
490
488
|
self.__ensure_grylibrary_is_available(codeunit_folder)
|
491
489
|
repository_folder: str = os.path.dirname(codeunit_folder)
|
@@ -494,51 +492,19 @@ class TasksForCommonProjectStructure:
|
|
494
492
|
for search_result in Path(codeunit_folder).glob('**/*.tt'):
|
495
493
|
tt_file = str(search_result)
|
496
494
|
relative_path_to_tt_file_from_repository = str(Path(tt_file).relative_to(repository_folder))
|
497
|
-
if (not ignore_git_ignored_files) or (ignore_git_ignored_files and not self.__sc.file_is_git_ignored(relative_path_to_tt_file_from_repository,repository_folder)):
|
495
|
+
if (not ignore_git_ignored_files) or (ignore_git_ignored_files and not self.__sc.file_is_git_ignored(relative_path_to_tt_file_from_repository, repository_folder)):
|
498
496
|
relative_path_to_tt_file_from_codeunit_file = str(Path(tt_file).relative_to(codeunit_folder))
|
499
497
|
argument = [f"--parameter=repositoryFolder={repository_folder}", f"--parameter=codeUnitName={codeunitname}", relative_path_to_tt_file_from_codeunit_file]
|
500
498
|
self.__sc.run_program_argsasarray("t4", argument, codeunit_folder, verbosity=verbosity)
|
501
499
|
|
502
500
|
@GeneralUtilities.check_arguments
|
503
|
-
def get_resource_from_global_resource(self,codeunit_folder:str,resource_name:str):
|
504
|
-
repository_folder:str= GeneralUtilities.resolve_relative_path("..", codeunit_folder)
|
505
|
-
source_folder:str=os.path.join(repository_folder,"Other","Resources",resource_name)
|
506
|
-
target_folder:str=os.path.join(codeunit_folder,"Other","Resources",resource_name)
|
501
|
+
def get_resource_from_global_resource(self, codeunit_folder: str, resource_name: str):
|
502
|
+
repository_folder: str = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
|
503
|
+
source_folder: str = os.path.join(repository_folder, "Other", "Resources", resource_name)
|
504
|
+
target_folder: str = os.path.join(codeunit_folder, "Other", "Resources", resource_name)
|
507
505
|
GeneralUtilities.ensure_folder_exists_and_is_empty(target_folder)
|
508
506
|
GeneralUtilities.copy_content_of_folder(source_folder, target_folder)
|
509
507
|
|
510
|
-
@GeneralUtilities.check_arguments
|
511
|
-
def clone_repository_as_resource(self,local_repository_folder:str,remote_repository_link:str, resource_name:str,repository_subname:str=None)->str:
|
512
|
-
commit_id:str=None
|
513
|
-
target_folder:str=os.path.join(local_repository_folder,"Other","Resources",resource_name)
|
514
|
-
if repository_subname is not None:
|
515
|
-
target_folder=os.path.join(target_folder,repository_subname)
|
516
|
-
if not os.path.isdir(target_folder):
|
517
|
-
GeneralUtilities.ensure_directory_exists(target_folder)
|
518
|
-
GeneralUtilities.write_message_to_stdout(f"Clone {remote_repository_link} into {target_folder}...")
|
519
|
-
self.__sc.run_program("git",f"clone --recurse-submodules {remote_repository_link} {target_folder}")
|
520
|
-
|
521
|
-
self.__sc.git_get_commit_id(target_folder)
|
522
|
-
|
523
|
-
git_folders:list[str]=[]
|
524
|
-
git_files:list[str]=[]
|
525
|
-
for dirpath, dirnames, filenames in os.walk(target_folder):
|
526
|
-
for dirname in dirnames:
|
527
|
-
if dirname == ".git":
|
528
|
-
full_path = os.path.join(dirpath, dirname)
|
529
|
-
git_folders.append(full_path)
|
530
|
-
for filename in filenames:
|
531
|
-
if filename == ".git":
|
532
|
-
full_path = os.path.join(dirpath, filename)
|
533
|
-
git_files.append(full_path)
|
534
|
-
for git_folder in git_folders:
|
535
|
-
if os.path.isdir(git_folder):
|
536
|
-
GeneralUtilities.ensure_directory_does_not_exist(git_folder)
|
537
|
-
for git_file in git_files:
|
538
|
-
if os.path.isdir(git_file):
|
539
|
-
GeneralUtilities.ensure_file_does_not_exist(git_file)
|
540
|
-
return commit_id
|
541
|
-
|
542
508
|
@GeneralUtilities.check_arguments
|
543
509
|
def standardized_tasks_generate_reference_by_docfx(self, generate_reference_script_file: str, verbosity: int, targetenvironmenttype: str, commandline_arguments: list[str]) -> None:
|
544
510
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
@@ -821,10 +787,9 @@ class TasksForCommonProjectStructure:
|
|
821
787
|
GeneralUtilities.write_message_to_stdout("Generate SBOM...")
|
822
788
|
self.assert_is_codeunit_folder(codeunit_folder)
|
823
789
|
codeunit_name = os.path.basename(codeunit_folder)
|
824
|
-
sc = ScriptCollectionCore()
|
825
790
|
bomfile_folder = "Other\\Artifacts\\BOM"
|
826
791
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
827
|
-
|
792
|
+
self.__sc.run_program_argsasarray("dotnet", ["CycloneDX", f"{codeunit_name}\\{codeunit_name}.csproj", "-o", bomfile_folder, "--disable-github-licenses"], codeunit_folder, verbosity=verbosity)
|
828
793
|
codeunitversion = self.get_version_of_codeunit(os.path.join(codeunit_folder, f"{codeunit_name}.codeunit.xml"))
|
829
794
|
target = f"{codeunit_folder}\\{bomfile_folder}\\{codeunit_name}.{codeunitversion}.sbom.xml"
|
830
795
|
GeneralUtilities.ensure_file_does_not_exist(target)
|
@@ -1495,8 +1460,7 @@ class TasksForCommonProjectStructure:
|
|
1495
1460
|
codeunit_folder = os.path.join(repository_folder, codeunitname)
|
1496
1461
|
artifacts_folder = self.get_artifacts_folder(repository_folder, codeunitname)
|
1497
1462
|
applicationimage_folder = os.path.join(artifacts_folder, "BuildResult_OCIImage")
|
1498
|
-
|
1499
|
-
image_file = sc.find_file_by_extension(applicationimage_folder, "tar")
|
1463
|
+
image_file = self.__sc.find_file_by_extension(applicationimage_folder, "tar")
|
1500
1464
|
image_filename = os.path.basename(image_file)
|
1501
1465
|
codeunit_version = self.get_version_of_codeunit(os.path.join(codeunit_folder, f"{codeunitname}.codeunit.xml"))
|
1502
1466
|
if remote_image_name is None:
|
@@ -1507,15 +1471,15 @@ class TasksForCommonProjectStructure:
|
|
1507
1471
|
remote_image_latest = f"{remote_repo}:latest"
|
1508
1472
|
remote_image_version = f"{remote_repo}:{codeunit_version}"
|
1509
1473
|
GeneralUtilities.write_message_to_stdout("Load image...")
|
1510
|
-
|
1474
|
+
self.__sc.run_program("docker", f"load --input {image_filename}", applicationimage_folder, verbosity=verbosity)
|
1511
1475
|
GeneralUtilities.write_message_to_stdout("Tag image...")
|
1512
|
-
|
1513
|
-
|
1476
|
+
self.__sc.run_program("docker", f"tag {local_image_name}:{codeunit_version} {remote_image_latest}", verbosity=verbosity)
|
1477
|
+
self.__sc.run_program("docker", f"tag {local_image_name}:{codeunit_version} {remote_image_version}", verbosity=verbosity)
|
1514
1478
|
GeneralUtilities.write_message_to_stdout("Push image...")
|
1515
|
-
|
1516
|
-
|
1479
|
+
self.__sc.run_program("docker", f"push {remote_image_latest}", verbosity=verbosity)
|
1480
|
+
self.__sc.run_program("docker", f"push {remote_image_version}", verbosity=verbosity)
|
1517
1481
|
if push_readme:
|
1518
|
-
|
1482
|
+
self.__sc.run_program("docker-pushrm", f"{remote_repo}", codeunit_folder, verbosity=verbosity)
|
1519
1483
|
|
1520
1484
|
@GeneralUtilities.check_arguments
|
1521
1485
|
def get_dependent_code_units(self, codeunit_file: str) -> list[str]:
|
@@ -1797,7 +1761,7 @@ class TasksForCommonProjectStructure:
|
|
1797
1761
|
@GeneralUtilities.check_arguments
|
1798
1762
|
def get_version_of_project(self, repository_folder: str) -> str:
|
1799
1763
|
self.__sc.assert_is_git_repository(repository_folder)
|
1800
|
-
return
|
1764
|
+
return self.__sc.get_semver_version_from_gitversion(repository_folder)
|
1801
1765
|
|
1802
1766
|
@GeneralUtilities.check_arguments
|
1803
1767
|
def replace_common_variables_in_nuspec_file(self, codeunit_folder: str) -> None:
|
@@ -2248,7 +2212,7 @@ class TasksForCommonProjectStructure:
|
|
2248
2212
|
openapi_spec_file = os.path.join(codeunit_folder, "Other", "Resources", "DependentCodeUnits", name_of_api_providing_codeunit, "APISpecification", f"{name_of_api_providing_codeunit}.latest.api.json")
|
2249
2213
|
target_folder = os.path.join(codeunit_folder, target_subfolder_in_codeunit)
|
2250
2214
|
GeneralUtilities.ensure_folder_exists_and_is_empty(target_folder)
|
2251
|
-
|
2215
|
+
self.__sc.run_program("java", f'-jar {openapigenerator_jar_file} generate -i {openapi_spec_file} -g {language} -o {target_folder} --global-property supportingFiles --global-property models --global-property apis', codeunit_folder)
|
2252
2216
|
|
2253
2217
|
@GeneralUtilities.check_arguments
|
2254
2218
|
def generate_api_client_from_dependent_codeunit_in_dotnet(self, file: str, name_of_api_providing_codeunit: str, base_namespace: str) -> None:
|
@@ -2266,7 +2230,7 @@ class TasksForCommonProjectStructure:
|
|
2266
2230
|
openapi_spec_file = os.path.join(codeunit_folder, "Other", "Resources", "DependentCodeUnits", name_of_api_providing_codeunit, "APISpecification", f"{name_of_api_providing_codeunit}.latest.api.json")
|
2267
2231
|
target_folder = os.path.join(codeunit_folder, target_subfolder_in_codeunit)
|
2268
2232
|
GeneralUtilities.ensure_directory_exists(target_folder)
|
2269
|
-
|
2233
|
+
self.__sc.run_program("java", f'-jar {openapigenerator_jar_file} generate -i {openapi_spec_file} -g {language} -o {target_folder} --global-property supportingFiles --global-property models --global-property apis {additional_properties}', codeunit_folder)
|
2270
2234
|
|
2271
2235
|
# move docs to correct folder
|
2272
2236
|
target_folder_docs = os.path.join(target_folder, "docs")
|
@@ -2464,11 +2428,13 @@ class TasksForCommonProjectStructure:
|
|
2464
2428
|
relative_script_file = task["command"]
|
2465
2429
|
|
2466
2430
|
relative_script_file = "."
|
2431
|
+
cwd: str = None
|
2467
2432
|
if "options" in task:
|
2468
2433
|
options = task["options"]
|
2469
2434
|
if "cwd" in options:
|
2470
|
-
cwd
|
2435
|
+
cwd = options["cwd"]
|
2471
2436
|
cwd = cwd.replace("${workspaceFolder}", ".")
|
2437
|
+
cwd = cwd.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
|
2472
2438
|
relative_script_file = cwd
|
2473
2439
|
if len(relative_script_file) == 0:
|
2474
2440
|
relative_script_file = "."
|
@@ -2486,15 +2452,16 @@ class TasksForCommonProjectStructure:
|
|
2486
2452
|
if append_cli_args_at_end:
|
2487
2453
|
command_with_args = f"{command_with_args} {{{{.CLI_ARGS}}}}"
|
2488
2454
|
|
2489
|
-
cwd_literal = cwd.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
|
2490
2455
|
description_literal = description.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
|
2456
|
+
command_with_args = command_with_args.replace("\\", "\\\\").replace('"', '\\"') # escape backslashes and double quotes for YAML
|
2491
2457
|
|
2492
2458
|
lines.append(f" {name}:")
|
2493
2459
|
lines.append(f' desc: "{description_literal}"')
|
2494
2460
|
lines.append(' silent: true')
|
2495
|
-
|
2461
|
+
if cwd is not None:
|
2462
|
+
lines.append(f' dir: "{cwd}"')
|
2496
2463
|
lines.append(" cmds:")
|
2497
|
-
lines.append(f
|
2464
|
+
lines.append(f' - "{command_with_args}"')
|
2498
2465
|
lines.append(' aliases:')
|
2499
2466
|
lines.append(f' - {name.lower()}')
|
2500
2467
|
if "aliases" in task:
|
@@ -2685,6 +2652,7 @@ class TasksForCommonProjectStructure:
|
|
2685
2652
|
|
2686
2653
|
@GeneralUtilities.check_arguments
|
2687
2654
|
def build_specific_codeunits(self, repository_folder: str, codeunits: list[str], verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, assume_dependent_codeunits_are_already_built: bool = True, commandline_arguments: list[str] = [], do_git_clean_when_no_changes: bool = False, note: str = None, check_for_new_files: bool = True) -> None:
|
2655
|
+
now_begin: datetime = datetime.now()
|
2688
2656
|
codeunits_list = "{"+", ".join(["a", "b"])+"}"
|
2689
2657
|
if verbosity > 2:
|
2690
2658
|
GeneralUtilities.write_message_to_stdout(f"Start building codeunits ({codeunits_list}) in repository '{repository_folder}'...")
|
@@ -2708,7 +2676,7 @@ class TasksForCommonProjectStructure:
|
|
2708
2676
|
sorted_codeunits = [codeunit for codeunit in sorted_codeunits if codeunit in codeunits]
|
2709
2677
|
project_version = self.get_version_of_project(repository_folder)
|
2710
2678
|
|
2711
|
-
message = f"Build codeunits in product {repository_name}..."
|
2679
|
+
message = f"Build codeunits in product {repository_name}... (Started: {GeneralUtilities.datetime_to_string(now_begin)})"
|
2712
2680
|
if note is not None:
|
2713
2681
|
message = f"{message} ({note})"
|
2714
2682
|
GeneralUtilities.write_message_to_stdout(message)
|
@@ -2750,7 +2718,8 @@ class TasksForCommonProjectStructure:
|
|
2750
2718
|
archive_file = os.path.join(os.getcwd(), f"{filename_without_extension}.zip")
|
2751
2719
|
shutil.move(archive_file, target_folder)
|
2752
2720
|
|
2753
|
-
|
2721
|
+
now_end: datetime = datetime.now()
|
2722
|
+
message2 = f"Finished build codeunits in product {repository_name}. (Finished: {GeneralUtilities.datetime_to_string(now_end)})"
|
2754
2723
|
if note is not None:
|
2755
2724
|
message2 = f"{message2} ({note})"
|
2756
2725
|
GeneralUtilities.write_message_to_stdout(message2)
|
@@ -2963,13 +2932,12 @@ class TasksForCommonProjectStructure:
|
|
2963
2932
|
|
2964
2933
|
@GeneralUtilities.check_arguments
|
2965
2934
|
def __generate_svg_files_from_plantuml(self, diagrams_files_folder: str, plant_uml_folder: str) -> None:
|
2966
|
-
sc = ScriptCollectionCore()
|
2967
2935
|
for file in GeneralUtilities.get_all_files_of_folder(diagrams_files_folder):
|
2968
2936
|
if file.endswith(".plantuml"):
|
2969
2937
|
output_filename = self.get_output_filename_for_plantuml_filename(file)
|
2970
2938
|
argument = ['-jar', f'{plant_uml_folder}/plantuml.jar', '-tsvg', os.path.basename(file)]
|
2971
2939
|
folder = os.path.dirname(file)
|
2972
|
-
|
2940
|
+
self.__sc.run_program_argsasarray("java", argument, folder, verbosity=0)
|
2973
2941
|
result_file = folder+"/" + output_filename
|
2974
2942
|
GeneralUtilities.assert_file_exists(result_file)
|
2975
2943
|
self.__sc.format_xml_file(result_file)
|
@@ -3067,7 +3035,7 @@ class TasksForCommonProjectStructure:
|
|
3067
3035
|
artifacts_folder = os.path.join(codeunit_folder, "Other", "Artifacts", artifact_name_of_zip)
|
3068
3036
|
manifest_folder = os.path.join(codeunit_folder, "Other", "Artifacts", "WinGet-Manifest")
|
3069
3037
|
GeneralUtilities.assert_folder_exists(artifacts_folder)
|
3070
|
-
artifacts_file =
|
3038
|
+
artifacts_file = self.__sc.find_file_by_extension(artifacts_folder, "zip")
|
3071
3039
|
winget_template_file = os.path.join(build_folder, "WinGet-Template.yaml")
|
3072
3040
|
winget_manifest_file = os.path.join(manifest_folder, "WinGet-Manifest.yaml")
|
3073
3041
|
GeneralUtilities.assert_file_exists(winget_template_file)
|
@@ -3502,3 +3470,57 @@ class TasksForCommonProjectStructure:
|
|
3502
3470
|
excluded = ["opendms"]
|
3503
3471
|
iu.update_all_services_in_docker_compose_file(dockercomposefile, VersionEcholon.LatestPatchOrLatestMinor, excluded)
|
3504
3472
|
iu.check_for_newest_version(dockercomposefile, excluded)
|
3473
|
+
|
3474
|
+
@GeneralUtilities.check_arguments
|
3475
|
+
def clone_repository_as_resource(self, local_repository_folder: str, remote_repository_link: str, resource_name: str, repository_subname: str = None) -> None:
|
3476
|
+
GeneralUtilities.write_message_to_stdout(f'Clone resource {resource_name}...')
|
3477
|
+
resrepo_commit_id_folder: str = os.path.join(local_repository_folder, "Other", "Resources", f"{resource_name}Version")
|
3478
|
+
resrepo_commit_id_file: str = os.path.join(resrepo_commit_id_folder, f"{resource_name}Version.txt")
|
3479
|
+
latest_version: str = GeneralUtilities.read_text_from_file(resrepo_commit_id_file)
|
3480
|
+
resrepo_data_folder: str = os.path.join(local_repository_folder, "Other", "Resources", resource_name).replace("\\", "/")
|
3481
|
+
current_version: str = None
|
3482
|
+
resrepo_data_version: str = os.path.join(resrepo_data_folder, f"{resource_name}Version.txt")
|
3483
|
+
if os.path.isdir(resrepo_data_folder):
|
3484
|
+
if os.path.isfile(resrepo_data_version):
|
3485
|
+
current_version = GeneralUtilities.read_text_from_file(resrepo_data_version)
|
3486
|
+
if (current_version is None) or (current_version != latest_version):
|
3487
|
+
target_folder: str = resrepo_data_folder
|
3488
|
+
if repository_subname is not None:
|
3489
|
+
target_folder = f"{resrepo_data_folder}/{repository_subname}"
|
3490
|
+
GeneralUtilities.ensure_folder_exists_and_is_empty(target_folder)
|
3491
|
+
self.__sc.run_program("git", f"clone --recurse-submodules {remote_repository_link} {target_folder}")
|
3492
|
+
self.__sc.run_program("git", f"checkout {latest_version}", target_folder)
|
3493
|
+
GeneralUtilities.write_text_to_file(resrepo_data_version, latest_version)
|
3494
|
+
|
3495
|
+
git_folders: list[str] = []
|
3496
|
+
git_files: list[str] = []
|
3497
|
+
for dirpath, dirnames, filenames in os.walk(target_folder):
|
3498
|
+
for dirname in dirnames:
|
3499
|
+
if dirname == ".git":
|
3500
|
+
full_path = os.path.join(dirpath, dirname)
|
3501
|
+
git_folders.append(full_path)
|
3502
|
+
for filename in filenames:
|
3503
|
+
if filename == ".git":
|
3504
|
+
full_path = os.path.join(dirpath, filename)
|
3505
|
+
git_files.append(full_path)
|
3506
|
+
for git_folder in git_folders:
|
3507
|
+
if os.path.isdir(git_folder):
|
3508
|
+
GeneralUtilities.ensure_directory_does_not_exist(git_folder)
|
3509
|
+
for git_file in git_files:
|
3510
|
+
if os.path.isdir(git_file):
|
3511
|
+
GeneralUtilities.ensure_file_does_not_exist(git_file)
|
3512
|
+
|
3513
|
+
def set_latest_version_for_clone_repository_as_resource(self, resourcename: str, github_link: str, branch: str = "main"):
|
3514
|
+
current_file = str(Path(__file__).absolute())
|
3515
|
+
repository_folder = GeneralUtilities.resolve_relative_path("../../..", current_file)
|
3516
|
+
|
3517
|
+
resrepo_commit_id_folder: str = os.path.join(repository_folder, "Other", "Resources", f"{resourcename}Version")
|
3518
|
+
resrepo_commit_id_file: str = os.path.join(resrepo_commit_id_folder, f"{resourcename}Version.txt")
|
3519
|
+
current_version: str = GeneralUtilities.read_text_from_file(resrepo_commit_id_file)
|
3520
|
+
|
3521
|
+
stdOut = [l.split("\t") for l in GeneralUtilities.string_to_lines(self.__sc.run_program("git", f"ls-remote {github_link}")[1])]
|
3522
|
+
stdOut = [l for l in stdOut if l[1] == f"refs/heads/{branch}"]
|
3523
|
+
GeneralUtilities.assert_condition(len(stdOut) == 1)
|
3524
|
+
latest_version: str = stdOut[0][0]
|
3525
|
+
if current_version != latest_version:
|
3526
|
+
GeneralUtilities.write_text_to_file(resrepo_commit_id_file, latest_version)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ScriptCollection
|
3
|
-
Version: 3.5.
|
3
|
+
Version: 3.5.153
|
4
4
|
Summary: The ScriptCollection is the place for reusable scripts.
|
5
5
|
Home-page: https://github.com/anionDev/ScriptCollection
|
6
6
|
Author: Marius Göcke
|
@@ -23,12 +23,12 @@ Classifier: Topic :: Utilities
|
|
23
23
|
Requires-Python: >=3.10
|
24
24
|
Description-Content-Type: text/markdown
|
25
25
|
Requires-Dist: build>=1.3.0
|
26
|
-
Requires-Dist: coverage>=7.10.
|
26
|
+
Requires-Dist: coverage>=7.10.5
|
27
27
|
Requires-Dist: cyclonedx-bom>=7.0.0
|
28
28
|
Requires-Dist: defusedxml>=0.7.1
|
29
29
|
Requires-Dist: keyboard>=0.13.5
|
30
30
|
Requires-Dist: lcov-cobertura>=2.1.1
|
31
|
-
Requires-Dist: lxml>=6.0.
|
31
|
+
Requires-Dist: lxml>=6.0.1
|
32
32
|
Requires-Dist: ntplib>=0.4.0
|
33
33
|
Requires-Dist: Pillow>=11.3.0
|
34
34
|
Requires-Dist: psutil>=7.0.0
|
@@ -36,7 +36,7 @@ Requires-Dist: pycdlib>=1.14.0
|
|
36
36
|
Requires-Dist: Pygments>=2.19.2
|
37
37
|
Requires-Dist: pylint>=3.3.8
|
38
38
|
Requires-Dist: pyOpenSSL>=25.1.0
|
39
|
-
Requires-Dist: PyPDF>=
|
39
|
+
Requires-Dist: PyPDF>=6.0.0
|
40
40
|
Requires-Dist: pytest>=8.4.1
|
41
41
|
Requires-Dist: PyYAML>=6.0.2
|
42
42
|
Requires-Dist: qrcode>=8.2
|
@@ -0,0 +1,17 @@
|
|
1
|
+
ScriptCollection/CertificateUpdater.py,sha256=OAxrG21k_o3W3niOOGNSZzUPJlvolOWc1lRB2dMhc3g,9212
|
2
|
+
ScriptCollection/Executables.py,sha256=BojgHGBYn5QqpsdIgn8r8raxb8bE_BUyb-fZ_rCEN0A,37050
|
3
|
+
ScriptCollection/GeneralUtilities.py,sha256=t8xp0s10V-MrWYQQiMx0ae3LLTM8G2wPyyWXqeIteXQ,48023
|
4
|
+
ScriptCollection/ImageUpdater.py,sha256=qTe3yoqzQJY7LZdXBbjbWvrsSQaeHy1VwmOxaRzU2ig,29305
|
5
|
+
ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
|
6
|
+
ScriptCollection/ProgramRunnerBase.py,sha256=2kMIAqdc65UjBAddOZkzy_aFx9h5roZ5a4bQNM6RV6Y,2480
|
7
|
+
ScriptCollection/ProgramRunnerEpew.py,sha256=4pjEd0r9Fcz3TTDv0MdTSd5KkigYXcWUVI1X43regfU,6477
|
8
|
+
ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
|
9
|
+
ScriptCollection/SCLog.py,sha256=49NlLEmK_f-icw_uEPq9U3qv-oBTMRcIqSg3jaO8VsA,4360
|
10
|
+
ScriptCollection/ScriptCollectionCore.py,sha256=XzMdqcTRG9UAV3uyZjvWYsa-hbMbSoT3Axb3OqIRMig,139119
|
11
|
+
ScriptCollection/TasksForCommonProjectStructure.py,sha256=glEoCoC9FotsG4jRu5-LgvvTB_qFntKlXT1kGhgy3s4,247136
|
12
|
+
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
+
scriptcollection-3.5.153.dist-info/METADATA,sha256=JvDOgE8UQCgopI-CORbEa3VeFodQY-YJgXORPqjoUfc,7689
|
14
|
+
scriptcollection-3.5.153.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
scriptcollection-3.5.153.dist-info/entry_points.txt,sha256=yZlEK0r5Ie7xrSLdlWZgFqzLZiIctsIAUJvDCgrYBRo,4193
|
16
|
+
scriptcollection-3.5.153.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
17
|
+
scriptcollection-3.5.153.dist-info/RECORD,,
|
@@ -56,4 +56,5 @@ scshowmissingfiles = ScriptCollection.Executables:ShowMissingFiles
|
|
56
56
|
scsigncertificate = ScriptCollection.Executables:SignCertificate
|
57
57
|
scupdateimagesindockercomposefile = ScriptCollection.Executables:UpdateImagesInDockerComposeFile
|
58
58
|
scupdatenugetpackagesincsharpproject = ScriptCollection.Executables:UpdateNugetpackagesInCsharpProject
|
59
|
+
scupdatetimestampinfile = ScriptCollection.Executables:UpdateTimestampInFile
|
59
60
|
scuploadfile = ScriptCollection.Executables:UploadFile
|
@@ -1,17 +0,0 @@
|
|
1
|
-
ScriptCollection/CertificateUpdater.py,sha256=OAxrG21k_o3W3niOOGNSZzUPJlvolOWc1lRB2dMhc3g,9212
|
2
|
-
ScriptCollection/Executables.py,sha256=eX94RLNBarpWoZKeDo02gcP_qzmJDZcIx8XBZFVCFNc,36396
|
3
|
-
ScriptCollection/GeneralUtilities.py,sha256=PKdzq382RYVSWeSG_6z6FiHu-SiTOi2BavJKvP-0slU,47308
|
4
|
-
ScriptCollection/ImageUpdater.py,sha256=3B5pgAMnyne3ZogWz-suqglZGIB9FAKyWn31P9E1ST0,24491
|
5
|
-
ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
|
6
|
-
ScriptCollection/ProgramRunnerBase.py,sha256=2kMIAqdc65UjBAddOZkzy_aFx9h5roZ5a4bQNM6RV6Y,2480
|
7
|
-
ScriptCollection/ProgramRunnerEpew.py,sha256=4pjEd0r9Fcz3TTDv0MdTSd5KkigYXcWUVI1X43regfU,6477
|
8
|
-
ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
|
9
|
-
ScriptCollection/SCLog.py,sha256=GJ44S6VaBVwX5Dd6MIrdZn6I0dpaaYKVq9w-N0nMXlo,4496
|
10
|
-
ScriptCollection/ScriptCollectionCore.py,sha256=YJ6uOGQa224jtsva_OX3r8h2aIzGR9GAfJH4h-9iIAc,138093
|
11
|
-
ScriptCollection/TasksForCommonProjectStructure.py,sha256=9vccEWsxlW7xGXFLc2RPPFMWCkmoGxbSGu7hi9NxkeU,244959
|
12
|
-
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
scriptcollection-3.5.151.dist-info/METADATA,sha256=-EuHJHBjH-Oe9njZujrMzqr5aUXDVt_20DyCPY_81RE,7689
|
14
|
-
scriptcollection-3.5.151.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
-
scriptcollection-3.5.151.dist-info/entry_points.txt,sha256=AvmVO9iyWImExpvzL3YYQ9AOEiUIN9guPRRG_W_VNWY,4116
|
16
|
-
scriptcollection-3.5.151.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
17
|
-
scriptcollection-3.5.151.dist-info/RECORD,,
|
File without changes
|
File without changes
|