| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 738e940 commit a83262b
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,17 +4,32 @@ | |||
| 4 | 4 | __all__ = ["Submodule", "UpdateProgress"] | |
| 5 | 5 | ||
| 6 | 6 | import gc | |
| 7 | - from io import BytesIO | ||
| 8 | 7 | import logging | |
| 9 | 8 | import ntpath | |
| 10 | 9 | import os | |
| 11 | 10 | import os.path as osp | |
| 12 | - from pathlib import Path | ||
| 13 | 11 | import shlex | |
| 14 | 12 | import stat | |
| 15 | 13 | import sys | |
| 16 | - import uuid | ||
| 17 | 14 | import urllib.parse | |
| 15 | + import uuid | ||
| 16 | + from io import BytesIO | ||
| 17 | + from pathlib import Path | ||
| 18 | + | ||
| 19 | + # typing ---------------------------------------------------------------------- | ||
| 20 | + from typing import ( | ||
| 21 | + TYPE_CHECKING, | ||
| 22 | + Any, | ||
| 23 | + Callable, | ||
| 24 | + Dict, | ||
| 25 | + Iterator, | ||
| 26 | + List, | ||
| 27 | + Literal, | ||
| 28 | + Mapping, | ||
| 29 | + Sequence, | ||
| 30 | + Union, | ||
| 31 | + cast, | ||
| 32 | + ) | ||
| 18 | 33 | ||
| 19 | 34 | import git | |
| 20 | 35 | from git.cmd import Git | |
@@ -46,23 +61,7 @@ | |||
| 46 | 61 | sm_section, | |
| 47 | 62 | ) | |
| 48 | 63 | ||
| 49 | - # typing ---------------------------------------------------------------------- | ||
| 50 | - | ||
| 51 | - from typing import ( | ||
| 52 | - Any, | ||
| 53 | - Callable, | ||
| 54 | - Dict, | ||
| 55 | - Iterator, | ||
| 56 | - List, | ||
| 57 | - Literal, | ||
| 58 | - Mapping, | ||
| 59 | - Sequence, | ||
| 60 | - TYPE_CHECKING, | ||
| 61 | - Union, | ||
| 62 | - cast, | ||
| 63 | - ) | ||
| 64 | - | ||
| 65 | - from git.types import Commit_ish, PathLike, TBD | ||
| 64 | + from git.types import TBD, Commit_ish, PathLike | ||
| 66 | 65 | ||
| 67 | 66 | if TYPE_CHECKING: | |
| 68 | 67 | from git.index import IndexFile | |
@@ -793,8 +792,9 @@ def update( | |||
| 793 | 792 | Allow unsafe options to be used, like ``--upload-pack``. | |
| 794 | 793 | ||
| 795 | 794 | :param no_fetch: | |
| 796 | - If ``True``, submodule updating will be attempted without fetching | ||
| 797 | - new changes from remotes. | ||
| 795 | + If ``True``, update using locally available objects and remote-tracking | ||
| 796 | + refs without fetching or cloning. Repositories retained after | ||
| 797 | + :meth:`deinit` can be restored without fetching. | ||
| 798 | 798 | ||
| 799 | 799 | :note: | |
| 800 | 800 | Does nothing in bare repositories. | |
@@ -886,15 +886,12 @@ def fetch_remotes(module_repo: "Repo") -> None: | |||
| 886 | 886 | raise OSError( | |
| 887 | 887 | "Module directory at %r does already exist and is non-empty" % checkout_module_abspath | |
| 888 | 888 | ) | |
| 889 | - elif no_fetch: | ||
| 890 | - raise ValueError( | ||
| 891 | - "Module directory at %r is empty but fetching is disabled" % checkout_module_abspath | ||
| 892 | - ) | ||
| 893 | 889 | os.makedirs(checkout_module_abspath, exist_ok=True) | |
| 894 | 890 | self._write_git_file_and_module_config(checkout_module_abspath, module_abspath) | |
| 895 | 891 | mrepo = git.Repo(checkout_module_abspath) | |
| 896 | 892 | mrepo.head.reset(mrepo.head.commit, index=True, working_tree=True) | |
| 897 | - fetch_remotes(mrepo) | ||
| 893 | + if not no_fetch: | ||
| 894 | + fetch_remotes(mrepo) | ||
| 898 | 895 | with self.repo.config_writer() as writer: | |
| 899 | 896 | writer.set_value(sm_section(self.name), "url", self.url) | |
| 900 | 897 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,19 +5,17 @@ | |||
| 5 | 5 | ||
| 6 | 6 | import logging | |
| 7 | 7 | ||
| 8 | + # typing ------------------------------------------------------------------- | ||
| 9 | + from typing import TYPE_CHECKING, Union | ||
| 10 | + | ||
| 8 | 11 | import git | |
| 9 | 12 | from git.exc import InvalidGitRepositoryError | |
| 13 | + from git.types import Commit_ish | ||
| 10 | 14 | from git.util import IterableList | |
| 11 | 15 | ||
| 12 | 16 | from .base import Submodule, UpdateProgress | |
| 13 | 17 | from .util import find_first_remote_branch | |
| 14 | 18 | ||
| 15 | - # typing ------------------------------------------------------------------- | ||
| 16 | - | ||
| 17 | - from typing import TYPE_CHECKING, Union | ||
| 18 | - | ||
| 19 | - from git.types import Commit_ish | ||
| 20 | - | ||
| 21 | 19 | if TYPE_CHECKING: | |
| 22 | 20 | from git.repo import Repo | |
| 23 | 21 | ||
@@ -148,8 +146,9 @@ def update( # type: ignore[override] | |||
| 148 | 146 | when updating submodules. | |
| 149 | 147 | ||
| 150 | 148 | :param no_fetch: | |
| 151 | - If ``True``, submodule updating will be attempted without fetching | ||
| 152 | - new changes from remotes. | ||
| 149 | + If ``True``, update using locally available objects and remote-tracking | ||
| 150 | + refs without fetching or cloning. Cached refs are preserved and used even | ||
| 151 | + when a submodule's URL changes. | ||
| 153 | 152 | ||
| 154 | 153 | :return: | |
| 155 | 154 | self | |
@@ -259,7 +258,7 @@ def update( # type: ignore[override] | |||
| 259 | 258 | # HANDLE URL CHANGE | |
| 260 | 259 | ################### | |
| 261 | 260 | if sm.url != psm.url: | |
| 262 | - # Add the new remote, remove the old one. | ||
| 261 | + # When fetching, add the new remote and remove the old one. | ||
| 263 | 262 | # This way, if the url just changes, the commits will not have | |
| 264 | 263 | # to be re-retrieved. | |
| 265 | 264 | nn = "__new_origin__" | |
@@ -277,34 +276,19 @@ def update( # type: ignore[override] | |||
| 277 | 276 | ) | |
| 278 | 277 | ||
| 279 | 278 | if not dry_run: | |
| 280 | - assert nn not in [r.name for r in rmts] | ||
| 281 | - smr = smm.create_remote(nn, sm.url) | ||
| 282 | - if not no_fetch: | ||
| 283 | - smr.fetch(progress=progress) | ||
| 284 | - | ||
| 285 | - # If we have a tracking branch, it should be available | ||
| 286 | - # in the new remote as well. | ||
| 287 | - if len([r for r in smr.refs if r.remote_head == sm.branch_name]) == 0: | ||
| 288 | - raise ValueError( | ||
| 289 | - "Submodule branch named %r was not available in new submodule remote at %r" | ||
| 290 | - % (sm.branch_name, sm.url) | ||
| 291 | - ) | ||
| 292 | - # END head is not detached | ||
| 293 | - | ||
| 294 | - # Now delete the changed one. | ||
| 295 | - rmt_for_deletion = None | ||
| 279 | + previous_remote = None | ||
| 296 | 280 | for remote in rmts: | |
| 297 | 281 | if remote.url == psm.url: | |
| 298 | - rmt_for_deletion = remote | ||
| 282 | + previous_remote = remote | ||
| 299 | 283 | break | |
| 300 | 284 | # END if urls match | |
| 301 | 285 | # END for each remote | |
| 302 | 286 | ||
| 303 | 287 | # If we didn't find a matching remote, but have exactly | |
| 304 | 288 | # one, we can safely use this one. | |
| 305 | - if rmt_for_deletion is None: | ||
| 289 | + if previous_remote is None: | ||
| 306 | 290 | if len(rmts) == 1: | |
| 307 | - rmt_for_deletion = rmts[0] | ||
| 291 | + previous_remote = rmts[0] | ||
| 308 | 292 | else: | |
| 309 | 293 | # If we have not found any remote with the | |
| 310 | 294 | # original URL we may not have a name. This is a | |
@@ -317,45 +301,64 @@ def update( # type: ignore[override] | |||
| 317 | 301 | # END handle one single remote | |
| 318 | 302 | # END handle check we found a remote | |
| 319 | 303 | ||
| 320 | - orig_name = rmt_for_deletion.name | ||
| 321 | - smm.delete_remote(rmt_for_deletion) | ||
| 322 | - # NOTE: Currently we leave tags from the deleted remotes | ||
| 323 | - # as well as separate tracking branches in the possibly | ||
| 324 | - # totally changed repository (someone could have changed | ||
| 325 | - # the url to another project). At some point, one might | ||
| 326 | - # want to clean it up, but the danger is high to remove | ||
| 327 | - # stuff the user has added explicitly. | ||
| 328 | - | ||
| 329 | - # Rename the new remote back to what it was. | ||
| 330 | - smr.rename(orig_name) | ||
| 331 | - | ||
| 332 | - # Early on, we verified that the our current tracking | ||
| 333 | - # branch exists in the remote. Now we have to ensure | ||
| 334 | - # that the sha we point to is still contained in the new | ||
| 335 | - # remote tracking branch. | ||
| 336 | - smsha = sm.binsha | ||
| 337 | - found = False | ||
| 338 | - rref = smr.refs[self.branch_name] | ||
| 339 | - for c in rref.commit.traverse(): | ||
| 340 | - if c.binsha == smsha: | ||
| 341 | - found = True | ||
| 342 | - break | ||
| 343 | - # END traverse all commits in search for sha | ||
| 344 | - # END for each commit | ||
| 345 | - | ||
| 346 | - if not found: | ||
| 347 | - # Adjust our internal binsha to use the one of the | ||
| 348 | - # remote this way, it will be checked out in the | ||
| 349 | - # next step. This will change the submodule relative | ||
| 350 | - # to us, so the user will be able to commit the | ||
| 351 | - # change easily. | ||
| 352 | - _logger.warning( | ||
| 353 | - "Current sha %s was not contained in the tracking\ | ||
| 304 | + if no_fetch: | ||
| 305 | + # A new remote would have no cached refs. Preserve | ||
| 306 | + # the existing refs and tracking configuration for | ||
| 307 | + # offline updates instead of replacing the remote. | ||
| 308 | + previous_remote.set_url(git.Git.polish_url(sm.url, expand_vars=False)) | ||
| 309 | + else: | ||
| 310 | + assert nn not in [r.name for r in rmts] | ||
| 311 | + smr = smm.create_remote(nn, sm.url) | ||
| 312 | + smr.fetch(progress=progress) | ||
| 313 | + | ||
| 314 | + # If we have a tracking branch, it should be available | ||
| 315 | + # in the new remote as well. | ||
| 316 | + if len([r for r in smr.refs if r.remote_head == sm.branch_name]) == 0: | ||
| 317 | + raise ValueError( | ||
| 318 | + "Submodule branch named %r was not available in new submodule remote at %r" | ||
| 319 | + % (sm.branch_name, sm.url) | ||
| 320 | + ) | ||
| 321 | + # END head is not detached | ||
| 322 | + | ||
| 323 | + orig_name = previous_remote.name | ||
| 324 | + smm.delete_remote(previous_remote) | ||
| 325 | + # NOTE: Currently we leave tags from the deleted remotes | ||
| 326 | + # as well as separate tracking branches in the possibly | ||
| 327 | + # totally changed repository (someone could have changed | ||
| 328 | + # the url to another project). At some point, one might | ||
| 329 | + # want to clean it up, but the danger is high to remove | ||
| 330 | + # stuff the user has added explicitly. | ||
| 331 | + | ||
| 332 | + # Rename the new remote back to what it was. | ||
| 333 | + smr.rename(orig_name) | ||
| 334 | + | ||
| 335 | + # Early on, we verified that the our current tracking | ||
| 336 | + # branch exists in the remote. Now we have to ensure | ||
| 337 | + # that the sha we point to is still contained in the new | ||
| 338 | + # remote tracking branch. | ||
| 339 | + smsha = sm.binsha | ||
| 340 | + found = False | ||
| 341 | + rref = smr.refs[self.branch_name] | ||
| 342 | + for c in rref.commit.traverse(): | ||
| 343 | + if c.binsha == smsha: | ||
| 344 | + found = True | ||
| 345 | + break | ||
| 346 | + # END traverse all commits in search for sha | ||
| 347 | + # END for each commit | ||
| 348 | + | ||
| 349 | + if not found: | ||
| 350 | + # Adjust our internal binsha to use the one of the | ||
| 351 | + # remote this way, it will be checked out in the | ||
| 352 | + # next step. This will change the submodule relative | ||
| 353 | + # to us, so the user will be able to commit the | ||
| 354 | + # change easily. | ||
| 355 | + _logger.warning( | ||
| 356 | + "Current sha %s was not contained in the tracking\ | ||
| 354 | 357 | branch at the new remote, setting it the the remote's tracking branch", | |
| 355 | - sm.hexsha, | ||
| 356 | - ) | ||
| 357 | - sm.binsha = rref.commit.binsha | ||
| 358 | - # END reset binsha | ||
| 358 | + sm.hexsha, | ||
| 359 | + ) | ||
| 360 | + sm.binsha = rref.commit.binsha | ||
| 361 | + # END reset binsha | ||
| 359 | 362 | ||
| 360 | 363 | # NOTE: All checkout is performed by the base | |
| 361 | 364 | # implementation of update. | |
@@ -385,11 +388,12 @@ def update( # type: ignore[override] | |||
| 385 | 388 | if not dry_run: | |
| 386 | 389 | smm = sm.module() | |
| 387 | 390 | smmr = smm.remotes | |
| 388 | - # As the branch might not exist yet, we will have to fetch | ||
| 389 | - # all remotes to be sure... | ||
| 390 | - for remote in smmr: | ||
| 391 | - remote.fetch(progress=progress) | ||
| 392 | - # END for each remote | ||
| 391 | + # As the branch might not exist yet, fetch all remotes | ||
| 392 | + # unless restricted to locally cached refs. | ||
| 393 | + if not no_fetch: | ||
| 394 | + for remote in smmr: | ||
| 395 | + remote.fetch(progress=progress) | ||
| 396 | + # END for each remote | ||
| 393 | 397 | ||
| 394 | 398 | try: | |
| 395 | 399 | tbr = git.Head.create( | |
@@ -458,6 +462,7 @@ def update( # type: ignore[override] | |||
| 458 | 462 | dry_run=dry_run, | |
| 459 | 463 | force_reset=force_reset, | |
| 460 | 464 | keep_going=keep_going, | |
| 465 | + no_fetch=no_fetch, | ||
| 461 | 466 | ) | |
| 462 | 467 | # END handle dry_run | |
| 463 | 468 | # END handle recursive | |
| Back | FazBrowse Home | New Git URL |
0 commit comments