mirror of
https://github.com/depp/syncfiles.git
synced 2024-11-22 03:30:57 +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