Skip to content

Commit

Permalink
Merge pull request conan-io#11830 from czoido/port_11823_to_1.50.2
Browse files Browse the repository at this point in the history
Port conan-io#11823 to 1.50.2
  • Loading branch information
czoido committed Aug 10, 2022
2 parents 302f83a + 3a9c93e commit bd1116a
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 2 deletions.
200 changes: 199 additions & 1 deletion conan/tools/scm/__init__.py
@@ -1,2 +1,200 @@
from conan.tools.scm.git import Git
from conans.model.version import Version
# develop2 uncomment the next line
# from conans.model.version import Version


# ######## DEVELOP2: Delete all the contents from here, this is copy-paste from the Version model
# ######## at conans.model.version (for an easier migration)
from functools import total_ordering
from conans.errors import ConanException


@total_ordering
class _VersionItem:
""" a single "digit" in a version, like X.Y.Z all X and Y and Z are VersionItems
They can be int or strings
"""
def __init__(self, item):
try:
self._v = int(item)
except ValueError:
self._v = item

@property
def value(self):
return self._v

def __str__(self):
return str(self._v)

def __add__(self, other):
# necessary for the "bump()" functionality. Other aritmetic operations are missing
return self._v + other

def __eq__(self, other):
if not isinstance(other, _VersionItem):
other = _VersionItem(other)
return self._v == other._v

def __hash__(self):
return hash(self._v)

def __lt__(self, other):
"""
@type other: _VersionItem
"""
if not isinstance(other, _VersionItem):
other = _VersionItem(other)
try:
return self._v < other._v
except TypeError:
return str(self._v) < str(other._v)


@total_ordering
class Version:
"""
This is NOT an implementation of semver, as users may use any pattern in their versions.
It is just a helper to parse "." or "-" and compare taking into account integers when possible
"""
def __init__(self, value):
value = str(value)
self._value = value

items = value.rsplit("+", 1) # split for build
if len(items) == 2:
value, build = items
self._build = Version(build) # This is a nested version by itself
else:
value = items[0]
self._build = None

items = value.rsplit("-", 1) # split for pre-release
if len(items) == 2:
value, pre = items
self._pre = Version(pre) # This is a nested version by itself
else:
value = items[0]
self._pre = None
items = value.split(".")
items = [_VersionItem(item) for item in items]
self._items = tuple(items)
while items and items[-1].value == 0:
del items[-1]
self._nonzero_items = tuple(items)

def bump(self, index):
"""
Increments by 1 the version field at the specified index, setting to 0 the fields
on the right.
2.5 => bump(1) => 2.6
1.5.7 => bump(0) => 2.0.0
"""
# this method is used to compute version ranges from tilde ~1.2 and caret ^1.2.1 ranges
# TODO: at this moment it only works for digits, cannot increment pre-release or builds
# better not make it public yet, keep it internal
items = list(self._items[:index])
try:
items.append(self._items[index]+1)
except TypeError:
raise ConanException(f"Cannot bump '{self._value} version index {index}, not an int")
items.extend([0] * (len(items) - index - 1))
v = ".".join(str(i) for i in items)
# prerelease and build are dropped while bumping digits
result = Version(v)
return result

def upper_bound(self, index):
items = list(self._items[:index])
try:
items.append(self._items[index] + 1)
except TypeError:
raise ConanException(f"Cannot bump '{self._value} version index {index}, not an int")
items.extend([0] * (len(items) - index - 1))
v = ".".join(str(i) for i in items)
v += "-" # Exclude prereleases
result = Version(v)
return result

@property
def pre(self):
return self._pre

@property
def build(self):
return self._build

@property
def main(self):
return self._items

@property
def major(self):
try:
return self.main[0]
except IndexError:
return None

@property
def minor(self):
try:
return self.main[1]
except IndexError:
return None

@property
def patch(self):
try:
return self.main[2]
except IndexError:
return None

@property
def micro(self):
try:
return self.main[3]
except IndexError:
return None

def __str__(self):
return self._value

def __repr__(self):
return self._value

def __eq__(self, other):
if other is None:
return False
if isinstance(other, str):
other = Version(other)

return (self._nonzero_items, self._pre, self._build) ==\
(other._nonzero_items, other._pre, other._build)

def __hash__(self):
return hash((self._nonzero_items, self._pre, self._build))

def __lt__(self, other):
if other is None:
return False
if not isinstance(other, Version):
other = Version(other)

if self._pre:
if other._pre: # both are pre-releases
return (self._nonzero_items, self._pre, self._build) < \
(other._nonzero_items, other._pre, other._build)
else: # Left hand is pre-release, right side is regular
if self._nonzero_items == other._nonzero_items: # Problem only happens if both equal
return True
else:
return self._nonzero_items < other._nonzero_items
else:
if other._pre: # Left hand is regular, right side is pre-release
if self._nonzero_items == other._nonzero_items: # Problem only happens if both equal
return False
else:
return self._nonzero_items < other._nonzero_items
else: # None of them is pre-release
return (self._nonzero_items, self._build) < (other._nonzero_items, other._build)

2 changes: 1 addition & 1 deletion conans/__init__.py
Expand Up @@ -20,4 +20,4 @@
SERVER_CAPABILITIES = [COMPLEX_SEARCH_CAPABILITY, REVISIONS] # Server is always with revisions
DEFAULT_REVISION_V1 = "0"

__version__ = '1.50.1'
__version__ = '1.50.2'
1 change: 1 addition & 0 deletions conans/client/migrations_settings.py
Expand Up @@ -3714,3 +3714,4 @@

settings_1_50_0 = settings_1_49_0
settings_1_50_1 = settings_1_50_0
settings_1_50_2 = settings_1_50_1
9 changes: 9 additions & 0 deletions conans/test/unittests/tools/scm/test_version.py
Expand Up @@ -16,8 +16,17 @@ class Pkg(ConanFile):
def configure(self):
v = Version(self.settings.compiler.version)
assert v > "10"
v = Version("1.2.3")
self.output.warning(f"The major of 1.2.3 is {v.major}")
self.output.warning(f"The minor of 1.2.3 is {v.minor}")
self.output.warning(f"The patch of 1.2.3 is {v.patch}")
""")
c.save({"conanfile.py": conanfile})
settings = "-s compiler=gcc -s compiler.libcxx=libstdc++11"
c.run("create . {} -s compiler.version=11".format(settings))
assert "The major of 1.2.3 is 1" in c.out
assert "The minor of 1.2.3 is 2" in c.out
assert "The patch of 1.2.3 is 3" in c.out

c.run("create . {} -s compiler.version=9".format(settings), assert_error=True)

0 comments on commit bd1116a

Please sign in to comment.