Compare commits

...

13 Commits

Author SHA1 Message Date
52d8e5b95e docs: Update 3 files
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 53s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m34s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 6s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
2025-07-20 15:03:37 +12:00
bfeaf4d0db Update gp/gp
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 54s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m21s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 6s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
2025-07-20 13:56:04 +12:00
6a3ca6bc10 Modify test_gp_1752976117
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 1m1s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m23s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 6s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 6s
2025-07-20 13:50:50 +12:00
7f8312ed59 test: Update 2 files
Some checks failed
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Has been cancelled
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Has been cancelled
Build-Test-Publish / build (linux/amd64) (push) Has been cancelled
Build-Test-Publish / build (linux/arm64) (push) Has been cancelled
2025-07-20 13:50:04 +12:00
1b03087c02 test: Update 13 files
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Successful in 54s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Has been cancelled
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Has been cancelled
Build-Test-Publish / build (linux/arm64) (push) Has been cancelled
2025-07-20 13:49:08 +12:00
0ba6227412 Modify README.md
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 53s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m34s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 7s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
2025-07-19 15:43:38 +12:00
f5ba2e719b Modify whatsdirty/publish.sh
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 54s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m23s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 7s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
2025-07-19 13:30:51 +12:00
73c94f34f6 Modify getpkg/src/main.cpp
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 55s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m23s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 6s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
2025-06-30 23:47:08 +12:00
af4cbbcab0 Update 2 files
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 54s
Build-Test-Publish / build (linux/arm64) (push) Successful in 1m23s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 7s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 7s
2025-06-30 23:13:51 +12:00
a415eb0f91 Modify buildtestpublish_all.sh
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Failing after 53s
Build-Test-Publish / build (linux/arm64) (push) Failing after 1m6s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Has been skipped
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Has been skipped
2025-06-30 23:09:07 +12:00
83d6cf1603 Modify dehydrate/test.sh
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Failing after 52s
Build-Test-Publish / build (linux/arm64) (push) Failing after 1m6s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Has been skipped
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Has been skipped
2025-06-30 23:03:59 +12:00
fbaa3a4089 Modify dehydrate/test.sh
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Failing after 53s
Build-Test-Publish / build (linux/arm64) (push) Failing after 1m6s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Has been skipped
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Has been skipped
2025-06-30 23:02:06 +12:00
0c767e065c Modify dehydrate/test.sh
Some checks failed
Build-Test-Publish / build (linux/amd64) (push) Failing after 53s
Build-Test-Publish / build (linux/arm64) (push) Failing after 1m18s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Has been skipped
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Has been skipped
2025-06-30 22:56:30 +12:00
27 changed files with 1340 additions and 259 deletions

View File

@ -0,0 +1,325 @@
# Design Document
## Overview
This design extends getpkg to support multiple package servers while maintaining full backward compatibility. The solution introduces a server configuration system, updates the client architecture to handle multiple servers, and reorganizes package metadata storage. The design prioritizes minimal disruption to existing functionality while providing powerful multi-server capabilities.
## Architecture
### High-Level Architecture
```mermaid
graph TB
CLI[CLI Commands] --> SM[ServerManager]
CLI --> PM[PackageManager]
PM --> SM
PM --> GC[GetbinClient]
SM --> CF[servers.json]
PM --> PF[packages/*.json]
GC --> S1[Server 1]
GC --> S2[Server 2]
GC --> SN[Server N]
```
### Server Management Flow
```mermaid
sequenceDiagram
participant User
participant CLI
participant ServerManager
participant Config
User->>CLI: getpkg server add example.com
CLI->>ServerManager: addServer("example.com")
ServerManager->>Config: load servers.json
ServerManager->>ServerManager: validate URL
ServerManager->>Config: save updated servers.json
ServerManager->>CLI: success confirmation
CLI->>User: Server added successfully
```
### Package Installation Flow
```mermaid
sequenceDiagram
participant User
participant CLI
participant PackageManager
participant GetbinClient
participant Server1
participant Server2
User->>CLI: getpkg install tool
CLI->>PackageManager: install("tool")
PackageManager->>GetbinClient: download("tool", servers[0])
GetbinClient->>Server1: GET /object/tool:arch
alt Package found
Server1-->>GetbinClient: 200 + package data
GetbinClient-->>PackageManager: success
else Package not found
Server1-->>GetbinClient: 404
GetbinClient->>Server2: GET /object/tool:arch
Server2-->>GetbinClient: 200 + package data
GetbinClient-->>PackageManager: success
end
PackageManager->>PackageManager: install package
PackageManager->>CLI: installation complete
```
## Components and Interfaces
### ServerManager Class
**Purpose**: Manages server configuration, write tokens, and provides server list to other components.
**Interface**:
```cpp
class ServerManager {
public:
ServerManager();
// Server management
bool addServer(const std::string& serverUrl, const std::string& writeToken = "");
bool removeServer(const std::string& serverUrl);
std::vector<std::string> getServers() const;
std::string getDefaultServer() const;
std::string getDefaultPublishServer() const; // First server with write token
// Token management
bool setWriteToken(const std::string& serverUrl, const std::string& token);
std::string getWriteToken(const std::string& serverUrl) const;
bool hasWriteToken(const std::string& serverUrl) const;
std::vector<std::string> getServersWithTokens() const;
// Configuration
bool loadConfiguration();
bool saveConfiguration();
void ensureDefaultConfiguration();
// Migration
bool migrateFromLegacy();
private:
std::vector<ServerConfig> servers_;
std::filesystem::path configPath_;
bool validateServerUrl(const std::string& url) const;
bool isServerReachable(const std::string& url) const;
ServerConfig* findServer(const std::string& url);
};
```
### Enhanced GetbinClient Class
**Purpose**: Extended to support multiple servers with fallback logic.
**Interface Changes**:
```cpp
class GetbinClient {
public:
GetbinClient(const std::vector<std::string>& servers);
// Existing methods with server selection
bool download(const std::string& toolName, const std::string& arch,
const std::string& outPath, ProgressCallback progressCallback = nullptr);
bool downloadFromServer(const std::string& serverUrl, const std::string& toolName,
const std::string& arch, const std::string& outPath,
ProgressCallback progressCallback = nullptr);
// Server-specific operations
bool upload(const std::string& serverUrl, const std::string& archivePath,
std::string& outUrl, std::string& outHash, const std::string& token,
ProgressCallback progressCallback = nullptr);
bool getHash(const std::string& serverUrl, const std::string& toolName,
const std::string& arch, std::string& outHash);
// Multi-server operations
bool findPackageServer(const std::string& toolName, const std::string& arch,
std::string& foundServer) const;
private:
std::vector<std::string> servers_;
std::string buildUrl(const std::string& serverUrl, const std::string& endpoint) const;
};
```
### PackageMetadata Structure
**Purpose**: Enhanced metadata structure to track server source.
**Structure**:
```cpp
struct PackageMetadata {
std::string name;
std::string version;
std::string hash;
std::string arch;
std::string sourceServer; // New field
std::string installDate; // New field for better tracking
// Serialization
nlohmann::json toJson() const;
static PackageMetadata fromJson(const nlohmann::json& j);
// Migration support
static PackageMetadata fromLegacyJson(const nlohmann::json& j, const std::string& defaultServer);
};
```
### Migration Manager
**Purpose**: Handles migration from single-server to multi-server configuration.
**Interface**:
```cpp
class MigrationManager {
public:
MigrationManager();
bool needsMigration() const;
bool performMigration();
private:
bool migrateServerConfiguration();
bool migratePackageMetadata();
bool movePackageFiles();
bool updatePackageMetadata();
std::filesystem::path oldConfigDir_;
std::filesystem::path newConfigDir_;
std::filesystem::path packagesDir_;
};
```
## Data Models
### Server Configuration Format
**File**: `~/.config/getpkg/servers.json`
```json
{
"version": "1.0",
"servers": [
{
"url": "getpkg.xyz",
"name": "Official getpkg Registry",
"default": true,
"writeToken": "",
"added": "2024-01-15T10:30:00Z"
},
{
"url": "packages.example.com",
"name": "Example Corporate Registry",
"default": false,
"writeToken": "abc123token456",
"added": "2024-01-16T14:20:00Z"
}
],
"lastUpdated": "2024-01-16T14:20:00Z"
}
```
### Enhanced Package Metadata Format
**File**: `~/.config/getpkg/packages/<tool_name>.json`
```json
{
"name": "example-tool",
"version": "2024.0115.1430",
"hash": "1234567890123456",
"arch": "x86_64",
"sourceServer": "getpkg.xyz",
"installDate": "2024-01-15T14:30:00Z",
"lastUpdated": "2024-01-15T14:30:00Z"
}
```
### Directory Structure Changes
```
~/.config/getpkg/
├── servers.json # New: Server configuration with embedded tokens
├── packages/ # New: Package metadata directory
│ ├── tool1.json
│ ├── tool2.json
│ └── ...
└── getpkg.xyz/ # Legacy: Will be migrated to servers.json
└── write_token.txt # Legacy: Will be migrated
```
## Error Handling
### Server Connectivity Issues
1. **Network Failures**: Graceful fallback to next server in list
2. **Invalid Responses**: Clear error messages with server identification
3. **Authentication Failures**: Server-specific error handling with token guidance
### Configuration Corruption
1. **Invalid JSON**: Automatic backup and reset to default configuration
2. **Missing Files**: Automatic creation with default settings
3. **Permission Issues**: Clear error messages with resolution steps
### Migration Failures
1. **Partial Migration**: Rollback capability with clear status reporting
2. **File Conflicts**: Safe handling with backup creation
3. **Metadata Corruption**: Individual file recovery without breaking entire system
## Testing Strategy
### Unit Tests
1. **ServerManager**: Configuration loading, validation, server management
2. **GetbinClient**: Multi-server communication, fallback logic
3. **PackageMetadata**: Serialization, migration, validation
4. **MigrationManager**: Legacy data handling, file operations
### Integration Tests
1. **End-to-End Installation**: Multi-server package discovery and installation
2. **Server Management**: Add/remove servers with real configuration
3. **Migration Testing**: Legacy to new format conversion
4. **Publish/Unpublish**: Server-specific operations
### Compatibility Tests
1. **Backward Compatibility**: Existing installations continue working
2. **Legacy Format**: Old package files are properly migrated
3. **Default Behavior**: No configuration changes for existing users
## Implementation Phases
### Phase 1: Core Infrastructure
- Implement ServerManager class
- Create server configuration format
- Add basic server validation
### Phase 2: Client Enhancement
- Extend GetbinClient for multi-server support
- Implement fallback logic
- Add server-specific operations
### Phase 3: Package Management
- Update package metadata format
- Implement packages directory structure
- Add server tracking to installations
### Phase 4: Migration System
- Create MigrationManager
- Implement automatic migration
- Add backward compatibility layer
### Phase 5: CLI Integration
- Add server management commands
- Update existing commands for multi-server
- Implement server selection options
### Phase 6: Testing and Polish
- Comprehensive testing suite
- Error handling refinement
- Documentation updates

