From 6b781fdc34b805e40c86bb177086e1c4d9c9f1e7 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 22 Jun 2025 11:26:39 +1200 Subject: [PATCH] 'Generic Commit' --- README.md | 16 ++-- getpkg/src/BashrcEditor.cpp | 1 + getpkg/src/DropshellScriptManager.cpp | 108 ++++++++++++++++++-------- getpkg/src/DropshellScriptManager.hpp | 2 + getpkg/src/main.cpp | 4 +- 5 files changed, 90 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index a25f67e..9eecfde 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # getpkg - Package Manager for Dropshell Tools -getpkg is a command-line package manager that simplifies tool installation, management, and publishing for the dropshell ecosystem. Tools are installed to `~/.local/bin/getpkg/` and automatically added to your PATH with bash completion. +getpkg is a command-line package manager that simplifies tool installation, management, and publishing for the dropshell ecosystem. Tools are installed to `~/.getpkg/` with executable symlinks in `~/.local/bin/getpkg/` and automatically added to your PATH with bash completion. ## Installation @@ -75,11 +75,12 @@ getpkg version When you install a tool, getpkg: 1. **Downloads** the tool archive from getpkg.xyz -2. **Extracts** it to `~/.local/bin/getpkg//` -3. **Updates PATH** by modifying `~/.bashrc_getpkg` -4. **Enables completion** for the tool -5. **Runs setup** if a `setup_script.sh` exists -6. **Stores metadata** in `~/.config/getpkg/.json` +2. **Extracts** it to `~/.getpkg//` +3. **Creates symlinks** for all executables in `~/.local/bin/getpkg/` +4. **Ensures PATH** includes `~/.local/bin/getpkg` (one-time setup) +5. **Enables completion** for the tool +6. **Runs setup** if a `setup_script.sh` exists +7. **Stores metadata** in `~/.config/getpkg/.json` ### Architecture Support @@ -92,7 +93,8 @@ Tools are automatically downloaded for your architecture, with fallback to unive ### File Locations -- **Installed tools**: `~/.local/bin/getpkg//` +- **Tool files**: `~/.getpkg//` (actual tool installation) +- **Executable symlinks**: `~/.local/bin/getpkg/` (in your PATH) - **Configuration**: `~/.config/getpkg/` - **PATH setup**: `~/.bashrc_getpkg` (sourced by `~/.bashrc`) diff --git a/getpkg/src/BashrcEditor.cpp b/getpkg/src/BashrcEditor.cpp index d46385b..2b97ba7 100644 --- a/getpkg/src/BashrcEditor.cpp +++ b/getpkg/src/BashrcEditor.cpp @@ -78,6 +78,7 @@ namespace dropshelltool } infile.close(); lines.push_back(BLOCK_START); + lines.push_back("export PATH=\"$HOME/.local/bin/getpkg:$PATH\""); lines.push_back("source \"" + DROPSHELL_RC_PATH.string() + "\""); lines.push_back(BLOCK_END); std::ofstream outfile(BASHRC_PATH, std::ios::trunc); diff --git a/getpkg/src/DropshellScriptManager.cpp b/getpkg/src/DropshellScriptManager.cpp index 897a81d..f24451e 100644 --- a/getpkg/src/DropshellScriptManager.cpp +++ b/getpkg/src/DropshellScriptManager.cpp @@ -31,41 +31,13 @@ void DropshellScriptManager::ensureExists() const { } void DropshellScriptManager::addToolEntry(const std::string& toolName, const std::string& toolDir) { - ensureExists(); - std::ifstream infile(dropshelltool::DROPSHELL_RC_PATH); - std::vector lines; - std::string line; - std::string exportLine = "export PATH=\"" + toolDir + ":$PATH\" # getpkg:" + toolName; - bool found = false; - while (std::getline(infile, line)) { - if (line.find("# getpkg:" + toolName) != std::string::npos) { - found = true; - lines.push_back(exportLine); - } else { - lines.push_back(line); - } - } - infile.close(); - if (!found) lines.push_back(exportLine); - std::ofstream outfile(dropshelltool::DROPSHELL_RC_PATH, std::ios::trunc); - for (const auto& l : lines) outfile << l << "\n"; - outfile.close(); + // Create symlinks instead of adding to PATH + createSymlinks(toolName, toolDir); } void DropshellScriptManager::removeToolEntry(const std::string& toolName) { - ensureExists(); - std::ifstream infile(dropshelltool::DROPSHELL_RC_PATH); - std::vector lines; - std::string line; - while (std::getline(infile, line)) { - if (line.find("# getpkg:" + toolName) == std::string::npos) { - lines.push_back(line); - } - } - infile.close(); - std::ofstream outfile(dropshelltool::DROPSHELL_RC_PATH, std::ios::trunc); - for (const auto& l : lines) outfile << l << "\n"; - outfile.close(); + // Remove symlinks instead of PATH entries + removeSymlinks(toolName); } void DropshellScriptManager::addAutocomplete(const std::string& toolName) { @@ -155,4 +127,76 @@ void DropshellScriptManager::removeAutocomplete(const std::string& toolName) { std::ofstream outfile(dropshelltool::DROPSHELL_RC_PATH, std::ios::trunc); for (const auto& l : lines) outfile << l << "\n"; outfile.close(); +} + +void DropshellScriptManager::createSymlinks(const std::string& toolName, const std::string& toolDir) { + std::string home = std::getenv("HOME"); + std::filesystem::path getpkgBinDir = std::filesystem::path(home) / ".local/bin/getpkg"; + + // Ensure the getpkg bin directory exists + std::filesystem::create_directories(getpkgBinDir); + + // Remove existing symlinks for this tool first + removeSymlinks(toolName); + + // Find all executable files in the tool directory + if (std::filesystem::exists(toolDir)) { + for (const auto& entry : std::filesystem::directory_iterator(toolDir)) { + if (entry.is_regular_file()) { + auto perms = std::filesystem::status(entry).permissions(); + // Check if the file is executable (any execute bit set) + if ((perms & std::filesystem::perms::owner_exec) != std::filesystem::perms::none || + (perms & std::filesystem::perms::group_exec) != std::filesystem::perms::none || + (perms & std::filesystem::perms::others_exec) != std::filesystem::perms::none) { + + std::string fileName = entry.path().filename().string(); + std::filesystem::path symlinkPath = getpkgBinDir / fileName; + + // Skip if a directory already exists with that name (tool installation directory) + if (std::filesystem::exists(symlinkPath) && std::filesystem::is_directory(symlinkPath)) { + continue; + } + + // Remove existing symlink if it exists + if (std::filesystem::exists(symlinkPath) && std::filesystem::is_symlink(symlinkPath)) { + std::filesystem::remove(symlinkPath); + } + + // Create symlink + try { + std::filesystem::create_symlink(entry.path(), symlinkPath); + std::cout << "Created symlink: " << symlinkPath << " -> " << entry.path() << std::endl; + } catch (const std::exception& e) { + std::cerr << "Warning: Failed to create symlink " << symlinkPath << ": " << e.what() << std::endl; + } + } + } + } + } +} + +void DropshellScriptManager::removeSymlinks(const std::string& toolName) { + std::string home = std::getenv("HOME"); + std::filesystem::path getpkgBinDir = std::filesystem::path(home) / ".local/bin/getpkg"; + std::filesystem::path toolDir = std::filesystem::path(home) / ".getpkg" / toolName; + + if (!std::filesystem::exists(getpkgBinDir)) { + return; + } + + // Remove symlinks that point to files in the tool directory + for (const auto& entry : std::filesystem::directory_iterator(getpkgBinDir)) { + if (entry.is_symlink()) { + try { + std::filesystem::path target = std::filesystem::read_symlink(entry.path()); + // Check if the symlink points to something in the tool directory + if (target.string().find(toolDir.string()) == 0) { + std::filesystem::remove(entry.path()); + std::cout << "Removed symlink: " << entry.path() << std::endl; + } + } catch (const std::exception& e) { + std::cerr << "Warning: Failed to process symlink " << entry.path() << ": " << e.what() << std::endl; + } + } + } } \ No newline at end of file diff --git a/getpkg/src/DropshellScriptManager.hpp b/getpkg/src/DropshellScriptManager.hpp index 396a95d..13c984f 100644 --- a/getpkg/src/DropshellScriptManager.hpp +++ b/getpkg/src/DropshellScriptManager.hpp @@ -10,4 +10,6 @@ public: void removeToolEntry(const std::string& toolName); void addAutocomplete(const std::string& toolName); void removeAutocomplete(const std::string& toolName); + void createSymlinks(const std::string& toolName, const std::string& toolDir); + void removeSymlinks(const std::string& toolName); }; \ No newline at end of file diff --git a/getpkg/src/main.cpp b/getpkg/src/main.cpp index ac3d4c3..65060b4 100644 --- a/getpkg/src/main.cpp +++ b/getpkg/src/main.cpp @@ -144,7 +144,7 @@ int install_tool(int argc, char* argv[]) { std::string arch = get_arch(); std::string home = get_home(); std::filesystem::path configDir = std::filesystem::path(home) / ".config/getpkg"; - std::filesystem::path binDir = std::filesystem::path(home) / ".local/bin/getpkg" / toolName; + std::filesystem::path binDir = std::filesystem::path(home) / ".getpkg" / toolName; std::filesystem::path archivePath = configDir / (toolName + ".tgz"); std::filesystem::path toolInfoPath = configDir / (toolName + ".json"); @@ -501,7 +501,7 @@ int uninstall_tool(int argc, char* argv[]) { std::string home = get_home(); std::filesystem::path configDir = std::filesystem::path(home) / ".config/getpkg"; - std::filesystem::path binDir = std::filesystem::path(home) / ".local/bin/getpkg" / toolName; + std::filesystem::path binDir = std::filesystem::path(home) / ".getpkg" / toolName; std::filesystem::path toolInfoPath = configDir / (toolName + ".json"); // Check if tool is installed