mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 911375 - Part 3: Remove PurgeManifest; r=glandium
This commit is contained in:
parent
faa364777d
commit
de7e8e4185
@ -1,79 +0,0 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# This script is used to purge a directory of unwanted files as defined by
|
||||
# a manifest file.
|
||||
|
||||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
|
||||
from mozpack.manifests import PurgeManifest
|
||||
|
||||
|
||||
def do_purge(purger, dest, state):
|
||||
state['result'] = purger.purge(dest)
|
||||
|
||||
|
||||
def process_manifest(topdir, manifest_path):
|
||||
manifest = PurgeManifest(path=manifest_path)
|
||||
purger = manifest.get_purger()
|
||||
full = os.path.join(topdir, manifest.relpath)
|
||||
|
||||
state = dict(
|
||||
relpath=manifest.relpath,
|
||||
result=None,
|
||||
)
|
||||
|
||||
t = threading.Thread(target=do_purge, args=(purger, full, state))
|
||||
state['thread'] = t
|
||||
t.start()
|
||||
|
||||
return state
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Purge a directory of untracked files.')
|
||||
|
||||
parser.add_argument('--directory', '-d',
|
||||
help='Directory containing manifest files. Will process every file '
|
||||
'in directory.')
|
||||
parser.add_argument('topdir',
|
||||
help='Top directory all paths are evaluated from.')
|
||||
parser.add_argument('manifests', nargs='*',
|
||||
help='List of manifest files defining purge operations to perform.')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
states = []
|
||||
|
||||
print('Purging unaccounted files from object directory...')
|
||||
|
||||
# We perform purging using threads for performance reasons. Hopefully
|
||||
# multiple I/O operations will be faster than just 1.
|
||||
paths = []
|
||||
if args.directory:
|
||||
for path in sorted(os.listdir(args.directory)):
|
||||
paths.append(os.path.join(args.directory, path))
|
||||
|
||||
paths.extend(args.manifests)
|
||||
|
||||
for path in paths:
|
||||
states.append(process_manifest(args.topdir, path))
|
||||
|
||||
for state in states:
|
||||
state['thread'].join()
|
||||
print('Deleted %d files and %d directories from %s.' % (
|
||||
state['result'].removed_files_count,
|
||||
state['result'].removed_directories_count,
|
||||
state['relpath']
|
||||
))
|
||||
|
||||
print('Finished purging.')
|
||||
|
||||
sys.exit(0)
|
@ -34,80 +34,6 @@ def _auto_fileobj(path, fileobj, mode='r'):
|
||||
fileobj.close()
|
||||
|
||||
|
||||
class UnreadablePurgeManifest(Exception):
|
||||
"""Error for failure when reading content of a serialized PurgeManifest."""
|
||||
|
||||
|
||||
class PurgeManifest(object):
|
||||
"""Describes actions to be used with a copier.FilePurger instance.
|
||||
|
||||
This class facilitates serialization and deserialization of data used
|
||||
to construct a copier.FilePurger and to perform a purge operation.
|
||||
|
||||
The manifest contains a set of entries (paths that are accounted for and
|
||||
shouldn't be purged) and a relative path. The relative path is optional and
|
||||
can be used to e.g. have several manifest files in a directory be
|
||||
dynamically applied to subdirectories under a common base directory.
|
||||
|
||||
Don't be confused by the name of this class: entries are files that are
|
||||
*not* purged.
|
||||
"""
|
||||
def __init__(self, relpath='', path=None, fileobj=None):
|
||||
self.relpath = relpath
|
||||
self.entries = set()
|
||||
|
||||
if not path and not fileobj:
|
||||
return
|
||||
|
||||
with _auto_fileobj(path, fileobj, mode='rt') as fh:
|
||||
self._read_from_fh(fh)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, PurgeManifest):
|
||||
return False
|
||||
|
||||
return other.relpath == self.relpath and other.entries == self.entries
|
||||
|
||||
def _read_from_fh(self, fileobj):
|
||||
version = fileobj.readline().rstrip()
|
||||
if version != '1':
|
||||
raise UnreadablePurgeManifest('Unknown manifest version: %s' %
|
||||
version)
|
||||
|
||||
self.relpath = fileobj.readline().rstrip()
|
||||
|
||||
for entry in fileobj:
|
||||
self.entries.add(entry.rstrip())
|
||||
|
||||
def add(self, path):
|
||||
return self.entries.add(path)
|
||||
|
||||
def write(self, path=None, fileobj=None):
|
||||
with _auto_fileobj(path, fileobj, 'wt') as fh:
|
||||
fh.write('1\n')
|
||||
fh.write('%s\n' % self.relpath)
|
||||
|
||||
# We write sorted so written output is consistent.
|
||||
for entry in sorted(self.entries):
|
||||
fh.write('%s\n' % entry)
|
||||
|
||||
def get_purger(self, prepend_relpath=False):
|
||||
"""Obtain a FilePurger instance from this manifest.
|
||||
|
||||
If :prepend_relpath is truish, the relative path in the manifest will
|
||||
be prepended to paths added to the FilePurger. Otherwise, the raw paths
|
||||
will be used.
|
||||
"""
|
||||
p = FilePurger()
|
||||
for entry in self.entries:
|
||||
if prepend_relpath:
|
||||
entry = mozpath.join(self.relpath, entry)
|
||||
|
||||
p.add(entry)
|
||||
|
||||
return p
|
||||
|
||||
|
||||
class UnreadableInstallManifest(Exception):
|
||||
"""Raised when an invalid install manifest is parsed."""
|
||||
|
||||
|
@ -14,43 +14,10 @@ from mozpack.copier import (
|
||||
)
|
||||
from mozpack.manifests import (
|
||||
InstallManifest,
|
||||
PurgeManifest,
|
||||
UnreadablePurgeManifest,
|
||||
)
|
||||
from mozpack.test.test_files import TestWithTmpDir
|
||||
|
||||
|
||||
class TestPurgeManifest(TestWithTmpDir):
|
||||
def test_construct(self):
|
||||
m = PurgeManifest()
|
||||
self.assertEqual(m.relpath, '')
|
||||
self.assertEqual(len(m.entries), 0)
|
||||
|
||||
def test_serialization(self):
|
||||
m = PurgeManifest(relpath='rel')
|
||||
m.add('foo')
|
||||
m.add('bar')
|
||||
p = self.tmppath('m')
|
||||
m.write(path=p)
|
||||
|
||||
self.assertTrue(os.path.exists(p))
|
||||
|
||||
m2 = PurgeManifest(path=p)
|
||||
self.assertEqual(m.relpath, m2.relpath)
|
||||
self.assertEqual(m.entries, m2.entries)
|
||||
self.assertEqual(m, m2)
|
||||
|
||||
def test_unknown_version(self):
|
||||
p = self.tmppath('bad')
|
||||
|
||||
with open(p, 'wt') as fh:
|
||||
fh.write('2\n')
|
||||
fh.write('not relevant')
|
||||
|
||||
with self.assertRaises(UnreadablePurgeManifest):
|
||||
PurgeManifest(path=p)
|
||||
|
||||
|
||||
class TestInstallManifest(TestWithTmpDir):
|
||||
def test_construct(self):
|
||||
m = InstallManifest()
|
||||
|
Loading…
Reference in New Issue
Block a user