diff --git a/contracts/Git3.sol b/contracts/Git3.sol index cd50ced..498709f 100644 --- a/contracts/Git3.sol +++ b/contracts/Git3.sol @@ -46,8 +46,26 @@ contract Git3 is LargeStorageManager { return _get(keccak256(bytes.concat(repoName, "/", path))); } - function createRepo(bytes memory repoName) external{ - require(repoNameToOwner[repoName] == address(0),"RepoName already exist"); + function createRepo(bytes memory repoName) external { + require( + repoName.length > 0 && repoName.length <= 100, + "RepoName length must be 1-100" + ); + for (uint i; i < repoName.length; i++) { + bytes1 char = repoName[i]; + require( + (char >= 0x61 && char <= 0x7A) || //a-z + (char >= 0x41 && char <= 0x5A) || //A-Z + (char >= 0x30 && char <= 0x39) || //0-9 + (char == 0x2D || char == 0x2E || char == 0x5F), //-._ + "RepoName must be alphanumeric or -._" + ); + } + + require( + repoNameToOwner[repoName] == address(0), + "RepoName already exist" + ); repoNameToOwner[repoName] = msg.sender; } @@ -55,7 +73,7 @@ contract Git3 is LargeStorageManager { bytes memory repoName, bytes memory path, bytes calldata data - ) external payable onlyOwner(repoName){ + ) external payable onlyOwner(repoName) { _putChunkFromCalldata( keccak256(bytes.concat(repoName, "/", path)), 0, @@ -69,7 +87,7 @@ contract Git3 is LargeStorageManager { bytes memory path, uint256 chunkId, bytes calldata data - ) external payable onlyOwner(repoName){ + ) external payable onlyOwner(repoName) { _putChunkFromCalldata( keccak256(bytes.concat(repoName, "/", path)), chunkId, @@ -100,10 +118,15 @@ contract Git3 is LargeStorageManager { return _countChunks(keccak256(bytes.concat(repoName, "/", name))); } - function listRefs(bytes memory repoName) public view returns (refData[] memory list) { + 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]]); + list[index] = _convertRefInfo( + repoName, + nameToRefInfo[repoNameToRefs[repoName][index]] + ); } } @@ -111,7 +134,7 @@ contract Git3 is LargeStorageManager { bytes memory repoName, bytes memory name, bytes20 refHash - ) public onlyOwner(repoName){ + ) public onlyOwner(repoName) { bytes memory fullName = bytes.concat(repoName, "/", name); // only execute `sload` once to reduce gas consumption refInfo memory srs; @@ -152,8 +175,11 @@ contract Git3 is LargeStorageManager { require(srs.index < refsLen, "System Error: Invalid index"); if (srs.index < refsLen - 1) { - repoNameToRefs[repoName][srs.index] = repoNameToRefs[repoName][refsLen - 1]; - nameToRefInfo[repoNameToRefs[repoName][refsLen - 1]].index = srs.index; + repoNameToRefs[repoName][srs.index] = repoNameToRefs[repoName][ + refsLen - 1 + ]; + nameToRefInfo[repoNameToRefs[repoName][refsLen - 1]].index = srs + .index; } repoNameToRefs[repoName].pop(); delete nameToRefInfo[fullName]; diff --git a/test/git3-test.js b/test/git3-test.js index a60ddb5..c28fb77 100644 --- a/test/git3-test.js +++ b/test/git3-test.js @@ -13,26 +13,27 @@ describe("Git3 Test", function () { let singer; [singer] = await ethers.getSigners(); + const repoName = Buffer.from("test"); - await git3.createRepo("0x11"); + await git3.createRepo(repoName); - await git3.upload("0x11", "0x616263", "0x112233"); - expect(await git3.download("0x11", "0x616263")).to.eql(["0x112233", true]); + await git3.upload(repoName, "0x616263", "0x112233"); + expect(await git3.download(repoName, "0x616263")).to.eql(["0x112233", true]); let data = Array.from({ length: 40 }, () => Math.floor(Math.random() * 256) ); - await git3.upload("0x11", "0x616263", data); - expect(await git3.download("0x11", "0x616263")).to.eql([ + await git3.upload(repoName, "0x616263", data); + expect(await git3.download(repoName, "0x616263")).to.eql([ ethers.utils.hexlify(data), true, ]); - expect(await git3.size("0x11", "0x616263")).to.eql([ToBig(40), ToBig(1)]); + expect(await git3.size(repoName, "0x616263")).to.eql([ToBig(40), ToBig(1)]); - await git3.remove("0x11", "0x616263"); - expect(await git3.size("0x11", "0x616263")).to.eql([ToBig(0), ToBig(0)]); + await git3.remove(repoName, "0x616263"); + expect(await git3.size(repoName, "0x616263")).to.eql([ToBig(0), ToBig(0)]); }); it("upload/download/remove chunks", async function () { @@ -40,15 +41,16 @@ describe("Git3 Test", function () { const git3 = await Git3.deploy(); await git3.deployed(); - await git3.createRepo("0x11"); + const repoName = Buffer.from("test"); + await git3.createRepo(repoName); - expect(await git3.countChunks("0x11", "0x616263")).to.eql(ToBig(0)); + expect(await git3.countChunks(repoName, "0x616263")).to.eql(ToBig(0)); let data0 = Array.from({ length: 10 }, () => Math.floor(Math.random() * 256) ); - await git3.uploadChunk("0x11", "0x616263", 0, data0); - expect(await git3.download("0x11", "0x616263")).to.eql([ + await git3.uploadChunk(repoName, "0x616263", 0, data0); + expect(await git3.download(repoName, "0x616263")).to.eql([ ethers.utils.hexlify(data0), true, ]); @@ -56,16 +58,16 @@ describe("Git3 Test", function () { let data1 = Array.from({ length: 20 }, () => Math.floor(Math.random() * 256) ); - await git3.uploadChunk("0x11", "0x616263", 1, data1); - expect(await git3.download("0x11", "0x616263")).to.eql([ + await git3.uploadChunk(repoName, "0x616263", 1, data1); + expect(await git3.download(repoName, "0x616263")).to.eql([ ethers.utils.hexlify(data0.concat(data1)), true, ]); - await git3.remove("0x11", "0x616263"); // should succeed - expect(await git3.size("0x11", "0x616263")).to.eql([ToBig(0), ToBig(0)]); - expect(await git3.download("0x11", "0x616263")).to.eql(["0x", false]); - expect(await git3.countChunks("0x11", "0x616263")).to.eql(ToBig(0)); + await git3.remove(repoName, "0x616263"); // should succeed + expect(await git3.size(repoName, "0x616263")).to.eql([ToBig(0), ToBig(0)]); + expect(await git3.download(repoName, "0x616263")).to.eql(["0x", false]); + expect(await git3.countChunks(repoName, "0x616263")).to.eql(ToBig(0)); }); it("set/update/list/remove Reference", async function () { @@ -73,22 +75,22 @@ describe("Git3 Test", function () { const git3 = await Git3.deploy(); await git3.deployed(); - let repoName = "0x11"; + let repoName = Buffer.from("test"); await git3.createRepo(repoName); function concatHexStr(s1, s2) { - return s1.concat("2f").concat(s2.slice(2)); + return "0x" + Buffer.concat([s1, Buffer.from("/"), s2]).toString("hex"); } - let key0 = "0x616263"; + let key0 = Buffer.from("refs/heads/master"); let data0 = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; await git3.setRef(repoName, key0, data0); - let key1 = "0x717273"; + let key1 = Buffer.from("refs/heads/dev"); let data1 = "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"; await git3.setRef(repoName, key1, data1); - let key2 = "0x818283"; + let key2 = Buffer.from("refs/heads/main"); let data2 = "0xcccccccccccccccccccccccccccccccccccccccc"; await git3.setRef(repoName, key2, data2); @@ -124,19 +126,34 @@ describe("Git3 Test", function () { let singer; let user1; - [singer,user1,] = await ethers.getSigners(); + [singer, user1,] = await ethers.getSigners(); + const repoName = Buffer.from("test") + + await git3.connect(singer).createRepo(repoName); - await git3.connect(singer).createRepo("0x11"); + await expect(git3.connect(user1).upload(repoName, "0x616263", "0x112233")).to.be.revertedWith("only owner"); + await expect(git3.connect(user1).uploadChunk(repoName, "0x616263", 0, "0x112233")).to.be.revertedWith("only owner"); + await expect(git3.connect(user1).setRef(repoName, "0x616263", "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")).to.be.revertedWith("only owner"); - 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(repoName, "0x616263", "0x112233") + expect(await git3.download(repoName, "0x616263")).to.eql(["0x112233", true]); + await git3.connect(singer).setRef(repoName, "0x616263", "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + + await expect(git3.connect(user1).remove(repoName, "0x616263")).to.be.revertedWith("only owner"); + await expect(git3.connect(user1).delRef(repoName, "0x616263")).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"); }); + + it("RepoName Check", async function () { + const Git3 = await ethers.getContractFactory("Git3"); + const git3 = await Git3.deploy(); + await git3.deployed(); + + let repoName = Buffer.from("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"); + await git3.createRepo(repoName); + await expect(git3.createRepo(repoName)).to.be.revertedWith("RepoName already exist"); + await expect(git3.createRepo(Buffer.from("a/b"))).to.be.revertedWith("RepoName must be alphanumeric or -._"); + await expect(git3.createRepo(Buffer.from("a".repeat(101)))).to.be.revertedWith("RepoName length must be 1-100"); + + }) });