instanceVersions.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. ########################################################################
  2. # Searx-Qt - Lightweight desktop application for Searx.
  3. # Copyright (C) 2020-2022 CYBERDEViL
  4. #
  5. # This file is part of Searx-Qt.
  6. #
  7. # Searx-Qt is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # Searx-Qt is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ########################################################################
  21. import datetime
  22. class VersionType:
  23. Unknown = 0
  24. Semantic = 1
  25. Date = 2
  26. class VersionFlags:
  27. No = 0 # No flags
  28. Git = 1 # Git version (short commit hash present)
  29. # SearXNG: +dirty Uncommited changes to git (except searx/settings.yml)
  30. # See: https://github.com/searxng/searxng/blob/master/searx/version.py
  31. Dirty = 2
  32. Extra = 4 # SearXNG: TODO idk what this is, extra files?
  33. # SearX: Unknown git commit
  34. # See: Dockerfile:59:ARG VERSION_GITCOMMIT=unknown
  35. # See: https://github.com/searx/searx/blob/master/Dockerfile#L65C11-L65C34
  36. Unknown = 8
  37. Invalid = 128
  38. VERSION_TYPE_STR = [
  39. "Unknown",
  40. "Semantic",
  41. "Date"
  42. ]
  43. VERSION_FLAG_STR = {
  44. 0: "None",
  45. 1: "Git",
  46. 2: "Dirty",
  47. 4: "Extra",
  48. 8: "Unknown",
  49. 128: "Invalid"
  50. }
  51. class InstanceVersion:
  52. def __init__(self, versionString=""):
  53. self.set(versionString)
  54. def __str__(self):
  55. return self.__str
  56. def __ge__(self, other):
  57. # Check if Major/Year version is greater
  58. otherParts = other.parts()
  59. if self.__parts[0] < otherParts[0]:
  60. return False
  61. elif self.__parts[0] == otherParts[0]:
  62. # Check if Minor/Month version is greater
  63. if self.__parts[1] < otherParts[1]:
  64. return False
  65. elif self.__parts[1] == otherParts[1]:
  66. # Check if Patch/Day version is greater
  67. if self.__parts[2] < otherParts[2]:
  68. return False
  69. return True
  70. def __lt__(self, other):
  71. return not (self >= other)
  72. def type(self):
  73. return self.__type
  74. def flags(self):
  75. return self.__flags
  76. def isValid(self):
  77. return self.__valid
  78. def error(self):
  79. return self.__error
  80. def parts(self):
  81. # Tuple with three ints (semantic version or date)
  82. return self.__parts
  83. def partsString(self):
  84. return f"{self.__parts[0]}.{self.__parts[1]}.{self.__parts[2]}"
  85. def commitHash(self):
  86. return self.__commit
  87. def set(self, versionString):
  88. # SearX examples:
  89. # --------------
  90. # 1.0.0
  91. # 1.0.0-unknown
  92. # 1.1.0-69-75b859d2
  93. #
  94. # SearXNG examples:
  95. # ----------------
  96. # 1.0.0
  97. # 2023.10.22
  98. # 2023.10.22+526d5c7b3
  99. # 2023.10.22+526d5c7b3+dirty
  100. # 2023.10.22+526d5c7b3+extra
  101. # 2023.10.22+526d5c7b3+dirty+extra
  102. # 2023.10.22+fd1422a6 (1dcc5768)
  103. # Set/reset values
  104. self.__str = str(versionString)
  105. self.__type = VersionType.Unknown
  106. self.__flags = VersionFlags.No
  107. self.__parts = (0,0,0)
  108. self.__commit = ""
  109. self.__otherCommit = ""
  110. self.__valid = False
  111. self.__error = ""
  112. if not versionString:
  113. return
  114. separator = ""
  115. if "+" in versionString: # SearXNG version with additions
  116. elements = versionString.split("+")
  117. separator = "+"
  118. elif "-" in versionString: # SearX version with additions
  119. elements = versionString.split("-")
  120. separator = "-"
  121. else:
  122. elements = [versionString]
  123. vElements = elements[0].split(".") # Should be a tuple with 3 ints
  124. # Verify that 'vElements' its length is 3 and that all values are digits
  125. if len(vElements) != 3:
  126. self.__error = "not 3 elements seperated by '.'"
  127. return
  128. for vElem in vElements:
  129. if not vElem.isdigit():
  130. self.__error = "non digit value in version"
  131. return
  132. # Initial date version type detected
  133. if int(vElements[0]) > 2000:
  134. # Verify date version
  135. vYear = int(vElements[0])
  136. vMonth = int(vElements[1])
  137. vDay = int(vElements[2])
  138. thisYear = datetime.date.today().year
  139. # Verify that the year is either this year or of a maximum of 3 years
  140. # ago.
  141. if vYear > thisYear or vYear < (thisYear - 3):
  142. self.__error = "year of the date is out of range"
  143. return
  144. # Verify that the month is in range 1-12
  145. if vMonth < 1 or vMonth > 12:
  146. self.__error = "month of the date is out of range [1-12]"
  147. return
  148. # Verify that the day is in range 1-31
  149. if vDay < 1 or vDay > 31:
  150. self.__error = "day of the date is out of range [1-31]"
  151. return
  152. self.__type = VersionType.Date
  153. self.__parts = (vYear, vMonth, vDay)
  154. # Semantic version
  155. else:
  156. vMajor = int(vElements[0])
  157. vMinor = int(vElements[1])
  158. vPatch = int(vElements[2])
  159. self.__type = VersionType.Semantic
  160. self.__parts = (vMajor, vMinor, vPatch)
  161. # "+" or "-" found in the version string, probably a git short hash is
  162. # behind the first separator, we need to check that it is actually a
  163. # short commit hash.
  164. if len(elements) > 1:
  165. # SearX:
  166. # "unknown" addition, example: "1.0.0-unknown"
  167. if elements[1] == "unknown":
  168. if len(elements) > 2:
  169. self.__error = "did not expect anything after '-unknown'"
  170. return
  171. self.__flags += VersionFlags.Unknown
  172. self.__valid = True
  173. return
  174. # Here we assume the first element is a short commit hash
  175. vHash = elements[1]
  176. # SearXNG:
  177. # It could be the case that there is a space and then another hash
  178. # between parentheses, example: "2023.10.5+fd1422a6 (1dcc5768)". IDK
  179. # what that hash represents, so TODO.
  180. if " " in vHash:
  181. spaceSepElems = vHash.split(" ")
  182. # We expect two elements after split by space in this case.
  183. if len(spaceSepElems) != 2:
  184. self.__error = "unknown format (1)"
  185. return
  186. otherHash = spaceSepElems[1]
  187. # Check that the length of the other hash is in expected range.
  188. if len(otherHash) < 10 or len(otherHash) > 12:
  189. self.__error = "otherHash check: invalid test string length"
  190. return
  191. # Sanity check that the other hash is between parenthesis.
  192. if otherHash[0] != "(" or otherHash[-1] != ")":
  193. self.__error = ("otherHash check: does not start with '(' or does not"
  194. "end with ')'")
  195. return
  196. # Remove the parenthesis
  197. otherHash = otherHash[1:len(otherHash)-2]
  198. # Check that the other hash is a hexadecimal value
  199. try:
  200. int(otherHash, 16)
  201. except ValueError:
  202. self.__error = "invalid other short commit hash, none hex characters in the string"
  203. return
  204. # We survived the above checks (this is a "+fd1422a6 (1dcc5768)" case).
  205. vHash = spaceSepElems[0]
  206. self.__otherCommit = otherHash[1:len(otherHash)-2]
  207. # SearX: git rev? ("1.1.0-69-75b859d2")
  208. if separator == "-" and len(elements) == 3:
  209. if not elements[1].isnumeric():
  210. self.__error = "unknown format (2)"
  211. return
  212. try:
  213. int(elements[2], 16)
  214. except ValueError:
  215. self.__error = "unknown format (3)"
  216. return
  217. self.__flags += VersionFlags.Git
  218. self.__commit = elements[2]
  219. self.__valid = True
  220. return
  221. # Only SearXNG versions remain..:
  222. # Check that each character of the short commit hash is in the hex
  223. # range.
  224. try:
  225. int(vHash, 16)
  226. except ValueError:
  227. self.__error = "invalid short commit hash, none hex characters in the string"
  228. return
  229. self.__flags += VersionFlags.Git
  230. self.__commit = vHash
  231. # SearXNG: Check flags
  232. if len(elements) >= 3:
  233. for i in range(2, len(elements)):
  234. if elements[i] == "dirty":
  235. self.__flags += VersionFlags.Dirty
  236. elif elements[i] == "extra":
  237. self.__flags += VersionFlags.Extra
  238. else:
  239. self.__error = f"unknown addition '{elements[i]}')"
  240. return
  241. self.__valid = True