From 21e6ee470711e38965d63a1c93eb51eb383744b9 Mon Sep 17 00:00:00 2001 From: axe312ger Date: Sat, 29 May 2021 01:17:10 +0200 Subject: [PATCH] switch to filenamify --- dist/restore/index.js | 166 ++++++++++++++++++++++++++++++++++++++++-- dist/save/index.js | 166 ++++++++++++++++++++++++++++++++++++++++-- package-lock.json | 34 ++++++++- package.json | 3 +- src/cache.ts | 15 ++-- 5 files changed, 358 insertions(+), 26 deletions(-) diff --git a/dist/restore/index.js b/dist/restore/index.js index 9d09b01cc..494d9f88b 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -67,6 +67,22 @@ function toCommandValue(input) { exports.toCommandValue = toCommandValue; //# sourceMappingURL=utils.js.map +/***/ }), + +/***/ 83: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const filenamify = __webpack_require__(356); +const filenamifyPath = __webpack_require__(244); + +const filenamifyCombined = filenamify; +filenamifyCombined.path = filenamifyPath; + +module.exports = filenamify; + + /***/ }), /***/ 87: @@ -117,6 +133,25 @@ exports.issueCommand = issueCommand; module.exports = require("child_process"); +/***/ }), + +/***/ 138: +/***/ (function(module) { + +"use strict"; + + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(matchOperatorsRe, '\\$&'); +}; + + /***/ }), /***/ 211: @@ -151,6 +186,72 @@ var Events; exports.RefKey = "GITHUB_REF"; +/***/ }), + +/***/ 244: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(622); +const filenamify = __webpack_require__(356); + +const filenamifyPath = (filePath, options) => { + filePath = path.resolve(filePath); + return path.join(path.dirname(filePath), filenamify(path.basename(filePath), options)); +}; + +module.exports = filenamifyPath; + + +/***/ }), + +/***/ 356: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const trimRepeated = __webpack_require__(567); +const filenameReservedRegex = __webpack_require__(634); +const stripOuter = __webpack_require__(448); + +// Doesn't make sense to have longer filenames +const MAX_FILENAME_LENGTH = 100; + +const reControlChars = /[\u0000-\u001f\u0080-\u009f]/g; // eslint-disable-line no-control-regex +const reRelativePath = /^\.+/; +const reTrailingPeriods = /\.+$/; + +const filenamify = (string, options = {}) => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + + const replacement = options.replacement === undefined ? '!' : options.replacement; + + if (filenameReservedRegex().test(replacement) && reControlChars.test(replacement)) { + throw new Error('Replacement string cannot contain reserved filename characters'); + } + + string = string.replace(filenameReservedRegex(), replacement); + string = string.replace(reControlChars, replacement); + string = string.replace(reRelativePath, replacement); + string = string.replace(reTrailingPeriods, ''); + + if (replacement.length > 0) { + string = trimRepeated(string, replacement); + string = string.length > 1 ? stripOuter(string, replacement) : string; + } + + string = filenameReservedRegex.windowsNames().test(string) ? string + replacement : string; + string = string.slice(0, typeof options.maxLength === 'number' ? options.maxLength : MAX_FILENAME_LENGTH); + + return string; +}; + +module.exports = filenamify; + + /***/ }), /***/ 431: @@ -331,6 +432,25 @@ function getInputAsInt(name, options) { exports.getInputAsInt = getInputAsInt; +/***/ }), + +/***/ 448: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +var escapeStringRegexp = __webpack_require__(138); + +module.exports = function (str, sub) { + if (typeof str !== 'string' || typeof sub !== 'string') { + throw new TypeError(); + } + + sub = escapeStringRegexp(sub); + return str.replace(new RegExp('^' + sub + '|' + sub + '$', 'g'), ''); +}; + + /***/ }), /***/ 470: @@ -576,6 +696,24 @@ function getState(name) { exports.getState = getState; //# sourceMappingURL=core.js.map +/***/ }), + +/***/ 567: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +var escapeStringRegexp = __webpack_require__(138); + +module.exports = function (str, target) { + if (typeof str !== 'string' || typeof target !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(new RegExp('(?:' + escapeStringRegexp(target) + '){2,}', 'g'), target); +}; + + /***/ }), /***/ 622: @@ -583,6 +721,19 @@ exports.getState = getState; module.exports = require("path"); +/***/ }), + +/***/ 634: +/***/ (function(module) { + +"use strict"; + +/* eslint-disable no-control-regex */ +// TODO: remove parens when Node.js 6 is targeted. Node.js 4 barfs at it. +module.exports = () => (/[<>:"\/\\|?*\x00-\x1F]/g); +module.exports.windowsNames = () => (/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i); + + /***/ }), /***/ 669: @@ -606,17 +757,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveCache = exports.restoreCache = exports.ValidationError = exports.ReserveCacheError = void 0; const child_process_1 = __webpack_require__(129); +const filenamify_1 = __importDefault(__webpack_require__(83)); const fs_1 = __webpack_require__(747); const path_1 = __webpack_require__(622); const util_1 = __webpack_require__(669); const execAsync = util_1.promisify(child_process_1.exec); const readDirAsync = util_1.promisify(fs_1.readdir); -function generateCacheName(path) { - return path.replace(/[^a-z0-9]/gi, "_"); -} class ReserveCacheError extends Error { constructor(message) { super(message); @@ -639,8 +791,8 @@ function checkPaths(paths) { } } function checkKey(key) { - if (key.length > 512) { - throw new ValidationError(`Key Validation Error: ${key} cannot be larger than 512 characters.`); + if (key.length > 255) { + throw new ValidationError(`Key Validation Error: ${key} cannot be larger than 255 characters.`); } const regex = /^[^,]*$/; if (!regex.test(key)) { @@ -695,7 +847,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) { // @todo order files by name/date yield streamOutputUntilResolved(mkdirPromise); const cacheFiles = yield readDirAsync(cacheDir); - const potentialCaches = (restoreKeys || [primaryKey]).map(generateCacheName); + const potentialCaches = (restoreKeys || [primaryKey]).map(key => filenamify_1.default(key)); console.log({ cacheFiles, potentialCaches }); const result = locateCache(potentialCaches, cacheFiles); if (typeof result !== "object") { @@ -733,7 +885,7 @@ function saveCache(paths, key, options) { checkKey(key); console.log(JSON.stringify({ env: process.env, paths, key, options }, null, 2)); const cacheDir = path_1.join(`/media/cache/`, process.env.GITHUB_REPOSITORY || ""); - const cacheName = `${generateCacheName(key)}.tar.lz4`; + const cacheName = `${filenamify_1.default(key)}.tar.lz4`; const cachePath = path_1.join(cacheDir, cacheName); const cmd = `mkdir -p ${cacheDir} && tar cf - ${paths.join(" ")} | lz4 -v > ${cachePath}`; console.log({ cacheDir, cacheName, cachePath, cmd }); diff --git a/dist/save/index.js b/dist/save/index.js index 20fef00ea..8e64f963d 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -67,6 +67,22 @@ function toCommandValue(input) { exports.toCommandValue = toCommandValue; //# sourceMappingURL=utils.js.map +/***/ }), + +/***/ 83: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const filenamify = __webpack_require__(356); +const filenamifyPath = __webpack_require__(244); + +const filenamifyCombined = filenamify; +filenamifyCombined.path = filenamifyPath; + +module.exports = filenamify; + + /***/ }), /***/ 87: @@ -117,6 +133,25 @@ exports.issueCommand = issueCommand; module.exports = require("child_process"); +/***/ }), + +/***/ 138: +/***/ (function(module) { + +"use strict"; + + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(matchOperatorsRe, '\\$&'); +}; + + /***/ }), /***/ 211: @@ -151,6 +186,72 @@ var Events; exports.RefKey = "GITHUB_REF"; +/***/ }), + +/***/ 244: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const path = __webpack_require__(622); +const filenamify = __webpack_require__(356); + +const filenamifyPath = (filePath, options) => { + filePath = path.resolve(filePath); + return path.join(path.dirname(filePath), filenamify(path.basename(filePath), options)); +}; + +module.exports = filenamifyPath; + + +/***/ }), + +/***/ 356: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +const trimRepeated = __webpack_require__(567); +const filenameReservedRegex = __webpack_require__(634); +const stripOuter = __webpack_require__(448); + +// Doesn't make sense to have longer filenames +const MAX_FILENAME_LENGTH = 100; + +const reControlChars = /[\u0000-\u001f\u0080-\u009f]/g; // eslint-disable-line no-control-regex +const reRelativePath = /^\.+/; +const reTrailingPeriods = /\.+$/; + +const filenamify = (string, options = {}) => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + + const replacement = options.replacement === undefined ? '!' : options.replacement; + + if (filenameReservedRegex().test(replacement) && reControlChars.test(replacement)) { + throw new Error('Replacement string cannot contain reserved filename characters'); + } + + string = string.replace(filenameReservedRegex(), replacement); + string = string.replace(reControlChars, replacement); + string = string.replace(reRelativePath, replacement); + string = string.replace(reTrailingPeriods, ''); + + if (replacement.length > 0) { + string = trimRepeated(string, replacement); + string = string.length > 1 ? stripOuter(string, replacement) : string; + } + + string = filenameReservedRegex.windowsNames().test(string) ? string + replacement : string; + string = string.slice(0, typeof options.maxLength === 'number' ? options.maxLength : MAX_FILENAME_LENGTH); + + return string; +}; + +module.exports = filenamify; + + /***/ }), /***/ 431: @@ -331,6 +432,25 @@ function getInputAsInt(name, options) { exports.getInputAsInt = getInputAsInt; +/***/ }), + +/***/ 448: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +var escapeStringRegexp = __webpack_require__(138); + +module.exports = function (str, sub) { + if (typeof str !== 'string' || typeof sub !== 'string') { + throw new TypeError(); + } + + sub = escapeStringRegexp(sub); + return str.replace(new RegExp('^' + sub + '|' + sub + '$', 'g'), ''); +}; + + /***/ }), /***/ 470: @@ -576,6 +696,24 @@ function getState(name) { exports.getState = getState; //# sourceMappingURL=core.js.map +/***/ }), + +/***/ 567: +/***/ (function(module, __unusedexports, __webpack_require__) { + +"use strict"; + +var escapeStringRegexp = __webpack_require__(138); + +module.exports = function (str, target) { + if (typeof str !== 'string' || typeof target !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(new RegExp('(?:' + escapeStringRegexp(target) + '){2,}', 'g'), target); +}; + + /***/ }), /***/ 622: @@ -583,6 +721,19 @@ exports.getState = getState; module.exports = require("path"); +/***/ }), + +/***/ 634: +/***/ (function(module) { + +"use strict"; + +/* eslint-disable no-control-regex */ +// TODO: remove parens when Node.js 6 is targeted. Node.js 4 barfs at it. +module.exports = () => (/[<>:"\/\\|?*\x00-\x1F]/g); +module.exports.windowsNames = () => (/^(con|prn|aux|nul|com[0-9]|lpt[0-9])$/i); + + /***/ }), /***/ 669: @@ -698,17 +849,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveCache = exports.restoreCache = exports.ValidationError = exports.ReserveCacheError = void 0; const child_process_1 = __webpack_require__(129); +const filenamify_1 = __importDefault(__webpack_require__(83)); const fs_1 = __webpack_require__(747); const path_1 = __webpack_require__(622); const util_1 = __webpack_require__(669); const execAsync = util_1.promisify(child_process_1.exec); const readDirAsync = util_1.promisify(fs_1.readdir); -function generateCacheName(path) { - return path.replace(/[^a-z0-9]/gi, "_"); -} class ReserveCacheError extends Error { constructor(message) { super(message); @@ -731,8 +883,8 @@ function checkPaths(paths) { } } function checkKey(key) { - if (key.length > 512) { - throw new ValidationError(`Key Validation Error: ${key} cannot be larger than 512 characters.`); + if (key.length > 255) { + throw new ValidationError(`Key Validation Error: ${key} cannot be larger than 255 characters.`); } const regex = /^[^,]*$/; if (!regex.test(key)) { @@ -787,7 +939,7 @@ function restoreCache(paths, primaryKey, restoreKeys, options) { // @todo order files by name/date yield streamOutputUntilResolved(mkdirPromise); const cacheFiles = yield readDirAsync(cacheDir); - const potentialCaches = (restoreKeys || [primaryKey]).map(generateCacheName); + const potentialCaches = (restoreKeys || [primaryKey]).map(key => filenamify_1.default(key)); console.log({ cacheFiles, potentialCaches }); const result = locateCache(potentialCaches, cacheFiles); if (typeof result !== "object") { @@ -825,7 +977,7 @@ function saveCache(paths, key, options) { checkKey(key); console.log(JSON.stringify({ env: process.env, paths, key, options }, null, 2)); const cacheDir = path_1.join(`/media/cache/`, process.env.GITHUB_REPOSITORY || ""); - const cacheName = `${generateCacheName(key)}.tar.lz4`; + const cacheName = `${filenamify_1.default(key)}.tar.lz4`; const cachePath = path_1.join(cacheDir, cacheName); const cmd = `mkdir -p ${cacheDir} && tar cf - ${paths.join(" ")} | lz4 -v > ${cachePath}`; console.log({ cacheDir, cacheName, cachePath, cmd }); diff --git a/package-lock.json b/package-lock.json index aa4f6bf3c..8a0e765de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2109,8 +2109,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "1.14.1", @@ -2670,6 +2669,21 @@ "dev": true, "optional": true }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "http://192.168.42.168:4873/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik=" + }, + "filenamify": { + "version": "4.3.0", + "resolved": "http://192.168.42.168:4873/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -5661,6 +5675,14 @@ "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", "dev": true }, + "strip-outer": { + "version": "1.0.1", + "resolved": "http://192.168.42.168:4873/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5928,6 +5950,14 @@ "punycode": "^2.1.0" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "http://192.168.42.168:4873/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "ts-jest": { "version": "26.5.4", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.4.tgz", diff --git a/package.json b/package.json index 167fe9f17..1ed990dc7 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "@actions/cache": "^1.0.7", "@actions/core": "^1.2.6", "@actions/exec": "^1.0.1", - "@actions/io": "^1.1.0" + "@actions/io": "^1.1.0", + "filenamify": "^4.3.0" }, "devDependencies": { "@types/jest": "^24.0.13", diff --git a/src/cache.ts b/src/cache.ts index 43d6717c6..faef006c6 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -1,4 +1,5 @@ import { exec, PromiseWithChild } from "child_process"; +import filenamify from "filenamify"; import { readdir } from "fs"; import { dirname, join } from "path"; import { promisify } from "util"; @@ -8,10 +9,6 @@ import { DownloadOptions, UploadOptions } from "./options"; const execAsync = promisify(exec); const readDirAsync = promisify(readdir); -function generateCacheName(path: string): string { - return path.replace(/[^a-z0-9]/gi, "_"); -} - export class ReserveCacheError extends Error { constructor(message: string) { super(message); @@ -37,9 +34,9 @@ function checkPaths(paths: string[]): void { } function checkKey(key: string): void { - if (key.length > 512) { + if (key.length > 255) { throw new ValidationError( - `Key Validation Error: ${key} cannot be larger than 512 characters.` + `Key Validation Error: ${key} cannot be larger than 255 characters.` ); } const regex = /^[^,]*$/; @@ -118,8 +115,8 @@ export async function restoreCache( const cacheFiles = await readDirAsync(cacheDir); - const potentialCaches = (restoreKeys || [primaryKey]).map( - generateCacheName + const potentialCaches = (restoreKeys || [primaryKey]).map(key => + filenamify(key) ); console.log({ cacheFiles, potentialCaches }); @@ -175,7 +172,7 @@ export async function saveCache( ); const cacheDir = join(`/media/cache/`, process.env.GITHUB_REPOSITORY || ""); - const cacheName = `${generateCacheName(key)}.tar.lz4`; + const cacheName = `${filenamify(key)}.tar.lz4`; const cachePath = join(cacheDir, cacheName); const cmd = `mkdir -p ${cacheDir} && tar cf - ${paths.join(