aboutsummaryrefslogtreecommitdiff
path: root/src/zenstore/workspaces.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-06-04 22:21:06 +0200
committerGitHub Enterprise <[email protected]>2024-06-04 22:21:06 +0200
commit3a82e1cb3b5a284d2c47e03d541a35b84589314b (patch)
treed4b6c3d7c548b2d6f83b105fb0a5668ca2152889 /src/zenstore/workspaces.cpp
parentadd batching of CacheStore requests for GetCacheValues/GetCacheChunks (#90) (diff)
downloadzen-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.cpp125
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