From f359d450373c05cb07693d111df32adefab73bb8 Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@uliege.be>
Date: Mon, 21 Sep 2020 11:09:10 +0200
Subject: [PATCH] add patch version in API version: it's not strictly necessary
 (we don't break the API between patch releases), but it makes things simpler.

rationale: with non-breaking API changes (e.g. adding a new function) one had to use gmsh/option/getNumber("General.Version") to check the Gmsh version; using the same numbering for the API and for Gmsh means one can simply examine the API version.

Fixes #997
---
 api/GenApi.py    | 115 +++++++++++++++++++++++++----------------------
 api/gen.py       |   5 ++-
 api/gmsh.h       |   5 ++-
 api/gmsh.h_cwrap |   2 +-
 api/gmsh.jl      |   5 ++-
 api/gmsh.py      |   3 +-
 api/gmshc.h      |   5 ++-
 7 files changed, 78 insertions(+), 62 deletions(-)

diff --git a/api/GenApi.py b/api/GenApi.py
index 90667ab6bf..a655a0c15d 100644
--- a/api/GenApi.py
+++ b/api/GenApi.py
@@ -793,7 +793,7 @@ cpp_header = """// {0}
 #ifndef {2}_H
 #define {2}_H
 
-// This file defines the {3} C++ API (v{4}.{5}).
+// This file defines the {3} C++ API (v{4}.{5}.{6}).
 //
 // Do not edit it directly: it is automatically generated by `api/gen.py'.
 //
@@ -807,9 +807,10 @@ cpp_header = """// {0}
 #include <utility>
 #include <functional>
 
-#define {2}_API_VERSION "{4}.{5}"
+#define {2}_API_VERSION "{4}.{5}.{6}"
 #define {2}_API_VERSION_MAJOR {4}
 #define {2}_API_VERSION_MINOR {5}
+#define {2}_API_VERSION_PATCH {6}
 
 #if defined({2}_DLL)
 #if defined({2}_DLL_EXPORT)
@@ -825,7 +826,7 @@ cpp_header = """// {0}
 #define M_PI (3.14159265358979323846)
 #endif
 
-namespace {6} {{
+namespace {7} {{
 
   // A geometrical entity in the {3} API is represented by two integers: its
   // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
@@ -852,7 +853,7 @@ c_header = """/*
 #define {2}C_H
 
 /*
- * This file defines the {3} C API (v{4}.{5}).
+ * This file defines the {3} C API (v{4}.{5}.{6}).
  *
  * Do not edit it directly: it is automatically generated by `api/gen.py'.
  *
@@ -862,9 +863,10 @@ c_header = """/*
 
 #include <stddef.h>
 
-#define {2}_API_VERSION "{4}.{5}"
+#define {2}_API_VERSION "{4}.{5}.{6}"
 #define {2}_API_VERSION_MAJOR {4}
 #define {2}_API_VERSION_MINOR {5}
+#define {2}_API_VERSION_PATCH {6}
 
 #if defined({2}_DLL)
 #if defined({2}_DLL_EXPORT)
@@ -876,8 +878,8 @@ c_header = """/*
 #define {2}_API
 #endif
 
-{2}_API void {6}Free(void *p);
-{2}_API void *{6}Malloc(size_t n);
+{2}_API void {7}Free(void *p);
+{2}_API void *{7}Malloc(size_t n);
 """
 
 c_footer = """
@@ -927,16 +929,16 @@ cwrap_header = """// {0}
 #ifndef {2}_H
 #define {2}_H
 
-// This file redefines the {3} C++ API in terms of the C API (v{4}.{5}).
+// This file redefines the {3} C++ API in terms of the C API (v{4}.{5}.{6}).
 //
 // This is provided as a convenience for users of the binary {3} SDK whose C++
 // compiler ABI is not compatible with the ABI of the C++ compiler used to create
-// the SDK (and who can thus not directly use the C++ API defined in `{6}.h').
+// the SDK (and who can thus not directly use the C++ API defined in `{7}.h').
 //
-// To use this header file in your C++ code, simply rename it as `{6}.h'.
+// To use this header file in your C++ code, simply rename it as `{7}.h'.
 //
 // Note that using this header file will lead to (slightly) reduced performance
-// compared to using the native {3} C++ API from the original `{6}.h', as it
+// compared to using the native {3} C++ API from the original `{7}.h', as it
 // entails additional data copies between this C++ wrapper, the C API and the
 // native C++ code.
 //
@@ -952,10 +954,10 @@ cwrap_header = """// {0}
 #endif
 
 extern \"C\" {{
-  #include "{6}c.h"
+  #include "{7}c.h"
 }}
 
-namespace {6} {{
+namespace {7} {{
 
   // A geometrical entity in the {3} API is represented by two integers: its
   // dimension (dim = 0, 1, 2 or 3) and its tag (its unique, strictly positive
@@ -1019,7 +1021,7 @@ python_header = """# {0}
 # See the LICENSE.txt file for license information. Please report all
 # issues on {1}
 
-# This file defines the {2} Python API (v{3}.{4}).
+# This file defines the {2} Python API (v{3}.{4}.{5}).
 #
 # Do not edit it directly: it is automatically generated by `api/gen.py'.
 #
@@ -1034,23 +1036,24 @@ import os
 import platform
 from math import pi
 
-{5}_API_VERSION = "{3}.{4}"
-{5}_API_VERSION_MAJOR = {3}
-{5}_API_VERSION_MINOR = {4}
+{6}_API_VERSION = "{3}.{4}"
+{6}_API_VERSION_MAJOR = {3}
+{6}_API_VERSION_MINOR = {4}
+{6}_API_VERSION_PATCH = {5}
 
-__version__ = {5}_API_VERSION
+__version__ = {6}_API_VERSION
 
 oldsig = signal.signal(signal.SIGINT, signal.SIG_DFL)
 libdir = os.path.dirname(os.path.realpath(__file__))
 if platform.system() == "Windows":
-    libpath = os.path.join(libdir, "{6}-{3}.{4}.dll")
+    libpath = os.path.join(libdir, "{7}-{3}.{4}.dll")
 elif platform.system() == "Darwin":
-    libpath = os.path.join(libdir, "lib{6}.dylib")
+    libpath = os.path.join(libdir, "lib{7}.dylib")
 else:
-    libpath = os.path.join(libdir, "lib{6}.so")
+    libpath = os.path.join(libdir, "lib{7}.so")
 
 if not os.path.exists(libpath):
-    libpath = find_library("{6}")
+    libpath = find_library("{7}")
 
 lib = CDLL(libpath)
 
@@ -1069,77 +1072,77 @@ except:
 
 def _ostring(s):
     sp = s.value.decode("utf-8")
-    lib.{6}Free(s)
+    lib.{7}Free(s)
     return sp
 
 def _ovectorpair(ptr, size):
     v = list((ptr[i * 2], ptr[i * 2 + 1]) for i in range(size//2))
-    lib.{6}Free(ptr)
+    lib.{7}Free(ptr)
     return v
 
 def _ovectorint(ptr, size):
     if use_numpy:
         if size == 0 :
-            lib.{6}Free(ptr)
+            lib.{7}Free(ptr)
             return numpy.ndarray((0,),numpy.int32)
         v = numpy.ctypeslib.as_array(ptr, (size, ))
-        weakreffinalize(v, lib.{6}Free, ptr)
+        weakreffinalize(v, lib.{7}Free, ptr)
     else:
         v = list(ptr[i] for i in range(size))
-        lib.{6}Free(ptr)
+        lib.{7}Free(ptr)
     return v
 
 def _ovectorsize(ptr, size):
     if use_numpy:
         if size == 0 :
-            lib.{6}Free(ptr)
+            lib.{7}Free(ptr)
             return numpy.ndarray((0,),numpy.uintp)
         v = numpy.ctypeslib.as_array(ptr, (size, ))
-        weakreffinalize(v, lib.{6}Free, ptr)
+        weakreffinalize(v, lib.{7}Free, ptr)
     else:
         v = list(ptr[i] for i in range(size))
-        lib.{6}Free(ptr)
+        lib.{7}Free(ptr)
     return v
 
 def _ovectordouble(ptr, size):
     if use_numpy:
         if size == 0 :
-            lib.{6}Free(ptr)
+            lib.{7}Free(ptr)
             return numpy.ndarray((0,),numpy.float64)
         v = numpy.ctypeslib.as_array(ptr, (size, ))
-        weakreffinalize(v, lib.{6}Free, ptr)
+        weakreffinalize(v, lib.{7}Free, ptr)
     else:
         v = list(ptr[i] for i in range(size))
-        lib.{6}Free(ptr)
+        lib.{7}Free(ptr)
     return v
 
 def _ovectorstring(ptr, size):
     v = list(_ostring(cast(ptr[i], c_char_p)) for i in range(size))
-    lib.{6}Free(ptr)
+    lib.{7}Free(ptr)
     return v
 
 def _ovectorvectorint(ptr, size, n):
     v = [_ovectorint(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
-    lib.{6}Free(size)
-    lib.{6}Free(ptr)
+    lib.{7}Free(size)
+    lib.{7}Free(ptr)
     return v
 
 def _ovectorvectorsize(ptr, size, n):
     v = [_ovectorsize(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
-    lib.{6}Free(size)
-    lib.{6}Free(ptr)
+    lib.{7}Free(size)
+    lib.{7}Free(ptr)
     return v
 
 def _ovectorvectordouble(ptr, size, n):
     v = [_ovectordouble(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
-    lib.{6}Free(size)
-    lib.{6}Free(ptr)
+    lib.{7}Free(size)
+    lib.{7}Free(ptr)
     return v
 
 def _ovectorvectorpair(ptr, size, n):
     v = [_ovectorpair(pointer(ptr[i].contents), size[i]) for i in range(n.value)]
-    lib.{6}Free(size)
-    lib.{6}Free(ptr)
+    lib.{7}Free(size)
+    lib.{7}Free(ptr)
     return v
 
 def _ivectorint(o):
@@ -1217,7 +1220,7 @@ julia_header = """# {0}
 # See the LICENSE.txt file for license information. Please report all
 # issues on {1}
 
-# This file defines the {2} Julia API (v{3}.{4}).
+# This file defines the {2} Julia API (v{3}.{4}.{5}).
 #
 # Do not edit it directly: it is automatically generated by `api/gen.py'.
 #
@@ -1235,12 +1238,14 @@ class API:
         self,
         version_major,
         version_minor,
+        version_patch,
         namespace="gmsh",
         code="Gmsh",
         copyright="Gmsh - Copyright (C) 1997-2020 C. Geuzaine, J.-F. Remacle",
         issues="https://gitlab.onelab.info/gmsh/gmsh/issues."):
         self.version_major = version_major
         self.version_minor = version_minor
+        self.version_patch = version_patch
         global ns
         ns = namespace
         self.code = code
@@ -1283,7 +1288,7 @@ class API:
             f.write(
                 cpp_header.format(self.copyright, self.issues, ns.upper(),
                                   self.code, self.version_major,
-                                  self.version_minor, ns))
+                                  self.version_minor, self.version_patch, ns))
             for m in self.modules:
                 write_module(m, "", "")
             f.write(cpp_footer)
@@ -1376,9 +1381,9 @@ class API:
             with open(ns + "c.cpp", "w") as fc:
                 with open(ns + ".h_cwrap", "w") as fcwrap:
                     f.write(
-                        c_header.format(self.copyright, self.issues,
-                                        ns.upper(), self.code,
-                                        self.version_major, self.version_minor,
+                        c_header.format(self.copyright, self.issues, ns.upper(),
+                                        self.code, self.version_major,
+                                        self.version_minor, self.version_patch,
                                         ns))
                     fc.write(
                         c_cpp_header.format(self.copyright, self.issues, ns,
@@ -1389,8 +1394,8 @@ class API:
                     fcwrap.write(
                         cwrap_header.format(self.copyright, self.issues,
                                             ns.upper(), self.code,
-                                            self.version_major,
-                                            self.version_minor, ns))
+                                            self.version_major, self.version_minor,
+                                            self.version_patch, ns))
                     fcwrap.write("namespace " + ns + " {\n")
                     s = cwrap_utils.format(ns, "inline ").split('\n')
                     for line in s:
@@ -1489,7 +1494,7 @@ class API:
             f.write(
                 python_header.format(self.copyright, self.issues, self.code,
                                      self.version_major, self.version_minor,
-                                     ns.upper(), ns))
+                                     self.version_patch, ns.upper(), ns))
             for module in self.modules:
                 write_module(f, module, "", "", "")
 
@@ -1553,12 +1558,15 @@ class API:
             f.write('"""\n')
             f.write("module " + m.name + "\n\n")
             if level == 1:
-                f.write('const {0}_API_VERSION = "{1}.{2}"\n'.format(
-                    ns.upper(), self.version_major, self.version_minor))
+                f.write('const {0}_API_VERSION = "{1}.{2}.{3}"\n'.format(
+                    ns.upper(), self.version_major, self.version_minor,
+                    self.version_patch))
                 f.write('const {0}_API_VERSION_MAJOR = {1}\n'.format(
                     ns.upper(), self.version_major))
                 f.write('const {0}_API_VERSION_MINOR = {1}\n'.format(
                     ns.upper(), self.version_minor))
+                f.write('const {0}_API_VERSION_PATCH = {1}\n'.format(
+                    ns.upper(), self.version_patch))
                 f.write('const libdir = dirname(@__FILE__)\n')
                 f.write(
                     'const libname = Sys.iswindows() ? "' + ns +
@@ -1584,7 +1592,8 @@ class API:
         with open(ns + ".jl", "w") as f:
             f.write(
                 julia_header.format(self.copyright, self.issues, self.code,
-                                    self.version_major, self.version_minor))
+                                    self.version_major, self.version_minor,
+                                    self.version_patch))
             for module in self.modules:
                 write_module(f, module, "", "", 1)
 
diff --git a/api/gen.py b/api/gen.py
index 9751f897cc..608df93183 100644
--- a/api/gen.py
+++ b/api/gen.py
@@ -34,8 +34,11 @@ with open(os.path.join(dirname, '..', 'CMakeLists.txt'), 'rt') as f:
     start = contents.find('GMSH_MINOR_VERSION') + 18
     end = contents.find(')', start)
     version_minor = int(contents[start:end])
+    start = contents.find('GMSH_PATCH_VERSION') + 18
+    end = contents.find(')', start)
+    version_patch = int(contents[start:end])
 
-api = API(version_major, version_minor)
+api = API(version_major, version_minor, version_patch)
 
 ################################################################################
 
diff --git a/api/gmsh.h b/api/gmsh.h
index 398ee4f9c2..6876adf170 100644
--- a/api/gmsh.h
+++ b/api/gmsh.h
@@ -6,7 +6,7 @@
 #ifndef GMSH_H
 #define GMSH_H
 
-// This file defines the Gmsh C++ API (v4.7).
+// This file defines the Gmsh C++ API (v4.7.0).
 //
 // Do not edit it directly: it is automatically generated by `api/gen.py'.
 //
@@ -20,9 +20,10 @@
 #include <utility>
 #include <functional>
 
-#define GMSH_API_VERSION "4.7"
+#define GMSH_API_VERSION "4.7.0"
 #define GMSH_API_VERSION_MAJOR 4
 #define GMSH_API_VERSION_MINOR 7
+#define GMSH_API_VERSION_PATCH 0
 
 #if defined(GMSH_DLL)
 #if defined(GMSH_DLL_EXPORT)
diff --git a/api/gmsh.h_cwrap b/api/gmsh.h_cwrap
index 701fb6b296..b888633143 100644
--- a/api/gmsh.h_cwrap
+++ b/api/gmsh.h_cwrap
@@ -6,7 +6,7 @@
 #ifndef GMSH_H
 #define GMSH_H
 
-// This file redefines the Gmsh C++ API in terms of the C API (v4.7).
+// This file redefines the Gmsh C++ API in terms of the C API (v4.7.0).
 //
 // This is provided as a convenience for users of the binary Gmsh SDK whose C++
 // compiler ABI is not compatible with the ABI of the C++ compiler used to create
diff --git a/api/gmsh.jl b/api/gmsh.jl
index 43b25cb67c..399e19e021 100644
--- a/api/gmsh.jl
+++ b/api/gmsh.jl
@@ -3,7 +3,7 @@
 # See the LICENSE.txt file for license information. Please report all
 # issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
 
-# This file defines the Gmsh Julia API (v4.7).
+# This file defines the Gmsh Julia API (v4.7.0).
 #
 # Do not edit it directly: it is automatically generated by `api/gen.py'.
 #
@@ -17,9 +17,10 @@ Top-level functions
 """
 module gmsh
 
-const GMSH_API_VERSION = "4.7"
+const GMSH_API_VERSION = "4.7.0"
 const GMSH_API_VERSION_MAJOR = 4
 const GMSH_API_VERSION_MINOR = 7
+const GMSH_API_VERSION_PATCH = 0
 const libdir = dirname(@__FILE__)
 const libname = Sys.iswindows() ? "gmsh-4.7.dll" : "libgmsh"
 import Libdl
diff --git a/api/gmsh.py b/api/gmsh.py
index a59f888959..256331908c 100644
--- a/api/gmsh.py
+++ b/api/gmsh.py
@@ -3,7 +3,7 @@
 # See the LICENSE.txt file for license information. Please report all
 # issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
 
-# This file defines the Gmsh Python API (v4.7).
+# This file defines the Gmsh Python API (v4.7.0).
 #
 # Do not edit it directly: it is automatically generated by `api/gen.py'.
 #
@@ -21,6 +21,7 @@ from math import pi
 GMSH_API_VERSION = "4.7"
 GMSH_API_VERSION_MAJOR = 4
 GMSH_API_VERSION_MINOR = 7
+GMSH_API_VERSION_PATCH = 0
 
 __version__ = GMSH_API_VERSION
 
diff --git a/api/gmshc.h b/api/gmshc.h
index 777a877bfb..336ec77b7b 100644
--- a/api/gmshc.h
+++ b/api/gmshc.h
@@ -9,7 +9,7 @@
 #define GMSHC_H
 
 /*
- * This file defines the Gmsh C API (v4.7).
+ * This file defines the Gmsh C API (v4.7.0).
  *
  * Do not edit it directly: it is automatically generated by `api/gen.py'.
  *
@@ -19,9 +19,10 @@
 
 #include <stddef.h>
 
-#define GMSH_API_VERSION "4.7"
+#define GMSH_API_VERSION "4.7.0"
 #define GMSH_API_VERSION_MAJOR 4
 #define GMSH_API_VERSION_MINOR 7
+#define GMSH_API_VERSION_PATCH 0
 
 #if defined(GMSH_DLL)
 #if defined(GMSH_DLL_EXPORT)
-- 
GitLab