Created
March 15, 2025 16:46
-
-
Save mzpqnxow/353b6dc4c7d9a273e2253f4d03def0cb to your computer and use it in GitHub Desktop.
Rebuild local files from pristine SVN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This is roughly equivalent to `svn export` | |
# Useful when you have a .svn directory but are unable to reach the SVN | |
# repository that it came from (e.g. a network-based one) | |
# If you have /tmp/someworking/.svn: | |
# $ python rebuild.py /tmp/someworking /tmp/rebuilt | |
# That will unpack all of the pristine files into /tmp/rebuilt | |
# | |
# mzpqnxow (by way of LLMs, with a few minor fixes) | |
# | |
import os | |
import sqlite3 | |
import shutil | |
def rebuild_working_copy(wc_path: str) -> None: | |
""" | |
Rebuilds the working copy from the .svn metadata. | |
Args: | |
wc_path: The root directory of your working copy (the directory that contains the .svn folder). | |
""" | |
svn_dir = os.path.join(wc_path, ".svn") | |
db_path = os.path.join(svn_dir, "wc.db") | |
pristine_path = os.path.join(svn_dir, "pristine") | |
if not os.path.exists(db_path): | |
print("wc.db not found. Is this a valid SVN working copy?") | |
return | |
# Connect to the wc.db SQLite database. | |
conn = sqlite3.connect(db_path) | |
cursor = conn.cursor() | |
# In SVN 1.7 and later, the NODES table holds the metadata. | |
# We'll select all items at the base layer (op_depth = 0) to get the original state. | |
cursor.execute("SELECT local_relpath, checksum, kind FROM NODES WHERE op_depth = 0") | |
rows = cursor.fetchall() | |
for local_relpath, checksum, kind in rows: | |
# Build the target path in the working copy. | |
target_path = os.path.join(wc_path, local_relpath) | |
if kind == "dir": | |
# Create the directory if it doesn't exist. | |
if not os.path.exists(target_path): | |
os.makedirs(target_path) | |
print(f"Created directory: {target_path}") | |
elif kind == "file": | |
# Files are stored in the pristine store. | |
# The checksum is stored as "sha1-<hash>". | |
if checksum.startswith("sha1-"): | |
hash_val = checksum[5:] | |
elif checksum.startswith("$sha1$"): | |
hash_val = checksum[6:] | |
else: | |
hash_val = checksum | |
# The file is located under .svn/pristine/<first two hash chars>/<hash_val>.svn-base | |
# subdir = hash_val[6:] | |
subdir = hash_val[0:2] | |
pristine_file = os.path.join(pristine_path, subdir, f"{hash_val}.svn-base") | |
if os.path.exists(pristine_file): | |
# Make sure the target directory exists. | |
os.makedirs(os.path.dirname(target_path), exist_ok=True) | |
shutil.copy2(pristine_file, target_path) | |
print(f"Recovered file: {target_path}") | |
else: | |
print(f"WARNING: Pristine file not found for {target_path} (expected at {pristine_file})") | |
else: | |
print(f"Unknown item kind: {kind} for path: {local_relpath}") | |
conn.close() | |
if __name__ == '__main__': | |
# Change this path to the root of your working copy | |
working_copy_path = "./" | |
rebuild_working_copy(working_copy_path) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment