def relinkfile(src, dst): bak = dst + '.bak' os.rename(dst, bak) try: util.os_link(src, dst) except OSError: os.rename(bak, dst) raise os.remove(bak)
ui.note(_('%d suboptimal nodes\n') % suboptimal) writerevs(ui, r1, r2, order, tr) report(ui, r1, r2) tr.close() except: # Abort transaction first, so we truncate the files before # deleting them. tr.abort() for fn in (tmpindexfn, tmpdatafn): ignoremissing(os.unlink)(fn) raise if not opts.get('dry_run'): # racy, both files cannot be renamed atomically # copy files util.os_link(indexfn, oldindexfn) ignoremissing(util.os_link)(datafn, olddatafn) # rename util.rename(tmpindexfn, indexfn) try: os.chmod(tmpdatafn, os.stat(datafn).st_mode) util.rename(tmpdatafn, datafn) except OSError, inst: if inst.errno != errno.ENOENT: raise ignoremissing(os.unlink)(datafn) else: for fn in (tmpindexfn, tmpdatafn): ignoremissing(os.unlink)(fn) finally:
def shrink(ui, repo, **opts): """ Shrink revlog by re-ordering revisions. Will operate on manifest for the given repository if no other revlog is specified.""" # Unbuffer stdout for nice progress output. sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) if not repo.local(): raise util.Abort('not a local repository: %s' % repo.root) fn = opts.get('revlog') if not fn: indexfn = repo.sjoin('00manifest.i') else: if not fn.endswith('.i'): raise util.Abort('--revlog option must specify the revlog index ' 'file (*.i), not %s' % opts.get('revlog')) indexfn = os.path.realpath(fn) store = repo.sjoin('') if not indexfn.startswith(store): raise util.Abort('--revlog option must specify a revlog in %s, ' 'not %s' % (store, indexfn)) datafn = indexfn[:-2] + '.d' if not os.path.exists(indexfn): raise util.Abort('no such file: %s' % indexfn) if '00changelog' in indexfn: raise util.Abort( 'shrinking the changelog will corrupt your repository') if not os.path.exists(datafn): # This is just a lazy shortcut because I can't be bothered to # handle all the special cases that entail from no .d file. raise util.Abort('%s does not exist: revlog not big enough ' 'to be worth shrinking' % datafn) oldindexfn = indexfn + '.old' olddatafn = datafn + '.old' if os.path.exists(oldindexfn) or os.path.exists(olddatafn): raise util.Abort('one or both of\n' ' %s\n' ' %s\n' 'exists from a previous run; please clean up before ' 'running again' % (oldindexfn, olddatafn)) ui.write('shrinking %s\n' % indexfn) prefix = os.path.basename(indexfn)[:-1] (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn), prefix=prefix, suffix='.i') tmpdatafn = tmpindexfn[:-2] + '.d' os.close(tmpfd) r1 = revlog.revlog(util.opener(os.getcwd(), audit=False), indexfn) r2 = revlog.revlog(util.opener(os.getcwd(), audit=False), tmpindexfn) # Don't use repo.transaction(), because then things get hairy with # paths: some need to be relative to .hg, and some need to be # absolute. Doing it this way keeps things simple: everything is an # absolute path. lock = repo.lock(wait=False) tr = transaction.transaction(ui.warn, open, repo.sjoin('journal')) try: try: order = toposort(ui, r1) writerevs(ui, r1, r2, order, tr) report(ui, datafn, tmpdatafn) tr.close() except: # Abort transaction first, so we truncate the files before # deleting them. tr.abort() if os.path.exists(tmpindexfn): os.unlink(tmpindexfn) if os.path.exists(tmpdatafn): os.unlink(tmpdatafn) raise if not opts.get('dry_run'): # Racy since both files cannot be renamed atomically util.os_link(indexfn, oldindexfn) util.os_link(datafn, olddatafn) util.rename(tmpindexfn, indexfn) util.rename(tmpdatafn, datafn) else: os.unlink(tmpindexfn) os.unlink(tmpdatafn) finally: lock.release() if not opts.get('dry_run'): ui.write( 'note: old revlog saved in:\n' ' %s\n' ' %s\n' '(You can delete those files when you are satisfied that your\n' 'repository is still sane. ' 'Running \'hg verify\' is strongly recommended.)\n' % (oldindexfn, olddatafn))
def shrink(ui, repo, **opts): """ Shrink revlog by re-ordering revisions. Will operate on manifest for the given repository if no other revlog is specified.""" # Unbuffer stdout for nice progress output. sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) if not repo.local(): raise util.Abort('not a local repository: %s' % repo.root) fn = opts.get('revlog') if not fn: indexfn = repo.sjoin('00manifest.i') else: if not fn.endswith('.i'): raise util.Abort('--revlog option must specify the revlog index ' 'file (*.i), not %s' % opts.get('revlog')) indexfn = os.path.realpath(fn) store = repo.sjoin('') if not indexfn.startswith(store): raise util.Abort('--revlog option must specify a revlog in %s, ' 'not %s' % (store, indexfn)) datafn = indexfn[:-2] + '.d' if not os.path.exists(indexfn): raise util.Abort('no such file: %s' % indexfn) if '00changelog' in indexfn: raise util.Abort('shrinking the changelog will corrupt your repository') if not os.path.exists(datafn): # This is just a lazy shortcut because I can't be bothered to # handle all the special cases that entail from no .d file. raise util.Abort('%s does not exist: revlog not big enough ' 'to be worth shrinking' % datafn) oldindexfn = indexfn + '.old' olddatafn = datafn + '.old' if os.path.exists(oldindexfn) or os.path.exists(olddatafn): raise util.Abort('one or both of\n' ' %s\n' ' %s\n' 'exists from a previous run; please clean up before ' 'running again' % (oldindexfn, olddatafn)) ui.write('shrinking %s\n' % indexfn) prefix = os.path.basename(indexfn)[:-1] (tmpfd, tmpindexfn) = tempfile.mkstemp(dir=os.path.dirname(indexfn), prefix=prefix, suffix='.i') tmpdatafn = tmpindexfn[:-2] + '.d' os.close(tmpfd) r1 = revlog.revlog(util.opener(os.getcwd(), audit=False), indexfn) r2 = revlog.revlog(util.opener(os.getcwd(), audit=False), tmpindexfn) # Don't use repo.transaction(), because then things get hairy with # paths: some need to be relative to .hg, and some need to be # absolute. Doing it this way keeps things simple: everything is an # absolute path. lock = repo.lock(wait=False) tr = transaction.transaction(ui.warn, open, repo.sjoin('journal')) try: try: order = toposort(ui, r1) writerevs(ui, r1, r2, order, tr) report(ui, datafn, tmpdatafn) tr.close() except: # Abort transaction first, so we truncate the files before # deleting them. tr.abort() if os.path.exists(tmpindexfn): os.unlink(tmpindexfn) if os.path.exists(tmpdatafn): os.unlink(tmpdatafn) raise if not opts.get('dry_run'): # Racy since both files cannot be renamed atomically util.os_link(indexfn, oldindexfn) util.os_link(datafn, olddatafn) util.rename(tmpindexfn, indexfn) util.rename(tmpdatafn, datafn) else: os.unlink(tmpindexfn) os.unlink(tmpdatafn) finally: lock.release() if not opts.get('dry_run'): ui.write('note: old revlog saved in:\n' ' %s\n' ' %s\n' '(You can delete those files when you are satisfied that your\n' 'repository is still sane. ' 'Running \'hg verify\' is strongly recommended.)\n' % (oldindexfn, olddatafn))