aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ryabitsev <konstantin@linuxfoundation.org>2019-01-03 11:48:57 -0500
committerKonstantin Ryabitsev <konstantin@linuxfoundation.org>2019-01-03 11:48:57 -0500
commitd23bdf8ea35e8bbc50dd525f6bc27a9c7afe6b18 (patch)
tree668ce1c1edfea17f41ed692e65ae6baeb8544dde
parent0cfd11f84c700f56b01c6e125dff6de45ca2d1fe (diff)
downloadgrokmirror-d23bdf8ea35e8bbc50dd525f6bc27a9c7afe6b18.tar.gz
Set preciousObjects for mother repos
Ensure even manual repacks using "git gc" or "git prune" done by admins cannot result in repository corruption. Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
-rw-r--r--CHANGELOG.rst11
-rwxr-xr-xgrokmirror/fsck.py36
2 files changed, 42 insertions, 5 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index f90312c..0bc901a 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -20,6 +20,17 @@ v1.2-master
to the git binary using the GITBIN env variable or by simply
adding it to your path.
+- Add "reclone_on_errors" setting in fsck.conf. If fsck/repack/prune
+ comes across a matching error, it will mark the repository for
+ recloning and it will be cloned anew from the master the next time
+ grok-pull runs. This is useful for auto-correcting corruption on the
+ mirrors. You can also manually request a reclone by creating a
+ "grokmirror.reclone" file in a repository.
+
+- Set extensions.preciousObjects for repositories used with git
+ alternates. This helps further protect them from erroneous pruning
+ (e.g. done manually by an administrator).
+
v1.1.1 (2018-07-25)
-------------------
diff --git a/grokmirror/fsck.py b/grokmirror/fsck.py
index 95fe623..609f3e3 100755
--- a/grokmirror/fsck.py
+++ b/grokmirror/fsck.py
@@ -37,15 +37,20 @@ def check_reclone_error(fullpath, config, errors):
for line in errors:
for estring in config['reclone_on_errors']:
if line.find(estring) != -1:
- reclone = line
- logger.debug('Will re-clone due to this error: %s', line)
- logger.info(' error : re-clone requested')
+ # is preciousObjects set for this repo?
+ if check_precious_objects(fullpath):
+ logger.critical('\tpreciousObjects set, not requesting auto-reclone')
+ return
+ else:
+ reclone = line
+ logger.critical('\trequested auto-reclone')
+ break
+ if reclone is not None:
break
if reclone is None:
return
- gitdir = '/' + os.path.relpath(fullpath, config['toplevel']).lstrip('/')
- rfile = os.path.join(gitdir, 'grokmirror.reclone')
+ rfile = os.path.join(fullpath, 'grokmirror.reclone')
# Have we already requested a reclone?
if os.path.exists(rfile):
logger.debug('Already requested repo reclone for %s', fullpath)
@@ -94,6 +99,7 @@ def run_git_prune(fullpath, config):
prune_ok = False
for entry in warn:
logger.critical("\t%s", entry)
+ check_reclone_error(fullpath, config, warn)
return prune_ok
@@ -119,6 +125,7 @@ def run_git_repack(fullpath, config, level=1):
gitdir = '/' + os.path.relpath(fullpath, config['toplevel']).lstrip('/')
if grokmirror.is_alt_repo(config['toplevel'], gitdir):
# we are a "mother repo"
+ set_precious_objects(fullpath)
# are we using alternates ourselves? Multiple levels of alternates are
# a bad idea in general due high possibility of corruption.
if os.path.exists(os.path.join(fullpath, 'objects', 'info', 'alternates')):
@@ -173,6 +180,7 @@ def run_git_repack(fullpath, config, level=1):
repack_ok = False
for entry in warn:
logger.critical("\t%s", entry)
+ check_reclone_error(fullpath, config, warn)
if not repack_ok:
# No need to repack refs if repo is broken
@@ -216,6 +224,8 @@ def run_git_repack(fullpath, config, level=1):
for entry in warn:
logger.critical("\t%s", entry)
+ check_reclone_error(fullpath, config, warn)
+
if repack_ok and 'prune' in config and config['prune'] == 'yes':
# run prune now
return run_git_prune(fullpath, config)
@@ -255,6 +265,7 @@ def run_git_fsck(fullpath, config, conn_only=False):
logger.critical('%s has critical errors:', fullpath)
for entry in warn:
logger.critical("\t%s", entry)
+ check_reclone_error(fullpath, config, warn)
def get_repo_obj_info(fullpath):
@@ -270,6 +281,21 @@ def get_repo_obj_info(fullpath):
return obj_info
+def set_precious_objects(fullpath):
+ # It's better to just set it blindly without checking first,
+ # as this results in one fewer shell-out.
+ args = ['config', 'extensions.preciousObjects', 'true']
+ grokmirror.run_git_command(fullpath, args)
+
+
+def check_precious_objects(fullpath):
+ args = ['config', '--get', 'extensions.preciousObjects']
+ retcode, output, error = grokmirror.run_git_command(fullpath, args)
+ if output.strip().lower() == 'true':
+ return True
+ return False
+
+
def fsck_mirror(name, config, verbose=False, force=False, repack_only=False,
conn_only=False, repack_all_quick=False, repack_all_full=False):
global logger