diff options
Diffstat (limited to 'subcmds/sync.py')
| -rw-r--r-- | subcmds/sync.py | 102 | 
1 files changed, 66 insertions, 36 deletions
| diff --git a/subcmds/sync.py b/subcmds/sync.py index b50df099..43d450be 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -14,10 +14,10 @@ | |||
| 14 | # limitations under the License. | 14 | # limitations under the License. | 
| 15 | 15 | ||
| 16 | from __future__ import print_function | 16 | from __future__ import print_function | 
| 17 | import json | ||
| 17 | import netrc | 18 | import netrc | 
| 18 | from optparse import SUPPRESS_HELP | 19 | from optparse import SUPPRESS_HELP | 
| 19 | import os | 20 | import os | 
| 20 | import pickle | ||
| 21 | import re | 21 | import re | 
| 22 | import shutil | 22 | import shutil | 
| 23 | import socket | 23 | import socket | 
| @@ -119,6 +119,11 @@ credentials. | |||
| 119 | The -f/--force-broken option can be used to proceed with syncing | 119 | The -f/--force-broken option can be used to proceed with syncing | 
| 120 | other projects if a project sync fails. | 120 | other projects if a project sync fails. | 
| 121 | 121 | ||
| 122 | The --force-sync option can be used to overwrite existing git | ||
| 123 | directories if they have previously been linked to a different | ||
| 124 | object direcotry. WARNING: This may cause data to be lost since | ||
| 125 | refs may be removed when overwriting. | ||
| 126 | |||
| 122 | The --no-clone-bundle option disables any attempt to use | 127 | The --no-clone-bundle option disables any attempt to use | 
| 123 | $URL/clone.bundle to bootstrap a new Git repository from a | 128 | $URL/clone.bundle to bootstrap a new Git repository from a | 
| 124 | resumeable bundle file on a content delivery network. This | 129 | resumeable bundle file on a content delivery network. This | 
| @@ -128,6 +133,13 @@ HTTP client or proxy configuration, but the Git binary works. | |||
| 128 | The --fetch-submodules option enables fetching Git submodules | 133 | The --fetch-submodules option enables fetching Git submodules | 
| 129 | of a project from server. | 134 | of a project from server. | 
| 130 | 135 | ||
| 136 | The -c/--current-branch option can be used to only fetch objects that | ||
| 137 | are on the branch specified by a project's revision. | ||
| 138 | |||
| 139 | The --optimized-fetch option can be used to only fetch projects that | ||
| 140 | are fixed to a sha1 revision if the sha1 revision does not already | ||
| 141 | exist locally. | ||
| 142 | |||
| 131 | SSH Connections | 143 | SSH Connections | 
| 132 | --------------- | 144 | --------------- | 
| 133 | 145 | ||
| @@ -167,6 +179,11 @@ later is required to fix a server side protocol bug. | |||
| 167 | p.add_option('-f', '--force-broken', | 179 | p.add_option('-f', '--force-broken', | 
| 168 | dest='force_broken', action='store_true', | 180 | dest='force_broken', action='store_true', | 
| 169 | help="continue sync even if a project fails to sync") | 181 | help="continue sync even if a project fails to sync") | 
| 182 | p.add_option('--force-sync', | ||
| 183 | dest='force_sync', action='store_true', | ||
| 184 | help="overwrite an existing git directory if it needs to " | ||
| 185 | "point to a different object directory. WARNING: this " | ||
| 186 | "may cause loss of data") | ||
| 170 | p.add_option('-l', '--local-only', | 187 | p.add_option('-l', '--local-only', | 
| 171 | dest='local_only', action='store_true', | 188 | dest='local_only', action='store_true', | 
| 172 | help="only update working tree, don't fetch") | 189 | help="only update working tree, don't fetch") | 
| @@ -203,6 +220,9 @@ later is required to fix a server side protocol bug. | |||
| 203 | p.add_option('--no-tags', | 220 | p.add_option('--no-tags', | 
| 204 | dest='no_tags', action='store_true', | 221 | dest='no_tags', action='store_true', | 
| 205 | help="don't fetch tags") | 222 | help="don't fetch tags") | 
| 223 | p.add_option('--optimized-fetch', | ||
| 224 | dest='optimized_fetch', action='store_true', | ||
| 225 | help='only fetch projects fixed to sha1 if revision does not exist locally') | ||
| 206 | if show_smart: | 226 | if show_smart: | 
| 207 | p.add_option('-s', '--smart-sync', | 227 | p.add_option('-s', '--smart-sync', | 
| 208 | dest='smart_sync', action='store_true', | 228 | dest='smart_sync', action='store_true', | 
| @@ -271,8 +291,10 @@ later is required to fix a server side protocol bug. | |||
| 271 | success = project.Sync_NetworkHalf( | 291 | success = project.Sync_NetworkHalf( | 
| 272 | quiet=opt.quiet, | 292 | quiet=opt.quiet, | 
| 273 | current_branch_only=opt.current_branch_only, | 293 | current_branch_only=opt.current_branch_only, | 
| 294 | force_sync=opt.force_sync, | ||
| 274 | clone_bundle=not opt.no_clone_bundle, | 295 | clone_bundle=not opt.no_clone_bundle, | 
| 275 | no_tags=opt.no_tags, archive=self.manifest.IsArchive) | 296 | no_tags=opt.no_tags, archive=self.manifest.IsArchive, | 
| 297 | optimized_fetch=opt.optimized_fetch) | ||
| 276 | self._fetch_times.Set(project, time.time() - start) | 298 | self._fetch_times.Set(project, time.time() - start) | 
| 277 | 299 | ||
| 278 | # Lock around all the rest of the code, since printing, updating a set | 300 | # Lock around all the rest of the code, since printing, updating a set | 
| @@ -508,6 +530,9 @@ later is required to fix a server side protocol bug. | |||
| 508 | self.manifest.Override(opt.manifest_name) | 530 | self.manifest.Override(opt.manifest_name) | 
| 509 | 531 | ||
| 510 | manifest_name = opt.manifest_name | 532 | manifest_name = opt.manifest_name | 
| 533 | smart_sync_manifest_name = "smart_sync_override.xml" | ||
| 534 | smart_sync_manifest_path = os.path.join( | ||
| 535 | self.manifest.manifestProject.worktree, smart_sync_manifest_name) | ||
| 511 | 536 | ||
| 512 | if opt.smart_sync or opt.smart_tag: | 537 | if opt.smart_sync or opt.smart_tag: | 
| 513 | if not self.manifest.manifest_server: | 538 | if not self.manifest.manifest_server: | 
| @@ -560,7 +585,10 @@ later is required to fix a server side protocol bug. | |||
| 560 | branch = branch[len(R_HEADS):] | 585 | branch = branch[len(R_HEADS):] | 
| 561 | 586 | ||
| 562 | env = os.environ.copy() | 587 | env = os.environ.copy() | 
| 563 | if 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env: | 588 | if 'SYNC_TARGET' in env: | 
| 589 | target = env['SYNC_TARGET'] | ||
| 590 | [success, manifest_str] = server.GetApprovedManifest(branch, target) | ||
| 591 | elif 'TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env: | ||
| 564 | target = '%s-%s' % (env['TARGET_PRODUCT'], | 592 | target = '%s-%s' % (env['TARGET_PRODUCT'], | 
| 565 | env['TARGET_BUILD_VARIANT']) | 593 | env['TARGET_BUILD_VARIANT']) | 
| 566 | [success, manifest_str] = server.GetApprovedManifest(branch, target) | 594 | [success, manifest_str] = server.GetApprovedManifest(branch, target) | 
| @@ -571,17 +599,16 @@ later is required to fix a server side protocol bug. | |||
| 571 | [success, manifest_str] = server.GetManifest(opt.smart_tag) | 599 | [success, manifest_str] = server.GetManifest(opt.smart_tag) | 
| 572 | 600 | ||
| 573 | if success: | 601 | if success: | 
| 574 | manifest_name = "smart_sync_override.xml" | 602 | manifest_name = smart_sync_manifest_name | 
| 575 | manifest_path = os.path.join(self.manifest.manifestProject.worktree, | ||
| 576 | manifest_name) | ||
| 577 | try: | 603 | try: | 
| 578 | f = open(manifest_path, 'w') | 604 | f = open(smart_sync_manifest_path, 'w') | 
| 579 | try: | 605 | try: | 
| 580 | f.write(manifest_str) | 606 | f.write(manifest_str) | 
| 581 | finally: | 607 | finally: | 
| 582 | f.close() | 608 | f.close() | 
| 583 | except IOError: | 609 | except IOError as e: | 
| 584 | print('error: cannot write manifest to %s' % manifest_path, | 610 | print('error: cannot write manifest to %s:\n%s' | 
| 611 | % (smart_sync_manifest_path, e), | ||
| 585 | file=sys.stderr) | 612 | file=sys.stderr) | 
| 586 | sys.exit(1) | 613 | sys.exit(1) | 
| 587 | self._ReloadManifest(manifest_name) | 614 | self._ReloadManifest(manifest_name) | 
| @@ -598,6 +625,13 @@ later is required to fix a server side protocol bug. | |||
| 598 | % (self.manifest.manifest_server, e.errcode, e.errmsg), | 625 | % (self.manifest.manifest_server, e.errcode, e.errmsg), | 
| 599 | file=sys.stderr) | 626 | file=sys.stderr) | 
| 600 | sys.exit(1) | 627 | sys.exit(1) | 
| 628 | else: # Not smart sync or smart tag mode | ||
| 629 | if os.path.isfile(smart_sync_manifest_path): | ||
| 630 | try: | ||
| 631 | os.remove(smart_sync_manifest_path) | ||
| 632 | except OSError as e: | ||
| 633 | print('error: failed to remove existing smart sync override manifest: %s' % | ||
| 634 | e, file=sys.stderr) | ||
| 601 | 635 | ||
| 602 | rp = self.manifest.repoProject | 636 | rp = self.manifest.repoProject | 
| 603 | rp.PreSync() | 637 | rp.PreSync() | 
| @@ -611,7 +645,8 @@ later is required to fix a server side protocol bug. | |||
| 611 | if not opt.local_only: | 645 | if not opt.local_only: | 
| 612 | mp.Sync_NetworkHalf(quiet=opt.quiet, | 646 | mp.Sync_NetworkHalf(quiet=opt.quiet, | 
| 613 | current_branch_only=opt.current_branch_only, | 647 | current_branch_only=opt.current_branch_only, | 
| 614 | no_tags=opt.no_tags) | 648 | no_tags=opt.no_tags, | 
| 649 | optimized_fetch=opt.optimized_fetch) | ||
| 615 | 650 | ||
| 616 | if mp.HasChanges: | 651 | if mp.HasChanges: | 
| 617 | syncbuf = SyncBuffer(mp.config) | 652 | syncbuf = SyncBuffer(mp.config) | 
| @@ -674,7 +709,7 @@ later is required to fix a server side protocol bug. | |||
| 674 | for project in all_projects: | 709 | for project in all_projects: | 
| 675 | pm.update() | 710 | pm.update() | 
| 676 | if project.worktree: | 711 | if project.worktree: | 
| 677 | project.Sync_LocalHalf(syncbuf) | 712 | project.Sync_LocalHalf(syncbuf, force_sync=opt.force_sync) | 
| 678 | pm.end() | 713 | pm.end() | 
| 679 | print(file=sys.stderr) | 714 | print(file=sys.stderr) | 
| 680 | if not syncbuf.Finish(): | 715 | if not syncbuf.Finish(): | 
| @@ -762,7 +797,7 @@ class _FetchTimes(object): | |||
| 762 | _ALPHA = 0.5 | 797 | _ALPHA = 0.5 | 
| 763 | 798 | ||
| 764 | def __init__(self, manifest): | 799 | def __init__(self, manifest): | 
| 765 | self._path = os.path.join(manifest.repodir, '.repopickle_fetchtimes') | 800 | self._path = os.path.join(manifest.repodir, '.repo_fetchtimes.json') | 
| 766 | self._times = None | 801 | self._times = None | 
| 767 | self._seen = set() | 802 | self._seen = set() | 
| 768 | 803 | ||
| @@ -781,22 +816,17 @@ class _FetchTimes(object): | |||
| 781 | def _Load(self): | 816 | def _Load(self): | 
| 782 | if self._times is None: | 817 | if self._times is None: | 
| 783 | try: | 818 | try: | 
| 784 | f = open(self._path, 'rb') | 819 | f = open(self._path) | 
| 785 | except IOError: | ||
| 786 | self._times = {} | ||
| 787 | return self._times | ||
| 788 | try: | ||
| 789 | try: | 820 | try: | 
| 790 | self._times = pickle.load(f) | 821 | self._times = json.load(f) | 
| 791 | except IOError: | 822 | finally: | 
| 792 | try: | 823 | f.close() | 
| 793 | os.remove(self._path) | 824 | except (IOError, ValueError): | 
| 794 | except OSError: | 825 | try: | 
| 795 | pass | 826 | os.remove(self._path) | 
| 796 | self._times = {} | 827 | except OSError: | 
| 797 | finally: | 828 | pass | 
| 798 | f.close() | 829 | self._times = {} | 
| 799 | return self._times | ||
| 800 | 830 | ||
| 801 | def Save(self): | 831 | def Save(self): | 
| 802 | if self._times is None: | 832 | if self._times is None: | 
| @@ -810,13 +840,13 @@ class _FetchTimes(object): | |||
| 810 | del self._times[name] | 840 | del self._times[name] | 
| 811 | 841 | ||
| 812 | try: | 842 | try: | 
| 813 | f = open(self._path, 'wb') | 843 | f = open(self._path, 'w') | 
| 814 | try: | 844 | try: | 
| 815 | pickle.dump(self._times, f) | 845 | json.dump(self._times, f, indent=2) | 
| 816 | except (IOError, OSError, pickle.PickleError): | 846 | finally: | 
| 817 | try: | 847 | f.close() | 
| 818 | os.remove(self._path) | 848 | except (IOError, TypeError): | 
| 819 | except OSError: | 849 | try: | 
| 820 | pass | 850 | os.remove(self._path) | 
| 821 | finally: | 851 | except OSError: | 
| 822 | f.close() | 852 | pass | 