View File

@ -0,0 +1,79 @@
# Requirements Document
## Introduction
This feature extends getpkg to support multiple package servers instead of being limited to only getpkg.xyz. Users will be able to add and remove package servers, with getpkg searching across all configured servers to find packages. The system will maintain backward compatibility while providing flexible server management capabilities.
## Requirements
### Requirement 1
**User Story:** As a developer, I want to configure multiple package servers, so that I can access packages from different repositories and have redundancy in case one server is unavailable.
#### Acceptance Criteria
1. WHEN I run `getpkg server add <server_url>` THEN the system SHALL add the server to the configuration and confirm the addition
2. WHEN I run `getpkg server remove <server_url>` THEN the system SHALL remove the server from the configuration and confirm the removal
3. WHEN I run `getpkg server list` THEN the system SHALL display all configured servers in the order they were added
4. WHEN no servers are configured THEN the system SHALL default to using getpkg.xyz as the primary server
5. WHEN I add the first custom server THEN getpkg.xyz SHALL remain as the default first server unless explicitly removed
### Requirement 2
**User Story:** As a user, I want getpkg to search across all configured servers when installing packages, so that I can access packages from any of my configured repositories.
#### Acceptance Criteria
1. WHEN I run `getpkg install <tool_name>` THEN the system SHALL search servers in the order they were configured
2. WHEN a package is found on the first server THEN the system SHALL install from that server and not check remaining servers
3. WHEN a package is not found on the first server THEN the system SHALL try the next server in order
4. WHEN a package is not found on any server THEN the system SHALL report that the package was not found
5. WHEN checking for updates THEN the system SHALL use the same server where the package was originally installed
### Requirement 3
**User Story:** As a package publisher, I want to specify which server to publish to and manage write tokens per server, so that I can control where my packages are distributed and authenticate appropriately.
#### Acceptance Criteria
1. WHEN I run `getpkg publish <tool_name> <folder>` without specifying a server THEN the system SHALL publish to the first configured server that has a write token
2. WHEN I run `getpkg publish --server <server_url> <tool_name> <folder>` THEN the system SHALL publish to the specified server using its stored write token
3. WHEN I run `getpkg unpublish <tool_name>` without specifying a server THEN the system SHALL unpublish from the first configured server that has a write token
4. WHEN I run `getpkg unpublish --server <server_url> <tool_name>` THEN the system SHALL unpublish from the specified server using its stored write token
5. WHEN no servers have write tokens THEN the system SHALL report an error and suggest adding a write token to a server
### Requirement 4
**User Story:** As a user, I want my package metadata to be organized by server, so that I can track which packages came from which servers and manage them appropriately.
#### Acceptance Criteria
1. WHEN a package is installed THEN the system SHALL store the package metadata in `~/.config/getpkg/packages/<tool_name>.json`
2. WHEN package metadata is stored THEN it SHALL include the source server URL in addition to existing fields
3. WHEN the packages directory doesn't exist THEN the system SHALL create it automatically
4. WHEN migrating from the old format THEN existing package JSON files SHALL be moved to the packages subdirectory
5. WHEN migrating from the old format THEN existing package metadata SHALL be updated to include getpkg.xyz as the source server
### Requirement 5
**User Story:** As a user, I want server configuration to be persistent and secure, so that my settings are maintained across sessions and my authentication tokens are protected.
#### Acceptance Criteria
1. WHEN server configuration is modified THEN it SHALL be stored in `~/.config/getpkg/servers.json`
2. WHEN the configuration file doesn't exist THEN the system SHALL create it with getpkg.xyz as the default server
3. WHEN reading server configuration THEN the system SHALL validate the JSON format and handle corruption gracefully
4. WHEN a server URL is invalid THEN the system SHALL reject the addition and provide a helpful error message
5. WHEN authentication tokens are needed THEN they SHALL continue to be stored per-server in the existing location pattern
### Requirement 6
**User Story:** As a user, I want the multi-server functionality to be backward compatible, so that existing installations continue to work without modification.
#### Acceptance Criteria
1. WHEN getpkg starts with no server configuration THEN it SHALL automatically configure getpkg.xyz as the default server
2. WHEN existing package JSON files are found in `~/.config/getpkg/` THEN they SHALL be automatically migrated to the packages subdirectory
3. WHEN migrated package files are processed THEN they SHALL be updated to include server source information
4. WHEN all existing functionality is used THEN it SHALL work exactly as before for users who don't configure additional servers
5. WHEN the migration process fails THEN the system SHALL provide clear error messages and not break existing functionality

