@@ -1412,14 +1412,12 @@ def _verify_restore_paths_writable(db_path: Path, data_dir: Path) -> tuple[bool,
14121412def _detect_old_data_dir (db_path : Path ) -> str | None :
14131413 """
14141414 Infer the data_dir used by a backup DB by inspecting org_dir values.
1415- Returns the old data directory as a string (may contain backslashes for Windows paths),
1416- or None if there are no organizations.
1415+ Returns the old data directory as a string, or None if there are no organizations.
14171416 """
14181417 try :
14191418 conn = sqlite3 .connect (f"file:{ db_path } ?mode=ro" , uri = True )
14201419 try :
1421- cursor = conn .execute ("SELECT org_dir FROM organizations LIMIT 10" )
1422- rows = [row [0 ] for row in cursor .fetchall ()]
1420+ rows = [row [0 ] for row in conn .execute ("SELECT org_dir FROM organizations LIMIT 10" )]
14231421 finally :
14241422 conn .close ()
14251423 except Exception as e :
@@ -1429,91 +1427,69 @@ def _detect_old_data_dir(db_path: Path) -> str | None:
14291427 if not rows :
14301428 return None
14311429
1432- # Determine path separator (\ for Windows, / for Unix)
1433- first_path = rows [0 ]
1434- sep = "\\ " if "\\ " in first_path else "/"
1430+ sep = "\\ " if "\\ " in rows [0 ] else "/"
1431+ parents = {path [:path .rfind (sep )] for path in rows if path .rfind (sep ) > 0 }
14351432
1436- # Extract parent directory by finding the last separator
1437- def get_parent (path : str ) -> str :
1438- idx = path .rfind (sep )
1439- return path [:idx ] if idx > 0 else ""
1440-
1441- parents = {get_parent (r ) for r in rows }
14421433 if len (parents ) != 1 :
1443- logger .warning (f "Inconsistent org_dir parents in backup DB; skipping path rewrite" )
1434+ logger .warning ("Inconsistent org_dir parents in backup DB; skipping path rewrite" )
14441435 return None
14451436
14461437 return parents .pop ()
14471438
14481439
14491440def _rewrite_paths_in_db (db_path : Path , old_data_dir : str , new_data_dir : Path ) -> int :
14501441 """
1451- Replace old_data_dir prefix with new_data_dir in all path-bearing columns.
1452- Handles both Windows and Unix paths correctly.
1453- Returns the number of rows updated.
1442+ Replace old_data_dir prefix with new_data_dir in path-bearing columns.
1443+ Handles both Windows and Unix paths. Returns the number of rows updated.
14541444 """
1455- old_prefix = old_data_dir
14561445 new_prefix = str (new_data_dir )
1446+ sep = "\\ " if "\\ " in old_data_dir else "/"
14571447 updated = 0
14581448
1449+ def rewrite_absolute (path : str ) -> str | None :
1450+ """Rewrite absolute path if it starts with old prefix, else return None."""
1451+ if not path .startswith (old_data_dir ):
1452+ return None
1453+ rel = path [len (old_data_dir ):].lstrip (sep ).replace ("\\ " , "/" )
1454+ return f"{ new_prefix } /{ rel } " if rel else new_prefix
1455+
14591456 try :
14601457 conn = sqlite3 .connect (str (db_path ))
14611458 try :
1462- # Detect separator in old path (Windows uses \, Unix uses /)
1463- sep = "\\ " if "\\ " in old_prefix else "/"
1464-
1465- # Rewrite organizations.org_dir
1466- cursor = conn .execute ("SELECT id, org_dir FROM organizations" )
1467- for org_id , org_dir in cursor .fetchall ():
1468- if org_dir .startswith (old_prefix ):
1469- # Extract relative part after old prefix and separator
1470- rel_part = org_dir [len (old_prefix ):]
1471- if rel_part .startswith (sep ):
1472- rel_part = rel_part [1 :]
1473- # Reconstruct with new prefix using forward slashes
1474- new_org_dir = f"{ new_prefix } /{ rel_part } " if rel_part else new_prefix
1475- conn .execute (
1476- "UPDATE organizations SET org_dir = ? WHERE id = ?" ,
1477- (new_org_dir , org_id )
1478- )
1459+ # Rewrite organizations.org_dir (absolute paths)
1460+ for org_id , org_dir in conn .execute ("SELECT id, org_dir FROM organizations" ):
1461+ new_path = rewrite_absolute (org_dir )
1462+ if new_path :
1463+ conn .execute ("UPDATE organizations SET org_dir = ? WHERE id = ?" , (new_path , org_id ))
14791464 updated += 1
14801465
1481- # Rewrite crls.crl_path if it contains absolute paths
1482- cursor = conn .execute ("SELECT id, crl_path FROM crls" )
1483- for crl_id , crl_path in cursor .fetchall ():
1484- if crl_path .startswith (old_prefix ):
1485- rel_part = crl_path [len (old_prefix ):]
1486- if rel_part .startswith (sep ):
1487- rel_part = rel_part [1 :]
1488- new_crl_path = f"{ new_prefix } /{ rel_part } " if rel_part else new_prefix
1489- conn .execute (
1490- "UPDATE crls SET crl_path = ? WHERE id = ?" ,
1491- (new_crl_path , crl_id )
1492- )
1466+ # Rewrite crls.crl_path (absolute or relative)
1467+ for crl_id , crl_path in conn .execute ("SELECT id, crl_path FROM crls" ):
1468+ new_path = rewrite_absolute (crl_path )
1469+ if new_path :
1470+ conn .execute ("UPDATE crls SET crl_path = ? WHERE id = ?" , (new_path , crl_id ))
1471+ updated += 1
1472+ elif sep == "\\ " and "\\ " in crl_path :
1473+ new_path = crl_path .replace ("\\ " , "/" )
1474+ conn .execute ("UPDATE crls SET crl_path = ? WHERE id = ?" , (new_path , crl_id ))
14931475 updated += 1
14941476
1495- # Rewrite relative paths in certificates table (convert \ to / if crossing platforms )
1496- if sep == "\\ " : # Windows paths being restored elsewhere
1497- cursor = conn .execute (
1477+ # Rewrite certificate paths (relative paths with backslashes )
1478+ if sep == "\\ " :
1479+ for cert_id , cert_path , key_path , csr_path , pwd_path in conn .execute (
14981480 "SELECT id, cert_path, key_path, csr_path, pwd_path FROM certificates"
1499- )
1500- for cert_id , cert_path , key_path , csr_path , pwd_path in cursor .fetchall ():
1481+ ):
15011482 updates = {}
1502- if cert_path and "\\ " in cert_path :
1503- updates ["cert_path" ] = cert_path .replace ("\\ " , "/" )
1504- if key_path and "\\ " in key_path :
1505- updates ["key_path" ] = key_path .replace ("\\ " , "/" )
1506- if csr_path and "\\ " in csr_path :
1507- updates ["csr_path" ] = csr_path .replace ("\\ " , "/" )
1508- if pwd_path and "\\ " in pwd_path :
1509- updates ["pwd_path" ] = pwd_path .replace ("\\ " , "/" )
1483+ for col , val in [("cert_path" , cert_path ), ("key_path" , key_path ),
1484+ ("csr_path" , csr_path ), ("pwd_path" , pwd_path )]:
1485+ if val and "\\ " in val :
1486+ updates [col ] = val .replace ("\\ " , "/" )
15101487
15111488 if updates :
15121489 set_clause = ", " .join (f"{ col } = ?" for col in updates .keys ())
1513- values = list (updates .values ()) + [cert_id ]
15141490 conn .execute (
15151491 f"UPDATE certificates SET { set_clause } WHERE id = ?" ,
1516- values
1492+ list ( updates . values ()) + [ cert_id ]
15171493 )
15181494 updated += len (updates )
15191495
0 commit comments