'Generic Commit'
All checks were successful
Build-Test-Publish / build (push) Successful in 58s

This commit is contained in:
Your Name 2025-06-22 10:43:54 +12:00
parent c08e718c95
commit 7b795600c1
3 changed files with 169 additions and 0 deletions

View File

@ -297,6 +297,83 @@ bool GetbinClient::getHash(const std::string& toolName, const std::string& arch,
cv.wait(lock, [&] { return done; });
}
worker.join();
return success;
}
bool GetbinClient::deleteObject(const std::string& hash, const std::string& token) {
bool success = false;
bool done = false;
std::mutex mtx;
std::condition_variable cv;
std::thread worker([&]() {
trantor::EventLoop loop;
auto client = drogon::HttpClient::newHttpClient(
"https://" + std::string(SERVER_HOST),
&loop
);
// Configure SSL certificates
std::string ca_path = find_ca_certificates();
if (!ca_path.empty()) {
std::cerr << "[GetbinClient] Found CA certificates at: " << ca_path << std::endl;
std::vector<std::pair<std::string, std::string>> sslConfigs;
sslConfigs.push_back({"VerifyCAFile", ca_path});
client->addSSLConfigs(sslConfigs);
} else {
std::cerr << "[GetbinClient] Warning: No system CA certificates found. SSL verification may fail." << std::endl;
}
client->enableCookies();
client->setUserAgent("getpkg/1.0");
std::string delete_path = "/deleteobject?hash=" + hash;
auto req = drogon::HttpRequest::newHttpRequest();
req->setMethod(drogon::Get);
req->setPath(delete_path);
req->addHeader("Authorization", "Bearer " + token);
client->sendRequest(req, [&](drogon::ReqResult result, const drogon::HttpResponsePtr& response) {
std::lock_guard<std::mutex> lock(mtx);
if (result == drogon::ReqResult::Ok && response) {
int status_code = static_cast<int>(response->getStatusCode());
std::string response_body(response->getBody());
if (status_code == 200) {
// Check if the response indicates success
try {
auto resp_json = json::parse(response_body);
if (resp_json.contains("result") && resp_json["result"] == "success") {
success = true;
}
} catch (...) {
// If not JSON, assume success if 200 OK
success = true;
}
} else {
std::cerr << "[GetbinClient::deleteObject] HTTP error: status code " << status_code << std::endl;
std::cerr << "[GetbinClient::deleteObject] Response body: " << response_body << std::endl;
}
} else {
std::cerr << "[GetbinClient::deleteObject] HTTP request failed." << std::endl;
}
done = true;
cv.notify_one();
loop.quit();
}, 10.0); // 10 second timeout
loop.loop();
});
// Wait for completion
{
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [&] { return done; });
}
worker.join();
return success;
}

View File

@ -7,4 +7,5 @@ public:
bool download(const std::string& toolName, const std::string& arch, const std::string& outPath);
bool upload(const std::string& archivePath, std::string& outUrl, std::string& outHash, const std::string& token);
bool getHash(const std::string& toolName, const std::string& arch, std::string& outHash);
bool deleteObject(const std::string& hash, const std::string& token);
};

View File

@ -403,6 +403,89 @@ int hash_command(int argc, char* argv[]) {
return 0;
}
int unpublish_tool(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: getpkg unpublish <tool_name[:ARCH]>" << std::endl;
std::cerr << " getpkg unpublish <hash>" << std::endl;
return 1;
}
std::string target = argv[2];
// Get token
std::string token;
const char* envToken = std::getenv("SOS_WRITE_TOKEN");
if (envToken && std::strlen(envToken) > 0) {
token = envToken;
} else {
std::string home = get_home();
std::filesystem::path tokenPath = std::filesystem::path(home) / ".config/getpkg.xyz/write_token.txt";
if (std::filesystem::exists(tokenPath)) {
std::ifstream tfile(tokenPath);
std::getline(tfile, token);
} else {
std::cout << "Enter getpkg.xyz write token: ";
std::getline(std::cin, token);
std::filesystem::create_directories(tokenPath.parent_path());
std::ofstream tfile(tokenPath);
tfile << token << std::endl;
}
}
if (token.empty()) {
std::cerr << "Error: No write token provided" << std::endl;
return 1;
}
GetbinClient getbin;
std::string hash = target;
// Check if target looks like a hash (all digits) or a tool name
bool isHash = true;
for (char c : target) {
if (!std::isdigit(c)) {
isHash = false;
break;
}
}
if (!isHash) {
// Target is a tool name, need to get hash first
std::string toolName = target;
std::string arch = "x86_64"; // default
// Check if arch is specified (contains :)
if (target.find(':') != std::string::npos) {
toolName = target.substr(0, target.find(':'));
arch = target.substr(target.find(':') + 1);
}
if (!getbin.getHash(toolName, arch, hash)) {
std::cerr << "Failed to get hash for " << target << std::endl;
return 1;
}
if (hash.empty()) {
std::cerr << "Tool " << target << " not found" << std::endl;
return 1;
}
std::cout << "Found hash " << hash << " for " << target << std::endl;
}
// Delete the object
if (getbin.deleteObject(hash, token)) {
std::cout << "Successfully unpublished " << target;
if (!isHash) {
std::cout << " (hash: " << hash << ")";
}
std::cout << std::endl;
return 0;
} else {
std::cerr << "Failed to unpublish " << target << std::endl;
return 1;
}
}
int uninstall_tool(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: getpkg uninstall <tool_name>" << std::endl;
@ -468,6 +551,10 @@ void show_help() {
std::cout << " ARCH is optional (defaults to 'universal')" << std::endl;
std::cout << " Requires SOS_WRITE_TOKEN environment variable" << std::endl;
std::cout << std::endl;
std::cout << " unpublish <tool_name[:ARCH]> Remove a published tool" << std::endl;
std::cout << " unpublish <hash> Remove a published tool by hash" << std::endl;
std::cout << " Requires SOS_WRITE_TOKEN environment variable" << std::endl;
std::cout << std::endl;
std::cout << " update Update getpkg and all installed tools" << std::endl;
std::cout << std::endl;
std::cout << " create <tool_name> <directory> Create a new tool project" << std::endl;
@ -485,6 +572,7 @@ void show_help() {
std::cout << " getpkg install myapp Install myapp (legacy syntax)" << std::endl;
std::cout << " getpkg publish myapp:x86_64 ./build Publish architecture-specific build" << std::endl;
std::cout << " getpkg publish myapp ./build Publish universal build" << std::endl;
std::cout << " getpkg unpublish myapp:x86_64 Remove published myapp" << std::endl;
std::cout << " getpkg uninstall myapp Remove myapp from system" << std::endl;
std::cout << " getpkg update Update everything" << std::endl;
std::cout << std::endl;
@ -511,6 +599,8 @@ int main(int argc, char* argv[]) {
return uninstall_tool(argc, argv);
} else if (command == "publish") {
return publish_tool(argc, argv);
} else if (command == "unpublish") {
return unpublish_tool(argc, argv);
} else if (command == "update") {
return update_tool(argc, argv);
} else if (command == "autocomplete") {
@ -518,6 +608,7 @@ int main(int argc, char* argv[]) {
if (args.empty()) std::cout << R"(install
uninstall
publish
unpublish
update
version
create