Commit a4d1c09a authored by hydrargyrum's avatar hydrargyrum

mv-with-thumb: like mv, but also moves XDG thumbnails

parent d9b7a317
#!/usr/bin/env python3
import argparse
import os
from pathlib import Path
import shutil
import vignette
old_rename = os.rename
def rename_with_thumb(src, dst):
if args.verbose:
print(f"{src!r} -> {dst!r}")
if src.startswith(vignette._thumb_path_prefix()):
return old_rename(src, dst)
tsrc = vignette.try_get_thumbnail(src, 'large')
if not tsrc:
return old_rename(src, dst)
ret = old_rename(src, dst)
vignette.put_thumbnail(dst, 'large', tsrc)
return ret
os.rename = rename_with_thumb
def copy_with_thumb(src, dst, **kwargs):
if args.verbose:
print(f"{src!r} -> {dst!r}")
if src.startswith(vignette._thumb_path_prefix()):
return shutil.copy2(src, dst)
tsrc = vignette.try_get_thumbnail(src, 'large')
if not tsrc:
return shutil.copy2(src, dst)
ret = shutil.copy2(src, dst, **kwargs)
vignette.put_thumbnail(dst, 'large', tsrc)
return ret
def scan_thumbs(path):
ret = {}
for sub in path.rglob('*'):
if not sub.is_file():
continue
thumb = vignette.try_get_thumbnail(str(sub), 'large')
if thumb:
ret[sub.lstat().st_ino] = thumb
return ret
def restore_thumbs(path, inodes):
for sub in path.rglob('*'):
thumb = inodes.get(sub.lstat().st_ino)
if thumb:
vignette.put_thumbnail(str(sub), 'large', thumb)
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('files', nargs='+')
args = parser.parse_args()
assert len(args.files) >= 2
dst = args.files[-1]
pdst = Path(dst)
try:
dst_dev = pdst.stat().st_dev
dst_is_dir = pdst.is_dir()
except FileNotFoundError:
assert len(args.files) == 2
dst_is_dir = True
dst_dev = pdst.parent.stat().st_dev
for src in args.files[:-1]:
psrc = Path(src)
inodes = None
if psrc.is_dir() and dst_is_dir and psrc.lstat().st_dev == dst_dev:
inodes = scan_thumbs(psrc)
shutil.move(src, dst, copy_with_thumb)
if inodes:
restore_thumbs(pdst, inodes)
#!/usr/bin/env pytest
import os
from pathlib import Path
from subprocess import check_call
from uuid import uuid4
import vignette
import pytest
os.chdir(Path(__file__).parent)
@pytest.fixture()
def src_path(tmp_path):
tmp_path.joinpath('foo').mkdir()
check_call([
'convert',
'rose:',
str(tmp_path.joinpath('foo/1.png'))
])
yield tmp_path.joinpath('foo')
@pytest.fixture(params=[0, 1])
def dst_path(tmp_path, request):
if request.param == 0:
ret = tmp_path.joinpath('bar')
else:
ret = Path(f'/run/user/{os.getuid()}/test-{uuid4()}/bar')
ret.parent.mkdir(parents=True)
ret.mkdir()
return ret
def test_file_file(src_path, dst_path):
othumb = vignette.get_thumbnail(str(src_path / '1.png'), 'large')
assert Path(othumb).exists()
assert src_path.joinpath('1.png').exists()
check_call([
'./mv-with-thumb',
str(src_path / '1.png'),
str(dst_path / '2.png'),
])
assert not src_path.joinpath('1.png').exists()
assert dst_path.joinpath('2.png').exists()
assert not Path(othumb).exists()
assert vignette.try_get_thumbnail(str(dst_path / '2.png'))
def test_file_dir(src_path, dst_path):
othumb = vignette.get_thumbnail(str(src_path / '1.png'))
assert Path(othumb).exists()
assert src_path.joinpath('1.png').exists()
check_call([
'./mv-with-thumb',
str(src_path / '1.png'),
str(dst_path),
])
assert not src_path.joinpath('1.png').exists()
assert dst_path.joinpath('1.png').exists()
assert not Path(othumb).exists()
assert vignette.try_get_thumbnail(str(dst_path / '1.png'))
def test_dir_name(src_path, dst_path):
othumb = vignette.get_thumbnail(str(src_path / '1.png'))
assert Path(othumb).exists()
assert src_path.joinpath('1.png').exists()
check_call([
'./mv-with-thumb',
str(src_path),
str(dst_path / 'quack'),
])
assert not src_path.exists()
assert dst_path.joinpath('quack').exists()
assert dst_path.joinpath('quack/1.png').exists()
assert not Path(othumb).exists()
assert vignette.try_get_thumbnail(str(dst_path / 'quack/1.png'))
def test_dir_subdir(src_path, dst_path):
othumb = vignette.get_thumbnail(str(src_path / '1.png'))
check_call([
'./mv-with-thumb',
str(src_path),
str(dst_path),
])
assert not Path(othumb).exists()
assert dst_path.joinpath('foo/1.png').exists()
assert vignette.try_get_thumbnail(str(dst_path.joinpath('foo/1.png')))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment