update: only copy graphics and screenshots if mtime/size has changed

Instead of copying every time, trust the filesystem to tell us when the
file has changed.
This commit is contained in:
Hans-Christoph Steiner 2019-08-28 12:25:53 +02:00
parent fbdecbceb7
commit 508af00e84
No known key found for this signature in database
GPG key ID: 3E177817BA1B9BFA
3 changed files with 35 additions and 11 deletions

1
.gitignore vendored
View file

@ -46,6 +46,7 @@ makebuildserver.config.py
/tests/archive/index.xml /tests/archive/index.xml
/tests/archive/index-v1.jar /tests/archive/index-v1.jar
/tests/archive/index-v1.json /tests/archive/index-v1.json
/tests/metadata/org.videolan.vlc/en-US/icon*.png
/tests/repo/index.jar /tests/repo/index.jar
/tests/repo/index_unsigned.jar /tests/repo/index_unsigned.jar
/tests/repo/index-v1.jar /tests/repo/index-v1.jar

View file

@ -707,33 +707,52 @@ def _set_author_entry(app, key, f):
app[key] = text app[key] = text
def _strip_and_copy_image(inpath, outpath): def _strip_and_copy_image(in_file, outpath):
"""Remove any metadata from image and copy it to new path """Remove any metadata from image and copy it to new path
Sadly, image metadata like EXIF can be used to exploit devices. Sadly, image metadata like EXIF can be used to exploit devices.
It is not used at all in the F-Droid ecosystem, so its much safer It is not used at all in the F-Droid ecosystem, so its much safer
just to remove it entirely. just to remove it entirely.
""" This uses size+mtime to check for a new file since this process
actually modifies the resulting file to strip out the EXIF.
outpath can be path to either a file or dir. The dir that outpath
refers to must exist before calling this.
"""
logging.debug('copying ' + in_file + ' ' + outpath)
extension = common.get_extension(inpath)[1]
if os.path.isdir(outpath): if os.path.isdir(outpath):
outpath = os.path.join(outpath, os.path.basename(inpath)) out_file = os.path.join(outpath, os.path.basename(in_file))
else:
out_file = outpath
if os.path.exists(out_file):
in_stat = os.stat(in_file)
out_stat = os.stat(out_file)
if in_stat.st_size == out_stat.st_size \
and in_stat.st_mtime == out_stat.st_mtime:
return
extension = common.get_extension(in_file)[1]
if extension == 'png': if extension == 'png':
with open(inpath, 'rb') as fp: with open(in_file, 'rb') as fp:
in_image = Image.open(fp) in_image = Image.open(fp)
in_image.save(outpath, "PNG", optimize=True, in_image.save(out_file, "PNG", optimize=True,
pnginfo=BLANK_PNG_INFO, icc_profile=None) pnginfo=BLANK_PNG_INFO, icc_profile=None)
elif extension == 'jpg' or extension == 'jpeg': elif extension == 'jpg' or extension == 'jpeg':
with open(inpath, 'rb') as fp: with open(in_file, 'rb') as fp:
in_image = Image.open(fp) in_image = Image.open(fp)
data = list(in_image.getdata()) data = list(in_image.getdata())
out_image = Image.new(in_image.mode, in_image.size) out_image = Image.new(in_image.mode, in_image.size)
out_image.putdata(data) out_image.putdata(data)
out_image.save(outpath, "JPEG", optimize=True) out_image.save(out_file, "JPEG", optimize=True)
else: else:
raise FDroidException(_('Unsupported file type "{extension}" for repo graphic') raise FDroidException(_('Unsupported file type "{extension}" for repo graphic')
.format(extension=extension)) .format(extension=extension))
stat_result = os.stat(in_file)
os.utime(out_file, times=(stat_result.st_atime, stat_result.st_mtime))
def copy_triple_t_store_metadata(apps): def copy_triple_t_store_metadata(apps):
@ -845,7 +864,6 @@ def copy_triple_t_store_metadata(apps):
os.makedirs(destdir, mode=0o755, exist_ok=True) os.makedirs(destdir, mode=0o755, exist_ok=True)
sourcefile = os.path.join(root, f) sourcefile = os.path.join(root, f)
destfile = os.path.join(destdir, repofilename) destfile = os.path.join(destdir, repofilename)
logging.debug('copying ' + sourcefile + ' ' + destfile)
_strip_and_copy_image(sourcefile, destfile) _strip_and_copy_image(sourcefile, destfile)
@ -934,7 +952,6 @@ def insert_localized_app_metadata(apps):
destdir = os.path.join('repo', packageName, locale) destdir = os.path.join('repo', packageName, locale)
if base in GRAPHIC_NAMES and extension in ALLOWED_EXTENSIONS: if base in GRAPHIC_NAMES and extension in ALLOWED_EXTENSIONS:
os.makedirs(destdir, mode=0o755, exist_ok=True) os.makedirs(destdir, mode=0o755, exist_ok=True)
logging.debug('copying ' + os.path.join(root, f) + ' ' + destdir)
_strip_and_copy_image(os.path.join(root, f), destdir) _strip_and_copy_image(os.path.join(root, f), destdir)
for d in dirs: for d in dirs:
if d in SCREENSHOT_DIRS: if d in SCREENSHOT_DIRS:
@ -946,7 +963,6 @@ def insert_localized_app_metadata(apps):
if extension in ALLOWED_EXTENSIONS: if extension in ALLOWED_EXTENSIONS:
screenshotdestdir = os.path.join(destdir, d) screenshotdestdir = os.path.join(destdir, d)
os.makedirs(screenshotdestdir, mode=0o755, exist_ok=True) os.makedirs(screenshotdestdir, mode=0o755, exist_ok=True)
logging.debug('copying ' + f + ' ' + screenshotdestdir)
_strip_and_copy_image(f, screenshotdestdir) _strip_and_copy_image(f, screenshotdestdir)
repofiles = sorted(glob.glob(os.path.join('repo', '[A-Za-z]*', '[a-z][a-z]*'))) repofiles = sorted(glob.glob(os.path.join('repo', '[A-Za-z]*', '[a-z][a-z]*')))

View file

@ -66,6 +66,13 @@ class UpdateTest(unittest.TestCase):
shutil.copytree(os.path.join('source-files', 'eu.siacs.conversations'), shutil.copytree(os.path.join('source-files', 'eu.siacs.conversations'),
os.path.join('build', 'eu.siacs.conversations')) os.path.join('build', 'eu.siacs.conversations'))
testfile = os.path.join('repo', 'org.videolan.vlc', 'en-US', 'icon.png')
cpdir = os.path.join('metadata', 'org.videolan.vlc', 'en-US')
cpfile = os.path.join(cpdir, 'icon.png')
os.makedirs(cpdir, exist_ok=True)
shutil.copy(testfile, cpfile)
shutil.copystat(testfile, cpfile)
apps = dict() apps = dict()
for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current', for packageName in ('info.guardianproject.urzip', 'org.videolan.vlc', 'obb.mainpatch.current',
'com.nextcloud.client', 'com.nextcloud.client.dev', 'com.nextcloud.client', 'com.nextcloud.client.dev',