View File

@ -0,0 +1,94 @@
# Implementation Plan
Based on analysis of the current codebase, the multi-server support feature needs to be built from scratch. The current implementation has a hardcoded `SERVER_HOST = "getpkg.xyz"` in `GetbinClient` and no server management infrastructure.
## Core Infrastructure Tasks
- [-] 1. Create ServerManager class and server configuration system
- Implement ServerManager class with server add/remove/list functionality
- Create server configuration JSON format and file handling
- Add server URL validation and reachability checks
- Implement write token management per server
- _Requirements: 1.1, 1.2, 1.3, 5.1, 5.2, 5.4_
- [ ] 2. Enhance GetbinClient for multi-server support
- Modify GetbinClient constructor to accept server list instead of hardcoded host
- Implement multi-server fallback logic for downloads
- Add server-specific upload and hash operations
- Create findPackageServer method for package discovery
- _Requirements: 2.1, 2.2, 2.3, 2.4_
- [ ] 3. Create enhanced package metadata system
- Design PackageMetadata structure with server source tracking
- Implement packages directory structure (~/.config/getpkg/packages/)
- Add JSON serialization/deserialization for enhanced metadata
- Create package metadata validation and error handling
- _Requirements: 4.1, 4.2, 4.3_
## Migration and Compatibility Tasks
- [ ] 4. Implement migration system for existing installations
- Create MigrationManager class for legacy data handling
- Implement automatic migration from single-server to multi-server config
- Migrate existing package JSON files to packages subdirectory
- Update existing package metadata to include server source information
- Add migration error handling and rollback capabilities
- _Requirements: 4.4, 4.5, 6.1, 6.2, 6.3, 6.5_
- [ ] 5. Ensure backward compatibility
- Implement default server configuration (getpkg.xyz) when no config exists
- Maintain existing CLI behavior for users without custom server configuration
- Preserve existing token storage location compatibility
- Add graceful handling of missing or corrupted configuration files
- _Requirements: 6.1, 6.4, 5.3_
## CLI Integration Tasks
- [ ] 6. Add server management commands to main.cpp
- Implement `getpkg server add <url>` command
- Implement `getpkg server remove <url>` command
- Implement `getpkg server list` command
- Add server URL validation and user feedback
- _Requirements: 1.1, 1.2, 1.3_
- [ ] 7. Update existing commands for multi-server support
- Modify install command to use ServerManager and multi-server GetbinClient
- Update publish command to support --server option and default server selection
- Update unpublish command to support --server option and default server selection
- Ensure update command works with multi-server package tracking
- _Requirements: 2.1, 2.2, 2.3, 2.4, 3.1, 3.2, 3.3, 3.4, 3.5_
## Integration and Testing Tasks
- [ ] 8. Integrate all components in main application flow
- Initialize ServerManager in main.cpp startup
- Trigger migration process on first run with new version
- Update package installation flow to use enhanced metadata
- Ensure proper error handling and user messaging throughout
- _Requirements: 6.1, 6.2, 6.3, 6.4, 6.5_
- [ ] 9. Add comprehensive error handling and validation
- Implement network error handling with server fallback
- Add configuration file corruption recovery
- Create user-friendly error messages for server connectivity issues
- Add validation for server URLs and authentication tokens
- _Requirements: 5.3, 5.4, 5.5_
- [ ] 10. Create unit tests for new components
- Write unit tests for ServerManager class functionality
- Test GetbinClient multi-server operations and fallback logic
- Test PackageMetadata serialization and migration
- Test MigrationManager with various legacy data scenarios
- Create integration tests for complete multi-server workflows
- _Requirements: All requirements validation_
## Notes
- Current codebase has `SERVER_HOST = "getpkg.xyz"` hardcoded in GetbinClient.cpp
- No existing server management or configuration infrastructure
- Package metadata is currently stored as individual JSON files in ~/.config/getpkg/
- Token storage is in ~/.config/getpkg.xyz/write_token.txt (legacy format)
- All functionality needs to be built from scratch while maintaining backward compatibility

23
.kiro/steering/product.md Normal file
View File

@ -0,0 +1,23 @@
# Product Overview
This repository contains **getpkg** - a command-line package manager for the dropshell ecosystem, along with a collection of developer tools.
## Core Product
- **getpkg**: Package manager that installs tools to `~/.getpkg/` with symlinks in `~/.local/bin/getpkg/`
- Supports multiple architectures (x86_64, aarch64, universal)
- Tools are published to and downloaded from `getpkg.xyz`
## Tool Collection
The repository includes several utility tools:
- **bb64**: Bash-compatible base64 encoder/decoder with custom character set
- **dehydrate**: Converts files/directories to C++ source code for embedding
- **whatsdirty**: Git repository status checker
- **sos**: Simple object storage client
- **gp**: Git push utility
## Key Features
- Cross-platform tool distribution
- Automated installation with PATH setup
- Bash completion support
- Architecture-aware downloads with fallbacks
- Publishing system with authentication tokens

View File

