summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-node/src')
-rw-r--r--packages/meshbay-node/src/meshbay_node/ops/roots.py15
-rw-r--r--packages/meshbay-node/src/meshbay_node/roots.py21
2 files changed, 33 insertions, 3 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/ops/roots.py b/packages/meshbay-node/src/meshbay_node/ops/roots.py
index b976e8f..c272978 100644
--- a/packages/meshbay-node/src/meshbay_node/ops/roots.py
+++ b/packages/meshbay-node/src/meshbay_node/ops/roots.py
@@ -14,7 +14,7 @@ from meshbay_node.ops.node_toml import (
_update_root_field,
toml_string,
)
-from meshbay_node.roots import RootError, RootSet, off_disk
+from meshbay_node.roots import RootError, RootSet, distinct_name, off_disk
log = logging.getLogger("meshbay_node.ops")
@@ -36,12 +36,21 @@ async def add_root(state: dict, group_id: str, path: str, *,
raise OpError("Group not configured on this node", status=404)
specs = [asdict(r) for r in cfg.roots]
- specs.append({"path": path, "name": name, "kind": kind,
- "writable": writable, "removable": removable})
try:
+ # Every caller sends the folder's basename when nobody typed a name, so
+ # that is the case that gets a distinct one. A name somebody chose is
+ # still refused on a clash.
+ target = Path(path).expanduser().resolve()
+ if name.strip() in ("", target.name):
+ taken = {r.folded for r in RootSet.build(specs).roots}
+ name = distinct_name(target, taken)
+ specs.append({"path": path, "name": name, "kind": kind,
+ "writable": writable, "removable": removable})
built = RootSet.build(specs)
except RootError as e:
raise OpError(str(e)) from e
+ except OSError as e:
+ raise OpError(f"{path}: {e}") from e
added = built.roots[-1]
diff --git a/packages/meshbay-node/src/meshbay_node/roots.py b/packages/meshbay-node/src/meshbay_node/roots.py
index 2b48292..7dded1f 100644
--- a/packages/meshbay-node/src/meshbay_node/roots.py
+++ b/packages/meshbay-node/src/meshbay_node/roots.py
@@ -211,6 +211,27 @@ def derive_name(path: Path) -> str:
return name
+def distinct_name(path: Path, taken: set[str]) -> str:
+ """
+ `derive_name(path)`, or, when a root in `taken` (folded names) already has
+ it, that name followed by where the directory is: `Archives (H)` for
+ `H:\\Archives` beside `G:\\Archives`, `Films (b)` for `/mnt/b/Films`.
+
+ The same folder name on two drives is the ordinary case, and the interface
+ has no field to type a name into, so refusing it left no way forward.
+ """
+ base = derive_name(path)
+ candidates = [base]
+ where = path.parent.name or path.drive.rstrip(":")
+ if where:
+ candidates.append(f"{base} ({where})")
+ candidates += [f"{base} ({n})" for n in range(2, 100)]
+ for name in candidates:
+ if fold(name) not in taken and not portable_name_problem(name):
+ return name
+ return base
+
+
@dataclass
class RootSet:
"""