136 lines
4.4 KiB
Solidity
136 lines
4.4 KiB
Solidity
// 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;
|
|
}
|
|
} |