diff options
| -rw-r--r-- | docs/internal-fs-layout.md | 2 | ||||
| -rw-r--r-- | subcmds/sync.py | 64 |
2 files changed, 66 insertions, 0 deletions
diff --git a/docs/internal-fs-layout.md b/docs/internal-fs-layout.md index 0c59f988..8cc3cabd 100644 --- a/docs/internal-fs-layout.md +++ b/docs/internal-fs-layout.md | |||
| @@ -110,6 +110,8 @@ Instead, you should use standard Git workflows like [git worktree] or | |||
| 110 | [gitsubmodules] with [superprojects]. | 110 | [gitsubmodules] with [superprojects]. |
| 111 | *** | 111 | *** |
| 112 | 112 | ||
| 113 | * `copy-link-files.json`: Tracking file used by `repo sync` to determine when | ||
| 114 | copyfile or linkfile are added or removed and need corresponding updates. | ||
| 113 | * `project.list`: Tracking file used by `repo sync` to determine when projects | 115 | * `project.list`: Tracking file used by `repo sync` to determine when projects |
| 114 | are added or removed and need corresponding updates in the checkout. | 116 | are added or removed and need corresponding updates in the checkout. |
| 115 | * `projects/`: Bare checkouts of every project synced by the manifest. The | 117 | * `projects/`: Bare checkouts of every project synced by the manifest. The |
diff --git a/subcmds/sync.py b/subcmds/sync.py index aafec1d2..0c386add 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | # See the License for the specific language governing permissions and | 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. | 13 | # limitations under the License. |
| 14 | 14 | ||
| 15 | import errno | ||
| 15 | import functools | 16 | import functools |
| 16 | import http.cookiejar as cookielib | 17 | import http.cookiejar as cookielib |
| 17 | import io | 18 | import io |
| @@ -614,6 +615,60 @@ later is required to fix a server side protocol bug. | |||
| 614 | fd.write('\n') | 615 | fd.write('\n') |
| 615 | return 0 | 616 | return 0 |
| 616 | 617 | ||
| 618 | def UpdateCopyLinkfileList(self): | ||
| 619 | """Save all dests of copyfile and linkfile, and update them if needed. | ||
| 620 | |||
| 621 | Returns: | ||
| 622 | Whether update was successful. | ||
| 623 | """ | ||
| 624 | new_paths = {} | ||
| 625 | new_linkfile_paths = [] | ||
| 626 | new_copyfile_paths = [] | ||
| 627 | for project in self.GetProjects(None, missing_ok=True): | ||
| 628 | new_linkfile_paths.extend(x.dest for x in project.linkfiles) | ||
| 629 | new_copyfile_paths.extend(x.dest for x in project.copyfiles) | ||
| 630 | |||
| 631 | new_paths = { | ||
| 632 | 'linkfile': new_linkfile_paths, | ||
| 633 | 'copyfile': new_copyfile_paths, | ||
| 634 | } | ||
| 635 | |||
| 636 | copylinkfile_name = 'copy-link-files.json' | ||
| 637 | copylinkfile_path = os.path.join(self.manifest.repodir, copylinkfile_name) | ||
| 638 | old_copylinkfile_paths = {} | ||
| 639 | |||
| 640 | if os.path.exists(copylinkfile_path): | ||
| 641 | with open(copylinkfile_path, 'rb') as fp: | ||
| 642 | try: | ||
| 643 | old_copylinkfile_paths = json.load(fp) | ||
| 644 | except: | ||
| 645 | print('error: %s is not a json formatted file.' % | ||
| 646 | copylinkfile_path, file=sys.stderr) | ||
| 647 | platform_utils.remove(copylinkfile_path) | ||
| 648 | return False | ||
| 649 | |||
| 650 | need_remove_files = [] | ||
| 651 | need_remove_files.extend( | ||
| 652 | set(old_copylinkfile_paths.get('linkfile', [])) - | ||
| 653 | set(new_linkfile_paths)) | ||
| 654 | need_remove_files.extend( | ||
| 655 | set(old_copylinkfile_paths.get('copyfile', [])) - | ||
| 656 | set(new_copyfile_paths)) | ||
| 657 | |||
| 658 | for need_remove_file in need_remove_files: | ||
| 659 | try: | ||
| 660 | platform_utils.remove(need_remove_file) | ||
| 661 | except OSError as e: | ||
| 662 | if e.errno == errno.ENOENT: | ||
| 663 | # Try to remove the updated copyfile or linkfile. | ||
| 664 | # So, if the file is not exist, nothing need to do. | ||
| 665 | pass | ||
| 666 | |||
| 667 | # Create copy-link-files.json, save dest path of "copyfile" and "linkfile". | ||
| 668 | with open(copylinkfile_path, 'w', encoding='utf-8') as fp: | ||
| 669 | json.dump(new_paths, fp) | ||
| 670 | return True | ||
| 671 | |||
| 617 | def _SmartSyncSetup(self, opt, smart_sync_manifest_path): | 672 | def _SmartSyncSetup(self, opt, smart_sync_manifest_path): |
| 618 | if not self.manifest.manifest_server: | 673 | if not self.manifest.manifest_server: |
| 619 | print('error: cannot smart sync: no manifest server defined in ' | 674 | print('error: cannot smart sync: no manifest server defined in ' |
| @@ -914,6 +969,13 @@ later is required to fix a server side protocol bug. | |||
| 914 | print('\nerror: Local checkouts *not* updated.', file=sys.stderr) | 969 | print('\nerror: Local checkouts *not* updated.', file=sys.stderr) |
| 915 | sys.exit(1) | 970 | sys.exit(1) |
| 916 | 971 | ||
| 972 | if not self.UpdateCopyLinkfileList(): | ||
| 973 | err_event.set() | ||
| 974 | err_update_linkfiles = True | ||
| 975 | if opt.fail_fast: | ||
| 976 | print('\nerror: Local update copyfile or linkfile failed.', file=sys.stderr) | ||
| 977 | sys.exit(1) | ||
| 978 | |||
| 917 | err_results = [] | 979 | err_results = [] |
| 918 | # NB: We don't exit here because this is the last step. | 980 | # NB: We don't exit here because this is the last step. |
| 919 | err_checkout = not self._Checkout(all_projects, opt, err_results) | 981 | err_checkout = not self._Checkout(all_projects, opt, err_results) |
| @@ -932,6 +994,8 @@ later is required to fix a server side protocol bug. | |||
| 932 | print('error: Downloading network changes failed.', file=sys.stderr) | 994 | print('error: Downloading network changes failed.', file=sys.stderr) |
| 933 | if err_update_projects: | 995 | if err_update_projects: |
| 934 | print('error: Updating local project lists failed.', file=sys.stderr) | 996 | print('error: Updating local project lists failed.', file=sys.stderr) |
| 997 | if err_update_linkfiles: | ||
| 998 | print('error: Updating copyfiles or linkfiles failed.', file=sys.stderr) | ||
| 935 | if err_checkout: | 999 | if err_checkout: |
| 936 | print('error: Checking out local projects failed.', file=sys.stderr) | 1000 | print('error: Checking out local projects failed.', file=sys.stderr) |
| 937 | if err_results: | 1001 | if err_results: |
