#include "exploit_cli.h" // Delete command implementation int cmd_delete(int argc, char *argv[]) { if (argc < 1) { printf("\033[33m🗑️ Usage: exp delete [path]\033[0m\n"); printf("\033[37mOptions:\033[0m\n"); printf("\033[90m [path] Path to file or folder to delete\033[0m\n"); printf("\033[90mIf path is not specified, will delete the current repository\033[0m\n"); printf("\033[37mExamples:\033[0m\n"); printf("\033[90m exp delete - Delete current repository\033[0m\n"); printf("\033[90m exp delete test/folder9 - Delete folder\033[0m\n"); printf("\033[90m exp delete test/folder9/file.txt - Delete file\033[0m\n"); return 1; } printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🗑️ Delete Operation ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); // Check token char *token = get_token(); if (!token) { print_error("You are not logged in. Use 'exp login' first"); return 1; } // Check repository configuration char repo_config_path[MAX_PATH]; snprintf(repo_config_path, MAX_PATH, "%s/repo_config", get_config_dir()); FILE *fp = fopen(repo_config_path, "r"); if (!fp) { print_error("Repository not initialized. Use 'exp init' first"); free(token); return 1; } char config_line[MAX_BUFFER]; char repo_name[MAX_BUFFER] = {0}; char username[MAX_BUFFER] = {0}; while (fgets(config_line, MAX_BUFFER, fp)) { if (strncmp(config_line, "name=", 5) == 0) { strcpy(repo_name, config_line + 5); // Remove newline if present size_t len = strlen(repo_name); if (len > 0 && repo_name[len-1] == '\n') { repo_name[len-1] = '\0'; } } else if (strncmp(config_line, "username=", 9) == 0) { strcpy(username, config_line + 9); // Remove newline if present size_t len = strlen(username); if (len > 0 && username[len-1] == '\n') { username[len-1] = '\0'; } } } fclose(fp); if (strlen(repo_name) == 0 || strlen(username) == 0) { print_error("Incomplete repository information"); free(token); return 1; } // Check if a path is provided char path[MAX_BUFFER] = {0}; if (argc > 1) { strncpy(path, argv[1], MAX_BUFFER - 1); // If path is a directory, add trailing slash if not present struct stat st; if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { size_t len = strlen(path); if (len > 0 && path[len - 1] != '/') { strcat(path, "/"); } } } // If path is specified, delete file/folder in repository if (argc > 1) { // Create URL for delete char url[MAX_PATH]; snprintf(url, MAX_PATH, "%s/repository/delete/", API_BASE_URL); // Create JSON for delete request char json_data[MAX_BUFFER]; int is_folder = 0; // Check if path ends with '/' to determine if it's a folder size_t path_len = strlen(path); if (path_len > 0 && path[path_len - 1] == '/') { is_folder = 1; } else { // Also check if it's a directory using stat struct stat st; if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { is_folder = 1; } } // Include is_folder flag in JSON request snprintf(json_data, MAX_BUFFER, "{\"name\":\"%s\",\"path\":\"%s\",\"is_folder\":%d}", repo_name, path, is_folder); // Sending delete request // Send delete request with JSON http_response_t response = http_post(url, token, json_data); if (!response.data) { print_error("Failed to delete file/folder"); free(token); return 1; } // Processing API response // Parse JSON response struct json_object *parsed_json; struct json_object *status_obj; struct json_object *message_obj; parsed_json = json_tokener_parse(response.data); if (!parsed_json) { print_error("Failed to parse JSON response"); free(response.data); free(token); return 1; } // Check response status json_object_object_get_ex(parsed_json, "status", &status_obj); json_object_object_get_ex(parsed_json, "message", &message_obj); const char *status = json_object_get_string(status_obj); const char *message = json_object_get_string(message_obj); if (strcmp(status, "success") != 0) { print_error(message); json_object_put(parsed_json); free(response.data); free(token); return 1; } printf("\n"); print_success("File/folder deleted successfully!"); printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🎉 Deletion Complete! ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); printf("\033[37m🗑️ Deleted: \033[31m%s\033[0m\n", path); printf("\033[90m💡 The item has been removed from your repository\033[0m\n"); printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up memory json_object_put(parsed_json); free(response.data); } else { // Confirm repository deletion char warning_msg[256]; snprintf(warning_msg, sizeof(warning_msg), "You are about to delete repository %s/%s", username, repo_name); print_warning(warning_msg); printf("Type 'yes' to confirm: "); char confirm[10]; fgets(confirm, sizeof(confirm), stdin); // Remove newline if present size_t len = strlen(confirm); if (len > 0 && confirm[len-1] == '\n') { confirm[len-1] = '\0'; } if (strcmp(confirm, "yes") != 0) { print_info("Repository deletion cancelled"); free(token); return 0; } // Create URL for delete repository char url[MAX_PATH]; snprintf(url, MAX_PATH, "%s/repository/delete/", API_BASE_URL); // Create JSON for delete repository request char json_data[MAX_BUFFER]; snprintf(json_data, MAX_BUFFER, "{\"name\":\"%s\"}", repo_name); // Send delete repository request with JSON http_response_t response = http_post(url, token, json_data); if (!response.data) { print_error("Failed to delete repository"); free(token); return 1; } // Parse JSON response struct json_object *parsed_json; struct json_object *status_obj; struct json_object *message_obj; parsed_json = json_tokener_parse(response.data); if (!parsed_json) { print_error("Failed to parse JSON response"); free(response.data); free(token); return 1; } // Check response status json_object_object_get_ex(parsed_json, "status", &status_obj); json_object_object_get_ex(parsed_json, "message", &message_obj); const char *status = json_object_get_string(status_obj); const char *message = json_object_get_string(message_obj); if (strcmp(status, "success") != 0) { print_error(message); json_object_put(parsed_json); free(response.data); free(token); return 1; } // Delete repository configuration file char repo_config_path[MAX_PATH]; snprintf(repo_config_path, MAX_PATH, "%s/repo_config", get_config_dir()); unlink(repo_config_path); printf("\n"); print_success("Repository deleted successfully!"); printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🎉 Repository Removed! ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); printf("\033[37m🗑️ Repository: \033[31m%s/%s\033[0m\n", username, repo_name); printf("\033[90m💡 All files and configuration have been removed\033[0m\n"); printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up memory json_object_put(parsed_json); free(response.data); } free(token); return 0; } // Delete-release command implementation int cmd_delete_release(int argc, char *argv[]) { if (argc < 2) { printf("\033[33m🗑️ Usage: exp delete-release \033[0m\n"); printf("\033[37mExample: \033[90mexp delete-release v1-0-0\033[0m\n"); printf("\033[37mNote: \033[90mUse hyphens instead of dots in tag names (v1-0-0 not v1.0.0)\033[0m\n"); return 1; } printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🗑️ Delete Release ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); // Check token char *token = get_token(); if (!token) { print_error("You are not logged in. Use 'exp login' first"); return 1; } // Check repository configuration char repo_config_path[MAX_PATH]; snprintf(repo_config_path, MAX_PATH, "%s/repo_config", get_config_dir()); FILE *fp = fopen(repo_config_path, "r"); if (!fp) { print_error("Repository not initialized. Use 'exp init' first"); free(token); return 1; } char config_line[MAX_BUFFER]; char repo_name[MAX_BUFFER] = {0}; char username[MAX_BUFFER] = {0}; while (fgets(config_line, MAX_BUFFER, fp)) { if (strncmp(config_line, "name=", 5) == 0) { strcpy(repo_name, config_line + 5); // Remove newline if present size_t len = strlen(repo_name); if (len > 0 && repo_name[len-1] == '\n') { repo_name[len-1] = '\0'; } } else if (strncmp(config_line, "username=", 9) == 0) { strcpy(username, config_line + 9); // Remove newline if present size_t len = strlen(username); if (len > 0 && username[len-1] == '\n') { username[len-1] = '\0'; } } } fclose(fp); if (strlen(repo_name) == 0 || strlen(username) == 0) { print_error("Incomplete repository information"); free(token); return 1; } const char *tag_name = argv[1]; // Create JSON for delete release request char json_data[MAX_BUFFER]; snprintf(json_data, MAX_BUFFER, "{\"tag_name\":\"%s\",\"repository\":\"%s\",\"username\":\"%s\"}", tag_name, repo_name, username); // Create URL for delete release char url[MAX_PATH]; snprintf(url, MAX_PATH, "%s/release/%s/%s/delete", API_BASE_URL, username, repo_name); // Send delete release request with POST method instead http_response_t response = http_post(url, token, json_data); if (!response.data) { print_error("Failed to delete release"); free(token); return 1; } // Parse JSON response struct json_object *parsed_json; struct json_object *status_obj; struct json_object *message_obj; parsed_json = json_tokener_parse(response.data); if (!parsed_json) { print_error("Failed to parse JSON response"); free(response.data); free(token); return 1; } // Check response status json_object_object_get_ex(parsed_json, "status", &status_obj); json_object_object_get_ex(parsed_json, "message", &message_obj); const char *status = json_object_get_string(status_obj); const char *message = json_object_get_string(message_obj); if (strcmp(status, "success") != 0) { print_error(message); json_object_put(parsed_json); free(response.data); free(token); return 1; } printf("\n"); print_success("Release deleted successfully!"); printf("\033[36m╔══════════════════════════════════════╗\033[0m\n"); printf("\033[36m║ 🎉 Release Removed! ║\033[0m\n"); printf("\033[36m╚══════════════════════════════════════╝\033[0m\n"); printf("\033[37m🏷️ Tag: \033[31m%s\033[0m\n", tag_name); printf("\033[90m💡 The release has been permanently deleted\033[0m\n"); printf("\033[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\033[0m\n"); // Clean up memory json_object_put(parsed_json); free(response.data); free(token); return 0; }