@ -0,0 +1,72 @@
# Project Structure
## Repository Layout
```
├── buildtestpublish_all.sh # Master build script for all projects
├── clean.sh # Global cleanup script
├── README.md # Main project documentation
└── <tool-name>/ # Individual tool directories
```
## Tool Directory Structure
### C++ Projects (CMake-based)
```
<tool-name>/
├── CMakeLists.txt # CMake configuration
├── build.sh # Build script
├── test.sh # Test script
├── clean.sh # Cleanup script
├── publish.sh # Publishing script
├── install.sh # Installation script
├── README.md # Tool documentation
├── Dockerfile.dropshell-build # Docker build configuration
├── src/ # Source code
│ ├── <tool>.cpp # Main source file
│ ├── version.hpp.in # Version template
│ └── ... # Additional sources
├── build/ # Build artifacts (generated)
├── output/ # Final executables (generated)
└── .vscode/ # VS Code configuration
```
### Shell Script Projects
```
<tool-name>/
├── <tool-name> # Executable shell script
├── build.sh # Build script (may be no-op)
├── test.sh # Test script
├── clean.sh # Cleanup script
├── publish.sh # Publishing script
└── setup_script.sh # Post-install setup (optional)
```
## Standard Files
### Required Scripts
- **build.sh**: Builds the project (Docker for C++, no-op for shell)
- **test.sh**: Runs project tests
- **clean.sh**: Removes build artifacts
- **publish.sh**: Publishes to getpkg.xyz registry
### Optional Files
- **install.sh**: System-wide installation script
- **setup_script.sh**: Post-install setup for getpkg
- **cmake_prebuild.sh**: Pre-build setup for CMake projects
### Generated Directories
- **build/**: CMake build artifacts (C++ projects)
- **output/**: Final executables ready for distribution
- **test_*/**: Test-specific directories
## Naming Conventions
- Tool directories match executable names
- C++ source files typically match project name
- Version templates use `.hpp.in` extension
- Docker files use `Dockerfile.dropshell-build` pattern
- Test directories prefixed with `test_`
## Configuration Files
- **.gitignore**: Standard ignore patterns for build artifacts
- **.vscode/**: VS Code workspace settings
- **CMakeLists.txt**: Follows standard template with PROJECT_NAME parameter

70
.kiro/steering/tech.md Normal file
View File

@ -0,0 +1,70 @@
# Technology Stack
## Build System
- **CMake 3.16+** with Ninja generator for C++ projects
- **Docker** containerized builds using `gitea.jde.nz/public/dropshell-build-base:latest`
- **Static linking** for all C++ executables (`-static` flag)
## Languages & Standards
- **C++23** standard for all C++ projects
- **Bash** for shell scripts and simple tools
- **Shell scripts** follow `set -euo pipefail` pattern
## Dependencies
- **nlohmann_json** for JSON handling in C++ projects
- **CPR (static)** for HTTP requests in getpkg
- Custom modules in `/usr/local/share/cmake/Modules`
## Common Build Patterns
### C++ Projects (CMake)
```bash
# Standard build command
cmake -G Ninja -S . -B ./build -DCMAKE_BUILD_TYPE=Debug -DPROJECT_NAME=<project>
cmake --build ./build
```
### Docker Build (for C++ tools)
```bash
# Uses Dockerfile.dropshell-build pattern
docker build -t <project>-build -f Dockerfile.dropshell-build --build-arg PROJECT=<project> --output ./output .
```
### Shell Tools
- No build step required
- Executable shell scripts with proper shebang
- Use `chmod +x` for permissions
## Common Commands
### Build
```bash
./build.sh # Build individual project
./buildtestpublish_all.sh # Build all projects
```
### Test
```bash
./test.sh # Run tests for individual project
```
### Clean
```bash
./clean.sh # Clean build artifacts
```
### Publish
```bash
./publish.sh # Publish to getpkg.xyz (requires SOS_WRITE_TOKEN)
```
## Version Management
- Automatic timestamp-based versioning: `YYYY.MMDD.HHMM`
- Version configured via `version.hpp.in` template files
- Pre-build scripts (`cmake_prebuild.sh`) for additional setup
## Environment Variables
- `CMAKE_BUILD_TYPE`: Debug/Release (default: Debug)
- `SOS_WRITE_TOKEN`: Authentication for publishing
- `NO_CACHE`: Skip Docker cache when set to "true"
- `PROJECT`: Project name for build scripts

278
README.md
View File

@ -1,192 +1,86 @@
# 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 `~/.getpkg/` with executable symlinks in `~/.local/bin/getpkg/` and automatically added to your PATH with bash completion.
## Installation
Install getpkg with a single command:
```bash
curl https://getbin.xyz/getpkg-install | bash
```
After installation, restart your shell or run `source ~/.bashrc` to enable the new PATH and completion settings.
## Basic Usage
### Installing Tools
Install any tool from the getpkg registry:
```bash
# Install a tool
getpkg install whatsdirty
```
### Managing Installed Tools
```bash
# List all available commands
getpkg help
# Update all installed tools
getpkg update
# Uninstall a tool
getpkg uninstall whatsdirty
# Check getpkg version
getpkg version
```
## Available Commands
### Core Package Management
- **`getpkg install <tool_name>`** - Install or update a tool
- **`getpkg uninstall <tool_name>`** - Remove an installed tool
- **`getpkg update`** - Update getpkg and all installed tools
### Publishing (Requires SOS_WRITE_TOKEN)
- **`getpkg publish <tool_name[:ARCH]> <folder>`** - Upload a tool to getpkg.xyz
- **`getpkg unpublish <tool_name[:ARCH]>`** - Remove a published tool
- **`getpkg unpublish <hash>`** - Remove a published tool by hash
### Development Tools
- **`getpkg create <tool_name> <directory>`** - Create a new tool project
- **`getpkg hash <file_or_directory>`** - Calculate hash of files/directories
### Information
- **`getpkg list`** - List all available packages with status
- **`getpkg clean`** - Clean up orphaned configs and symlinks
- **`getpkg version`** - Show getpkg version
- **`getpkg help`** - Show detailed help
- **`getpkg autocomplete`** - Show available commands for completion
## How It Works
### Installation Process
When you install a tool, getpkg:
1. **Downloads** the tool archive from getpkg.xyz
2. **Extracts** it to `~/.getpkg/<tool_name>/`
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/<tool_name>.json`
### Architecture Support
getpkg supports multiple architectures:
- `x86_64` (Intel/AMD 64-bit)
- `aarch64` (ARM 64-bit)
- `universal` (cross-platform tools)
Tools are automatically downloaded for your architecture, with fallback to universal versions.
### File Locations
- **Tool files**: `~/.getpkg/<tool_name>/` (actual tool installation)
- **Executable symlinks**: `~/.local/bin/getpkg/` (in your PATH)
- **Configuration**: `~/.config/getpkg/`
- **PATH setup**: `~/.bashrc_getpkg` (sourced by `~/.bashrc`)
## Examples
### Installing Popular Tools
```bash
# Install available tools
getpkg install dehydrate # File to C++ code generator
getpkg install bb64 # Bash base64 encoder/decoder
# Development tools (for repository development)
getpkg install whatsdirty # Check git repo status
getpkg install sos # Simple object storage client
getpkg install gp # Git push utility
```
### Publishing Your Own Tools
```bash
# Set your publishing token
export SOS_WRITE_TOKEN="your-token-here"
# Create a new tool project
getpkg create mytool ./mytool-project
# Publish architecture-specific build
getpkg publish mytool:x86_64 ./build/
# Publish universal tool
getpkg publish mytool ./build/
# Remove published tool
getpkg unpublish mytool:x86_64
```
### Development Workflow
```bash
# Create tool structure
getpkg create awesome-tool ./awesome-tool
cd awesome-tool
# Build your tool...
# Add executable to the directory
# Test locally
./awesome-tool --version
# Publish when ready
getpkg publish awesome-tool:x86_64 .
```
## Environment Variables
- **`SOS_WRITE_TOKEN`** - Authentication token for publishing tools
## Troubleshooting
### Tool Not Found
If a tool isn't found after installation, ensure your shell has loaded the new PATH:
```bash
source ~/.bashrc
```
### Permission Issues
getpkg installs to your home directory and doesn't require root access. If you encounter permission issues, check that `~/.local/bin/` is writable.
### Network Issues
All tools are downloaded from `getpkg.xyz`. Ensure you have internet connectivity and the domain is accessible.
## Development
### Building getpkg
```bash
# Build debug version
cd getpkg && ./build.sh
# Run tests
cd getpkg && ./test.sh
# Publish (requires SOS_WRITE_TOKEN)
cd getpkg && ./publish.sh
```
### Tool Development
When creating tools for getpkg:
1. Create a directory with your tool binary
2. Optionally include a `setup_script.sh` for post-install setup
3. The tool should support `version` and `autocomplete` subcommands
4. Use `getpkg publish` to upload to the registry
For more details, see the development documentation in each tool's directory.
# getpkg - Simple Package Manager
getpkg is a command-line package manager that makes it easy to install and manage developer tools. Tools are automatically installed to your home directory and added to your PATH.
## Quick Start
Install getpkg with one command:
```bash
curl https://getbin.xyz/getpkg-install | bash
```
After installation, restart your shell or run:
```bash
source ~/.bashrc
```
## Basic Commands
### Install Tools
```bash
getpkg install <tool_name> # Install a tool
getpkg list # See all available tools
getpkg update # Update all installed tools
```
### Manage Tools
```bash
getpkg uninstall <tool_name> # Remove a tool
getpkg version # Check getpkg version
getpkg help # Show all commands
```
## Popular Tools
Install these useful developer tools:
```bash
getpkg install bb64 # Bash-compatible base64 encoder/decoder
getpkg install dehydrate # Convert files to C++ source code
getpkg install whatsdirty # Check git repository status
getpkg install sos # Simple object storage client
getpkg install gp # Git push utility
```
## How It Works
When you install a tool:
1. Downloads from getpkg.xyz
2. Installs to `~/.getpkg/<tool_name>/`
3. Creates shortcuts in `~/.local/bin/getpkg/`
4. Adds to your PATH automatically
5. Enables bash completion
## File Locations
- **Installed tools**: `~/.getpkg/<tool_name>/`
- **Shortcuts**: `~/.local/bin/getpkg/` (in your PATH)
- **Settings**: `~/.config/getpkg/`
## Architecture Support
getpkg automatically downloads the right version for your system:
- Intel/AMD 64-bit (`x86_64`)
- ARM 64-bit (`aarch64`)
- Universal (works everywhere)
## Troubleshooting
**Tool not found after install?**
```bash
source ~/.bashrc
```
**Permission errors?**
getpkg installs to your home directory - no root access needed.
**Network issues?**
Check your internet connection to `getpkg.xyz`.
## Need Help?
```bash
getpkg help # Show detailed help
getpkg list # See what's available
```

View File

@ -109,7 +109,7 @@ function buildtestpublish() {
# Add to projects list
PROJECTS+=("$TOOLNAME")
#cd "$dir" || echo "Failed to cd to $dir"
cd "$dir" || echo "Failed to cd to $dir"
subtitle "🔨 BUILDING $TOOLNAME_UPPER 🔨"
if dothis build "$dir" "$TOOLNAME"; then

View File

@ -3,7 +3,7 @@ set -euo pipefail
# Get script directory - handle different execution contexts
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PROJECT="$(basename "$(dirname "${SCRIPT_DIR}")")"
PROJECT="$(basename "${SCRIPT_DIR}")"
# Debug output for CI
echo "${PROJECT} build script running from: ${SCRIPT_DIR}"

View File

@ -8,8 +8,10 @@ PROJECT="dehydrate"
# Handle running locally or in Gitea runner
if [ -n "${GITEA_CONTAINER_NAME:-}" ]; then
echo "Running in Gitea CI environment"
OUTPUT_DIR="${GITHUB_WORKSPACE}/${PROJECT}/output"
TEST_DIR="${GITHUB_WORKSPACE}/${PROJECT}/test_temp"
echo "GITHUB_WORKSPACE: ${GITHUB_WORKSPACE}"
echo "Current directory: $(pwd)"
OUTPUT_DIR="${GITHUB_WORKSPACE}/dehydrate/output"
TEST_DIR="${GITHUB_WORKSPACE}/dehydrate/test_temp"
else
OUTPUT_DIR="${SCRIPT_DIR}/output"
TEST_DIR="${SCRIPT_DIR}/test_temp"
@ -57,6 +59,10 @@ echo -e "${YELLOW}Running dehydrate tests...${NC}\n"
# Debug output
echo "Looking for dehydrate at: $DEHYDRATE"
echo "Workspace structure:"
ls -la "${GITHUB_WORKSPACE}" 2>/dev/null || echo "Workspace not found"
echo "Dehydrate directory contents:"
ls -la "${GITHUB_WORKSPACE}/dehydrate" 2>/dev/null || echo "Dehydrate directory not found"
echo "Output directory contents:"
ls -la "$OUTPUT_DIR" 2>/dev/null || echo "Output directory not found"
@ -64,6 +70,18 @@ ls -la "$OUTPUT_DIR" 2>/dev/null || echo "Output directory not found"
if [ ! -f "$DEHYDRATE" ]; then
echo -e "${RED}Error: dehydrate binary not found at $DEHYDRATE${NC}"
echo "Please run ./build.sh first to build dehydrate"
if [ -n "${GITEA_CONTAINER_NAME:-}" ]; then
echo "Checking if build directory exists..."
BUILD_DIR="${GITHUB_WORKSPACE}/dehydrate/build"
if [ -d "$BUILD_DIR" ]; then
echo "Build directory exists, checking contents:"
ls -la "$BUILD_DIR"
else
echo "Build directory $BUILD_DIR does not exist"
fi
fi
exit 1
fi

207
getpkg/README.md Normal file
View File

@ -0,0 +1,207 @@
# 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 `~/.getpkg/` with executable symlinks in `~/.local/bin/getpkg/` and automatically added to your PATH with bash completion.
## Installation
Install getpkg with a single command:
```bash
curl https://getbin.xyz/getpkg-install | bash
```
After installation, restart your shell or run `source ~/.bashrc` to enable the new PATH and completion settings.
## Basic Usage
### Installing Tools
Install any tool from the getpkg registry:
```bash
# Install a tool
getpkg install whatsdirty
```
### Managing Installed Tools
```bash
# List all available commands
getpkg help
# Update all installed tools
getpkg update
# Uninstall a tool
getpkg uninstall whatsdirty
# Check getpkg version
getpkg version
```
## Available Commands
### Core Package Management
- **`getpkg install <tool_name>`** - Install or update a tool
- **`getpkg uninstall <tool_name>`** - Remove an installed tool
- **`getpkg update`** - Update getpkg and all installed tools
### Publishing (Requires SOS_WRITE_TOKEN)
- **`getpkg publish <tool_name[:ARCH]> <folder>`** - Upload a tool to getpkg.xyz
- **`getpkg unpublish <tool_name[:ARCH]>`** - Remove a published tool
- **`getpkg unpublish <hash>`** - Remove a published tool by hash
### Development Tools
- **`getpkg create <tool_name> <directory>`** - Create a new tool project
- **`getpkg hash <file_or_directory>`** - Calculate hash of files/directories
### Information
- **`getpkg list`** - List all available packages with status
- **`getpkg clean`** - Clean up orphaned configs and symlinks
- **`getpkg version`** - Show getpkg version
- **`getpkg help`** - Show detailed help
- **`getpkg autocomplete`** - Show available commands for completion
## How It Works
### Installation Process
When you install a tool, getpkg:
1. **Downloads** the tool archive from getpkg.xyz
2. **Extracts** it to `~/.getpkg/<tool_name>/`
3. **Creates symlinks** for all executables in `~/.local/bin/getpkg/`
4. **Ensures PATH** includes `~/.local/bin/getpkg` (one-time setup)
5. **Enables bash completion** for the tool
6. **Runs setup** if a `setup_script.sh` exists
7. **Stores metadata** in `~/.config/getpkg/<tool_name>.json`
### Architecture Support
getpkg supports multiple architectures:
- `x86_64` (Intel/AMD 64-bit)
- `aarch64` (ARM 64-bit)
- `universal` (cross-platform tools)
Tools are automatically downloaded for your architecture, with fallback to universal versions.
### File Locations
- **Tool files**: `~/.getpkg/<tool_name>/` (actual tool installation)
- **Executable symlinks**: `~/.local/bin/getpkg/` (in your PATH)
- **Configuration**: `~/.config/getpkg/`
- **PATH setup**: `~/.bashrc_getpkg` (sourced by `~/.bashrc`)
## Examples
### Installing Popular Tools
```bash
# Install available tools
getpkg install dehydrate # File to C++ code generator
getpkg install bb64 # Bash base64 encoder/decoder
# Development tools (for repository development)
getpkg install whatsdirty # Check git repo status
getpkg install sos # Simple object storage client
getpkg install gp # Git push utility
```
### Publishing Your Own Tools
```bash
# Set your publishing token
export SOS_WRITE_TOKEN="your-token-here"
# Create a new tool project
getpkg create mytool ./mytool-project
# Publish architecture-specific build
getpkg publish mytool:x86_64 ./build/
# Publish universal tool
getpkg publish mytool ./build/
# Remove published tool
getpkg unpublish mytool:x86_64
```
### Development Workflow
```bash
# Create tool structure
getpkg create awesome-tool ./awesome-tool
cd awesome-tool
# Build your tool...
# Add executable to the directory
# Test locally
./awesome-tool --version
# Publish when ready
getpkg publish awesome-tool:x86_64 .
```
## Environment Variables
- **`SOS_WRITE_TOKEN`** - Authentication token for publishing tools
## Troubleshooting
### Tool Not Found
If a tool isn't found after installation, ensure your shell has loaded the new PATH:
```bash
source ~/.bashrc
```
### Permission Issues
getpkg installs to your home directory and doesn't require root access. If you encounter permission issues, check that `~/.local/bin/` is writable.
### Network Issues
All tools are downloaded from `getpkg.xyz`. Ensure you have internet connectivity and the domain is accessible.
## Development
### Building getpkg
```bash
# Build debug version
cd getpkg && ./build.sh
# Run tests
cd getpkg && ./test.sh
# Publish (requires SOS_WRITE_TOKEN)
cd getpkg && ./publish.sh
```
### Tool Development
When creating tools for getpkg:
1. Create a directory with your tool binary
2. Optionally include a `setup_script.sh` for post-install setup
3. The tool should support `version` and `autocomplete` subcommands
4. Use `getpkg publish` to upload to the registry
### Testing
The test script creates all temporary files and directories in `test_temp/` to keep the main directory clean:
```bash
# Run tests
./test.sh
# Clean up orphaned test files from old test runs (one-time)
bash cleanup_old_test_files.sh
# Clean up orphaned test packages from getpkg.xyz
bash cleanup_test_packages.sh
```
For more details, see the development documentation in each tool's directory.

View File

@ -3,7 +3,7 @@ set -euo pipefail
# Get script directory - handle different execution contexts
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PROJECT="$(basename "$(dirname "${SCRIPT_DIR}")")"
PROJECT="$(basename "${SCRIPT_DIR}")"
# Debug output for CI
echo "${PROJECT} build script running from: ${SCRIPT_DIR}"

98
getpkg/cleanup_test_packages.sh Executable file
View File

@ -0,0 +1,98 @@
#!/bin/bash
# Cleanup script for orphaned test packages from getpkg testing
# This script removes test packages that start with "test-" from getpkg.xyz
# Run from the getpkg directory: bash cleanup_test_packages.sh
set -euo pipefail
GETPKG="./output/getpkg"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${YELLOW}Cleaning up orphaned test packages...${NC}"
# Check if getpkg binary exists
if [ ! -f "$GETPKG" ]; then
echo -e "${RED}Error: getpkg binary not found at $GETPKG${NC}"
echo "Please run ./build.sh first to build getpkg"
exit 1
fi
# Check if SOS_WRITE_TOKEN is set
if [ -z "${SOS_WRITE_TOKEN:-}" ]; then
echo -e "${RED}Error: SOS_WRITE_TOKEN environment variable is not set${NC}"
echo "This token is required to unpublish packages from getpkg.xyz"
exit 1
fi
echo "Using getpkg binary: $GETPKG"
echo "SOS_WRITE_TOKEN is set (${#SOS_WRITE_TOKEN} characters)"
# Get list of all packages from /dir endpoint
echo "Fetching package list from getpkg.xyz/dir..."
DIR_RESPONSE=$(curl -s "https://getpkg.xyz/dir" 2>/dev/null || echo "")
if [ -z "$DIR_RESPONSE" ]; then
echo -e "${RED}Failed to fetch package list from server${NC}"
exit 1
fi
# Extract test package labeltags from JSON response
# Try with jq first, fallback to grep/sed if jq is not available
if command -v jq >/dev/null 2>&1; then
TEST_PACKAGES=$(echo "$DIR_RESPONSE" | jq -r '.entries[]?.labeltags[]? // empty' 2>/dev/null | grep "^test-" | sort -u || echo "")
else
# Fallback: extract labeltags using grep and sed (less reliable but works without jq)
TEST_PACKAGES=$(echo "$DIR_RESPONSE" | grep -o '"test-[^"]*"' | sed 's/"//g' | sort -u || echo "")
fi
if [ -z "$TEST_PACKAGES" ]; then
echo -e "${GREEN}No test packages found to clean up${NC}"
exit 0
fi
echo -e "\n${YELLOW}Found test packages to clean up:${NC}"
echo "$TEST_PACKAGES" | while read -r package; do
echo " - $package"
done
echo -e "\n${YELLOW}Cleaning up test packages...${NC}"
CLEANED_COUNT=0
FAILED_COUNT=0
# Use process substitution to avoid subshell issues
while IFS= read -r package; do
if [ -n "$package" ]; then
echo -n "Cleaning up $package... "
# Try to unpublish the package (temporarily disable set -e)
set +e
$GETPKG unpublish "$package" >/dev/null 2>&1
UNPUBLISH_RESULT=$?
set -e
if [ $UNPUBLISH_RESULT -eq 0 ]; then
echo -e "${GREEN}OK${NC}"
((CLEANED_COUNT++))
else
echo -e "${RED}FAILED${NC}"
((FAILED_COUNT++))
fi
fi
done <<< "$TEST_PACKAGES"
echo -e "\n${YELLOW}Cleanup Summary:${NC}"
echo "Packages cleaned: $CLEANED_COUNT"
echo "Failed cleanups: $FAILED_COUNT"
if [ $FAILED_COUNT -eq 0 ]; then
echo -e "${GREEN}All test packages cleaned up successfully!${NC}"
else
echo -e "${YELLOW}Some packages failed to clean up. They may need manual removal.${NC}"
fi

View File

@ -1 +0,0 @@
Debug content

View File

@ -1150,6 +1150,85 @@ void show_help() {
std::cout << " ~/.local/bin/getpkg/ Installed tool binaries" << std::endl;
}
int autocomplete_command(int argc, char* argv[]) {
std::vector<std::string> args(argv + 2, argv + argc);
// If no arguments, return all commands
if (args.empty()) {
std::cout << "install\n";
std::cout << "uninstall\n";
std::cout << "publish\n";
std::cout << "unpublish\n";
std::cout << "update\n";
std::cout << "version\n";
std::cout << "create\n";
std::cout << "hash\n";
std::cout << "list\n";
std::cout << "clean\n";
std::cout << "help\n";
return 0;
}
const std::string& subcommand = args[0];
// Handle autocompletion for specific commands
if (subcommand == "install") {
// For install, we could suggest popular packages or recently published ones
// For now, just return empty (no specific completions)
return 0;
} else if (subcommand == "uninstall") {
// For uninstall, list installed tools
std::filesystem::path configDir = std::filesystem::path(std::getenv("HOME")) / ".config" / "getpkg";
if (std::filesystem::exists(configDir)) {
for (const auto& entry : std::filesystem::directory_iterator(configDir)) {
if (entry.path().extension() == ".json") {
std::string toolName = entry.path().stem().string();
std::cout << toolName << "\n";
}
}
}
return 0;
} else if (subcommand == "publish") {
// For publish, suggest architecture suffixes after tool name
if (args.size() >= 2) {
// If we have tool_name already, suggest architectures
std::cout << "x86_64\n";
std::cout << "aarch64\n";
std::cout << "universal\n";
}
return 0;
} else if (subcommand == "unpublish") {
// For unpublish, list installed tools (similar to uninstall)
std::filesystem::path configDir = std::filesystem::path(std::getenv("HOME")) / ".config" / "getpkg";
if (std::filesystem::exists(configDir)) {
for (const auto& entry : std::filesystem::directory_iterator(configDir)) {
if (entry.path().extension() == ".json") {
std::string toolName = entry.path().stem().string();
std::cout << toolName << "\n";
// Also suggest with architecture suffixes
std::cout << toolName << ":x86_64\n";
std::cout << toolName << ":aarch64\n";
std::cout << toolName << ":universal\n";
}
}
}
return 0;
} else if (subcommand == "create") {
// For create, no specific completions (tool name and directory are user-defined)
return 0;
} else if (subcommand == "hash") {
// For hash, suggest file extensions
if (args.size() >= 2) {
std::cout << "*.tgz\n";
std::cout << "*.tar.gz\n";
}
return 0;
}
// No specific completions for other commands
return 0;
}
} // end anonymous namespace
int main(int argc, char* argv[]) {
@ -1169,19 +1248,7 @@ int main(int argc, char* argv[]) {
} else if (command == "update") {
return update_tool(argc, argv);
} else if (command == "autocomplete") {
std::vector<std::string> args(argv + 2, argv + argc);
if (args.empty()) std::cout << R"(install
uninstall
publish
unpublish
update
version
create
hash
list
clean
help
)";
return autocomplete_command(argc, argv);
} else if (command == "version") {
std::cout << dropshell::VERSION << std::endl;
} else if (command == "create") {

View File

@ -1 +0,0 @@
test

View File

@ -1,7 +0,0 @@
#\!/bin/bash
if [ "$1" = "version" ]; then
echo "1.0.0"
elif [ "$1" = "autocomplete" ]; then
echo "help"
echo "version"
fi

View File

@ -1,7 +0,0 @@
#\!/bin/bash
if [ "$1" = "version" ]; then
echo "1.0.0"
elif [ "$1" = "autocomplete" ]; then
echo "help"
echo "version"
fi

View File

@ -68,6 +68,28 @@ cleanup() {
# Clean up noarch variant
$GETPKG unpublish "${TEST_TOOL_NAME}-noarch:universal" 2>/dev/null || true
# Clean up any remaining test packages that start with "test-"
echo "Cleaning up any remaining test packages..."
DIR_RESPONSE=$(curl -s "https://getpkg.xyz/dir" 2>/dev/null || echo "")
if [ -n "$DIR_RESPONSE" ]; then
# Extract test package labeltags from JSON response
if command -v jq >/dev/null 2>&1; then
TEST_PACKAGES=$(echo "$DIR_RESPONSE" | jq -r '.entries[]?.labeltags[]? // empty' 2>/dev/null | grep "^test-" | sort -u || echo "")
else
# Fallback: extract labeltags using grep and sed
TEST_PACKAGES=$(echo "$DIR_RESPONSE" | grep -o '"test-[^"]*"' | sed 's/"//g' | sort -u || echo "")
fi
if [ -n "$TEST_PACKAGES" ]; then
echo "$TEST_PACKAGES" | while read -r package; do
if [ -n "$package" ]; then
echo " Cleaning up orphaned test package: $package"
$GETPKG unpublish "$package" 2>/dev/null || true
fi
done
fi
fi
echo "Cleaned up test tools from getpkg.xyz"
else
echo "Note: SOS_WRITE_TOKEN not set, cannot clean up remote test objects"

View File

@ -1 +0,0 @@
#!/bin/bash\necho debug

View File

@ -1 +0,0 @@
#!/bin/bash\necho debug2

View File

@ -1 +0,0 @@
#!/bin/bash\necho display test

View File

@ -1 +0,0 @@
#!/bin/bash\necho multi arch

View File

@ -1 +0,0 @@
#!/bin/bash\necho robust test

View File

@ -1 +0,0 @@
test content

187
gp/gp
View File

@ -49,27 +49,43 @@ EOF
# Function to generate commit message based on changes
generate_commit_message() {
local files_changed
files_changed=$(git diff --cached --name-only)
local files_count
files_count=$(echo "$files_changed" | wc -l)
if [ -z "$files_changed" ]; then
files_changed=$(git diff --name-only)
files_count=$(echo "$files_changed" | wc -l)
# First check if we have staged changes
local has_staged_changes=false
if ! git diff --cached --quiet; then
has_staged_changes=true
fi
# If add-all is enabled, also include untracked files
if [ "$ADD_ALL" = true ] && [ -z "$files_changed" ]; then
files_changed=$(git ls-files --others --exclude-standard)
files_count=$(echo "$files_changed" | wc -l)
# Determine which changes to analyze based on staging status and ADD_ALL setting
local status_command=""
if [ "$has_staged_changes" = true ]; then
status_command="git diff --cached --name-status"
else
status_command="git diff --name-status"
fi
if [ -z "$files_changed" ]; then
# Get all changes (staged or unstaged depending on context)
local all_changes
all_changes=$($status_command)
# If no changes from diff, check for untracked files when add-all is enabled
if [ -z "$all_changes" ] && [ "$ADD_ALL" = true ]; then
local untracked_files
untracked_files=$(git ls-files --others --exclude-standard)
if [ -n "$untracked_files" ]; then
# Convert untracked files to "A" (added) status format
all_changes=$(echo "$untracked_files" | sed 's/^/A\t/')
fi
fi
if [ -z "$all_changes" ]; then
echo "No changes to commit"
return 1
fi
# Count total files
local files_count
files_count=$(echo "$all_changes" | wc -l)
# Generate smart commit message based on file types and changes
local has_source_files=false
local has_config_files=false
@ -77,7 +93,8 @@ generate_commit_message() {
local has_tests=false
local message=""
while IFS= read -r file; do
# Extract just the filenames for type detection
while IFS=$'\t' read -r status file; do
[ -z "$file" ] && continue
case "$file" in
@ -94,15 +111,18 @@ generate_commit_message() {
has_tests=true
;;
esac
done <<< "$files_changed"
done <<< "$all_changes"
# Create descriptive commit message
if [ "$files_count" -eq 1 ]; then
local change_line
change_line=$(echo "$all_changes" | head -1)
local status
local single_file
single_file=$(echo "$files_changed" | head -1)
local change_type
change_type=$(git diff --cached --name-status -- "$single_file" 2>/dev/null || git diff --name-status -- "$single_file")
case "${change_type:0:1}" in
status=$(echo "$change_line" | cut -f1)
single_file=$(echo "$change_line" | cut -f2)
case "${status:0:1}" in
A) message="Add $single_file" ;;
M) message="Update $single_file" ;;
D) message="Remove $single_file" ;;
@ -110,6 +130,58 @@ generate_commit_message() {
*) message="Modify $single_file" ;;
esac
else
# For multiple files, analyze the types of changes
local added_count=0
local modified_count=0
local deleted_count=0
local renamed_count=0
# Use the all_changes variable we already have
# Count different types of changes
while IFS=$'\t' read -r status file; do
[ -z "$status" ] && continue
case "${status:0:1}" in
A) ((added_count++)) ;;
M) ((modified_count++)) ;;
D) ((deleted_count++)) ;;
R) ((renamed_count++)) ;;
esac
done <<< "$all_changes"
# Also count untracked files if add-all is enabled
if [ "$ADD_ALL" = true ]; then
local untracked_files
untracked_files=$(git ls-files --others --exclude-standard)
if [ -n "$untracked_files" ]; then
local untracked_count
untracked_count=$(echo "$untracked_files" | wc -l)
((added_count += untracked_count))
fi
fi
# Generate message based on change types
local change_parts=()
[ $added_count -gt 0 ] && change_parts+=("add $added_count")
[ $modified_count -gt 0 ] && change_parts+=("update $modified_count")
[ $deleted_count -gt 0 ] && change_parts+=("remove $deleted_count")
[ $renamed_count -gt 0 ] && change_parts+=("rename $renamed_count")
local change_desc=""
if [ ${#change_parts[@]} -eq 1 ]; then
change_desc="${change_parts[0]}"
elif [ ${#change_parts[@]} -eq 2 ]; then
change_desc="${change_parts[0]} and ${change_parts[1]}"
else
# Join all but last with commas, last with "and"
local last_idx=$((${#change_parts[@]} - 1))
for i in $(seq 0 $((last_idx - 1))); do
[ $i -gt 0 ] && change_desc+=", "
change_desc+="${change_parts[i]}"
done
change_desc+=" and ${change_parts[last_idx]}"
fi
local prefix=""
if $has_tests; then
prefix="test: "
@ -121,7 +193,10 @@ generate_commit_message() {
prefix="feat: "
fi
message="${prefix}Update $files_count files"
# Capitalize first letter of change description
change_desc="$(echo "${change_desc:0:1}" | tr '[:lower:]' '[:upper:]')${change_desc:1}"
message="${prefix}${change_desc} files"
fi
echo "$message"
@ -225,19 +300,77 @@ show_status_and_confirm() {
# Show staged changes
if ! git diff --cached --quiet; then
print_info "Staged changes:"
git diff --cached --name-only -- | while IFS= read -r line; do echo " $line"; done
local staged_modified=""
local staged_deleted=""
local staged_added=""
# Get staged file status and categorize
while IFS=$'\t' read -r status file; do
[ -z "$status" ] && continue
case "${status:0:1}" in
A) staged_added="${staged_added}${file}\n" ;;
M) staged_modified="${staged_modified}${file}\n" ;;
D) staged_deleted="${staged_deleted}${file}\n" ;;
*) staged_modified="${staged_modified}${file}\n" ;; # Default to modified for other statuses
esac
done < <(git diff --cached --name-status)
# Show staged added files
if [ -n "$staged_added" ]; then
print_info "Staged new files:"
echo -e "$staged_added" | grep -v '^$' | while IFS= read -r line; do echo " $line"; done
fi
# Show staged modified files
if [ -n "$staged_modified" ]; then
print_info "Staged modified files:"
echo -e "$staged_modified" | grep -v '^$' | while IFS= read -r line; do echo " $line"; done
fi
# Show staged deleted files
if [ -n "$staged_deleted" ]; then
print_info "Staged deleted files:"
echo -e "$staged_deleted" | grep -v '^$' | while IFS= read -r line; do echo " $line"; done
fi
has_staged_changes=true
fi
# Show unstaged changes
if ! git diff --quiet; then
if [ "$ADD_ALL" = true ]; then
print_info "Modified files (will be added):"
else
print_info "Modified files (unstaged, will NOT be included):"
local modified_files=""
local deleted_files=""
# Get file status and categorize
while IFS=$'\t' read -r status file; do
[ -z "$status" ] && continue
case "${status:0:1}" in
M) modified_files="${modified_files}${file}\n" ;;
D) deleted_files="${deleted_files}${file}\n" ;;
*) modified_files="${modified_files}${file}\n" ;; # Default to modified for other statuses
esac
done < <(git diff --name-status)
# Show modified files
if [ -n "$modified_files" ]; then
if [ "$ADD_ALL" = true ]; then
print_info "Modified files (will be added):"
else
print_info "Modified files (unstaged, will NOT be included):"
fi
echo -e "$modified_files" | grep -v '^$' | while IFS= read -r line; do echo " $line"; done
fi
git diff --name-only -- | while IFS= read -r line; do echo " $line"; done
# Show deleted files
if [ -n "$deleted_files" ]; then
if [ "$ADD_ALL" = true ]; then
print_info "Deleted files (will be removed):"
else
print_info "Deleted files (unstaged, will NOT be included):"
fi
echo -e "$deleted_files" | grep -v '^$' | while IFS= read -r line; do echo " $line"; done
fi
has_unstaged_changes=true
fi

View File

@ -25,6 +25,7 @@ GETPKG="${SCRIPT_DIR}/../getpkg/output/getpkg"
TOOLDIR="${SCRIPT_DIR}/tool"
mkdir -p "${TOOLDIR}"
cp "${SCRIPT_DIR}/whatsdirty" "${TOOLDIR}/whatsdirty"
cp "${SCRIPT_DIR}/setup_script.sh" "${TOOLDIR}/"
# publish universal tool.
"${GETPKG}" publish "whatsdirty" "${TOOLDIR}"