Add Windows support to `get-stx.py` script
authorJan Vrany <jan.vrany@labware.com>
Sun, 10 Jul 2022 10:54:11 +0200
changeset 327 d1f3217edb67
parent 326 42a9250a00b2
child 328 8d869177607c
Add Windows support to `get-stx.py` script
bin/get-stx.py
--- a/bin/get-stx.py	Mon Jun 27 15:27:52 2022 +0100
+++ b/bin/get-stx.py	Sun Jul 10 10:54:11 2022 +0200
@@ -118,20 +118,39 @@
         raise
 
 def extract(url, dir_name = '.'):
-    def unpack_tar(tarfile, dir_name):
-        try:
-            tarfile_root_dir = None
-            unpacked = []
-            for member in tarfile:
-                if member.isdir():
-                    if tarfile_root_dir is None or len(tarfile_root_dir) > len(member.name):
-                        tarfile_root_dir = member.name
-                tarfile.extract(member, dir_name)
-            return os.path.join(dir_name, tarfile_root_dir)
-        except:
-            if tarfile_root_dir is not None and os.path.exists(tarfile_root_dir):
-                os.remove(tarfile_root_dir)
-            raise
+    def unpack_tar(file_name, dir_name):
+        import tarfile
+        with tarfile.open(file_name, "r:bz2") as archive:
+            try:
+                archive_root_dir = None
+                unpacked = []
+                for member in archive:
+                    if member.isdir():
+                        if archive_root_dir is None or len(archive_root_dir) > len(member.name):
+                            archive_root_dir = member.name
+                    archive.extract(member, dir_name)
+                return os.path.join(dir_name, archive_root_dir)
+            except:
+                if archive_root_dir is not None and os.path.exists(archive_root_dir):
+                    os.remove(archive_root_dir)
+                raise
+
+    def unpack_zip(file_name, dir_name):
+        import zipfile
+        with zipfile.ZipFile(file_name) as archive:
+            try:
+                archive_root_dir = None
+                unpacked = []
+                for member in archive.infolist():
+                    if member.is_dir():
+                        if archive_root_dir is None or len(archive_root_dir) > len(member.filename):
+                            archive_root_dir = member.filename
+                    archive.extract(member, dir_name)
+                return os.path.join(dir_name, archive_root_dir)
+            except:
+                if archive_root_dir is not None and os.path.exists(archive_root_dir):
+                    os.remove(archive_root_dir)
+                raise
 
     file_name = os.path.join(dir_name, basename_url(url))
     try:
@@ -139,12 +158,13 @@
             download(url, file_name)
 
         if file_name.endswith('.tar.bz2') or file_name.endswith('.tbz2'):
-            import tarfile
-            with tarfile.open(file_name, "r:bz2") as archive:
-                print("Extracting: %s" % file_name)
-                stx_dir = unpack_tar(archive, dir_name)
+            print("Extracting: %s" % file_name)
+            stx_dir = unpack_tar(file_name, dir_name)
+        elif file_name.endswith('.zip'):
+            print("Extracting: %s" % file_name)
+            stx_dir = unpack_zip(file_name, dir_name)
         else:
-            raise Exception('archive type not supported')
+            raise Exception("archive type not supported: %s" % file_name)
         if os.path.exists(stx_dir):
             os.rename(stx_dir, os.path.join(dir_name, 'stx'))
             print("")
@@ -157,12 +177,16 @@
 def host_triplet():
     import platform
     uname = platform.uname()
-    if uname.machine == 'x86_64':
-        if uname.system == 'Linux':
-            return 'x86_64-pc-linux-gnu'
-    raise Exception("unsupported host type: %s" % uname)
+    if uname.system == 'Linux' and uname.machine == 'x86_64':
+        return 'x86_64-pc-linux-gnu'
+    elif uname.system == 'Windows' and uname.machine == 'AMD64':
+        return 'x86_64-w64-mingw32'
+    elif uname.system.startswith('MSYS_NT-') and uname.machine == 'x86_64':
+        return 'x86_64-w64-mingw32'
+    else:
+        raise Exception("unsupported host type: " + str(uname))
 
-def get_stx(repo, dir_name):
+def get_stx(repo, target_triplet, dir_name):
     if not os.path.exists(dir_name):
         raise Exception("no such directory: %s" % dir_name)
     elif not os.path.isdir(dir_name):
@@ -171,7 +195,7 @@
         raise Exception("file or directory already exists: %s" % os.path.join(dir_name, 'stx'))
 
     build = repo.latest()
-    artifact = build.artifact('smalltalkx-jv-branch-\d+.\d+.\d+_build\d+_%s\.' % host_triplet())
+    artifact = build.artifact('smalltalkx-jv-branch-\d+.\d+.\d+_build\d+_%s\.' % target_triplet)
     extract(artifact.url(), dir_name)
 
 if __name__ == '__main__':
@@ -179,15 +203,19 @@
     import sys
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument("directory",
-                      nargs='?',
-                      help="directory where download and extract Smalltalk/X jv-branch (default is current directory)",
-                      default='.')
+                        nargs='?',
+                        help="directory where download and extract Smalltalk/X jv-branch (default is current directory)",
+                        default='.')
+    parser.add_argument("--target",
+                        default=host_triplet(),
+                        help="target system to run St/X on ('x86_64-pc-linux-gnu' or 'x86_64-w64-mingw32')")
     options = parser.parse_args(sys.argv[1:])
 
     repo = PlainHTTPRepository()
-    dir_name = options.directory
 
     try:
-        get_stx(repo, dir_name)
+        get_stx(repo, options.target, options.directory)
     except Exception as ex:
         sys.stderr.write("ERROR: %s\n" % str(ex))
+        # for debugging:
+        #raise ex