feat: suppot multiple repos

main
cyl19970726 2 years ago
parent 6823e4df65
commit 8a76ef124e

@ -21,13 +21,14 @@ contract Git3 is LargeStorageManager {
mapping(bytes => address) public repoNameToOwner;
mapping(bytes => refInfo) public nameToRefInfo; // dev => {hash: 0x1234..., index: 1 }
bytes[] public refs; // [main, dev, test, staging]
mapping(bytes => bytes[]) public repoNameToRefs; // [main, dev, test, staging]
function _convertRefInfo(
bytes memory repoName,
refInfo memory info
) internal view returns (refData memory res) {
res.hash = info.hash;
res.name = refs[info.index];
res.name = repoNameToRefs[repoName][info.index];
}
constructor() LargeStorageManager(0) {}
@ -45,20 +46,16 @@ contract Git3 is LargeStorageManager {
return _get(keccak256(bytes.concat(repoName, "/", path)));
}
function _createRepo(bytes memory repoName) internal {
if (repoNameToOwner[repoName] == address(0)) {
repoNameToOwner[repoName] = msg.sender;
} else {
require(repoNameToOwner[repoName] == msg.sender, "only owner");
}
function createRepo(bytes memory repoName) external{
require(repoNameToOwner[repoName] == address(0),"RepoName already exist");
repoNameToOwner[repoName] = msg.sender;
}
function upload(
bytes memory repoName,
bytes memory path,
bytes calldata data
) external payable {
_createRepo(repoName);
) external payable onlyOwner(repoName){
_putChunkFromCalldata(
keccak256(bytes.concat(repoName, "/", path)),
0,
@ -72,8 +69,7 @@ contract Git3 is LargeStorageManager {
bytes memory path,
uint256 chunkId,
bytes calldata data
) external payable {
_createRepo(repoName);
) external payable onlyOwner(repoName){
_putChunkFromCalldata(
keccak256(bytes.concat(repoName, "/", path)),
chunkId,
@ -104,11 +100,10 @@ contract Git3 is LargeStorageManager {
return _countChunks(keccak256(bytes.concat(repoName, "/", name)));
}
function listRefs() public view returns (refData[] memory list) {
// todo: Differentiate all refs corresponding to a repo
list = new refData[](refs.length);
for (uint index = 0; index < refs.length; index++) {
list[index] = _convertRefInfo(nameToRefInfo[refs[index]]);
function listRefs(bytes memory repoName) public view returns (refData[] memory list) {
list = new refData[](repoNameToRefs[repoName].length);
for (uint index = 0; index < repoNameToRefs[repoName].length; index++) {
list[index] = _convertRefInfo(repoName,nameToRefInfo[repoNameToRefs[repoName][index]]);
}
}
@ -116,14 +111,12 @@ contract Git3 is LargeStorageManager {
bytes memory repoName,
bytes memory name,
bytes20 refHash
) public {
) public onlyOwner(repoName){
bytes memory fullName = bytes.concat(repoName, "/", name);
// only execute `sload` once to reduce gas consumption
refInfo memory srs;
srs = nameToRefInfo[fullName];
uint256 refsLen = refs.length;
_createRepo(repoName);
uint256 refsLen = repoNameToRefs[repoName].length;
if (srs.hash == bytes20(0)) {
// store refHash for the first time
@ -135,7 +128,7 @@ contract Git3 is LargeStorageManager {
nameToRefInfo[fullName].hash = refHash;
nameToRefInfo[fullName].index = uint96(refsLen);
refs.push(fullName);
repoNameToRefs[repoName].push(fullName);
} else {
// only update refHash
nameToRefInfo[fullName].hash = refHash;
@ -150,7 +143,7 @@ contract Git3 is LargeStorageManager {
// only execute `sload` once to reduce gas consumption
refInfo memory srs;
srs = nameToRefInfo[fullName];
uint256 refsLen = refs.length;
uint256 refsLen = repoNameToRefs[repoName].length;
require(
srs.hash != bytes20(0),
@ -159,10 +152,10 @@ contract Git3 is LargeStorageManager {
require(srs.index < refsLen, "System Error: Invalid index");
if (srs.index < refsLen - 1) {
refs[srs.index] = refs[refsLen - 1];
nameToRefInfo[refs[refsLen - 1]].index = srs.index;
repoNameToRefs[repoName][srs.index] = repoNameToRefs[repoName][refsLen - 1];
nameToRefInfo[repoNameToRefs[repoName][refsLen - 1]].index = srs.index;
}
refs.pop();
repoNameToRefs[repoName].pop();
delete nameToRefInfo[fullName];
}
}

@ -13,7 +13,8 @@ describe("Git3 Test", function () {
let singer;
[singer] = await ethers.getSigners();
console.log("singer", singer.address);
await git3.createRepo("0x11");
await git3.upload("0x11", "0x616263", "0x112233");
expect(await git3.download("0x11", "0x616263")).to.eql(["0x112233", true]);
@ -39,6 +40,8 @@ describe("Git3 Test", function () {
const git3 = await Git3.deploy();
await git3.deployed();
await git3.createRepo("0x11");
expect(await git3.countChunks("0x11", "0x616263")).to.eql(ToBig(0));
let data0 = Array.from({ length: 10 }, () =>
@ -71,6 +74,8 @@ describe("Git3 Test", function () {
await git3.deployed();
let repoName = "0x11";
await git3.createRepo(repoName);
function concatHexStr(s1, s2) {
return s1.concat("2f").concat(s2.slice(2));
}
@ -87,7 +92,7 @@ describe("Git3 Test", function () {
let data2 = "0xcccccccccccccccccccccccccccccccccccccccc";
await git3.setRef(repoName, key2, data2);
let refs = await git3.listRefs();
let refs = await git3.listRefs(repoName);
expect(refs[0]).to.eql([data0, concatHexStr(repoName, key0)]);
expect(refs[1]).to.eql([data1, concatHexStr(repoName, key1)]);
expect(refs[2]).to.eql([data2, concatHexStr(repoName, key2)]);
@ -95,20 +100,43 @@ describe("Git3 Test", function () {
// check delRef
await git3.delRef(repoName, key0);
refs = await git3.listRefs();
refs = await git3.listRefs(repoName);
expect(refs[0]).to.eql([data2, concatHexStr(repoName, key2)]);
expect(refs[1]).to.eql([data1, concatHexStr(repoName, key1)]);
expect(refs.length).to.eql(2);
await git3.delRef(repoName, key1);
refs = await git3.listRefs();
refs = await git3.listRefs(repoName);
expect(refs[0]).to.eql([data2, concatHexStr(repoName, key2)]);
expect(refs.length).to.eql(1);
// check update
let data3 = "0xdddddddddddddddddddddddddddddddddddddddd";
await git3.setRef(repoName, key2, data3);
refs = await git3.listRefs();
refs = await git3.listRefs(repoName);
expect(refs[0]).to.eql([data3, concatHexStr(repoName, key2)]);
});
it("Access Control", async function () {
const Git3 = await ethers.getContractFactory("Git3");
const git3 = await Git3.deploy();
await git3.deployed();
let singer;
let user1;
[singer,user1,] = await ethers.getSigners();
await git3.connect(singer).createRepo("0x11");
await expect(git3.connect(user1).upload("0x11", "0x616263", "0x112233")).to.be.revertedWith("only owner");
await expect(git3.connect(user1).uploadChunk("0x11", "0x616263", 0,"0x112233")).to.be.revertedWith("only owner");
await expect(git3.connect(user1).setRef("0x11", "0x616263", "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")).to.be.revertedWith("only owner");
await git3.connect(singer).upload("0x11", "0x616263", "0x112233")
expect(await git3.download("0x11", "0x616263")).to.eql(["0x112233", true]);
await git3.connect(singer).setRef("0x11", "0x616263", "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
await expect(git3.connect(user1).remove("0x11", "0x616263")).to.be.revertedWith("only owner");
await expect(git3.connect(user1).delRef("0x11", "0x616263")).to.be.revertedWith("only owner");
});
});

Loading…
Cancel
Save