diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 478807b..1767de9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -599,6 +599,7 @@ jobs: - name: Setup with cache uses: ./ with: + enable-cache: true cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-cache-local - run: | if [ "$UV_CACHE_DIR" != "${{ matrix.inputs.expected-cache-dir }}" ]; then @@ -607,6 +608,25 @@ jobs: fi shell: bash + test-cache-local-cache-disabled: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: Setup without cache + uses: ./ + with: + enable-cache: false + + - name: Check UV_CACHE_DIR is not set + run: | + if [ -n "$UV_CACHE_DIR" ]; then + echo "UV_CACHE_DIR should not be set when cache is disabled: $UV_CACHE_DIR" + exit 1 + fi + shell: bash + test-setup-cache-local: runs-on: selfhosted-ubuntu-arm64 steps: @@ -791,6 +811,31 @@ jobs: - run: uv run long-running.py & working-directory: __tests__/fixtures/uv-project + test-cache-dir-from-file: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + - name: Verify uv cache dir is not populated + run: | + if [ -f "/tmp/pyproject-toml-defined-cache-path/CACHEDIR.TAG" ]; then + echo "Cache dir should not exist" + exit 1 + fi + - name: Setup uv + uses: ./ + with: + working-directory: __tests__/fixtures/cache-dir-defined-project + - run: uv sync + working-directory: __tests__/fixtures/cache-dir-defined-project + - name: Verify uv cache dir is populated + run: | + if [ ! -f "/tmp/pyproject-toml-defined-cache-path/CACHEDIR.TAG" ]; then + echo "Cache dir should exist" + exit 1 + fi + all-tests-passed: runs-on: ubuntu-latest needs: @@ -811,6 +856,7 @@ jobs: - test-activate-environment - test-musl - test-cache-local + - test-cache-local-cache-disabled - test-setup-cache - test-restore-cache - test-setup-cache-requirements-txt @@ -831,6 +877,7 @@ jobs: - test-absolute-path - test-relative-path - test-cache-prune-force + - test-cache-dir-from-file if: always() steps: - name: All tests passed diff --git a/README.md b/README.md index 04e313e..abd319e 100644 --- a/README.md +++ b/README.md @@ -316,11 +316,18 @@ By default, the cache will be saved. ### Local cache path -This action controls where uv stores its cache on the runner's filesystem by setting `UV_CACHE_DIR`. +If caching is enabled, this action controls where uv stores its cache on the runner's filesystem +by setting `UV_CACHE_DIR`. + It defaults to `setup-uv-cache` in the `TMP` dir, `D:\a\_temp\uv-tool-dir` on Windows and `/tmp/setup-uv-cache` on Linux/macOS. You can change the default by specifying the path with the `cache-local-path` input. +> [!NOTE] +> If the environment variable `UV_CACHE_DIR` is already set this action will not override it. +> If you configured [cache-dir](https://docs.astral.sh/uv/reference/settings/#cache-dir) in your +> config file then it is also respected and this action will not set `UV_CACHE_DIR`. + ```yaml - name: Define a custom uv cache path uses: astral-sh/setup-uv@v6 diff --git a/__tests__/fixtures/cache-dir-defined-project/README.md b/__tests__/fixtures/cache-dir-defined-project/README.md new file mode 100644 index 0000000..e69de29 diff --git a/__tests__/fixtures/cache-dir-defined-project/pyproject.toml b/__tests__/fixtures/cache-dir-defined-project/pyproject.toml new file mode 100644 index 0000000..285cc36 --- /dev/null +++ b/__tests__/fixtures/cache-dir-defined-project/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "uv-project" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.12" +dependencies = [ + "ruff>=0.6.2", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.uv] +cache-dir = "/tmp/pyproject-toml-defined-cache-path" diff --git a/__tests__/fixtures/cache-dir-defined-project/src/uv_project/__init__.py b/__tests__/fixtures/cache-dir-defined-project/src/uv_project/__init__.py new file mode 100644 index 0000000..94ebc9c --- /dev/null +++ b/__tests__/fixtures/cache-dir-defined-project/src/uv_project/__init__.py @@ -0,0 +1,2 @@ +def hello() -> str: + return "Hello from uv-project!" diff --git a/__tests__/fixtures/cache-dir-defined-project/uv.lock b/__tests__/fixtures/cache-dir-defined-project/uv.lock new file mode 100644 index 0000000..3838f8c --- /dev/null +++ b/__tests__/fixtures/cache-dir-defined-project/uv.lock @@ -0,0 +1,38 @@ +version = 1 +requires-python = ">=3.12" + +[[package]] +name = "ruff" +version = "0.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/23/f4/279d044f66b79261fd37df76bf72b64471afab5d3b7906a01499c4451910/ruff-0.6.2.tar.gz", hash = "sha256:239ee6beb9e91feb8e0ec384204a763f36cb53fb895a1a364618c6abb076b3be", size = 2460281 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/4b/47dd7a69287afb4069fa42c198e899463605460a58120196711bfcf0446b/ruff-0.6.2-py3-none-linux_armv6l.whl", hash = "sha256:5c8cbc6252deb3ea840ad6a20b0f8583caab0c5ef4f9cca21adc5a92b8f79f3c", size = 9695871 }, + { url = "https://files.pythonhosted.org/packages/ae/c3/8aac62ac4638c14a740ee76a755a925f2d0d04580ab790a9887accb729f6/ruff-0.6.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:17002fe241e76544448a8e1e6118abecbe8cd10cf68fde635dad480dba594570", size = 9459354 }, + { url = "https://files.pythonhosted.org/packages/2f/cf/77fbd8d4617b9b9c503f9bffb8552c4e3ea1a58dc36975e7a9104ffb0f85/ruff-0.6.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3dbeac76ed13456f8158b8f4fe087bf87882e645c8e8b606dd17b0b66c2c1158", size = 9163871 }, + { url = "https://files.pythonhosted.org/packages/05/1c/765192bab32b79efbb498b06f0b9dcb3629112b53b8777ae1d19b8209e09/ruff-0.6.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:094600ee88cda325988d3f54e3588c46de5c18dae09d683ace278b11f9d4d534", size = 10096250 }, + { url = "https://files.pythonhosted.org/packages/08/d0/86f3cb0f6934c99f759c232984a5204d67a26745cad2d9edff6248adf7d2/ruff-0.6.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:316d418fe258c036ba05fbf7dfc1f7d3d4096db63431546163b472285668132b", size = 9475376 }, + { url = "https://files.pythonhosted.org/packages/cd/cc/4c8d0e225b559a3fae6092ec310d7150d3b02b4669e9223f783ef64d82c0/ruff-0.6.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d72b8b3abf8a2d51b7b9944a41307d2f442558ccb3859bbd87e6ae9be1694a5d", size = 10295634 }, + { url = "https://files.pythonhosted.org/packages/db/96/d2699cfb1bb5a01c68122af43454c76c31331e1c8a9bd97d653d7c82524b/ruff-0.6.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2aed7e243be68487aa8982e91c6e260982d00da3f38955873aecd5a9204b1d66", size = 11024941 }, + { url = "https://files.pythonhosted.org/packages/8b/a9/6ecd66af8929e0f2a1ed308a4137f3521789f28f0eb97d32c2ca3aa7000c/ruff-0.6.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d371f7fc9cec83497fe7cf5eaf5b76e22a8efce463de5f775a1826197feb9df8", size = 10606894 }, + { url = "https://files.pythonhosted.org/packages/e4/73/2ee4cd19f44992fedac1cc6db9e3d825966072f6dcbd4032f21cbd063170/ruff-0.6.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8f310d63af08f583363dfb844ba8f9417b558199c58a5999215082036d795a1", size = 11552886 }, + { url = "https://files.pythonhosted.org/packages/60/4c/c0f1cd35ce4a93c54a6bb1ee6934a3a205fa02198dd076678193853ceea1/ruff-0.6.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7db6880c53c56addb8638fe444818183385ec85eeada1d48fc5abe045301b2f1", size = 10264945 }, + { url = "https://files.pythonhosted.org/packages/c4/89/e45c9359b9cdd4245512ea2b9f2bb128a997feaa5f726fc9e8c7a66afadf/ruff-0.6.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1175d39faadd9a50718f478d23bfc1d4da5743f1ab56af81a2b6caf0a2394f23", size = 10100007 }, + { url = "https://files.pythonhosted.org/packages/06/74/0bd4e0a7ed5f6908df87892f9bf60a2356c0fd74102d8097298bd9b4f346/ruff-0.6.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5b939f9c86d51635fe486585389f54582f0d65b8238e08c327c1534844b3bb9a", size = 9559267 }, + { url = "https://files.pythonhosted.org/packages/54/03/3dc6dc9419f276f05805bf888c279e3e0b631284abd548d9e87cebb93aec/ruff-0.6.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d0d62ca91219f906caf9b187dea50d17353f15ec9bb15aae4a606cd697b49b4c", size = 9905304 }, + { url = "https://files.pythonhosted.org/packages/5c/5b/d6a72a6a6bbf097c09de468326ef5fa1c9e7aa5e6e45979bc0d984b0dbe7/ruff-0.6.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7438a7288f9d67ed3c8ce4d059e67f7ed65e9fe3aa2ab6f5b4b3610e57e3cb56", size = 10341480 }, + { url = "https://files.pythonhosted.org/packages/79/a9/0f2f21fe15ba537c46598f96aa9ae4a3d4b9ec64926664617ca6a8c772f4/ruff-0.6.2-py3-none-win32.whl", hash = "sha256:279d5f7d86696df5f9549b56b9b6a7f6c72961b619022b5b7999b15db392a4da", size = 7961901 }, + { url = "https://files.pythonhosted.org/packages/b0/80/fff12ffe11853d9f4ea3e5221e6dd2e93640a161c05c9579833e09ad40a7/ruff-0.6.2-py3-none-win_amd64.whl", hash = "sha256:d9f3469c7dd43cd22eb1c3fc16926fb8258d50cb1b216658a07be95dd117b0f2", size = 8783320 }, + { url = "https://files.pythonhosted.org/packages/56/91/577cdd64cce5e74d3f8b5ecb93f29566def569c741eb008aed4f331ef821/ruff-0.6.2-py3-none-win_arm64.whl", hash = "sha256:f28fcd2cd0e02bdf739297516d5643a945cc7caf09bd9bcb4d932540a5ea4fa9", size = 8225886 }, +] + +[[package]] +name = "uv-project" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [{ name = "ruff" }] diff --git a/dist/save-cache/index.js b/dist/save-cache/index.js index 5b14ce7..5fc3dd8 100644 --- a/dist/save-cache/index.js +++ b/dist/save-cache/index.js @@ -90875,6 +90875,67 @@ async function pruneCache() { run(); +/***/ }), + +/***/ 5465: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getConfigValueFromTomlFile = getConfigValueFromTomlFile; +const node_fs_1 = __importDefault(__nccwpck_require__(3024)); +const toml = __importStar(__nccwpck_require__(7106)); +function getConfigValueFromTomlFile(filePath, key) { + if (!node_fs_1.default.existsSync(filePath) || !filePath.endsWith(".toml")) { + return undefined; + } + const fileContent = node_fs_1.default.readFileSync(filePath, "utf-8"); + if (filePath.endsWith("pyproject.toml")) { + const tomlContent = toml.parse(fileContent); + return tomlContent?.tool?.uv?.[key]; + } + const tomlContent = toml.parse(fileContent); + return tomlContent[key]; +} + + /***/ }), /***/ 6156: @@ -90938,6 +90999,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.addProblemMatchers = exports.manifestFile = exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreEmptyWorkdir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.saveCache = exports.restoreCache = exports.enableCache = exports.checkSum = exports.activateEnvironment = exports.pythonVersion = exports.versionFile = exports.version = exports.workingDirectory = void 0; const node_path_1 = __importDefault(__nccwpck_require__(6760)); const core = __importStar(__nccwpck_require__(7484)); +const config_file_1 = __nccwpck_require__(5465); exports.workingDirectory = core.getInput("working-directory"); exports.version = core.getInput("version"); exports.versionFile = getVersionFile(); @@ -91007,6 +91069,14 @@ function getCacheLocalPath() { const tildeExpanded = expandTilde(cacheLocalPathInput); return resolveRelativePath(tildeExpanded); } + const cacheDirFromConfig = getCacheDirFromConfig(); + if (cacheDirFromConfig !== undefined) { + return cacheDirFromConfig; + } + if (process.env.UV_CACHE_DIR !== undefined) { + core.info(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`); + return process.env.UV_CACHE_DIR; + } if (process.env.RUNNER_ENVIRONMENT === "github-hosted") { if (process.env.RUNNER_TEMP !== undefined) { return `${process.env.RUNNER_TEMP}${node_path_1.default.sep}setup-uv-cache`; @@ -91018,6 +91088,24 @@ function getCacheLocalPath() { } return `${process.env.HOME}${node_path_1.default.sep}.cache${node_path_1.default.sep}uv`; } +function getCacheDirFromConfig() { + for (const filePath of [exports.versionFile, "uv.toml", "pyproject.toml"]) { + const resolvedPath = resolveRelativePath(filePath); + try { + const cacheDir = (0, config_file_1.getConfigValueFromTomlFile)(resolvedPath, "cache-dir"); + if (cacheDir !== undefined) { + core.info(`Found cache-dir in ${resolvedPath}: ${cacheDir}`); + return cacheDir; + } + } + catch (err) { + const message = err.message; + core.warning(`Error while parsing ${filePath}: ${message}`); + return undefined; + } + } + return undefined; +} function getCacheDependencyGlob() { const cacheDependencyGlobInput = core.getInput("cache-dependency-glob"); if (cacheDependencyGlobInput !== "") { @@ -93059,6 +93147,915 @@ function parseParams (str) { module.exports = parseParams +/***/ }), + +/***/ 7106: +/***/ ((module) => { + +"use strict"; + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// dist/index.js +var index_exports = {}; +__export(index_exports, { + TomlDate: () => TomlDate, + TomlError: () => TomlError, + default: () => index_default, + parse: () => parse, + stringify: () => stringify +}); +module.exports = __toCommonJS(index_exports); + +// dist/error.js +function getLineColFromPtr(string, ptr) { + let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g); + return [lines.length, lines.pop().length + 1]; +} +function makeCodeBlock(string, line, column) { + let lines = string.split(/\r\n|\n|\r/g); + let codeblock = ""; + let numberLen = (Math.log10(line + 1) | 0) + 1; + for (let i = line - 1; i <= line + 1; i++) { + let l = lines[i - 1]; + if (!l) + continue; + codeblock += i.toString().padEnd(numberLen, " "); + codeblock += ": "; + codeblock += l; + codeblock += "\n"; + if (i === line) { + codeblock += " ".repeat(numberLen + column + 2); + codeblock += "^\n"; + } + } + return codeblock; +} +var TomlError = class extends Error { + line; + column; + codeblock; + constructor(message, options) { + const [line, column] = getLineColFromPtr(options.toml, options.ptr); + const codeblock = makeCodeBlock(options.toml, line, column); + super(`Invalid TOML document: ${message} + +${codeblock}`, options); + this.line = line; + this.column = column; + this.codeblock = codeblock; + } +}; + +// dist/util.js +function isEscaped(str, ptr) { + let i = 0; + while (str[ptr - ++i] === "\\") + ; + return --i && i % 2; +} +function indexOfNewline(str, start = 0, end = str.length) { + let idx = str.indexOf("\n", start); + if (str[idx - 1] === "\r") + idx--; + return idx <= end ? idx : -1; +} +function skipComment(str, ptr) { + for (let i = ptr; i < str.length; i++) { + let c = str[i]; + if (c === "\n") + return i; + if (c === "\r" && str[i + 1] === "\n") + return i + 1; + if (c < " " && c !== " " || c === "\x7F") { + throw new TomlError("control characters are not allowed in comments", { + toml: str, + ptr + }); + } + } + return str.length; +} +function skipVoid(str, ptr, banNewLines, banComments) { + let c; + while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n")) + ptr++; + return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines); +} +function skipUntil(str, ptr, sep, end, banNewLines = false) { + if (!end) { + ptr = indexOfNewline(str, ptr); + return ptr < 0 ? str.length : ptr; + } + for (let i = ptr; i < str.length; i++) { + let c = str[i]; + if (c === "#") { + i = indexOfNewline(str, i); + } else if (c === sep) { + return i + 1; + } else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) { + return i; + } + } + throw new TomlError("cannot find end of structure", { + toml: str, + ptr + }); +} +function getStringEnd(str, seek) { + let first = str[seek]; + let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] ? str.slice(seek, seek + 3) : first; + seek += target.length - 1; + do + seek = str.indexOf(target, ++seek); + while (seek > -1 && first !== "'" && isEscaped(str, seek)); + if (seek > -1) { + seek += target.length; + if (target.length > 1) { + if (str[seek] === first) + seek++; + if (str[seek] === first) + seek++; + } + } + return seek; +} + +// dist/date.js +var DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}:\d{2}(?:\.\d+)?)?(Z|[-+]\d{2}:\d{2})?$/i; +var TomlDate = class _TomlDate extends Date { + #hasDate = false; + #hasTime = false; + #offset = null; + constructor(date) { + let hasDate = true; + let hasTime = true; + let offset = "Z"; + if (typeof date === "string") { + let match = date.match(DATE_TIME_RE); + if (match) { + if (!match[1]) { + hasDate = false; + date = `0000-01-01T${date}`; + } + hasTime = !!match[2]; + hasTime && date[10] === " " && (date = date.replace(" ", "T")); + if (match[2] && +match[2] > 23) { + date = ""; + } else { + offset = match[3] || null; + date = date.toUpperCase(); + if (!offset && hasTime) + date += "Z"; + } + } else { + date = ""; + } + } + super(date); + if (!isNaN(this.getTime())) { + this.#hasDate = hasDate; + this.#hasTime = hasTime; + this.#offset = offset; + } + } + isDateTime() { + return this.#hasDate && this.#hasTime; + } + isLocal() { + return !this.#hasDate || !this.#hasTime || !this.#offset; + } + isDate() { + return this.#hasDate && !this.#hasTime; + } + isTime() { + return this.#hasTime && !this.#hasDate; + } + isValid() { + return this.#hasDate || this.#hasTime; + } + toISOString() { + let iso = super.toISOString(); + if (this.isDate()) + return iso.slice(0, 10); + if (this.isTime()) + return iso.slice(11, 23); + if (this.#offset === null) + return iso.slice(0, -1); + if (this.#offset === "Z") + return iso; + let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6); + offset = this.#offset[0] === "-" ? offset : -offset; + let offsetDate = new Date(this.getTime() - offset * 6e4); + return offsetDate.toISOString().slice(0, -1) + this.#offset; + } + static wrapAsOffsetDateTime(jsDate, offset = "Z") { + let date = new _TomlDate(jsDate); + date.#offset = offset; + return date; + } + static wrapAsLocalDateTime(jsDate) { + let date = new _TomlDate(jsDate); + date.#offset = null; + return date; + } + static wrapAsLocalDate(jsDate) { + let date = new _TomlDate(jsDate); + date.#hasTime = false; + date.#offset = null; + return date; + } + static wrapAsLocalTime(jsDate) { + let date = new _TomlDate(jsDate); + date.#hasDate = false; + date.#offset = null; + return date; + } +}; + +// dist/primitive.js +var INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/; +var FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/; +var LEADING_ZERO = /^[+-]?0[0-9_]/; +var ESCAPE_REGEX = /^[0-9a-f]{4,8}$/i; +var ESC_MAP = { + b: "\b", + t: " ", + n: "\n", + f: "\f", + r: "\r", + '"': '"', + "\\": "\\" +}; +function parseString(str, ptr = 0, endPtr = str.length) { + let isLiteral = str[ptr] === "'"; + let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1]; + if (isMultiline) { + endPtr -= 2; + if (str[ptr += 2] === "\r") + ptr++; + if (str[ptr] === "\n") + ptr++; + } + let tmp = 0; + let isEscape; + let parsed = ""; + let sliceStart = ptr; + while (ptr < endPtr - 1) { + let c = str[ptr++]; + if (c === "\n" || c === "\r" && str[ptr] === "\n") { + if (!isMultiline) { + throw new TomlError("newlines are not allowed in strings", { + toml: str, + ptr: ptr - 1 + }); + } + } else if (c < " " && c !== " " || c === "\x7F") { + throw new TomlError("control characters are not allowed in strings", { + toml: str, + ptr: ptr - 1 + }); + } + if (isEscape) { + isEscape = false; + if (c === "u" || c === "U") { + let code = str.slice(ptr, ptr += c === "u" ? 4 : 8); + if (!ESCAPE_REGEX.test(code)) { + throw new TomlError("invalid unicode escape", { + toml: str, + ptr: tmp + }); + } + try { + parsed += String.fromCodePoint(parseInt(code, 16)); + } catch { + throw new TomlError("invalid unicode escape", { + toml: str, + ptr: tmp + }); + } + } else if (isMultiline && (c === "\n" || c === " " || c === " " || c === "\r")) { + ptr = skipVoid(str, ptr - 1, true); + if (str[ptr] !== "\n" && str[ptr] !== "\r") { + throw new TomlError("invalid escape: only line-ending whitespace may be escaped", { + toml: str, + ptr: tmp + }); + } + ptr = skipVoid(str, ptr); + } else if (c in ESC_MAP) { + parsed += ESC_MAP[c]; + } else { + throw new TomlError("unrecognized escape sequence", { + toml: str, + ptr: tmp + }); + } + sliceStart = ptr; + } else if (!isLiteral && c === "\\") { + tmp = ptr - 1; + isEscape = true; + parsed += str.slice(sliceStart, tmp); + } + } + return parsed + str.slice(sliceStart, endPtr - 1); +} +function parseValue(value, toml, ptr, integersAsBigInt) { + if (value === "true") + return true; + if (value === "false") + return false; + if (value === "-inf") + return -Infinity; + if (value === "inf" || value === "+inf") + return Infinity; + if (value === "nan" || value === "+nan" || value === "-nan") + return NaN; + if (value === "-0") + return integersAsBigInt ? 0n : 0; + let isInt = INT_REGEX.test(value); + if (isInt || FLOAT_REGEX.test(value)) { + if (LEADING_ZERO.test(value)) { + throw new TomlError("leading zeroes are not allowed", { + toml, + ptr + }); + } + value = value.replace(/_/g, ""); + let numeric = +value; + if (isNaN(numeric)) { + throw new TomlError("invalid number", { + toml, + ptr + }); + } + if (isInt) { + if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) { + throw new TomlError("integer value cannot be represented losslessly", { + toml, + ptr + }); + } + if (isInt || integersAsBigInt === true) + numeric = BigInt(value); + } + return numeric; + } + const date = new TomlDate(value); + if (!date.isValid()) { + throw new TomlError("invalid value", { + toml, + ptr + }); + } + return date; +} + +// dist/extract.js +function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) { + let value = str.slice(startPtr, endPtr); + let commentIdx = value.indexOf("#"); + if (commentIdx > -1) { + skipComment(str, commentIdx); + value = value.slice(0, commentIdx); + } + let trimmed = value.trimEnd(); + if (!allowNewLines) { + let newlineIdx = value.indexOf("\n", trimmed.length); + if (newlineIdx > -1) { + throw new TomlError("newlines are not allowed in inline tables", { + toml: str, + ptr: startPtr + newlineIdx + }); + } + } + return [trimmed, commentIdx]; +} +function extractValue(str, ptr, end, depth, integersAsBigInt) { + if (depth === 0) { + throw new TomlError("document contains excessively nested structures. aborting.", { + toml: str, + ptr + }); + } + let c = str[ptr]; + if (c === "[" || c === "{") { + let [value, endPtr2] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt); + let newPtr = end ? skipUntil(str, endPtr2, ",", end) : endPtr2; + if (endPtr2 - newPtr && end === "}") { + let nextNewLine = indexOfNewline(str, endPtr2, newPtr); + if (nextNewLine > -1) { + throw new TomlError("newlines are not allowed in inline tables", { + toml: str, + ptr: nextNewLine + }); + } + } + return [value, newPtr]; + } + let endPtr; + if (c === '"' || c === "'") { + endPtr = getStringEnd(str, ptr); + let parsed = parseString(str, ptr, endPtr); + if (end) { + endPtr = skipVoid(str, endPtr, end !== "]"); + if (str[endPtr] && str[endPtr] !== "," && str[endPtr] !== end && str[endPtr] !== "\n" && str[endPtr] !== "\r") { + throw new TomlError("unexpected character encountered", { + toml: str, + ptr: endPtr + }); + } + endPtr += +(str[endPtr] === ","); + } + return [parsed, endPtr]; + } + endPtr = skipUntil(str, ptr, ",", end); + let slice = sliceAndTrimEndOf(str, ptr, endPtr - +(str[endPtr - 1] === ","), end === "]"); + if (!slice[0]) { + throw new TomlError("incomplete key-value declaration: no value specified", { + toml: str, + ptr + }); + } + if (end && slice[1] > -1) { + endPtr = skipVoid(str, ptr + slice[1]); + endPtr += +(str[endPtr] === ","); + } + return [ + parseValue(slice[0], str, ptr, integersAsBigInt), + endPtr + ]; +} + +// dist/struct.js +var KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/; +function parseKey(str, ptr, end = "=") { + let dot = ptr - 1; + let parsed = []; + let endPtr = str.indexOf(end, ptr); + if (endPtr < 0) { + throw new TomlError("incomplete key-value: cannot find end of key", { + toml: str, + ptr + }); + } + do { + let c = str[ptr = ++dot]; + if (c !== " " && c !== " ") { + if (c === '"' || c === "'") { + if (c === str[ptr + 1] && c === str[ptr + 2]) { + throw new TomlError("multiline strings are not allowed in keys", { + toml: str, + ptr + }); + } + let eos = getStringEnd(str, ptr); + if (eos < 0) { + throw new TomlError("unfinished string encountered", { + toml: str, + ptr + }); + } + dot = str.indexOf(".", eos); + let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot); + let newLine = indexOfNewline(strEnd); + if (newLine > -1) { + throw new TomlError("newlines are not allowed in keys", { + toml: str, + ptr: ptr + dot + newLine + }); + } + if (strEnd.trimStart()) { + throw new TomlError("found extra tokens after the string part", { + toml: str, + ptr: eos + }); + } + if (endPtr < eos) { + endPtr = str.indexOf(end, eos); + if (endPtr < 0) { + throw new TomlError("incomplete key-value: cannot find end of key", { + toml: str, + ptr + }); + } + } + parsed.push(parseString(str, ptr, eos)); + } else { + dot = str.indexOf(".", ptr); + let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot); + if (!KEY_PART_RE.test(part)) { + throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", { + toml: str, + ptr + }); + } + parsed.push(part.trimEnd()); + } + } + } while (dot + 1 && dot < endPtr); + return [parsed, skipVoid(str, endPtr + 1, true, true)]; +} +function parseInlineTable(str, ptr, depth, integersAsBigInt) { + let res = {}; + let seen = /* @__PURE__ */ new Set(); + let c; + let comma = 0; + ptr++; + while ((c = str[ptr++]) !== "}" && c) { + let err = { toml: str, ptr: ptr - 1 }; + if (c === "\n") { + throw new TomlError("newlines are not allowed in inline tables", err); + } else if (c === "#") { + throw new TomlError("inline tables cannot contain comments", err); + } else if (c === ",") { + throw new TomlError("expected key-value, found comma", err); + } else if (c !== " " && c !== " ") { + let k; + let t = res; + let hasOwn = false; + let [key, keyEndPtr] = parseKey(str, ptr - 1); + for (let i = 0; i < key.length; i++) { + if (i) + t = hasOwn ? t[k] : t[k] = {}; + k = key[i]; + if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) { + throw new TomlError("trying to redefine an already defined value", { + toml: str, + ptr + }); + } + if (!hasOwn && k === "__proto__") { + Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true }); + } + } + if (hasOwn) { + throw new TomlError("trying to redefine an already defined value", { + toml: str, + ptr + }); + } + let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt); + seen.add(value); + t[k] = value; + ptr = valueEndPtr; + comma = str[ptr - 1] === "," ? ptr - 1 : 0; + } + } + if (comma) { + throw new TomlError("trailing commas are not allowed in inline tables", { + toml: str, + ptr: comma + }); + } + if (!c) { + throw new TomlError("unfinished table encountered", { + toml: str, + ptr + }); + } + return [res, ptr]; +} +function parseArray(str, ptr, depth, integersAsBigInt) { + let res = []; + let c; + ptr++; + while ((c = str[ptr++]) !== "]" && c) { + if (c === ",") { + throw new TomlError("expected value, found comma", { + toml: str, + ptr: ptr - 1 + }); + } else if (c === "#") + ptr = skipComment(str, ptr); + else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") { + let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt); + res.push(e[0]); + ptr = e[1]; + } + } + if (!c) { + throw new TomlError("unfinished array encountered", { + toml: str, + ptr + }); + } + return [res, ptr]; +} + +// dist/parse.js +function peekTable(key, table, meta, type) { + let t = table; + let m = meta; + let k; + let hasOwn = false; + let state; + for (let i = 0; i < key.length; i++) { + if (i) { + t = hasOwn ? t[k] : t[k] = {}; + m = (state = m[k]).c; + if (type === 0 && (state.t === 1 || state.t === 2)) { + return null; + } + if (state.t === 2) { + let l = t.length - 1; + t = t[l]; + m = m[l].c; + } + } + k = key[i]; + if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) { + return null; + } + if (!hasOwn) { + if (k === "__proto__") { + Object.defineProperty(t, k, { enumerable: true, configurable: true, writable: true }); + Object.defineProperty(m, k, { enumerable: true, configurable: true, writable: true }); + } + m[k] = { + t: i < key.length - 1 && type === 2 ? 3 : type, + d: false, + i: 0, + c: {} + }; + } + } + state = m[k]; + if (state.t !== type && !(type === 1 && state.t === 3)) { + return null; + } + if (type === 2) { + if (!state.d) { + state.d = true; + t[k] = []; + } + t[k].push(t = {}); + state.c[state.i++] = state = { t: 1, d: false, i: 0, c: {} }; + } + if (state.d) { + return null; + } + state.d = true; + if (type === 1) { + t = hasOwn ? t[k] : t[k] = {}; + } else if (type === 0 && hasOwn) { + return null; + } + return [k, t, state.c]; +} +function parse(toml, { maxDepth = 1e3, integersAsBigInt } = {}) { + let res = {}; + let meta = {}; + let tbl = res; + let m = meta; + for (let ptr = skipVoid(toml, 0); ptr < toml.length; ) { + if (toml[ptr] === "[") { + let isTableArray = toml[++ptr] === "["; + let k = parseKey(toml, ptr += +isTableArray, "]"); + if (isTableArray) { + if (toml[k[1] - 1] !== "]") { + throw new TomlError("expected end of table declaration", { + toml, + ptr: k[1] - 1 + }); + } + k[1]++; + } + let p = peekTable( + k[0], + res, + meta, + isTableArray ? 2 : 1 + /* Type.EXPLICIT */ + ); + if (!p) { + throw new TomlError("trying to redefine an already defined table or value", { + toml, + ptr + }); + } + m = p[2]; + tbl = p[1]; + ptr = k[1]; + } else { + let k = parseKey(toml, ptr); + let p = peekTable( + k[0], + tbl, + m, + 0 + /* Type.DOTTED */ + ); + if (!p) { + throw new TomlError("trying to redefine an already defined table or value", { + toml, + ptr + }); + } + let v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt); + p[1][p[0]] = v[0]; + ptr = v[1]; + } + ptr = skipVoid(toml, ptr, true); + if (toml[ptr] && toml[ptr] !== "\n" && toml[ptr] !== "\r") { + throw new TomlError("each key-value declaration must be followed by an end-of-line", { + toml, + ptr + }); + } + ptr = skipVoid(toml, ptr); + } + return res; +} + +// dist/stringify.js +var BARE_KEY = /^[a-z0-9-_]+$/i; +function extendedTypeOf(obj) { + let type = typeof obj; + if (type === "object") { + if (Array.isArray(obj)) + return "array"; + if (obj instanceof Date) + return "date"; + } + return type; +} +function isArrayOfTables(obj) { + for (let i = 0; i < obj.length; i++) { + if (extendedTypeOf(obj[i]) !== "object") + return false; + } + return obj.length != 0; +} +function formatString(s) { + return JSON.stringify(s).replace(/\x7f/g, "\\u007f"); +} +function stringifyValue(val, type, depth, numberAsFloat) { + if (depth === 0) { + throw new Error("Could not stringify the object: maximum object depth exceeded"); + } + if (type === "number") { + if (isNaN(val)) + return "nan"; + if (val === Infinity) + return "inf"; + if (val === -Infinity) + return "-inf"; + if (numberAsFloat && Number.isInteger(val)) + return val.toFixed(1); + return val.toString(); + } + if (type === "bigint" || type === "boolean") { + return val.toString(); + } + if (type === "string") { + return formatString(val); + } + if (type === "date") { + if (isNaN(val.getTime())) { + throw new TypeError("cannot serialize invalid date"); + } + return val.toISOString(); + } + if (type === "object") { + return stringifyInlineTable(val, depth, numberAsFloat); + } + if (type === "array") { + return stringifyArray(val, depth, numberAsFloat); + } +} +function stringifyInlineTable(obj, depth, numberAsFloat) { + let keys = Object.keys(obj); + if (keys.length === 0) + return "{}"; + let res = "{ "; + for (let i = 0; i < keys.length; i++) { + let k = keys[i]; + if (i) + res += ", "; + res += BARE_KEY.test(k) ? k : formatString(k); + res += " = "; + res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat); + } + return res + " }"; +} +function stringifyArray(array, depth, numberAsFloat) { + if (array.length === 0) + return "[]"; + let res = "[ "; + for (let i = 0; i < array.length; i++) { + if (i) + res += ", "; + if (array[i] === null || array[i] === void 0) { + throw new TypeError("arrays cannot contain null or undefined values"); + } + res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat); + } + return res + " ]"; +} +function stringifyArrayTable(array, key, depth, numberAsFloat) { + if (depth === 0) { + throw new Error("Could not stringify the object: maximum object depth exceeded"); + } + let res = ""; + for (let i = 0; i < array.length; i++) { + res += `[[${key}]] +`; + res += stringifyTable(array[i], key, depth, numberAsFloat); + res += "\n\n"; + } + return res; +} +function stringifyTable(obj, prefix, depth, numberAsFloat) { + if (depth === 0) { + throw new Error("Could not stringify the object: maximum object depth exceeded"); + } + let preamble = ""; + let tables = ""; + let keys = Object.keys(obj); + for (let i = 0; i < keys.length; i++) { + let k = keys[i]; + if (obj[k] !== null && obj[k] !== void 0) { + let type = extendedTypeOf(obj[k]); + if (type === "symbol" || type === "function") { + throw new TypeError(`cannot serialize values of type '${type}'`); + } + let key = BARE_KEY.test(k) ? k : formatString(k); + if (type === "array" && isArrayOfTables(obj[k])) { + tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat); + } else if (type === "object") { + let tblKey = prefix ? `${prefix}.${key}` : key; + tables += `[${tblKey}] +`; + tables += stringifyTable(obj[k], tblKey, depth - 1, numberAsFloat); + tables += "\n\n"; + } else { + preamble += key; + preamble += " = "; + preamble += stringifyValue(obj[k], type, depth, numberAsFloat); + preamble += "\n"; + } + } + } + return `${preamble} +${tables}`.trim(); +} +function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) { + if (extendedTypeOf(obj) !== "object") { + throw new TypeError("stringify can only be called with an object"); + } + return stringifyTable(obj, "", maxDepth, numbersAsFloat); +} + +// dist/index.js +var index_default = { parse, stringify, TomlDate, TomlError }; +// Annotate the CommonJS export names for ESM import in node: +0 && (0); +/*! + * Copyright (c) Squirrel Chat et al., All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + /***/ }), /***/ 4012: diff --git a/dist/setup/index.js b/dist/setup/index.js index 2153bf9..3596c2f 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -129387,6 +129387,7 @@ const core = __importStar(__nccwpck_require__(37484)); const exec = __importStar(__nccwpck_require__(95236)); const restore_cache_1 = __nccwpck_require__(95391); const download_version_1 = __nccwpck_require__(28255); +const config_file_1 = __nccwpck_require__(27846); const constants_1 = __nccwpck_require__(56156); const inputs_1 = __nccwpck_require__(9612); const platforms_1 = __nccwpck_require__(98361); @@ -129409,7 +129410,7 @@ async function run() { setupPython(); await activateEnvironment(); addMatchers(); - setCacheDir(inputs_1.cacheLocalPath); + setCacheDir(); core.setOutput("uv-version", setupResult.version); core.saveState(constants_1.STATE_UV_VERSION, setupResult.version); core.info(`Successfully installed uv version ${setupResult.version}`); @@ -129537,9 +129538,16 @@ async function activateEnvironment() { core.exportVariable("VIRTUAL_ENV", path.resolve(`${inputs_1.workingDirectory}${path.sep}.venv`)); } } -function setCacheDir(cacheLocalPath) { - core.exportVariable("UV_CACHE_DIR", cacheLocalPath); - core.info(`Set UV_CACHE_DIR to ${cacheLocalPath}`); +function setCacheDir() { + if (inputs_1.enableCache) { + const cacheDirFromConfig = (0, config_file_1.getConfigValueFromTomlFile)("", "cache-dir"); + if (cacheDirFromConfig !== undefined) { + core.info("Using cache-dir from uv config file, not modifying UV_CACHE_DIR"); + return; + } + core.exportVariable("UV_CACHE_DIR", inputs_1.cacheLocalPath); + core.info(`Set UV_CACHE_DIR to ${inputs_1.cacheLocalPath}`); + } } function addMatchers() { if (inputs_1.addProblemMatchers) { @@ -129550,6 +129558,67 @@ function addMatchers() { run(); +/***/ }), + +/***/ 27846: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getConfigValueFromTomlFile = getConfigValueFromTomlFile; +const node_fs_1 = __importDefault(__nccwpck_require__(73024)); +const toml = __importStar(__nccwpck_require__(27106)); +function getConfigValueFromTomlFile(filePath, key) { + if (!node_fs_1.default.existsSync(filePath) || !filePath.endsWith(".toml")) { + return undefined; + } + const fileContent = node_fs_1.default.readFileSync(filePath, "utf-8"); + if (filePath.endsWith("pyproject.toml")) { + const tomlContent = toml.parse(fileContent); + return tomlContent?.tool?.uv?.[key]; + } + const tomlContent = toml.parse(fileContent); + return tomlContent[key]; +} + + /***/ }), /***/ 56156: @@ -129642,6 +129711,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.addProblemMatchers = exports.manifestFile = exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreEmptyWorkdir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.saveCache = exports.restoreCache = exports.enableCache = exports.checkSum = exports.activateEnvironment = exports.pythonVersion = exports.versionFile = exports.version = exports.workingDirectory = void 0; const node_path_1 = __importDefault(__nccwpck_require__(76760)); const core = __importStar(__nccwpck_require__(37484)); +const config_file_1 = __nccwpck_require__(27846); exports.workingDirectory = core.getInput("working-directory"); exports.version = core.getInput("version"); exports.versionFile = getVersionFile(); @@ -129711,6 +129781,14 @@ function getCacheLocalPath() { const tildeExpanded = expandTilde(cacheLocalPathInput); return resolveRelativePath(tildeExpanded); } + const cacheDirFromConfig = getCacheDirFromConfig(); + if (cacheDirFromConfig !== undefined) { + return cacheDirFromConfig; + } + if (process.env.UV_CACHE_DIR !== undefined) { + core.info(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`); + return process.env.UV_CACHE_DIR; + } if (process.env.RUNNER_ENVIRONMENT === "github-hosted") { if (process.env.RUNNER_TEMP !== undefined) { return `${process.env.RUNNER_TEMP}${node_path_1.default.sep}setup-uv-cache`; @@ -129722,6 +129800,24 @@ function getCacheLocalPath() { } return `${process.env.HOME}${node_path_1.default.sep}.cache${node_path_1.default.sep}uv`; } +function getCacheDirFromConfig() { + for (const filePath of [exports.versionFile, "uv.toml", "pyproject.toml"]) { + const resolvedPath = resolveRelativePath(filePath); + try { + const cacheDir = (0, config_file_1.getConfigValueFromTomlFile)(resolvedPath, "cache-dir"); + if (cacheDir !== undefined) { + core.info(`Found cache-dir in ${resolvedPath}: ${cacheDir}`); + return cacheDir; + } + } + catch (err) { + const message = err.message; + core.warning(`Error while parsing ${filePath}: ${message}`); + return undefined; + } + } + return undefined; +} function getCacheDependencyGlob() { const cacheDependencyGlobInput = core.getInput("cache-dependency-glob"); if (cacheDependencyGlobInput !== "") { @@ -129888,67 +129984,6 @@ async function isMuslOs() { } -/***/ }), - -/***/ 9931: -/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { - -"use strict"; - -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || (function () { - var ownKeys = function(o) { - ownKeys = Object.getOwnPropertyNames || function (o) { - var ar = []; - for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; - return ar; - }; - return ownKeys(o); - }; - return function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); - __setModuleDefault(result, mod); - return result; - }; -})(); -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getRequiredVersionFromConfigFile = getRequiredVersionFromConfigFile; -const node_fs_1 = __importDefault(__nccwpck_require__(73024)); -const toml = __importStar(__nccwpck_require__(27106)); -function getRequiredVersionFromConfigFile(filePath) { - if (!filePath.endsWith(".toml")) { - return undefined; - } - const fileContent = node_fs_1.default.readFileSync(filePath, "utf-8"); - if (filePath.endsWith("pyproject.toml")) { - const tomlContent = toml.parse(fileContent); - return tomlContent?.tool?.uv?.["required-version"]; - } - const tomlContent = toml.parse(fileContent); - return tomlContent["required-version"]; -} - - /***/ }), /***/ 4569: @@ -130068,7 +130103,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getUvVersionFromFile = getUvVersionFromFile; const node_fs_1 = __importDefault(__nccwpck_require__(73024)); const core = __importStar(__nccwpck_require__(37484)); -const config_file_1 = __nccwpck_require__(9931); +const config_file_1 = __nccwpck_require__(27846); const requirements_file_1 = __nccwpck_require__(4569); const tool_versions_file_1 = __nccwpck_require__(4895); function getUvVersionFromFile(filePath) { @@ -130081,7 +130116,7 @@ function getUvVersionFromFile(filePath) { try { uvVersion = (0, tool_versions_file_1.getUvVersionFromToolVersions)(filePath); if (uvVersion === undefined) { - uvVersion = (0, config_file_1.getRequiredVersionFromConfigFile)(filePath); + uvVersion = (0, config_file_1.getConfigValueFromTomlFile)(filePath, "required-version"); } if (uvVersion === undefined) { uvVersion = (0, requirements_file_1.getUvVersionFromRequirementsFile)(filePath); diff --git a/src/setup-uv.ts b/src/setup-uv.ts index 0863755..b47ae19 100644 --- a/src/setup-uv.ts +++ b/src/setup-uv.ts @@ -8,6 +8,7 @@ import { resolveVersion, tryGetFromToolCache, } from "./download/download-version"; +import { getConfigValueFromTomlFile } from "./utils/config-file"; import { STATE_UV_PATH, STATE_UV_VERSION } from "./utils/constants"; import { activateEnvironment as activateEnvironmentInput, @@ -53,7 +54,7 @@ async function run(): Promise { setupPython(); await activateEnvironment(); addMatchers(); - setCacheDir(cacheLocalPath); + setCacheDir(); core.setOutput("uv-version", setupResult.version); core.saveState(STATE_UV_VERSION, setupResult.version); @@ -224,9 +225,18 @@ async function activateEnvironment(): Promise { } } -function setCacheDir(cacheLocalPath: string): void { - core.exportVariable("UV_CACHE_DIR", cacheLocalPath); - core.info(`Set UV_CACHE_DIR to ${cacheLocalPath}`); +function setCacheDir(): void { + if (enableCache) { + const cacheDirFromConfig = getConfigValueFromTomlFile("", "cache-dir"); + if (cacheDirFromConfig !== undefined) { + core.info( + "Using cache-dir from uv config file, not modifying UV_CACHE_DIR", + ); + return; + } + core.exportVariable("UV_CACHE_DIR", cacheLocalPath); + core.info(`Set UV_CACHE_DIR to ${cacheLocalPath}`); + } } function addMatchers(): void { diff --git a/src/utils/config-file.ts b/src/utils/config-file.ts new file mode 100644 index 0000000..1633431 --- /dev/null +++ b/src/utils/config-file.ts @@ -0,0 +1,24 @@ +import fs from "node:fs"; +import * as toml from "smol-toml"; + +export function getConfigValueFromTomlFile( + filePath: string, + key: string, +): string | undefined { + if (!fs.existsSync(filePath) || !filePath.endsWith(".toml")) { + return undefined; + } + const fileContent = fs.readFileSync(filePath, "utf-8"); + + if (filePath.endsWith("pyproject.toml")) { + const tomlContent = toml.parse(fileContent) as { + tool?: { uv?: Record }; + }; + return tomlContent?.tool?.uv?.[key]; + } + const tomlContent = toml.parse(fileContent) as Record< + string, + string | undefined + >; + return tomlContent[key]; +} diff --git a/src/utils/inputs.ts b/src/utils/inputs.ts index d971d79..faf2f59 100644 --- a/src/utils/inputs.ts +++ b/src/utils/inputs.ts @@ -1,5 +1,6 @@ import path from "node:path"; import * as core from "@actions/core"; +import { getConfigValueFromTomlFile } from "./config-file"; export const workingDirectory = core.getInput("working-directory"); export const version = core.getInput("version"); @@ -82,6 +83,14 @@ function getCacheLocalPath(): string { const tildeExpanded = expandTilde(cacheLocalPathInput); return resolveRelativePath(tildeExpanded); } + const cacheDirFromConfig = getCacheDirFromConfig(); + if (cacheDirFromConfig !== undefined) { + return cacheDirFromConfig; + } + if (process.env.UV_CACHE_DIR !== undefined) { + core.info(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`); + return process.env.UV_CACHE_DIR; + } if (process.env.RUNNER_ENVIRONMENT === "github-hosted") { if (process.env.RUNNER_TEMP !== undefined) { return `${process.env.RUNNER_TEMP}${path.sep}setup-uv-cache`; @@ -96,6 +105,24 @@ function getCacheLocalPath(): string { return `${process.env.HOME}${path.sep}.cache${path.sep}uv`; } +function getCacheDirFromConfig(): string | undefined { + for (const filePath of [versionFile, "uv.toml", "pyproject.toml"]) { + const resolvedPath = resolveRelativePath(filePath); + try { + const cacheDir = getConfigValueFromTomlFile(resolvedPath, "cache-dir"); + if (cacheDir !== undefined) { + core.info(`Found cache-dir in ${resolvedPath}: ${cacheDir}`); + return cacheDir; + } + } catch (err) { + const message = (err as Error).message; + core.warning(`Error while parsing ${filePath}: ${message}`); + return undefined; + } + } + return undefined; +} + function getCacheDependencyGlob(): string { const cacheDependencyGlobInput = core.getInput("cache-dependency-glob"); if (cacheDependencyGlobInput !== "") { diff --git a/src/version/config-file.ts b/src/version/config-file.ts deleted file mode 100644 index 20ec190..0000000 --- a/src/version/config-file.ts +++ /dev/null @@ -1,22 +0,0 @@ -import fs from "node:fs"; -import * as toml from "smol-toml"; - -export function getRequiredVersionFromConfigFile( - filePath: string, -): string | undefined { - if (!filePath.endsWith(".toml")) { - return undefined; - } - const fileContent = fs.readFileSync(filePath, "utf-8"); - - if (filePath.endsWith("pyproject.toml")) { - const tomlContent = toml.parse(fileContent) as { - tool?: { uv?: { "required-version"?: string } }; - }; - return tomlContent?.tool?.uv?.["required-version"]; - } - const tomlContent = toml.parse(fileContent) as { - "required-version"?: string; - }; - return tomlContent["required-version"]; -} diff --git a/src/version/resolve.ts b/src/version/resolve.ts index 6746f7e..42106cb 100644 --- a/src/version/resolve.ts +++ b/src/version/resolve.ts @@ -1,6 +1,6 @@ import fs from "node:fs"; import * as core from "@actions/core"; -import { getRequiredVersionFromConfigFile } from "./config-file"; +import { getConfigValueFromTomlFile } from "../utils/config-file"; import { getUvVersionFromRequirementsFile } from "./requirements-file"; import { getUvVersionFromToolVersions } from "./tool-versions-file"; @@ -14,7 +14,7 @@ export function getUvVersionFromFile(filePath: string): string | undefined { try { uvVersion = getUvVersionFromToolVersions(filePath); if (uvVersion === undefined) { - uvVersion = getRequiredVersionFromConfigFile(filePath); + uvVersion = getConfigValueFromTomlFile(filePath, "required-version"); } if (uvVersion === undefined) { uvVersion = getUvVersionFromRequirementsFile(filePath);