From 63171aea031511765dad935d6b35b8d1574339c0 Mon Sep 17 00:00:00 2001 From: source_weaver_3 Date: Sun, 19 Apr 2026 09:09:28 +0000 Subject: [PATCH] citizen: implement Implement: Serves as the entry point that imports and wires together all other modules --- contracts/RepositoryExplorer.sol | 136 +++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 contracts/RepositoryExplorer.sol diff --git a/contracts/RepositoryExplorer.sol b/contracts/RepositoryExplorer.sol new file mode 100644 index 0000000..226ff6f --- /dev/null +++ b/contracts/RepositoryExplorer.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./Repository.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; + +contract RepositoryExplorer is Ownable, ReentrancyGuard { + Repository[] public repositories; + mapping(address => bool) public registeredRepositories; + uint256 public totalRepositories; + + event RepositoryAdded(address indexed repositoryAddress, uint256 indexed repositoryId); + event RepositoryRemoved(address indexed repositoryAddress, uint256 indexed repositoryId); + + constructor() Ownable(msg.sender) {} + + function createRepository( + string memory name, + string memory description, + address[] memory initialContributors + ) external nonReentrant returns (address) { + require(bytes(name).length > 0, "Repository name cannot be empty"); + require(bytes(description).length > 0, "Repository description cannot be empty"); + + Repository newRepository = new Repository( + name, + description, + initialContributors, + msg.sender + ); + + address repositoryAddress = address(newRepository); + repositories.push(newRepository); + registeredRepositories[repositoryAddress] = true; + totalRepositories++; + + emit RepositoryAdded(repositoryAddress, totalRepositories - 1); + return repositoryAddress; + } + + function removeRepository(uint256 repositoryId) external onlyOwner { + require(repositoryId < repositories.length, "Invalid repository ID"); + + Repository repository = repositories[repositoryId]; + address repositoryAddress = address(repository); + + require(registeredRepositories[repositoryAddress], "Repository not registered"); + + // Remove repository by replacing with last element and reducing array length + repositories[repositoryId] = repositories[repositories.length - 1]; + repositories.pop(); + + registeredRepositories[repositoryAddress] = false; + totalRepositories--; + + emit RepositoryRemoved(repositoryAddress, repositoryId); + } + + function getRepositoryDetails(uint256 repositoryId) + external + view + returns ( + string memory name, + string memory description, + address owner, + uint256 contributorCount + ) + { + require(repositoryId < repositories.length, "Invalid repository ID"); + Repository repository = repositories[repositoryId]; + + return ( + repository.getName(), + repository.getDescription(), + repository.owner(), + repository.getContributorCount() + ); + } + + function listRepositories() external view returns (Repository[] memory) { + return repositories; + } + + function searchRepositoriesByName(string memory searchTerm) + external + view + returns (Repository[] memory) + { + Repository[] memory matchingRepositories = new Repository[](repositories.length); + uint256 matchCount = 0; + + for (uint256 i = 0; i < repositories.length; i++) { + if (containsSearchTerm(repositories[i].getName(), searchTerm)) { + matchingRepositories[matchCount] = repositories[i]; + matchCount++; + } + } + + // Trim array to actual matches + Repository[] memory trimmedResults = new Repository[](matchCount); + for (uint256 i = 0; i < matchCount; i++) { + trimmedResults[i] = matchingRepositories[i]; + } + + return trimmedResults; + } + + function containsSearchTerm(string memory source, string memory searchTerm) + internal + pure + returns (bool) + { + bytes memory sourceBytes = bytes(source); + bytes memory searchBytes = bytes(searchTerm); + + if (sourceBytes.length < searchBytes.length) { + return false; + } + + for (uint256 i = 0; i <= sourceBytes.length - searchBytes.length; i++) { + bool found = true; + for (uint256 j = 0; j < searchBytes.length; j++) { + if (sourceBytes[i + j] != searchBytes[j]) { + found = false; + break; + } + } + if (found) { + return true; + } + } + + return false; + } +} \ No newline at end of file