71 lines
1.8 KiB
Python
Executable File
71 lines
1.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
# description: Write or overwrite a file; must read with file_read first
|
||
# Args: <file_path> <content>
|
||
|
||
import sys
|
||
import os
|
||
import hashlib
|
||
import difflib
|
||
|
||
def marker_path(file_path):
|
||
sid = os.environ.get('OLLIE_SESSION_ID', '')
|
||
if not sid:
|
||
print("error: OLLIE_SESSION_ID is not set")
|
||
sys.exit(1)
|
||
h = hashlib.sha256(file_path.encode()).hexdigest()[:64]
|
||
return f"/tmp/ollie/{sid}/{h}"
|
||
|
||
def unified_diff(path, old, new):
|
||
old_lines = old.splitlines(keepends=True)
|
||
new_lines = new.splitlines(keepends=True)
|
||
return ''.join(difflib.unified_diff(old_lines, new_lines, fromfile=path, tofile=path))
|
||
|
||
if len(sys.argv) < 3:
|
||
print("usage: file_write <file_path> <content>")
|
||
sys.exit(1)
|
||
|
||
file_path = sys.argv[1]
|
||
content = sys.argv[2]
|
||
|
||
if not os.path.isabs(file_path):
|
||
print(f"error: path must be absolute, got: {file_path}")
|
||
sys.exit(1)
|
||
|
||
marker = marker_path(file_path)
|
||
if not os.path.exists(marker):
|
||
print(f"error: {file_path} must be read first with file_read")
|
||
sys.exit(1)
|
||
|
||
exists = os.path.exists(file_path)
|
||
old_content = ""
|
||
if exists:
|
||
with open(marker, 'r', errors='replace') as f:
|
||
old_content = f.read()
|
||
|
||
parent = os.path.dirname(file_path)
|
||
if parent and not os.path.isdir(parent):
|
||
print(f"error: parent directory does not exist: {parent}")
|
||
sys.exit(1)
|
||
|
||
try:
|
||
with open(marker, 'w') as f:
|
||
f.write(content)
|
||
with open(file_path, 'w') as f:
|
||
f.write(content)
|
||
except OSError as e:
|
||
print(f"error: {e}")
|
||
sys.exit(1)
|
||
|
||
try:
|
||
os.unlink(marker)
|
||
except OSError as e:
|
||
print(f"error: failed to remove marker: {e}")
|
||
sys.exit(1)
|
||
|
||
if not exists:
|
||
for line in content.splitlines():
|
||
print(f"+{line}")
|
||
else:
|
||
diff = unified_diff(file_path, old_content, content)
|
||
print(diff if diff else "(no changes)", end='' if diff else '\n')
|