From a513a5b23d47831424a9b72ce5915ecf33056f3f Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Sat, 6 Dec 2025 12:00:35 -0500 Subject: [PATCH] fix: create WebDAV collection when reconfiguring sibling to new URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using `existing='reconfigure'` with create_sibling_webdav, the code uses `git annex enableremote` instead of `initremote`. Unlike initremote, enableremote doesn't create the directory structure on the WebDAV server. This fix adds explicit WebDAV collection creation using MKCOL when reconfiguring to ensure the target directory exists before git-annex tries to use it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../commands/create_sibling_webdav.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/datalad_next/commands/create_sibling_webdav.py b/datalad_next/commands/create_sibling_webdav.py index 899a2077c..e32f4b9d5 100644 --- a/datalad_next/commands/create_sibling_webdav.py +++ b/datalad_next/commands/create_sibling_webdav.py @@ -14,6 +14,8 @@ urlunparse, ) +import requests + from datalad_next.commands import ( EnsureCommandParameterization, ValidatedInterface, @@ -553,6 +555,47 @@ def _get_skip_sibling_result(name, ds, type_): ) +def _ensure_webdav_collection(url, credential): + """Ensure the WebDAV collection (directory) at URL exists. + + Uses MKCOL to create the directory if it doesn't exist. Intermediate + directories must already exist (WebDAV MKCOL does not create parents). + This is fine for our use case since git-annex will handle the nested + structure internally. + + Parameters + ---------- + url: str + WebDAV URL for the collection to ensure + credential: tuple + (username, password) tuple for authentication + """ + # First check if it already exists with a PROPFIND + response = requests.request( + 'PROPFIND', + url, + auth=(credential[0], credential[1]), + headers={'Depth': '0'}, + ) + if response.status_code in (200, 207): + # Collection already exists + return + + # Try to create it with MKCOL + response = requests.request( + 'MKCOL', + url, + auth=(credential[0], credential[1]), + ) + # 201 = Created, 405 = Method Not Allowed (often means it exists) + # We don't raise on error - let git-annex handle any issues downstream + if response.status_code not in (201, 405): + lgr.debug( + "MKCOL request to %s returned status %s", + url, response.status_code + ) + + def _create_git_sibling( ds, url, name, credential_name, credential, export, existing, known, publish_depends=None): @@ -632,6 +675,12 @@ def _create_storage_sibling( yield _get_skip_sibling_result(name, ds, 'storage') return + # When reconfiguring, enableremote doesn't create the directory on the + # WebDAV server (unlike initremote). We need to explicitly ensure the + # collection exists. + if known and existing == 'reconfigure': + _ensure_webdav_collection(url, credential) + cmd_args = [ 'enableremote' if known and existing == 'reconfigure' else 'initremote',