run.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. #!/usr/bin/env node
  2. const cp = require('child_process');
  3. const fs = require('fs');
  4. const path = require('path');
  5. const format = require('./format-lines');
  6. function getVersion(path) {
  7. try {
  8. return fs.readFileSync(path, 'utf8').match(/\/\/ OpenZeppelin Contracts \(last updated v[^)]+\)/)[0];
  9. } catch {
  10. return null;
  11. }
  12. }
  13. function generateFromTemplate(file, template, outputPrefix = '', lint = false) {
  14. const script = path.relative(path.join(__dirname, '../..'), __filename);
  15. const input = path.join(path.dirname(script), template);
  16. const output = path.join(outputPrefix, file);
  17. const version = getVersion(output);
  18. const content = format(
  19. '// SPDX-License-Identifier: MIT',
  20. ...(version ? [version + ` (${file})`] : []),
  21. `// This file was procedurally generated from ${input}.`,
  22. '',
  23. require(template).trimEnd(),
  24. );
  25. fs.writeFileSync(output, content);
  26. lint && cp.execFileSync('prettier', ['--write', output]);
  27. }
  28. // Some templates needs to go through the linter after generation
  29. const needsLinter = ['utils/structs/EnumerableMap.sol'];
  30. // Contracts
  31. for (const [file, template] of Object.entries({
  32. 'utils/cryptography/MerkleProof.sol': './templates/MerkleProof.js',
  33. 'utils/math/SafeCast.sol': './templates/SafeCast.js',
  34. 'utils/structs/Checkpoints.sol': './templates/Checkpoints.js',
  35. 'utils/structs/EnumerableSet.sol': './templates/EnumerableSet.js',
  36. 'utils/structs/EnumerableMap.sol': './templates/EnumerableMap.js',
  37. 'utils/SlotDerivation.sol': './templates/SlotDerivation.js',
  38. 'utils/StorageSlot.sol': './templates/StorageSlot.js',
  39. 'utils/TransientSlot.sol': './templates/TransientSlot.js',
  40. 'utils/Arrays.sol': './templates/Arrays.js',
  41. 'utils/Packing.sol': './templates/Packing.js',
  42. 'mocks/StorageSlotMock.sol': './templates/StorageSlotMock.js',
  43. 'mocks/TransientSlotMock.sol': './templates/TransientSlotMock.js',
  44. })) {
  45. generateFromTemplate(file, template, './contracts/', needsLinter.includes(file));
  46. }
  47. // Tests
  48. for (const [file, template] of Object.entries({
  49. 'utils/structs/Checkpoints.t.sol': './templates/Checkpoints.t.js',
  50. 'utils/Packing.t.sol': './templates/Packing.t.js',
  51. 'utils/SlotDerivation.t.sol': './templates/SlotDerivation.t.js',
  52. })) {
  53. generateFromTemplate(file, template, './test/', needsLinter.includes(file));
  54. }