No need to run on Python 2 any more.
[cdist.git] / cdist
diff --git a/cdist b/cdist
index 9b164e74c8a9fa55dc17fee114e73dcae549cb50..0c9874f5934a7f29d4ebb1c5a9a23143168cddf3 100755 (executable)
--- a/cdist
+++ b/cdist
@@ -29,6 +29,7 @@ import os
 from pathlib import Path
 import platform
 import re
+import signal
 import shlex
 import shutil
 import subprocess
@@ -87,7 +88,7 @@ globals = Globals()
 # Configuration
 #
 
-class Option(object):
+class Option:
     def __init__(self, key, default=None):
         self.key = key
         self.value = default
@@ -96,7 +97,7 @@ class Option(object):
         if key == self.key:
             self.value = value
 
-class BoolOption(object):
+class BoolOption:
     def __init__(self, key):
         self.key = key
         self.value = False
@@ -382,7 +383,7 @@ class Version:
 # Targets
 #
 
-class Target(object):
+class Target:
     """
     Class representing the target that we are building for.  This is exposed to cscripts,
     though not all of it is guaranteed 'API'.  cscripts may expect:
@@ -447,19 +448,16 @@ class Target(object):
             copyfile(p, os.path.join(output_dir, os.path.basename(devel_to_git(tree.commit, p))))
 
     def package(self, project, checkout, output_dir, options, notarize):
-        # Build the dependencies; the cscript must call its own build() method if it needs to
-        tree = globals.trees.get(project, checkout, self)
-        if self.build_dependencies:
-            tree.build_dependencies(options)
+        tree = self.build(project, checkout, options, for_package=True)
         tree.add_defaults(options)
         p = self._cscript_package(tree, options)
         self._copy_packages(tree, p, output_dir)
 
-    def build(self, project, checkout, options):
+    def build(self, project, checkout, options, for_package=False):
         tree = globals.trees.get(project, checkout, self)
         if self.build_dependencies:
             tree.build_dependencies(options)
-        tree.build(options)
+        tree.build(options, for_package=for_package)
         return tree
 
     def test(self, project, checkout, target, test, options):
@@ -546,12 +544,17 @@ class DockerTarget(Target):
         if self.privileged:
             opts += '--privileged=true '
         if self.ccache:
-            opts += "-e CCACHE_DIR=/ccache/%s-%d --mount source=ccache,target=/ccache" % (self.image, os.getuid())
+            opts += "-e CCACHE_DIR=/ccache/%s-%d --mount source=ccache,target=/ccache " % (self.image, os.getuid())
+        opts += "--rm "
 
         tag = self.image
         if config.has('docker_hub_repository'):
             tag = '%s:%s' % (config.get('docker_hub_repository'), tag)
 
+        def signal_handler(signum, frame):
+            raise Error('Killed')
+        signal.signal(signal.SIGTERM, signal_handler)
+
         self.container = command_and_read('%s run %s %s -itd %s /bin/bash' % (config.docker(), self._user_tag(), opts, tag))[0].strip()
 
     def command(self, cmd):
@@ -858,7 +861,7 @@ class OSXSingleTarget(OSXTarget):
             self.set('CXX', '"ccache g++"')
 
     def package(self, project, checkout, output_dir, options, notarize):
-        tree = self.build(project, checkout, options)
+        tree = self.build(project, checkout, options, for_package=True)
         tree.add_defaults(options)
         self.unlock_keychain()
         p = self._cscript_package_and_notarize(tree, options, self.can_notarize and notarize)
@@ -879,7 +882,7 @@ class OSXUniversalTarget(OSXTarget):
         for target in self.sub_targets:
             tree = globals.trees.get(project, checkout, target)
             tree.build_dependencies(options)
-            tree.build(options)
+            tree.build(options, for_package=True)
 
         self.unlock_keychain()
         tree = globals.trees.get(project, checkout, self)
@@ -888,7 +891,7 @@ class OSXUniversalTarget(OSXTarget):
             self._copy_packages(tree, p, output_dir)
 
 class SourceTarget(Target):
-    """Build a source .tar.bz2"""
+    """Build a source .tar.bz2 and .zst"""
     def __init__(self):
         super(SourceTarget, self).__init__('source')
 
@@ -904,8 +907,12 @@ class SourceTarget(Target):
         with TreeDirectory(tree):
             name = read_wscript_variable(os.getcwd(), 'APPNAME')
             command('./waf dist')
-            p = os.path.abspath('%s-%s.tar.bz2' % (name, tree.version))
-            copyfile(p, os.path.join(output_dir, os.path.basename(devel_to_git(tree.commit, p))))
+            bz2 = os.path.abspath('%s-%s.tar.bz2' % (name, tree.version))
+            copyfile(bz2, os.path.join(output_dir, os.path.basename(devel_to_git(tree.commit, bz2))))
+            command('tar xjf %s' % bz2)
+            command('tar --zstd -cf %s-%s.tar.zst %s-%s' % (name, tree.version, name, tree.version))
+            zstd = os.path.abspath('%s-%s.tar.zst' % (name, tree.version))
+            copyfile(zstd, os.path.join(output_dir, os.path.basename(devel_to_git(tree.commit, zstd))))
 
 # @param s Target string:
 #       windows-{32,64}
@@ -979,7 +986,7 @@ def target_factory(args):
 # Tree
 #
 
-class Tree(object):
+class Tree:
     """Description of a tree, which is a checkout of a project,
        possibly built.  This class is never exposed to cscripts.
        Attributes:
@@ -1014,7 +1021,7 @@ class Tree(object):
                 ref = '--reference-if-able %s/%s.git' % (config.get('git_reference'), self.name)
             else:
                 ref = ''
-            command('git clone %s %s %s/%s.git %s/src/%s' % (flags, ref, config.get('git_prefix'), self.name, target.directory, self.name))
+            command('git -c protocol.file.allow=always clone %s %s %s/%s.git %s/src/%s' % (flags, ref, config.get('git_prefix'), self.name, target.directory, self.name))
             os.chdir('%s/src/%s' % (target.directory, self.name))
 
             if self.commit_ish is not None:
@@ -1038,7 +1045,7 @@ class Tree(object):
                         if os.path.exists(ref_path):
                             ref = '--reference %s' % ref_path
                     path = path.split(' ')[1]
-                    command('git submodule --quiet update %s %s' % (ref, path))
+                    command('git -c protocol.file.allow=always submodule --quiet update %s %s' % (ref, path))
 
         if os.path.exists('%s/wscript' % proj):
             v = read_wscript_variable(proj, "VERSION");
@@ -1112,7 +1119,7 @@ class Tree(object):
         for i in self.dependencies(options):
             i[0].build(i[1])
 
-    def build(self, options):
+    def build(self, options, for_package=False):
         if self.built:
             return
 
@@ -1124,7 +1131,10 @@ class Tree(object):
         self.add_defaults(options)
 
         if not globals.dry_run:
-            if len(inspect.getfullargspec(self.cscript['build']).args) == 2:
+            num_args = len(inspect.getfullargspec(self.cscript['build']).args)
+            if num_args == 3:
+                self.call('build', options, for_package)
+            elif num_args == 2:
                 self.call('build', options)
             else:
                 self.call('build')
@@ -1241,8 +1251,8 @@ def main():
         if args.target is None:
             raise Error('you must specify -t or --target')
 
+        target = target_factory(args)
         try:
-            target = target_factory(args)
             target.build(args.project, args.checkout, get_command_line_options(args))
         finally:
             if not args.keep: