diff options
| author | Dan Engelbrecht <[email protected]> | 2024-06-04 22:21:06 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-06-04 22:21:06 +0200 |
| commit | 3a82e1cb3b5a284d2c47e03d541a35b84589314b (patch) | |
| tree | d4b6c3d7c548b2d6f83b105fb0a5668ca2152889 /src/zenstore/workspaces.cpp | |
| parent | add batching of CacheStore requests for GetCacheValues/GetCacheChunks (#90) (diff) | |
| download | zen-3a82e1cb3b5a284d2c47e03d541a35b84589314b.tar.xz zen-3a82e1cb3b5a284d2c47e03d541a35b84589314b.zip | |
workspace share aliases (#91)
- Add `zen workspace-share` `--root-path` option - the root local file path of the workspace - if given it will automatically create the workspace before creating the share. If `--workspace` is omitted, an id will be generated from the `--root-path` parameter
- Add `/ws/share/{alias}/` endpoint - a shortcut to `/ws/{workspace_id}/{share_id}/` based endpoints using the alias for a workspace share
- Add `--alias` option to replace `--workspace` and `--share` options for `workspace-share` zen commands
- Rename `zen workspace create` `folder` option to `root-path`
- Rename `zen workspace create` `folder` option to `share-path`
Diffstat (limited to 'src/zenstore/workspaces.cpp')
| -rw-r--r-- | src/zenstore/workspaces.cpp | 125 |
1 files changed, 121 insertions, 4 deletions
diff --git a/src/zenstore/workspaces.cpp b/src/zenstore/workspaces.cpp index 958d7b3f5..669d675dd 100644 --- a/src/zenstore/workspaces.cpp +++ b/src/zenstore/workspaces.cpp @@ -26,6 +26,10 @@ namespace { CbObjectWriter ShareWriter; ShareWriter.AddObjectId("id"sv, ShareConfig.Id); ShareWriter.AddString("share_path"sv, reinterpret_cast<const char*>(ShareConfig.SharePath.u8string().c_str())); + if (!ShareConfig.Alias.empty()) + { + ShareWriter.AddString("alias"sv, ShareConfig.Alias); + } ExtendableStringBuilder<256> Json; ShareWriter.Save().ToJson(Json); return Json.ToString(); @@ -43,9 +47,10 @@ namespace { { Oid ShareId = Object["id"sv].AsObjectId(); std::filesystem::path SharePath = Object["share_path"sv].AsU8String(); + std::string_view Alias = Object["alias"sv].AsString(); if (ShareId != Oid::Zero && !SharePath.empty()) { - return {.Id = ShareId, .SharePath = SharePath}; + return {.Id = ShareId, .SharePath = SharePath, .Alias = std::string(Alias)}; } } } @@ -436,8 +441,23 @@ Workspaces::RemoveWorkspace(const Oid& WorkspaceId) RwLock::ExclusiveLockScope Lock(m_Lock); if (auto It = m_Workspaces.find(WorkspaceId); It != m_Workspaces.end()) { + std::vector<std::string> Aliases; + for (const auto& AliasIt : m_ShareAliases) + { + if (AliasIt.second.WorkspaceId == WorkspaceId) + { + Aliases.push_back(AliasIt.first); + } + } + + for (const std::string& Alias : Aliases) + { + m_ShareAliases.erase(Alias); + } + m_Workspaces.erase(It); - ZEN_INFO("Removed workspace '{}'", WorkspaceId); + + ZEN_INFO("Removed workspace '{}' and {} aliases", WorkspaceId, Aliases.size()); return true; } return false; @@ -466,7 +486,12 @@ Workspaces::AddWorkspaceShare(const Oid& WorkspaceId, { RwLock::ExclusiveLockScope _(m_Lock); Workspace->SetShare(Configuration.Id, std::move(NewShare)); + if (!Configuration.Alias.empty()) + { + m_ShareAliases.insert_or_assign(Configuration.Alias, ShareAlias{.WorkspaceId = WorkspaceId, .ShareId = Configuration.Id}); + } } + ZEN_INFO("Added workspace share '{}' in workspace '{}' with path '{}'", Configuration.Id, WorkspaceId, Configuration.SharePath); return true; @@ -501,12 +526,20 @@ Workspaces::RemoveWorkspaceShare(const Oid& WorkspaceId, const Oid& ShareId) } } RwLock::ExclusiveLockScope _(m_Lock); - if (!Workspace->GetShare(ShareId)) + Ref<WorkspaceShare> ExistingShare = Workspace->GetShare(ShareId); + if (!ExistingShare) { return false; } + std::string Alias = ExistingShare->GetConfig().Alias; + if (!Alias.empty()) + { + m_ShareAliases.erase(Alias); + } + Workspace->SetShare(ShareId, {}); + ZEN_INFO("Removed workspace share '{}' in workspace '{}'", ShareId, WorkspaceId); return true; } @@ -622,12 +655,15 @@ Workspaces::WriteState(const std::filesystem::path& WorkspaceStatePath) ZEN_INFO("Writing workspaces state to {}", WorkspaceStatePath); + std::filesystem::path TempWritePath = WorkspaceStatePath.parent_path() / (WorkspaceStatePath.filename().string() + "_new"); + CreateDirectories(TempWritePath); + RwLock::SharedLockScope _(m_Lock); for (auto It : m_Workspaces) { const WorkspaceConfiguration& WorkspaceConfig = It.second->GetConfig(); ZEN_ASSERT(WorkspaceConfig.Id == It.first); - std::filesystem::path WorkspaceConfigDir = WorkspaceStatePath / WorkspaceConfig.Id.ToString(); + std::filesystem::path WorkspaceConfigDir = TempWritePath / WorkspaceConfig.Id.ToString(); CreateDirectories(WorkspaceConfigDir); std::string WorkspaceConfigJson = WorkspaceToJson(WorkspaceConfig); TemporaryFile::SafeWriteFile(WorkspaceConfigDir / "config.json"sv, @@ -643,6 +679,24 @@ Workspaces::WriteState(const std::filesystem::path& WorkspaceStatePath) TemporaryFile::SafeWriteFile(ShareConfigDir / "config.json"sv, MemoryView(ShareConfigJson.data(), ShareConfigJson.size())); } } + + // Overwrite with rename + std::filesystem::path OldStateDirectory = WorkspaceStatePath.parent_path() / (WorkspaceStatePath.filename().string() + "_old"); + if (std::filesystem::is_directory(WorkspaceStatePath)) + { + if (std::filesystem::is_directory(OldStateDirectory)) + { + std::filesystem::remove_all(OldStateDirectory); + } + std::filesystem::rename(WorkspaceStatePath, OldStateDirectory); + } + + std::filesystem::rename(TempWritePath, WorkspaceStatePath); + + if (std::filesystem::is_directory(OldStateDirectory)) + { + std::filesystem::remove_all(OldStateDirectory); + } } void @@ -705,6 +759,17 @@ Workspaces::ReadState(const std::filesystem::path& WorkspaceStatePath, std::func } } +std::optional<Workspaces::ShareAlias> +Workspaces::GetShareAlias(std::string_view Alias) const +{ + RwLock::SharedLockScope Lock(m_Lock); + if (auto It = m_ShareAliases.find(std::string(Alias)); It != m_ShareAliases.end()) + { + return It->second; + } + return {}; +} + std::pair<Ref<Workspace>, Ref<WorkspaceShare>> Workspaces::FindWorkspaceShare(const Oid& WorkspaceId, const Oid& ShareId, bool ForceRefresh, WorkerThreadPool& WorkerPool) { @@ -945,6 +1010,58 @@ TEST_CASE("workspace.share.basic") CHECK(!WS.RemoveWorkspace(PathToId(RootPath))); } +TEST_CASE("workspace.share.alias") +{ + using namespace std::literals; + + WorkerThreadPool WorkerPool(std::thread::hardware_concurrency()); + + ScopedTemporaryDirectory TempDir; + std::filesystem::path RootPath = TempDir.Path(); + std::vector<std::pair<std::filesystem::path, IoBuffer>> Content = GenerateFolderContent(RootPath); + + Workspaces WS; + CHECK(WS.AddWorkspace({PathToId(RootPath), RootPath})); + CHECK(WS.AddWorkspaceShare(PathToId(RootPath), + {PathToId("second_folder"), "second_folder", "my_share"}, + [](const std::filesystem::path& Path) { return PathToId(Path); })); + + std::optional<Workspaces::ShareAlias> Alias = WS.GetShareAlias("my_share"); + CHECK(Alias.has_value()); + CHECK(!WS.GetShareAlias("my_share2").has_value()); + + std::filesystem::path SharePath = RootPath / "second_folder"; + std::vector<std::filesystem::path> Paths = {{std::filesystem::relative(Content[4].first, SharePath)}, + {std::filesystem::relative(Content[6].first, SharePath)}, + {std::filesystem::relative(Content[7].first, SharePath)}, + {"the_file_that_is_not_there.txt"}}; + std::vector<IoBuffer> Chunks = WS.GetWorkspaceShareChunks(Alias->WorkspaceId, + Alias->ShareId, + std::vector<Workspaces::ChunkRequest>{{.ChunkId = PathToId(Paths[0])}, + {.ChunkId = PathToId(Paths[1])}, + {.ChunkId = PathToId(Paths[2])}, + {.ChunkId = PathToId(Paths[3])}}, + WorkerPool); + CHECK(Chunks.size() == 4); + CHECK(Chunks[0].GetView().EqualBytes(Content[4].second.GetView())); + CHECK(Chunks[1].GetView().EqualBytes(Content[6].second.GetView())); + CHECK(Chunks[2].GetView().EqualBytes(Content[7].second.GetView())); + CHECK(Chunks[3].GetSize() == 0); + + CHECK(WS.RemoveWorkspaceShare(Alias->WorkspaceId, Alias->ShareId)); + + CHECK(!WS.GetShareAlias("my_share").has_value()); + + CHECK(WS.AddWorkspaceShare(PathToId(RootPath), + {PathToId("second_folder"), "second_folder", "my_share"}, + [](const std::filesystem::path& Path) { return PathToId(Path); })); + CHECK(WS.GetShareAlias("my_share").has_value()); + + CHECK(WS.RemoveWorkspace(PathToId(RootPath))); + CHECK(!WS.RemoveWorkspace(PathToId(RootPath))); + + CHECK(!WS.GetShareAlias("my_share").has_value()); +} #endif void |