summaryrefslogtreecommitdiffstats
path: root/subcmds/sync.py
diff options
context:
space:
mode:
authorLaMont Jones <lamontjones@google.com>2022-09-08 20:17:58 +0000
committerXin Li <delphij@google.com>2022-09-09 19:04:30 +0000
commit891e8f72ce3551a19c377456574bbfbeac5c8b8e (patch)
treeae82c8d18b6ca66898266b9c43dcebdba75ef0ac /subcmds/sync.py
parentaf8fb132d50bc76386677140ebeaf323f0f5d4e1 (diff)
downloadgit-repo-891e8f72ce3551a19c377456574bbfbeac5c8b8e.tar.gz
sync: save any cruft after calling git gc.v2.29.2
This is ENABLED BY DEFAULT due to data corruption potential. To disable it, set REPO_BACKUP_OBJECTS=0 in the environment. While the workspace will grow over time, this provides a recovery path for an issue where objects are erroneously deleted from the workspace, resulting in lost work. Once the root cause is determined, we will be able to stop saving backups again. Backups are kept in .git/objects/.repo/pack.bak Bug: https://crbug.com/gerrit/16247 Change-Id: Ib8b5c9b4bf0dfa9e29606e0f5c881d65996b2a40 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/345114 Reviewed-by: Jonathan Tan <jonathantanmy@google.com> Tested-by: LaMont Jones <lamontjones@google.com> Reviewed-by: Xin Li <delphij@google.com>
Diffstat (limited to 'subcmds/sync.py')
-rw-r--r--subcmds/sync.py48
1 files changed, 44 insertions, 4 deletions
diff --git a/subcmds/sync.py b/subcmds/sync.py
index de4ac3a7..caa55880 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -21,6 +21,7 @@ import multiprocessing
21import netrc 21import netrc
22from optparse import SUPPRESS_HELP 22from optparse import SUPPRESS_HELP
23import os 23import os
24import shutil
24import socket 25import socket
25import sys 26import sys
26import tempfile 27import tempfile
@@ -58,11 +59,16 @@ from error import RepoChangedException, GitError, ManifestParseError
58import platform_utils 59import platform_utils
59from project import SyncBuffer 60from project import SyncBuffer
60from progress import Progress 61from progress import Progress
62from repo_trace import IsTrace, Trace
61import ssh 63import ssh
62from wrapper import Wrapper 64from wrapper import Wrapper
63from manifest_xml import GitcManifest 65from manifest_xml import GitcManifest
64 66
65_ONE_DAY_S = 24 * 60 * 60 67_ONE_DAY_S = 24 * 60 * 60
68# Env var to implicitly turn off object backups.
69REPO_BACKUP_OBJECTS = 'REPO_BACKUP_OBJECTS'
70
71_BACKUP_OBJECTS = os.environ.get(REPO_BACKUP_OBJECTS) != '0'
66 72
67 73
68class Sync(Command, MirrorSafeCommand): 74class Sync(Command, MirrorSafeCommand):
@@ -694,13 +700,46 @@ later is required to fix a server side protocol bug.
694 700
695 jobs = opt.jobs 701 jobs = opt.jobs
696 702
703 def _backup_cruft(bare_git):
704 # Find any cruft packs in the current gitdir, and save them.
705 # b/221065125 (repo sync complains that objects are missing). This does
706 # not prevent that state, but makes it so that the missing objects are
707 # available.
708 if not _BACKUP_OBJECTS:
709 return
710 saved = []
711 objdir = bare_git.GetDotgitPath('objects')
712 pack_dir = os.path.join(objdir, 'pack')
713 bak_dir = os.path.join(objdir, '.repo','pack.bak')
714 files = set(platform_utils.listdir(pack_dir))
715 to_backup = []
716 for f in files:
717 base, ext = os.path.splitext(f)
718 if base + ".mtimes" in files:
719 to_backup.append(f)
720 if to_backup and not platform_utils.isdir(bak_dir):
721 os.makedirs(bak_dir)
722 for fname in to_backup:
723 bak_fname = os.path.join(bak_dir, fname)
724 if not os.path.exists(bak_fname):
725 saved.append(fname)
726 # Use a tmp file so that we are sure of a complete copy.
727 shutil.copy(os.path.join(pack_dir, fname), bak_fname + '.tmp')
728 shutil.move(bak_fname + '.tmp', bak_fname)
729 if saved and IsTrace():
730 Trace('%s saved %s', bare_git._project.name, ' '.join(saved))
731
732 gc_args = ('--auto', '--cruft')
733 pack_refs_args = ()
697 if jobs < 2: 734 if jobs < 2:
698 for (run_gc, bare_git) in tidy_dirs.values(): 735 for (run_gc, bare_git) in tidy_dirs.values():
699 pm.update(msg=bare_git._project.name) 736 pm.update(msg=bare_git._project.name)
737
700 if run_gc: 738 if run_gc:
701 bare_git.gc('--auto') 739 bare_git.gc(*gc_args)
702 else: 740 else:
703 bare_git.pack_refs() 741 bare_git.pack_refs(*pack_refs_args)
742 _backup_cruft(bare_git)
704 pm.end() 743 pm.end()
705 return 744 return
706 745
@@ -715,15 +754,16 @@ later is required to fix a server side protocol bug.
715 try: 754 try:
716 try: 755 try:
717 if run_gc: 756 if run_gc:
718 bare_git.gc('--auto', config=config) 757 bare_git.gc(*gc_args, config=config)
719 else: 758 else:
720 bare_git.pack_refs(config=config) 759 bare_git.pack_refs(*pack_refs_args, config=config)
721 except GitError: 760 except GitError:
722 err_event.set() 761 err_event.set()
723 except Exception: 762 except Exception:
724 err_event.set() 763 err_event.set()
725 raise 764 raise
726 finally: 765 finally:
766 _backup_cruft(bare_git)
727 pm.finish(bare_git._project.name) 767 pm.finish(bare_git._project.name)
728 sem.release() 768 sem.release()
729 769