diff --git a/remotefilelog/__init__.py b/remotefilelog/__init__.py --- a/remotefilelog/__init__.py +++ b/remotefilelog/__init__.py @@ -992,13 +992,16 @@ @command('repack', [ ('', 'background', None, _('run in a background process'), None), ('', 'incremental', None, _('do an incremental repack'), None), + ('', 'packsonly', None, _('only repack packs (skip loose objects)'), None), ], _('hg repack [OPTIONS]')) def repack(ui, repo, *pats, **opts): if opts.get('background'): repackmod.backgroundrepack(repo, incremental=opts.get('incremental')) return + options = {'packsonly': opts.get('packsonly')} + if opts.get('incremental'): - repackmod.incrementalrepack(repo) + repackmod.incrementalrepack(repo, options=options) else: - repackmod.fullrepack(repo) + repackmod.fullrepack(repo, options=options) diff --git a/remotefilelog/basepack.py b/remotefilelog/basepack.py --- a/remotefilelog/basepack.py +++ b/remotefilelog/basepack.py @@ -161,7 +161,7 @@ return missing - def markledger(self, ledger): + def markledger(self, ledger, options=None): for pack in self.packs: pack.markledger(ledger) @@ -281,7 +281,7 @@ def getmissing(self, keys): raise NotImplemented() - def markledger(self, ledger): + def markledger(self, ledger, options=None): raise NotImplemented() def cleanup(self, ledger): diff --git a/remotefilelog/basestore.py b/remotefilelog/basestore.py --- a/remotefilelog/basestore.py +++ b/remotefilelog/basestore.py @@ -3,6 +3,7 @@ import errno, hashlib, heapq, os, shutil, time from . import ( + constants, shallowutil, ) @@ -55,7 +56,9 @@ # BELOW THIS ARE IMPLEMENTATIONS OF REPACK SOURCE - def markledger(self, ledger): + def markledger(self, ledger, options=None): + if options and options.get(constants.OPTION_PACKSONLY): + return if self._shared: for filename, nodes in self._getfiles(): for node in nodes: diff --git a/remotefilelog/constants.py b/remotefilelog/constants.py --- a/remotefilelog/constants.py +++ b/remotefilelog/constants.py @@ -30,3 +30,6 @@ return _("files") if category == TREEPACK_CATEGORY: return _("trees") + +# Repack options passed to ``marledger``. +OPTION_PACKSONLY = 'packsonly' diff --git a/remotefilelog/contentstore.py b/remotefilelog/contentstore.py --- a/remotefilelog/contentstore.py +++ b/remotefilelog/contentstore.py @@ -127,9 +127,9 @@ else: raise RuntimeError("no writable store configured") - def markledger(self, ledger): + def markledger(self, ledger, options=None): for store in self.stores: - store.markledger(ledger) + store.markledger(ledger, options) def markforrefresh(self): for store in self.stores: @@ -219,7 +219,7 @@ def getmissing(self, keys): return keys - def markledger(self, ledger): + def markledger(self, ledger, options=None): pass class manifestrevlogstore(object): @@ -301,7 +301,9 @@ self._repackstartlinkrev = startrev self._repackendlinkrev = endrev - def markledger(self, ledger): + def markledger(self, ledger, options=None): + if options and options.get(constants.OPTION_PACKSONLY): + return treename = '' rl = revlog.revlog(self._svfs, '00manifesttree.i') startlinkrev = self._repackstartlinkrev diff --git a/remotefilelog/datapack.py b/remotefilelog/datapack.py --- a/remotefilelog/datapack.py +++ b/remotefilelog/datapack.py @@ -223,7 +223,7 @@ return struct.unpack(self.INDEXFORMAT, entry) - def markledger(self, ledger): + def markledger(self, ledger, options=None): for filename, node in self: ledger.markdataentry(self, filename, node) @@ -323,7 +323,7 @@ def add(self, name, node, data): raise RuntimeError("cannot add to datapack (%s:%s)" % (name, node)) - def markledger(self, ledger): + def markledger(self, ledger, options=None): for filename, node in self: ledger.markdataentry(self, filename, node) diff --git a/remotefilelog/historypack.py b/remotefilelog/historypack.py --- a/remotefilelog/historypack.py +++ b/remotefilelog/historypack.py @@ -270,7 +270,7 @@ endnode = midnode return None - def markledger(self, ledger): + def markledger(self, ledger, options=None): for filename, node in self: ledger.markhistoryentry(self, filename, node) diff --git a/remotefilelog/metadatastore.py b/remotefilelog/metadatastore.py --- a/remotefilelog/metadatastore.py +++ b/remotefilelog/metadatastore.py @@ -96,9 +96,9 @@ missing = store.getmissing(missing) return missing - def markledger(self, ledger): + def markledger(self, ledger, options=None): for store in self.stores: - store.markledger(ledger) + store.markledger(ledger, options) def getmetrics(self): metrics = [s.getmetrics() for s in self.stores] @@ -143,5 +143,5 @@ def getmissing(self, keys): return keys - def markledger(self, ledger): + def markledger(self, ledger, options=None): pass diff --git a/remotefilelog/repack.py b/remotefilelog/repack.py --- a/remotefilelog/repack.py +++ b/remotefilelog/repack.py @@ -36,9 +36,12 @@ repo.ui.warn(msg) runshellcommand(cmd, os.environ) -def fullrepack(repo): +def fullrepack(repo, options=None): + """If ``packsonly`` is True, stores creating only loose objects are skipped. + """ if util.safehasattr(repo, 'shareddatastores'): - datasource = contentstore.unioncontentstore(*repo.shareddatastores) + datasource = contentstore.unioncontentstore( + *repo.shareddatastores) historysource = metadatastore.unionmetadatastore( *repo.sharedhistorystores, allowincomplete=True) @@ -47,11 +50,11 @@ repo, constants.FILEPACK_CATEGORY) _runrepack(repo, datasource, historysource, packpath, - constants.FILEPACK_CATEGORY) + constants.FILEPACK_CATEGORY, options=options) if repo.ui.configbool('treemanifest', 'server'): treemfmod = extensions.find('treemanifest') - treemfmod.serverrepack(repo) + treemfmod.serverrepack(repo, options=options) elif util.safehasattr(repo.manifestlog, 'datastore'): localdata, shareddata = _getmanifeststores(repo) lpackpath, ldstores, lhstores = localdata @@ -63,7 +66,7 @@ *shstores, allowincomplete=True) _runrepack(repo, datasource, historysource, spackpath, - constants.TREEPACK_CATEGORY) + constants.TREEPACK_CATEGORY, options=options) # Repack the local manifest store datasource = contentstore.unioncontentstore( @@ -73,10 +76,10 @@ *lhstores, allowincomplete=True) _runrepack(repo, datasource, historysource, lpackpath, - constants.TREEPACK_CATEGORY) + constants.TREEPACK_CATEGORY, options=options) -def incrementalrepack(repo): +def incrementalrepack(repo, options=None): """This repacks the repo by looking at the distribution of pack files in the repo and performing the most minimal repack to keep the repo in good shape. """ @@ -88,7 +91,8 @@ repo.shareddatastores, repo.sharedhistorystores, packpath, - constants.FILEPACK_CATEGORY) + constants.FILEPACK_CATEGORY, + options=options) if repo.ui.configbool('treemanifest', 'server'): treemfmod = extensions.find('treemanifest') @@ -103,7 +107,8 @@ sdstores, shstores, spackpath, - constants.TREEPACK_CATEGORY) + constants.TREEPACK_CATEGORY, + options=options) # Repack the local manifest store _incrementalrepack(repo, @@ -111,7 +116,8 @@ lhstores, lpackpath, constants.TREEPACK_CATEGORY, - allowincompletedata=True) + allowincompletedata=True, + options=options) def _getmanifeststores(repo): shareddatastores = repo.manifestlog.shareddatastores @@ -142,7 +148,7 @@ return packs def _incrementalrepack(repo, datastore, historystore, packpath, category, - allowincompletedata=False): + allowincompletedata=False, options=None): shallowutil.mkstickygroupdir(repo.ui, packpath) files = osutil.listdir(packpath, stat=True) @@ -179,7 +185,8 @@ packpath, category, fullhistory=metadatastore.unionmetadatastore( *allhistorypacks, - allowincomplete=True)) + allowincomplete=True), + options=options) def _computeincrementaldatapack(ui, files): """Given a set of pack files and a set of generation size limits, this @@ -284,7 +291,8 @@ return chosenpacks -def _runrepack(repo, data, history, packpath, category, fullhistory=None): +def _runrepack(repo, data, history, packpath, category, fullhistory=None, + options=None): shallowutil.mkstickygroupdir(repo.ui, packpath) def isold(repo, filename, node): @@ -305,8 +313,7 @@ if not fullhistory: fullhistory = history packer = repacker(repo, data, history, fullhistory, category, - gc=garbagecollect, - isold=isold) + gc=garbagecollect, isold=isold, options=options) # internal config: remotefilelog.datapackversion dv = repo.ui.configint('remotefilelog', 'datapackversion', 0) @@ -385,13 +392,14 @@ new format. """ def __init__(self, repo, data, history, fullhistory, category, gc=False, - isold=None): + isold=None, options=None): self.repo = repo self.data = data self.history = history self.fullhistory = fullhistory self.unit = constants.getunits(category) self.garbagecollect = gc + self.options = options if self.garbagecollect: if not isold: raise ValueError("Function 'isold' is not properly specified") @@ -407,8 +415,8 @@ self.repo.hook('prerepack') # Populate ledger from source - self.data.markledger(ledger) - self.history.markledger(ledger) + self.data.markledger(ledger, options=self.options) + self.history.markledger(ledger, options=self.options) # Run repack self.repackdata(ledger, targetdata) diff --git a/remotefilelog/wirepack.py b/remotefilelog/wirepack.py --- a/remotefilelog/wirepack.py +++ b/remotefilelog/wirepack.py @@ -221,7 +221,7 @@ if count == 0 and filename == '': break - def markledger(self, ledger): + def markledger(self, ledger, options=None): pass def cleanup(self, ledger): diff --git a/tests/test-remotefilelog-repack.t b/tests/test-remotefilelog-repack.t --- a/tests/test-remotefilelog-repack.t +++ b/tests/test-remotefilelog-repack.t @@ -82,6 +82,18 @@ $TESTTMP/hgcache/master/packs/8e25dec685d5e0bb1f1b39df3acebda0e0d75c6e.datapack $TESTTMP/hgcache/repos +# First assert that with --packsonly, the loose object will be ignored: + + $ hg repack --packsonly + + $ find $CACHEDIR -type f | sort + $TESTTMP/hgcache/master/11/f6ad8ec52a2984abaafd7c3b516503785c2072/d4a3ed9310e5bd9887e3bf779da5077efab28216 + $TESTTMP/hgcache/master/packs/276d308429d0303762befa376788300f0310f90e.histidx + $TESTTMP/hgcache/master/packs/276d308429d0303762befa376788300f0310f90e.histpack + $TESTTMP/hgcache/master/packs/8e25dec685d5e0bb1f1b39df3acebda0e0d75c6e.dataidx + $TESTTMP/hgcache/master/packs/8e25dec685d5e0bb1f1b39df3acebda0e0d75c6e.datapack + $TESTTMP/hgcache/repos + $ hg repack --traceback $ find $CACHEDIR -type f | sort diff --git a/tests/test-treemanifest-repack.t b/tests/test-treemanifest-repack.t --- a/tests/test-treemanifest-repack.t +++ b/tests/test-treemanifest-repack.t @@ -118,7 +118,10 @@ $ ls_l .hg/store/packs/manifests | grep datapack -r--r--r-- 248 5d1716bbef6e7200192de6509055d1ee31a4172c.datapack -r--r--r-- 146 cffef142da32f3e52c1779490e5d0ddac5f9b82b.datapack - $ hg repack + +# As we only have packs, also test that --packsonly doesn't prevent packs from +being repacked + $ hg repack --packsonly $ ls_l .hg/store/packs/manifests | grep datapack -r--r--r-- 386 d15c09a9a5a13bb689bd9764455a415a20dc885e.datapack @@ -185,6 +188,10 @@ data/dir/b.i meta/dir/00manifest.i +--packsonly shouldn't repack anything: + $ hg repack --packsonly + $ ls .hg/cache/packs/manifests + $ hg repack $ ls .hg/cache/packs/manifests 56e8c6f0ca2a324b8b5ca1a2730323a1b4d0793a.dataidx diff --git a/treemanifest/__init__.py b/treemanifest/__init__.py --- a/treemanifest/__init__.py +++ b/treemanifest/__init__.py @@ -1462,13 +1462,13 @@ def getmissing(self, keys): return keys - def markledger(self, ledger): + def markledger(self, ledger, options=None): pass def getmetrics(self): return {} -def serverrepack(repo, incremental=False): +def serverrepack(repo, incremental=False, options=None): packpath = repo.vfs.join('cache/packs/%s' % PACK_CATEGORY) dpackstore = datapackstore(repo.ui, packpath) @@ -1492,7 +1492,8 @@ startrev = latestpackedlinkrev + 1 revlogstore.setrepacklinkrevrange(startrev, endrev) - _runrepack(repo, datastore, histstore, packpath, PACK_CATEGORY) + _runrepack(repo, datastore, histstore, packpath, PACK_CATEGORY, + options=options) def striptrees(orig, repo, tr, striprev, files): if not treeenabled(repo.ui):