#include "../../CppCliInterop/CppCliInterop.h"
#include <magic_enum.hpp>
#include <chrono>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <process.h>
#include <random>
#include <thread>
using namespace MineTrustConnector;
using namespace std::chrono_literals;
namespace fs = std::filesystem;
template <>
struct magic_enum::customize::enum_range<
CppCliInterop::LogEvent> {
static constexpr int min = 1000;
static constexpr int max = 5000;
};
static std::string random_string(std::string::size_type length)
{
static auto& chrs = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
thread_local static std::mt19937 rg{ std::random_device{}() };
thread_local static std::uniform_int_distribution<std::string::size_type> pick(0, sizeof(chrs) - 2);
std::string s;
s.reserve(length);
while (length--)
s += chrs[pick(rg)];
return s;
}
namespace
{
constexpr bool showUI = false;
{
std::cout << "Package processing in main thread" << std::endl;
CppCliInterop::LockPackage(newConfiguration.
packageUID, _getpid(), showUI);
CppCliInterop::SyncNow(newConfiguration.
packageUID, showUI);
CppCliInterop::UnlockPackage(newConfiguration.
packageUID,
true, showUI);
std::cout << "Finished processing in main thread" << std::endl;
}
{
concurrency::cancellation_token_source cts;
auto token = cts.get_token();
auto t = CppCliInterop::SyncNowTask(newConfiguration.
packageUID, showUI, token)
{
return CppCliInterop::LockPackageTask(newConfiguration.
packageUID, _getpid(), showUI, token);
}, token)
{
cts.cancel();
return CppCliInterop::SyncNowTask(newConfiguration.
packageUID, showUI, token);
}, token)
{
return CppCliInterop::UnlockPackageTask(newConfiguration.
packageUID,
false, showUI, token);
}, token);
std::cout << "Package processing in background" << std::endl;
const concurrency::task_status taskStatus = t.wait();
std::cout << "Finished processing in background being canceled? " <<
std::boolalpha << (concurrency::task_status::canceled == taskStatus) << std::endl;
CppCliInterop::UnlockPackage(newConfiguration.
packageUID,
false, showUI);
}
{
bool done = false;
{
std::cout << "Preparing multiple Sync processing in background" << std::endl;
auto t = CppCliInterop::SyncNowTask(newConfiguration.
packageUID, showUI)
{
std::cout << "Done processing" << std::endl;
done = true;
});
std::cout << "Leave task scope" << std::endl;
}
std::cout << "Out of scope processing in background" << std::endl;
while (!done)
{
std::cout << "Still waiting for task to be done" << std::endl;
std::this_thread::sleep_for(1s);
}
std::cout << "Done waiting" << std::endl;
}
void SubscribeToEvents()
{
std::list<CppCliInterop::LogEvent> eventIds;
eventIds.push_back(CppCliInterop::LogEvent::AllFilesUpToDate);
eventIds.push_back(CppCliInterop::LogEvent::SyncStarted);
eventIds.push_back(CppCliInterop::LogEvent::SyncCompleted);
eventIds.push_back(CppCliInterop::LogEvent::GeneralSyncError);
{
std::cout << connectorEvent.
time
<<
": Event (" << magic_enum::enum_name(connectorEvent.
eventId) <<
") received: "
<< connectorEvent.
message << std::endl;
}, eventIds);
std::this_thread::sleep_for(10s);
}
auto AddRandomFile(const std::string& baseName, const fs::path& destinationDir)
{
auto rnd_suffix = random_string(6);
auto localFileName = baseName + "_" + rnd_suffix + ".txt";
auto localFilePath = destinationDir / localFileName;
std::ofstream outfile(localFilePath);
outfile.close();
return localFilePath.string();
}
auto SetUpTestPackage(const std::string& baseName, const std::string& serverUrl, int numberTestFiles = 10)
{
auto rnd_suffix = random_string(6);
auto displayName = baseName + "_" + rnd_suffix;
packageConfiguration.
enabled =
true;
packageConfiguration.
localRoot = R
"(C:\temp\test\)" + rnd_suffix;
packageConfiguration.visibility = CppCliInterop::PackageConfiguration::SHARED_PACKAGE_VISIBILITY;
CppCliInterop::SavePackageConfiguration(packageConfiguration);
packageConfiguration = CppCliInterop::FindPackageConfigurations("$.DisplayName", displayName)[0];
CppCliInterop::SyncNow(packageConfiguration.
packageUID);
for (int i = 0; i < numberTestFiles; ++i)
{
AddRandomFile(std::format(
"dummy {} ({})", i, rnd_suffix), packageConfiguration.
localRoot);
}
if (numberTestFiles > 0)
{
CppCliInterop::SyncNow(packageConfiguration.
packageUID);
}
return packageConfiguration;
}
}
int main()
{
try
{
std::cout << CppCliInterop::GetShellExtensionName() << std::endl;
std::cout << "Connector is installed: " << std::boolalpha << CppCliInterop::IsMineTrustConnectorInstalled() << std::endl;
std::cout << "Connector is running: " << std::boolalpha << CppCliInterop::IsMineTrustConnectorRunning() << std::endl;
std::string serverUrl = CppCliInterop::ListServerURLs()[0];
std::cout << serverUrl << std::endl;
{
std::cout <<
"Package is enabled: " << packageConfiguration.
packageUID << std::endl;
}
{
std::cout << "Tag name: " << tagRecord.name << " / Tag value: " << tagRecord.value << std::endl;
#pragma warning( push )
#pragma warning( disable : 4996)
for (
const auto& packageUIDAndFiles :
CppCliInterop::FindPackageConfigurationItems(tagRecord.name, tagRecord.value))
#pragma warning( pop )
{
std::cout << " - In package " << packageUIDAndFiles.first << ":" << std::endl;
for (const std::string& includeConfigFile : packageUIDAndFiles.second)
{
std::cout << " - Include files: " << includeConfigFile << std::endl;
}
}
{
std::cout << "File record file found: " << fileRecord.name << std::endl;
}
}
{
std::cout << "Level map file found: " << fileRecord.name << std::endl;
}
for (
const std::string& packageUID :
CppCliInterop::GetDeletedPackages())
{
std::cout << "Package has been deleted: " << packageUID << std::endl;
}
for (
const std::string& packageUID :
CppCliInterop::GetArchivedPackages())
{
std::cout << "Package has been archived: " << packageUID << std::endl;
}
auto testPackage1 = SetUpTestPackage("Cpp/CLI Package Test 1", serverUrl);
DoSync(testPackage1);
DoAsync(testPackage1);
DoAsyncLeavingScope(testPackage1);
SubscribeToEvents();
for (
const std::string& localFile :
CppCliInterop::EnumerateLocalContents(testPackage1.packageUID))
{
std::cout << "Test package has local file: " << localFile << std::endl;
}
auto testFile1a = AddRandomFile("testFile1a", testPackage1.localRoot);
CppCliInterop::SyncNow(testPackage1.packageUID);
CppCliInterop::TagFile(testPackage1, testFile1a, "Status", "Published");
CppCliInterop::SavePackageConfiguration(testPackage1);
CppCliInterop::SyncNow(testPackage1.packageUID, showUI);
for (
const std::string& localFile :
CppCliInterop::EnumerateLocalFilesByTag(testPackage1.packageUID,
"Status",
"Published"))
{
std::cout << "Located the following file by tag in the test package: " << localFile << std::endl;
}
auto testFile1b = AddRandomFile("testFile1b", testPackage1.localRoot);
CppCliInterop::SyncNow(testPackage1.packageUID);
{
include.
tags.insert(std::make_pair(
"Status",
"Published"));
});
CppCliInterop::SavePackageConfiguration(testPackage1);
CppCliInterop::SyncNow(testPackage1.packageUID, showUI);
for (
const std::string& localFile :
CppCliInterop::EnumerateLocalFilesByTag(testPackage1.packageUID,
"Status",
"Published"))
{
std::cout << "Located the following file by tag in the test package: " << localFile << std::endl;
}
testPackage1.enabled = false;
testPackage1.localRoot = std::string();
CppCliInterop::SavePackageConfiguration(testPackage1);
auto testPackage2 = SetUpTestPackage("Cpp/CLI Package Test 2", serverUrl);
auto testFile2a = AddRandomFile("testFile2a", testPackage2.localRoot);
auto testFile2b = AddRandomFile("testFile2b", testPackage2.localRoot);
CppCliInterop::SyncNow(testPackage2.packageUID);
CppCliInterop::TagFile(testPackage2, testFile2a, "Status", "Draft");
CppCliInterop::TagFile(testPackage2, testFile2b, "Status", "Draft");
CppCliInterop::TagFile(testPackage2, testFile2b, "LocalOnly", "True");
CppCliInterop::SavePackageConfiguration(testPackage2);
CppCliInterop::SyncNow(testPackage2.packageUID, showUI);
{
CppCliInterop::SyncNow(serverConfiguration.packageUID, showUI);
}
auto publishedFiles = CppCliInterop::FindFiles("Status", "Published");
CppCliInterop::ReceiveFiles(publishedFiles, [&](const std::vector<CppCliInterop::LocalFileRecord>& receivedFiles)
{
{
std::cout << "Received file: " << receivedFile.localFilePath << std::endl;
const fs::path tempDir(testPackage2.localRoot);
if (!fs::exists(tempDir / receivedFile.name))
{
fs::copy_file(receivedFile.localFilePath, tempDir / receivedFile.name);
}
}
}).wait();
auto draftFiles = CppCliInterop::FindFiles("Status", "Draft");
{
{
if (tagRecord.name == "LocalOnly" && tagRecord.value == "True")
{
}
}
std::cout <<
"Sending file to package: " << localFileRecord.
localFilePath << std::endl;
return testPackage1;
}).wait();
for (
const std::string& permittedValue :
CppCliInterop::GetPermittedValues(
"Studio Mapper/Mine"))
{
std::cout << "Permitted value: " << permittedValue << std::endl;
}
}
catch (const std::runtime_error& e)
{
std::cout << "Sample app encountered an error: " << e.what() << std::endl;
}
return 0;
}
Definition CppCliInterop.h:26
LockPackageResultCodes
Definition CppCliInterop.h:654
SyncNowResultCodes
Definition CppCliInterop.h:742
Definition CppCliInterop.h:271
std::unordered_map< std::string, std::string > tags
Definition CppCliInterop.h:287
Definition CppCliInterop.h:468
std::string localFilePath
Definition CppCliInterop.h:488
Definition CppCliInterop.h:447
Definition CppCliInterop.h:495
LogEvent eventId
Definition CppCliInterop.h:500
std::string message
Definition CppCliInterop.h:508
std::chrono::system_clock::time_point time
Definition CppCliInterop.h:504
Definition CppCliInterop.h:300
std::string displayName
Definition CppCliInterop.h:321
std::string localRoot
Definition CppCliInterop.h:333
std::string visibility
Definition CppCliInterop.h:372
std::string serverUrl
Definition CppCliInterop.h:329
bool enabled
Definition CppCliInterop.h:317
std::string packageUID
Definition CppCliInterop.h:325