[update] Implement `--update-to` repo

Authored by: Grub4K, pukkandan
pull/6876/head
Simon Sawicki 2 years ago
parent d2e84d5eb0
commit 665472a7de
No known key found for this signature in database

@ -196,12 +196,15 @@ There are currently two release channels for binaries, `stable` and `nightly`.
The `nightly` channel has releases built after each push to the master branch, and will have the most recent fixes and additions, but also have more risk of regressions. They are available in [their own repo](https://github.com/yt-dlp/yt-dlp-nightly-builds/releases). The `nightly` channel has releases built after each push to the master branch, and will have the most recent fixes and additions, but also have more risk of regressions. They are available in [their own repo](https://github.com/yt-dlp/yt-dlp-nightly-builds/releases).
When using `--update`/`-U`, a release binary will only update to its current channel. When using `--update`/`-U`, a release binary will only update to its current channel.
This release channel can be changed by using the `--update-to` option. `--update-to` can also be used to upgrade or downgrade to specific tags from a channel. `--update-to CHANNEL` can be used to switch to a different channel when a newer version is available. `--update-to [CHANNEL@]TAG` can also be used to upgrade or downgrade to specific tags from a channel.
You may also use `--update-to <repository>` (`<owner>/<repository>`) to update to a channel on a completely different repository. Be careful with what repository you are updating to though, there is no verification done for binaries from different repositories.
Example usage: Example usage:
* `yt-dlp --update-to nightly` change to `nightly` channel and update to its latest release * `yt-dlp --update-to nightly` change to `nightly` channel and update to its latest release
* `yt-dlp --update-to stable@2023.02.17` upgrade/downgrade to release to `stable` channel tag `2023.02.17` * `yt-dlp --update-to stable@2023.02.17` upgrade/downgrade to release to `stable` channel tag `2023.02.17`
* `yt-dlp --update-to 2023.01.06` upgrade/downgrade to tag `2023.01.06` if it exists on the current channel * `yt-dlp --update-to 2023.01.06` upgrade/downgrade to tag `2023.01.06` if it exists on the current channel
* `yt-dlp --update-to example/yt-dlp@2023.03.01` upgrade/downgrade to the release from the `example/yt-dlp` repository, tag `2023.03.01`
<!-- MANPAGE: BEGIN EXCLUDED SECTION --> <!-- MANPAGE: BEGIN EXCLUDED SECTION -->
## RELEASE FILES ## RELEASE FILES
@ -360,10 +363,10 @@ If you fork the project on GitHub, you can run your fork's [build workflow](.git
-U, --update Update this program to the latest version -U, --update Update this program to the latest version
--no-update Do not check for updates (default) --no-update Do not check for updates (default)
--update-to [CHANNEL]@[TAG] Upgrade/downgrade to a specific version. --update-to [CHANNEL]@[TAG] Upgrade/downgrade to a specific version.
CHANNEL and TAG defaults to "stable" and CHANNEL can be a repository as well. CHANNEL
"latest" respectively if omitted; See and TAG default to "stable" and "latest"
"UPDATE" for details. Supported channels: respectively if omitted; See "UPDATE" for
stable, nightly details. Supported channels: stable, nightly
-i, --ignore-errors Ignore download and postprocessing errors. -i, --ignore-errors Ignore download and postprocessing errors.
The download will be considered successful The download will be considered successful
even if the postprocessing fails even if the postprocessing fails

@ -939,7 +939,7 @@ def _real_main(argv=None):
ydl.cache.remove() ydl.cache.remove()
try: try:
updater = Updater(ydl, opts.update_self if isinstance(opts.update_self, str) else None) updater = Updater(ydl, opts.update_self)
if opts.update_self and updater.update() and actual_use: if opts.update_self and updater.update() and actual_use:
if updater.cmd: if updater.cmd:
return updater.restart() return updater.restart()

@ -323,7 +323,7 @@ def create_parser():
help='Print program version and exit') help='Print program version and exit')
general.add_option( general.add_option(
'-U', '--update', '-U', '--update',
action='store_true', dest='update_self', action='store_const', dest='update_self', const=CHANNEL,
help=format_field( help=format_field(
is_non_updateable(), None, 'Check if updates are available. %s', is_non_updateable(), None, 'Check if updates are available. %s',
default=f'Update this program to the latest {CHANNEL} version')) default=f'Update this program to the latest {CHANNEL} version'))
@ -335,9 +335,9 @@ def create_parser():
'--update-to', '--update-to',
action='store', dest='update_self', metavar='[CHANNEL]@[TAG]', action='store', dest='update_self', metavar='[CHANNEL]@[TAG]',
help=( help=(
'Upgrade/downgrade to a specific version. CHANNEL and TAG defaults to ' 'Upgrade/downgrade to a specific version. CHANNEL can be a repository as well. '
f'"{CHANNEL}" and "latest" respectively if omitted; See "UPDATE" for details. ' f'CHANNEL and TAG default to "{CHANNEL.partition("@")[0]}" and "latest" respectively if omitted; '
f'Supported channels: {", ".join(UPDATE_SOURCES)}')) f'See "UPDATE" for details. Supported channels: {", ".join(UPDATE_SOURCES)}'))
general.add_option( general.add_option(
'-i', '--ignore-errors', '-i', '--ignore-errors',
action='store_true', dest='ignoreerrors', action='store_true', dest='ignoreerrors',

@ -129,27 +129,36 @@ class Updater:
self.ydl = ydl self.ydl = ydl
self.target_channel, sep, self.target_tag = (target or CHANNEL).rpartition('@') self.target_channel, sep, self.target_tag = (target or CHANNEL).rpartition('@')
if not sep and self.target_tag in UPDATE_SOURCES: # stable => stable@latest # stable => stable@latest
self.target_channel, self.target_tag = self.target_tag, None if not sep and ('/' in self.target_tag or self.target_tag in UPDATE_SOURCES):
self.target_channel = self.target_tag
self.target_tag = None
elif not self.target_channel: elif not self.target_channel:
self.target_channel = CHANNEL self.target_channel = CHANNEL.partition('@')[0]
if not self.target_tag: if not self.target_tag:
self.target_tag, self._exact = 'latest', False self.target_tag = 'latest'
self._exact = False
elif self.target_tag != 'latest': elif self.target_tag != 'latest':
self.target_tag = f'tags/{self.target_tag}' self.target_tag = f'tags/{self.target_tag}'
@property if '/' in self.target_channel:
def _target_repo(self): self._target_repo = self.target_channel
try: if self.target_channel not in (CHANNEL, *UPDATE_SOURCES.values()):
return UPDATE_SOURCES[self.target_channel] self.ydl.report_warning(
except KeyError: f'You are switching to an {self.ydl._format_err("unofficial", "red")} executable '
return self._report_error( f'from {self.ydl._format_err(self._target_repo, self.ydl.Styles.EMPHASIS)}. '
f'Invalid update channel {self.target_channel!r} requested. ' f'Run {self.ydl._format_err("at your own risk", "light red")}')
f'Valid channels are {", ".join(UPDATE_SOURCES)}', True) self.restart = self._blocked_restart
else:
self._target_repo = UPDATE_SOURCES.get(self.target_channel)
if not self._target_repo:
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): def _version_compare(self, a, b, channel=CHANNEL):
if channel != self.target_channel: if self._exact and channel != self.target_channel:
return False return False
if _VERSION_RE.fullmatch(f'{a}.{b}'): if _VERSION_RE.fullmatch(f'{a}.{b}'):
@ -372,6 +381,12 @@ class Updater:
_, _, returncode = Popen.run(self.cmd) _, _, returncode = Popen.run(self.cmd)
return returncode return returncode
def _blocked_restart(self):
self._report_error(
'Automatically restarting into custom builds is disabled for security reasons. '
'Restart yt-dlp to use the updated version', expected=True)
return self.ydl._download_retcode
def run_update(ydl): def run_update(ydl):
"""Update the program file with the latest version from the repository """Update the program file with the latest version from the repository

Loading…
Cancel
Save