]> jfr.im git - yt-dlp.git/commitdiff
[update] Implement `--update-to` repo
authorSimon Sawicki <redacted>
Sat, 20 May 2023 19:21:32 +0000 (21:21 +0200)
committerSimon Sawicki <redacted>
Sat, 20 May 2023 19:21:32 +0000 (21:21 +0200)
Authored by: Grub4K, pukkandan

README.md
yt_dlp/__init__.py
yt_dlp/options.py
yt_dlp/update.py

index 6dff57b4c5950ade5d22a2631b4d86f3972c8b72..d0eaba74774b941a28002b062619a6063320bec0 100644 (file)
--- a/README.md
+++ b/README.md
@@ -196,12 +196,15 @@ ## UPDATE
 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.
-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:
 * `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 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 -->
 ## RELEASE FILES
@@ -360,10 +363,10 @@ ## General Options:
     -U, --update                    Update this program to the latest version
     --no-update                     Do not check for updates (default)
     --update-to [CHANNEL]@[TAG]     Upgrade/downgrade to a specific version.
-                                    CHANNEL and TAG defaults to "stable" and
-                                    "latest" respectively if omitted; See
-                                    "UPDATE" for details. Supported channels:
-                                    stable, nightly
+                                    CHANNEL can be a repository as well. CHANNEL
+                                    and TAG default to "stable" and "latest"
+                                    respectively if omitted; See "UPDATE" for
+                                    details. Supported channels: stable, nightly
     -i, --ignore-errors             Ignore download and postprocessing errors.
                                     The download will be considered successful
                                     even if the postprocessing fails
index 8806106d31d0e101f84808664443e1bec0b89701..9563d784aaf32322f4c215af9a5d55b6ab327cdf 100644 (file)
@@ -939,7 +939,7 @@ def _real_main(argv=None):
             ydl.cache.remove()
 
         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 updater.cmd:
                     return updater.restart()
index dc46ce998452d2e277dadb4a72066c0d10e07fef..838d79fcb12a1ecebfea5b23d03e3f3b21994df8 100644 (file)
@@ -323,7 +323,7 @@ def _alias_callback(option, opt_str, value, parser, opts, nargs):
         help='Print program version and exit')
     general.add_option(
         '-U', '--update',
-        action='store_true', dest='update_self',
+        action='store_const', dest='update_self', const=CHANNEL,
         help=format_field(
             is_non_updateable(), None, 'Check if updates are available. %s',
             default=f'Update this program to the latest {CHANNEL} version'))
@@ -335,9 +335,9 @@ def _alias_callback(option, opt_str, value, parser, opts, nargs):
         '--update-to',
         action='store', dest='update_self', metavar='[CHANNEL]@[TAG]',
         help=(
-            'Upgrade/downgrade to a specific version. CHANNEL and TAG defaults to '
-            f'"{CHANNEL}" and "latest" respectively if omitted; See "UPDATE" for details. '
-            f'Supported channels: {", ".join(UPDATE_SOURCES)}'))
+            'Upgrade/downgrade to a specific version. CHANNEL can be a repository as well. '
+            f'CHANNEL and TAG default to "{CHANNEL.partition("@")[0]}" and "latest" respectively if omitted; '
+            f'See "UPDATE" for details. Supported channels: {", ".join(UPDATE_SOURCES)}'))
     general.add_option(
         '-i', '--ignore-errors',
         action='store_true', dest='ignoreerrors',
index 7914de832f1dbdc25680c5fe5b256c8175bb926b..6c9bdaf1c7bfe6616c7d9d839b616730b2379554 100644 (file)
@@ -129,27 +129,36 @@ def __init__(self, ydl, target=None):
         self.ydl = ydl
 
         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
+        # stable => stable@latest
+        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:
-            self.target_channel = CHANNEL
+            self.target_channel = CHANNEL.partition('@')[0]
 
         if not self.target_tag:
-            self.target_tag, self._exact = 'latest', False
+            self.target_tag = 'latest'
+            self._exact = 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)
+        if '/' in self.target_channel:
+            self._target_repo = self.target_channel
+            if self.target_channel not in (CHANNEL, *UPDATE_SOURCES.values()):
+                self.ydl.report_warning(
+                    f'You are switching to an {self.ydl._format_err("unofficial", "red")} executable '
+                    f'from {self.ydl._format_err(self._target_repo, self.ydl.Styles.EMPHASIS)}. '
+                    f'Run {self.ydl._format_err("at your own risk", "light red")}')
+                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):
-        if channel != self.target_channel:
+        if self._exact and channel != self.target_channel:
             return False
 
         if _VERSION_RE.fullmatch(f'{a}.{b}'):
@@ -372,6 +381,12 @@ def restart(self):
         _, _, returncode = Popen.run(self.cmd)
         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):
     """Update the program file with the latest version from the repository