+ self.target_channel, sep, self.target_tag = (target or CHANNEL).rpartition('@')
+ if not sep and self.target_tag in UPDATE_SOURCES: # stable => stable@latest
+ self.target_channel, self.target_tag = self.target_tag, None
+ elif not self.target_channel:
+ self.target_channel = CHANNEL
+
+ if not self.target_tag:
+ self.target_tag, self._exact = 'latest', False
+ elif self.target_tag != 'latest':
+ self.target_tag = f'tags/{self.target_tag}'
+
+ @property
+ def _target_repo(self):
+ try:
+ return UPDATE_SOURCES[self.target_channel]
+ except KeyError:
+ return self._report_error(
+ f'Invalid update channel {self.target_channel!r} requested. '
+ f'Valid channels are {", ".join(UPDATE_SOURCES)}', True)
+
+ def _version_compare(self, a, b, channel=CHANNEL):
+ if channel != self.target_channel:
+ return False
+
+ if _VERSION_RE.fullmatch(f'{a}.{b}'):
+ a, b = version_tuple(a), version_tuple(b)
+ return a == b if self._exact else a >= b
+ return a == b
+