mirror of
https://github.com/depp/syncfiles.git
synced 2024-11-21 12:30:58 +00:00
Add fallback program for copying files
This program is written in Python, and does the conversions to and from a local directory containing the Macintosh version of the files.
This commit is contained in:
parent
9224a9b789
commit
5f1b8e872b
115
copymac.py
Normal file
115
copymac.py
Normal file
@ -0,0 +1,115 @@
|
||||
"""copymac.py -- Copy source files to/from Basilisk, with conversions."""
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List
|
||||
|
||||
import xattr # type: ignore
|
||||
|
||||
SUBDIRS = ". macos sync lib".split()
|
||||
TEXT_SUFFIXES = ".c .h .r".split()
|
||||
TEXT_CREATOR = b"R*ch" # BBEdit
|
||||
|
||||
|
||||
class Converter(metaclass=ABCMeta):
|
||||
name: str
|
||||
|
||||
@abstractmethod
|
||||
def convert(self, src: pathlib.Path, dest: pathlib.Path) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class TextConverter(Converter):
|
||||
enc_in: str
|
||||
enc_out: str
|
||||
newline: str
|
||||
|
||||
name = "Text"
|
||||
|
||||
def __init__(self, enc_in: str, enc_out: str, newline: str) -> None:
|
||||
self.enc_in = enc_in
|
||||
self.enc_out = enc_out
|
||||
self.newline = newline
|
||||
|
||||
def convert(self, src: pathlib.Path, dest: pathlib.Path) -> None:
|
||||
text = src.read_text(encoding=self.enc_in)
|
||||
lines = text.splitlines()
|
||||
lines.append("")
|
||||
dest.write_text(self.newline.join(lines), encoding=self.enc_out)
|
||||
|
||||
|
||||
class DataConverter(Converter):
|
||||
name = "Data"
|
||||
|
||||
def convert(self, src: pathlib.Path, dest: pathlib.Path) -> None:
|
||||
data = src.read_bytes()
|
||||
dest.write_bytes(data)
|
||||
|
||||
|
||||
@dataclass
|
||||
class FileType:
|
||||
converter: Converter
|
||||
filetype: bytes
|
||||
creator: bytes
|
||||
|
||||
def finder_info(self) -> bytes:
|
||||
assert len(self.filetype) == 4
|
||||
assert len(self.creator) == 4
|
||||
return self.filetype + self.creator + b"\x01" + b"\x00" * 23
|
||||
|
||||
|
||||
def main(argv: List[str]) -> None:
|
||||
if not argv:
|
||||
print("Usage: python copymac.py (push|pull)", file=sys.stderr)
|
||||
print(" pull: pull FROM guest (macintosh), into guest (unix)", file=sys.stderr)
|
||||
print(" push: push TO guest (macintosh), from host (unix)", file=sys.stderr)
|
||||
raise SystemExit(2)
|
||||
unix_dir = pathlib.Path(__file__).resolve().parent
|
||||
mac_dir = pathlib.Path(pathlib.Path.home(), "SyncFiles")
|
||||
cmd = argv[0]
|
||||
|
||||
suffixes: Dict[str, FileType] = {}
|
||||
text: Converter
|
||||
data = DataConverter()
|
||||
if cmd == "pull":
|
||||
text = TextConverter("macintosh", "utf-8", "\n")
|
||||
src_dir, dest_dir = mac_dir, unix_dir
|
||||
elif cmd == "push":
|
||||
text = TextConverter("utf-8", "macintosh", "\r")
|
||||
src_dir, dest_dir = unix_dir, mac_dir
|
||||
else:
|
||||
print("Error: unknown command", file=sys.stderr)
|
||||
raise SystemExit(2)
|
||||
|
||||
text_type = FileType(text, b"TEXT", TEXT_CREATOR)
|
||||
for suffix in TEXT_SUFFIXES:
|
||||
suffixes[suffix] = text_type
|
||||
suffixes[".mcp"] = FileType(data, b"MMPr", b"CWIE")
|
||||
|
||||
for subdir in SUBDIRS:
|
||||
src_subdir = src_dir / subdir
|
||||
dest_subdir = dest_dir / subdir
|
||||
dest_subdir.mkdir(exist_ok=True)
|
||||
fset = set()
|
||||
for src in src_subdir.iterdir():
|
||||
print(src)
|
||||
file_type = suffixes.get(src.suffix)
|
||||
if file_type is not None:
|
||||
fset.add(src.name)
|
||||
print(file_type.converter.name, pathlib.Path(subdir, src.name))
|
||||
dest = dest_subdir / src.name
|
||||
file_type.converter.convert(src, dest)
|
||||
if cmd == "push":
|
||||
info = file_type.finder_info()
|
||||
attr = xattr.xattr(dest)
|
||||
attr["com.apple.FinderInfo"] = info
|
||||
for dest in dest_subdir.iterdir():
|
||||
if dest.suffix in suffixes and not dest.name in fset:
|
||||
print("Delete", pathlib.Path(subdir, dest.name))
|
||||
dest.unlink()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
Loading…
Reference in New Issue
Block a user