Prepare for 1.2.1

Signed-off-by: Konstantin Ryabitsev <konstantin@linuxfoundation.org>
diff --git a/.gitignore b/.gitignore
index f7bd224..5dbf5a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@
 *.pdf
 *~
 dist
+build
 *.egg-info
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 460b805..33fd5d8 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,3 +1,14 @@
+v1.2.1 (2019-03-11)
+-------------------
+- Minor feature improvement changing how precious=yes works.
+  Grokmirror will now turn preciousObjects off for the duration
+  of the repack. We still protect shared repositories against
+  inadvertent object pruning by outside processes, but this
+  allows us to clean up loose objects and obsolete packs.
+  To have the 1.2.0 behaviour back, set precious=always, but it
+  is only really useful in very rare cases.
+
+
 v1.2.0 (2019-02-14)
 -------------------
 - Make sure to set gc.auto=0 on repositories to avoid pruning repos
diff --git a/README.rst b/README.rst
index 936bee7..2bfb093 100644
--- a/README.rst
+++ b/README.rst
@@ -8,7 +8,7 @@
 :Date:      2019-02-14
 :Copyright: The Linux Foundation and contributors
 :License:   GPLv3+
-:Version:   1.2.0
+:Version:   1.2.1
 
 DESCRIPTION
 -----------
diff --git a/fsck.conf b/fsck.conf
index 882e613..d056ff5 100644
--- a/fsck.conf
+++ b/fsck.conf
@@ -69,10 +69,18 @@
 # potential corruption.
 prune = yes
 #
-# Setting precious=yes will add extensions.preciousObjects=true git configuration
-# to all repositories that are parents to others (via git alternates). Turning this
-# on will help eliminate the possibility of repository corruption, but at a price of
-# keeping all redundant objects on disk forever. Repositories with preciousObjects
-# will still be repacked periodically, but redundant packs and loose objects will
-# never be cleaned up and will be kept around forever.
-precious = no
+# Grokmirror is extremely careful about not pruning the repositories that are
+# used by others via git alternates. However, it cannot prevent some other git
+# process (not grokmirror-managed) from inadvertently running "git prune/gc". For
+# example, this may happen if an admin mistypes a command in the wrong directory.
+# Setting precious=yes will add extensions.preciousObjects=true to the git
+# configuration file in such repositories, which will help prevent repository
+# corruption between grok-fsck runs.
+# When set to "yes", grokmirror will temporarily turn this feature off when running
+# scheduled repacks in order to be able to delete redundant packs and loose objects
+# that have already been packed. This is usually a safe operation when done by
+# grok-fsck itself. However, if you set this to "always", grokmirror will leave this
+# enabled even during grok-fsck runs, for maximum paranoia. Be warned, that this will
+# result in ever-growing git repositories, so it only makes sense in very rare
+# situations, such as for backup purposes.
+precious = yes
diff --git a/grokmirror/__init__.py b/grokmirror/__init__.py
index 4279a41..8f30349 100644
--- a/grokmirror/__init__.py
+++ b/grokmirror/__init__.py
@@ -29,7 +29,7 @@
 
 from git import Repo
 
-VERSION = '1.2.0'
+VERSION = '1.2.1'
 MANIFEST_LOCKH = None
 REPO_LOCKH = {}
 GITBIN = '/usr/bin/git'
@@ -206,6 +206,7 @@
 def is_alt_repo(toplevel, refrepo):
     global _alt_repo_cache
     if _alt_repo_cache is None:
+        logger.info('Finding all repositories using alternates')
         # Populate a simple byte string with contents of all
         # objects/info/alternates we find, and then do a simple match
         _alt_repo_cache = b''
diff --git a/grokmirror/fsck.py b/grokmirror/fsck.py
index 7397f1a..a2648c7 100755
--- a/grokmirror/fsck.py
+++ b/grokmirror/fsck.py
@@ -63,7 +63,7 @@
 
 def run_git_prune(fullpath, config):
     prune_ok = True
-    if 'prune' not in config.keys() or config['prune'] != 'yes':
+    if 'prune' not in config or config['prune'] != 'yes':
         return prune_ok
 
     # Are any other repos using us in their objects/info/alternates?
@@ -109,7 +109,11 @@
     # Returns false if we hit any errors on the way
     repack_ok = True
 
-    is_precious = check_precious_objects(fullpath)
+    if 'precious' not in config:
+        config['precious'] = 'yes'
+
+    is_precious = False
+    set_precious = False
 
     # Figure out what our repack flags should be.
     repack_flags = list()
@@ -124,9 +128,15 @@
     gitdir = '/' + os.path.relpath(fullpath, config['toplevel']).lstrip('/')
     if grokmirror.is_alt_repo(config['toplevel'], gitdir):
         # we are a "mother repo"
-        if not is_precious and ('precious' in config and config['precious'] == 'yes'):
+        # Force preciousObjects if precious is "always"
+        if config['precious'] == 'always':
             is_precious = True
-            set_precious_objects(fullpath)
+            set_precious_objects(fullpath, enabled=True)
+        else:
+            # Turn precious off during repacks
+            set_precious_objects(fullpath, enabled=False)
+            # Turn it back on after we're done
+            set_precious = True
 
         # are we using alternates ourselves? Multiple levels of alternates are
         # a bad idea in general due high possibility of corruption.
@@ -170,6 +180,9 @@
 
     retcode, output, error = grokmirror.run_git_command(fullpath, args)
 
+    if set_precious:
+        set_precious_objects(fullpath, enabled=True)
+
     # With newer versions of git, repack may return warnings that are safe to ignore
     # so use the same strategy to weed out things we aren't interested in seeing
     if error:
@@ -294,11 +307,15 @@
     return obj_info
 
 
-def set_precious_objects(fullpath):
+def set_precious_objects(fullpath, enabled=True):
     # It's better to just set it blindly without checking first,
     # as this results in one fewer shell-out.
     logger.debug('Setting preciousObjects for %s', fullpath)
-    args = ['config', 'extensions.preciousObjects', 'true']
+    if enabled:
+        poval = 'true'
+    else:
+        poval = 'false'
+    args = ['config', 'extensions.preciousObjects', poval]
     grokmirror.run_git_command(fullpath, args)
 
 
@@ -319,14 +336,14 @@
     # noinspection PyTypeChecker
     em = enlighten.get_manager(series=' -=#')
 
-    if 'log' in config.keys():
+    if 'log' in config:
         ch = logging.FileHandler(config['log'])
         formatter = logging.Formatter(
             "[%(process)d] %(asctime)s - %(levelname)s - %(message)s")
         ch.setFormatter(formatter)
         loglevel = logging.INFO
 
-        if 'loglevel' in config.keys():
+        if 'loglevel' in config:
             if config['loglevel'] == 'debug':
                 loglevel = logging.DEBUG
 
@@ -475,7 +492,10 @@
         schedcheck = datetime.datetime.strptime(status[fullpath]['nextcheck'], '%Y-%m-%d')
         nextcheck = today + datetime.timedelta(days=checkdelay)
 
-        if 'repack' not in config.keys() or config['repack'] != 'yes':
+        if 'precious' not in config:
+            config['precious'] = 'yes'
+
+        if 'repack' not in config or config['repack'] != 'yes':
             # don't look at me if you turned off repack
             logger.debug('Not repacking because repack=no in config')
             needs_repack = 0
@@ -526,7 +546,7 @@
                                  fullpath, pc_loose_size)
                     needs_repack = 1
 
-        if needs_repack > 0 and check_precious_objects(fullpath):
+        if needs_repack > 0 and (config['precious'] == 'always' and check_precious_objects(fullpath)):
             # if we have preciousObjects, then we only repack based on the same
             # schedule as fsck.
             logger.debug('preciousObjects is set')
@@ -720,5 +740,6 @@
     return grok_fsck(opts.config, opts.verbose, opts.force, opts.repack_only, opts.conn_only,
                      opts.repack_all_quick, opts.repack_all_full)
 
+
 if __name__ == '__main__':
     command()
diff --git a/setup.py b/setup.py
index 82e6387..7fda34d 100644
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@
 from setuptools import setup
 
 NAME = 'grokmirror'
-VERSION = '1.2.0'
+VERSION = '1.2.1'
 
 
 # Utility function to read the README file.