| 2263 | /// \pre location.path is not empty. |
| 2264 | template <class ContainerClient, class CreateDirIfNotExists> |
| 2265 | Status CreateDirTemplate(const ContainerClient& container_client, |
| 2266 | CreateDirIfNotExists&& create_if_not_exists, |
| 2267 | const AzureLocation& location, bool recursive) { |
| 2268 | DCHECK(!location.container.empty()); |
| 2269 | DCHECK(!location.path.empty()); |
| 2270 | if (recursive) { |
| 2271 | // Recursive CreateDir calls require that all path segments be |
| 2272 | // either a directory or not found. |
| 2273 | |
| 2274 | // Check each path segment is a directory or not |
| 2275 | // found. Nonexistent segments are collected to |
| 2276 | // nonexistent_locations. We'll create directories for |
| 2277 | // nonexistent segments later. |
| 2278 | std::vector<AzureLocation> nonexistent_locations; |
| 2279 | for (auto prefix = location; !prefix.path.empty(); prefix = prefix.parent()) { |
| 2280 | ARROW_ASSIGN_OR_RAISE(auto info, GetFileInfo(container_client, prefix)); |
| 2281 | if (info.type() == FileType::File) { |
| 2282 | return NotADir(prefix); |
| 2283 | } |
| 2284 | if (info.type() == FileType::NotFound) { |
| 2285 | nonexistent_locations.push_back(prefix); |
| 2286 | } |
| 2287 | } |
| 2288 | // Ensure container exists |
| 2289 | ARROW_ASSIGN_OR_RAISE(auto container, |
| 2290 | AzureLocation::FromString(location.container)); |
| 2291 | ARROW_ASSIGN_OR_RAISE(auto container_info, |
| 2292 | GetContainerPropsAsFileInfo(container, container_client)); |
| 2293 | if (container_info.type() == FileType::NotFound) { |
| 2294 | try { |
| 2295 | container_client.CreateIfNotExists(); |
| 2296 | } catch (const Core::RequestFailedException& exception) { |
| 2297 | return ExceptionToStatus(exception, "Failed to create directory '", |
| 2298 | location.all, "': ", container_client.GetUrl()); |
| 2299 | } |
| 2300 | } |
| 2301 | // Create nonexistent directories from shorter to longer: |
| 2302 | // |
| 2303 | // Example: |
| 2304 | // |
| 2305 | // * location: /container/a/b/c/d/ |
| 2306 | // * Nonexistent path segments: |
| 2307 | // * /container/a/ |
| 2308 | // * /container/a/c/ |
| 2309 | // * /container/a/c/d/ |
| 2310 | // * target_locations: |
| 2311 | // 1. /container/a/c/d/ |
| 2312 | // 2. /container/a/c/ |
| 2313 | // 3. /container/a/ |
| 2314 | // |
| 2315 | // Create order: |
| 2316 | // 1. /container/a/ |
| 2317 | // 2. /container/a/c/ |
| 2318 | // 3. /container/a/c/d/ |
| 2319 | for (size_t i = nonexistent_locations.size(); i > 0; --i) { |
| 2320 | const auto& nonexistent_location = nonexistent_locations[i - 1]; |
| 2321 | try { |
| 2322 | create_if_not_exists(container_client, nonexistent_location); |
nothing calls this directly
no test coverage detected