diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 0af524b143..0000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,1005 +0,0 @@ -const vitestPlugin = require('@vitest/eslint-plugin'); -const restrictedSyntax = ['WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression']; - -module.exports = { - root: true, - reportUnusedDisableDirectives: true, - ignorePatterns: [ - '/web_src/js/vendor', - '/web_src/fomantic', - '/public/assets/js', - ], - parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - ecmaVersion: 'latest', - project: true, - extraFileExtensions: ['.vue'], - parser: '@typescript-eslint/parser', // for vue plugin - https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser - }, - settings: { - 'import-x/extensions': ['.js', '.ts'], - 'import-x/parsers': { - '@typescript-eslint/parser': ['.js', '.ts'], - }, - 'import-x/resolver': { - typescript: true, - }, - }, - plugins: [ - '@eslint-community/eslint-plugin-eslint-comments', - '@stylistic/eslint-plugin-js', - '@typescript-eslint/eslint-plugin', - 'eslint-plugin-array-func', - 'eslint-plugin-github', - 'eslint-plugin-import-x', - 'eslint-plugin-no-jquery', - 'eslint-plugin-no-use-extend-native', - 'eslint-plugin-regexp', - 'eslint-plugin-sonarjs', - 'eslint-plugin-unicorn', - 'eslint-plugin-wc', - ], - env: { - es2024: true, - node: true, - }, - overrides: [ - { - files: ['**/*.cjs'], - rules: { - 'import-x/no-commonjs': [0], - '@typescript-eslint/no-require-imports': [0], - }, - }, - { - files: ['web_src/**/*'], - globals: { - __webpack_public_path__: true, - process: false, // https://github.com/webpack/webpack/issues/15833 - }, - }, - { - files: ['web_src/**/*', 'docs/**/*'], - env: { - browser: true, - node: false, - }, - }, - { - files: ['*.config.*'], - rules: { - 'import-x/no-unused-modules': [0], - }, - }, - { - files: ['**/*.d.ts'], - rules: { - 'import-x/no-unused-modules': [0], - '@typescript-eslint/consistent-type-definitions': [0], - '@typescript-eslint/consistent-type-imports': [0], - }, - }, - { - files: ['web_src/js/types.ts'], - rules: { - 'import-x/no-unused-modules': [0], - }, - }, - { - files: ['**/*.test.*', 'web_src/js/test/setup.ts'], - plugins: ['@vitest/eslint-plugin'], - globals: vitestPlugin.environments.env.globals, - rules: { - 'github/unescaped-html-literal': [0], - '@vitest/consistent-test-filename': [0], - '@vitest/consistent-test-it': [0], - '@vitest/expect-expect': [0], - '@vitest/max-expects': [0], - '@vitest/max-nested-describe': [0], - '@vitest/no-alias-methods': [0], - '@vitest/no-commented-out-tests': [0], - '@vitest/no-conditional-expect': [0], - '@vitest/no-conditional-in-test': [0], - '@vitest/no-conditional-tests': [0], - '@vitest/no-disabled-tests': [0], - '@vitest/no-done-callback': [0], - '@vitest/no-duplicate-hooks': [0], - '@vitest/no-focused-tests': [2], - '@vitest/no-hooks': [0], - '@vitest/no-identical-title': [2], - '@vitest/no-interpolation-in-snapshots': [0], - '@vitest/no-large-snapshots': [0], - '@vitest/no-mocks-import': [0], - '@vitest/no-restricted-matchers': [0], - '@vitest/no-restricted-vi-methods': [0], - '@vitest/no-standalone-expect': [0], - '@vitest/no-test-prefixes': [0], - '@vitest/no-test-return-statement': [0], - '@vitest/prefer-called-with': [0], - '@vitest/prefer-comparison-matcher': [0], - '@vitest/prefer-each': [0], - '@vitest/prefer-equality-matcher': [0], - '@vitest/prefer-expect-resolves': [0], - '@vitest/prefer-hooks-in-order': [0], - '@vitest/prefer-hooks-on-top': [2], - '@vitest/prefer-lowercase-title': [0], - '@vitest/prefer-mock-promise-shorthand': [0], - '@vitest/prefer-snapshot-hint': [0], - '@vitest/prefer-spy-on': [0], - '@vitest/prefer-strict-equal': [0], - '@vitest/prefer-to-be': [0], - '@vitest/prefer-to-be-falsy': [0], - '@vitest/prefer-to-be-object': [0], - '@vitest/prefer-to-be-truthy': [0], - '@vitest/prefer-to-contain': [0], - '@vitest/prefer-to-have-length': [0], - '@vitest/prefer-todo': [0], - '@vitest/require-hook': [0], - '@vitest/require-to-throw-message': [0], - '@vitest/require-top-level-describe': [0], - '@vitest/valid-describe-callback': [2], - '@vitest/valid-expect': [2], - '@vitest/valid-title': [2], - }, - }, - { - files: ['web_src/js/modules/fetch.ts', 'web_src/js/standalone/**/*'], - rules: { - 'no-restricted-syntax': [2, ...restrictedSyntax], - }, - }, - { - files: ['**/*.vue'], - plugins: [ - 'eslint-plugin-vue', - 'eslint-plugin-vue-scoped-css', - ], - extends: [ - 'plugin:vue/recommended', - 'plugin:vue-scoped-css/vue3-recommended', - ], - rules: { - 'vue/attributes-order': [0], - 'vue/html-closing-bracket-spacing': [2, {startTag: 'never', endTag: 'never', selfClosingTag: 'never'}], - 'vue/max-attributes-per-line': [0], - 'vue/singleline-html-element-content-newline': [0], - }, - }, - { - files: ['tests/e2e/**'], - plugins: [ - 'eslint-plugin-playwright', - ], - extends: [ - 'plugin:playwright/recommended', - ], - }, - ], - rules: { - '@eslint-community/eslint-comments/disable-enable-pair': [2], - '@eslint-community/eslint-comments/no-aggregating-enable': [2], - '@eslint-community/eslint-comments/no-duplicate-disable': [2], - '@eslint-community/eslint-comments/no-restricted-disable': [0], - '@eslint-community/eslint-comments/no-unlimited-disable': [2], - '@eslint-community/eslint-comments/no-unused-disable': [2], - '@eslint-community/eslint-comments/no-unused-enable': [2], - '@eslint-community/eslint-comments/no-use': [0], - '@eslint-community/eslint-comments/require-description': [0], - '@stylistic/js/array-bracket-newline': [0], - '@stylistic/js/array-bracket-spacing': [2, 'never'], - '@stylistic/js/array-element-newline': [0], - '@stylistic/js/arrow-parens': [2, 'always'], - '@stylistic/js/arrow-spacing': [2, {before: true, after: true}], - '@stylistic/js/block-spacing': [0], - '@stylistic/js/brace-style': [2, '1tbs', {allowSingleLine: true}], - '@stylistic/js/comma-dangle': [2, 'always-multiline'], - '@stylistic/js/comma-spacing': [2, {before: false, after: true}], - '@stylistic/js/comma-style': [2, 'last'], - '@stylistic/js/computed-property-spacing': [2, 'never'], - '@stylistic/js/dot-location': [2, 'property'], - '@stylistic/js/eol-last': [2], - '@stylistic/js/function-call-argument-newline': [0], - '@stylistic/js/function-call-spacing': [2, 'never'], - '@stylistic/js/function-paren-newline': [0], - '@stylistic/js/generator-star-spacing': [0], - '@stylistic/js/implicit-arrow-linebreak': [0], - '@stylistic/js/indent': [2, 2, {ignoreComments: true, SwitchCase: 1}], - '@stylistic/js/key-spacing': [2], - '@stylistic/js/keyword-spacing': [2], - '@stylistic/js/line-comment-position': [0], - '@stylistic/js/linebreak-style': [2, 'unix'], - '@stylistic/js/lines-around-comment': [0], - '@stylistic/js/lines-between-class-members': [0], - '@stylistic/js/max-len': [0], - '@stylistic/js/max-statements-per-line': [0], - '@stylistic/js/multiline-comment-style': [0], - '@stylistic/js/multiline-ternary': [0], - '@stylistic/js/new-parens': [2], - '@stylistic/js/newline-per-chained-call': [0], - '@stylistic/js/no-confusing-arrow': [0], - '@stylistic/js/no-extra-parens': [0], - '@stylistic/js/no-extra-semi': [2], - '@stylistic/js/no-floating-decimal': [0], - '@stylistic/js/no-mixed-operators': [0], - '@stylistic/js/no-mixed-spaces-and-tabs': [2], - '@stylistic/js/no-multi-spaces': [2, {ignoreEOLComments: true, exceptions: {Property: true}}], - '@stylistic/js/no-multiple-empty-lines': [2, {max: 1, maxEOF: 0, maxBOF: 0}], - '@stylistic/js/no-tabs': [2], - '@stylistic/js/no-trailing-spaces': [2], - '@stylistic/js/no-whitespace-before-property': [2], - '@stylistic/js/nonblock-statement-body-position': [2], - '@stylistic/js/object-curly-newline': [0], - '@stylistic/js/object-curly-spacing': [2, 'never'], - '@stylistic/js/object-property-newline': [0], - '@stylistic/js/one-var-declaration-per-line': [0], - '@stylistic/js/operator-linebreak': [2, 'after'], - '@stylistic/js/padded-blocks': [2, 'never'], - '@stylistic/js/padding-line-between-statements': [0], - '@stylistic/js/quote-props': [0], - '@stylistic/js/quotes': [2, 'single', {avoidEscape: true, allowTemplateLiterals: true}], - '@stylistic/js/rest-spread-spacing': [2, 'never'], - '@stylistic/js/semi': [2, 'always', {omitLastInOneLineBlock: true}], - '@stylistic/js/semi-spacing': [2, {before: false, after: true}], - '@stylistic/js/semi-style': [2, 'last'], - '@stylistic/js/space-before-blocks': [2, 'always'], - '@stylistic/js/space-before-function-paren': [2, {anonymous: 'ignore', named: 'never', asyncArrow: 'always'}], - '@stylistic/js/space-in-parens': [2, 'never'], - '@stylistic/js/space-infix-ops': [2], - '@stylistic/js/space-unary-ops': [2], - '@stylistic/js/spaced-comment': [2, 'always'], - '@stylistic/js/switch-colon-spacing': [2], - '@stylistic/js/template-curly-spacing': [2, 'never'], - '@stylistic/js/template-tag-spacing': [2, 'never'], - '@stylistic/js/wrap-iife': [2, 'inside'], - '@stylistic/js/wrap-regex': [0], - '@stylistic/js/yield-star-spacing': [2, 'after'], - '@typescript-eslint/adjacent-overload-signatures': [0], - '@typescript-eslint/array-type': [0], - '@typescript-eslint/await-thenable': [2], - '@typescript-eslint/ban-ts-comment': [2, {'ts-expect-error': false, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}], - '@typescript-eslint/ban-tslint-comment': [0], - '@typescript-eslint/class-literal-property-style': [0], - '@typescript-eslint/class-methods-use-this': [0], - '@typescript-eslint/consistent-generic-constructors': [0], - '@typescript-eslint/consistent-indexed-object-style': [0], - '@typescript-eslint/consistent-return': [0], - '@typescript-eslint/consistent-type-assertions': [2, {assertionStyle: 'as', objectLiteralTypeAssertions: 'allow'}], - '@typescript-eslint/consistent-type-definitions': [2, 'type'], - '@typescript-eslint/consistent-type-exports': [2, {fixMixedExportsWithInlineTypeSpecifier: false}], - '@typescript-eslint/consistent-type-imports': [2, {prefer: 'type-imports', fixStyle: 'separate-type-imports', disallowTypeAnnotations: true}], - '@typescript-eslint/default-param-last': [0], - '@typescript-eslint/dot-notation': [0], - '@typescript-eslint/explicit-function-return-type': [0], - '@typescript-eslint/explicit-member-accessibility': [0], - '@typescript-eslint/explicit-module-boundary-types': [0], - '@typescript-eslint/init-declarations': [0], - '@typescript-eslint/max-params': [0], - '@typescript-eslint/member-ordering': [0], - '@typescript-eslint/method-signature-style': [0], - '@typescript-eslint/naming-convention': [0], - '@typescript-eslint/no-array-constructor': [2], - '@typescript-eslint/no-array-delete': [2], - '@typescript-eslint/no-base-to-string': [0], - '@typescript-eslint/no-confusing-non-null-assertion': [2], - '@typescript-eslint/no-confusing-void-expression': [0], - '@typescript-eslint/no-deprecated': [2], - '@typescript-eslint/no-dupe-class-members': [0], - '@typescript-eslint/no-duplicate-enum-values': [2], - '@typescript-eslint/no-duplicate-type-constituents': [2, {ignoreUnions: true}], - '@typescript-eslint/no-dynamic-delete': [0], - '@typescript-eslint/no-empty-function': [0], - '@typescript-eslint/no-empty-interface': [0], - '@typescript-eslint/no-empty-object-type': [2], - '@typescript-eslint/no-explicit-any': [0], - '@typescript-eslint/no-extra-non-null-assertion': [2], - '@typescript-eslint/no-extraneous-class': [0], - '@typescript-eslint/no-floating-promises': [0], - '@typescript-eslint/no-for-in-array': [2], - '@typescript-eslint/no-implied-eval': [2], - '@typescript-eslint/no-import-type-side-effects': [0], // dupe with consistent-type-imports - '@typescript-eslint/no-inferrable-types': [0], - '@typescript-eslint/no-invalid-this': [0], - '@typescript-eslint/no-invalid-void-type': [0], - '@typescript-eslint/no-loop-func': [0], - '@typescript-eslint/no-loss-of-precision': [0], - '@typescript-eslint/no-magic-numbers': [0], - '@typescript-eslint/no-meaningless-void-operator': [0], - '@typescript-eslint/no-misused-new': [2], - '@typescript-eslint/no-misused-promises': [2, {checksVoidReturn: {attributes: false, arguments: false}}], - '@typescript-eslint/no-mixed-enums': [0], - '@typescript-eslint/no-namespace': [2], - '@typescript-eslint/no-non-null-asserted-nullish-coalescing': [0], - '@typescript-eslint/no-non-null-asserted-optional-chain': [2], - '@typescript-eslint/no-non-null-assertion': [0], - '@typescript-eslint/no-redeclare': [0], - '@typescript-eslint/no-redundant-type-constituents': [2], - '@typescript-eslint/no-require-imports': [2], - '@typescript-eslint/no-restricted-imports': [0], - '@typescript-eslint/no-restricted-types': [0], - '@typescript-eslint/no-shadow': [0], - '@typescript-eslint/no-this-alias': [0], // handled by unicorn/no-this-assignment - '@typescript-eslint/no-unnecessary-boolean-literal-compare': [0], - '@typescript-eslint/no-unnecessary-condition': [0], - '@typescript-eslint/no-unnecessary-qualifier': [0], - '@typescript-eslint/no-unnecessary-template-expression': [0], - '@typescript-eslint/no-unnecessary-type-arguments': [0], - '@typescript-eslint/no-unnecessary-type-assertion': [2], - '@typescript-eslint/no-unnecessary-type-constraint': [2], - '@typescript-eslint/no-unnecessary-type-conversion': [2], - '@typescript-eslint/no-unsafe-argument': [0], - '@typescript-eslint/no-unsafe-assignment': [0], - '@typescript-eslint/no-unsafe-call': [0], - '@typescript-eslint/no-unsafe-declaration-merging': [2], - '@typescript-eslint/no-unsafe-enum-comparison': [2], - '@typescript-eslint/no-unsafe-function-type': [2], - '@typescript-eslint/no-unsafe-member-access': [0], - '@typescript-eslint/no-unsafe-return': [0], - '@typescript-eslint/no-unsafe-unary-minus': [2], - '@typescript-eslint/no-unused-expressions': [0], - '@typescript-eslint/no-unused-vars': [2, {vars: 'all', args: 'all', caughtErrors: 'all', ignoreRestSiblings: false, argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_'}], - '@typescript-eslint/no-use-before-define': [2, {functions: false, classes: true, variables: true, allowNamedExports: true, typedefs: false, enums: false, ignoreTypeReferences: true}], - '@typescript-eslint/no-useless-constructor': [0], - '@typescript-eslint/no-useless-empty-export': [0], - '@typescript-eslint/no-wrapper-object-types': [2], - '@typescript-eslint/non-nullable-type-assertion-style': [0], - '@typescript-eslint/only-throw-error': [2], - '@typescript-eslint/parameter-properties': [0], - '@typescript-eslint/prefer-as-const': [2], - '@typescript-eslint/prefer-destructuring': [0], - '@typescript-eslint/prefer-enum-initializers': [0], - '@typescript-eslint/prefer-find': [2], - '@typescript-eslint/prefer-for-of': [2], - '@typescript-eslint/prefer-function-type': [2], - '@typescript-eslint/prefer-includes': [2], - '@typescript-eslint/prefer-literal-enum-member': [0], - '@typescript-eslint/prefer-namespace-keyword': [0], - '@typescript-eslint/prefer-nullish-coalescing': [0], - '@typescript-eslint/prefer-optional-chain': [2, {requireNullish: true}], - '@typescript-eslint/prefer-promise-reject-errors': [0], - '@typescript-eslint/prefer-readonly': [0], - '@typescript-eslint/prefer-readonly-parameter-types': [0], - '@typescript-eslint/prefer-reduce-type-parameter': [0], - '@typescript-eslint/prefer-regexp-exec': [0], - '@typescript-eslint/prefer-return-this-type': [0], - '@typescript-eslint/prefer-string-starts-ends-with': [2, {allowSingleElementEquality: 'always'}], - '@typescript-eslint/promise-function-async': [0], - '@typescript-eslint/require-array-sort-compare': [0], - '@typescript-eslint/require-await': [0], - '@typescript-eslint/restrict-plus-operands': [2], - '@typescript-eslint/restrict-template-expressions': [0], - '@typescript-eslint/return-await': [0], - '@typescript-eslint/strict-boolean-expressions': [0], - '@typescript-eslint/switch-exhaustiveness-check': [0], - '@typescript-eslint/triple-slash-reference': [2], - '@typescript-eslint/typedef': [0], - '@typescript-eslint/unbound-method': [0], // too many false-positives - '@typescript-eslint/unified-signatures': [2], - 'accessor-pairs': [2], - 'array-callback-return': [2, {checkForEach: true}], - 'array-func/avoid-reverse': [2], - 'array-func/from-map': [2], - 'array-func/no-unnecessary-this-arg': [2], - 'array-func/prefer-array-from': [2], - 'array-func/prefer-flat-map': [0], // handled by unicorn/prefer-array-flat-map - 'array-func/prefer-flat': [0], // handled by unicorn/prefer-array-flat - 'arrow-body-style': [0], - 'block-scoped-var': [2], - 'camelcase': [0], - 'capitalized-comments': [0], - 'class-methods-use-this': [0], - 'complexity': [0], - 'consistent-return': [0], - 'consistent-this': [0], - 'constructor-super': [2], - 'curly': [0], - 'default-case-last': [2], - 'default-case': [0], - 'default-param-last': [0], - 'dot-notation': [0], - 'eqeqeq': [2], - 'for-direction': [2], - 'func-name-matching': [2], - 'func-names': [0], - 'func-style': [0], - 'getter-return': [2], - 'github/a11y-aria-label-is-well-formatted': [0], - 'github/a11y-no-title-attribute': [0], - 'github/a11y-no-visually-hidden-interactive-element': [0], - 'github/a11y-role-supports-aria-props': [0], - 'github/a11y-svg-has-accessible-name': [0], - 'github/array-foreach': [0], - 'github/async-currenttarget': [2], - 'github/async-preventdefault': [0], // https://github.com/github/eslint-plugin-github/issues/599 - 'github/authenticity-token': [0], - 'github/get-attribute': [0], - 'github/js-class-name': [0], - 'github/no-blur': [0], - 'github/no-d-none': [0], - 'github/no-dataset': [2], - 'github/no-dynamic-script-tag': [2], - 'github/no-implicit-buggy-globals': [2], - 'github/no-inner-html': [0], - 'github/no-innerText': [2], - 'github/no-then': [2], - 'github/no-useless-passive': [2], - 'github/prefer-observers': [2], - 'github/require-passive-events': [2], - 'github/unescaped-html-literal': [2], - 'grouped-accessor-pairs': [2], - 'guard-for-in': [0], - 'id-blacklist': [0], - 'id-length': [0], - 'id-match': [0], - 'import-x/consistent-type-specifier-style': [0], - 'import-x/default': [0], - 'import-x/dynamic-import-chunkname': [0], - 'import-x/export': [2], - 'import-x/exports-last': [0], - 'import-x/extensions': [2, 'always', {ignorePackages: true}], - 'import-x/first': [2], - 'import-x/group-exports': [0], - 'import-x/max-dependencies': [0], - 'import-x/named': [2], - 'import-x/namespace': [0], - 'import-x/newline-after-import': [0], - 'import-x/no-absolute-path': [0], - 'import-x/no-amd': [2], - 'import-x/no-anonymous-default-export': [0], - 'import-x/no-commonjs': [2], - 'import-x/no-cycle': [2, {ignoreExternal: true, maxDepth: 1}], - 'import-x/no-default-export': [0], - 'import-x/no-deprecated': [0], - 'import-x/no-dynamic-require': [0], - 'import-x/no-empty-named-blocks': [2], - 'import-x/no-extraneous-dependencies': [2], - 'import-x/no-import-module-exports': [0], - 'import-x/no-internal-modules': [0], - 'import-x/no-mutable-exports': [0], - 'import-x/no-named-as-default-member': [0], - 'import-x/no-named-as-default': [0], - 'import-x/no-named-default': [0], - 'import-x/no-named-export': [0], - 'import-x/no-namespace': [0], - 'import-x/no-nodejs-modules': [0], - 'import-x/no-relative-packages': [0], - 'import-x/no-relative-parent-imports': [0], - 'import-x/no-restricted-paths': [0], - 'import-x/no-self-import': [2], - 'import-x/no-unassigned-import': [0], - 'import-x/no-unresolved': [2, {commonjs: true, ignore: ['\\?.+$']}], - 'import-x/no-unused-modules': [2, {unusedExports: true}], - 'import-x/no-useless-path-segments': [2, {commonjs: true}], - 'import-x/no-webpack-loader-syntax': [2], - 'import-x/order': [0], - 'import-x/prefer-default-export': [0], - 'import-x/unambiguous': [0], - 'init-declarations': [0], - 'line-comment-position': [0], - 'logical-assignment-operators': [0], - 'max-classes-per-file': [0], - 'max-depth': [0], - 'max-lines-per-function': [0], - 'max-lines': [0], - 'max-nested-callbacks': [0], - 'max-params': [0], - 'max-statements': [0], - 'multiline-comment-style': [0], - 'new-cap': [0], - 'no-alert': [0], - 'no-array-constructor': [0], // handled by @typescript-eslint/no-array-constructor - 'no-async-promise-executor': [0], - 'no-await-in-loop': [0], - 'no-bitwise': [0], - 'no-buffer-constructor': [0], - 'no-caller': [2], - 'no-case-declarations': [2], - 'no-class-assign': [2], - 'no-compare-neg-zero': [2], - 'no-cond-assign': [2, 'except-parens'], - 'no-console': [1, {allow: ['debug', 'info', 'warn', 'error']}], - 'no-const-assign': [2], - 'no-constant-binary-expression': [2], - 'no-constant-condition': [0], - 'no-constructor-return': [2], - 'no-continue': [0], - 'no-control-regex': [0], - 'no-debugger': [1], - 'no-delete-var': [2], - 'no-div-regex': [0], - 'no-dupe-args': [2], - 'no-dupe-class-members': [2], - 'no-dupe-else-if': [2], - 'no-dupe-keys': [2], - 'no-duplicate-case': [2], - 'no-duplicate-imports': [0], - 'no-else-return': [2], - 'no-empty-character-class': [2], - 'no-empty-function': [0], - 'no-empty-pattern': [2], - 'no-empty-static-block': [2], - 'no-empty': [2, {allowEmptyCatch: true}], - 'no-eq-null': [2], - 'no-eval': [2], - 'no-ex-assign': [2], - 'no-extend-native': [2], - 'no-extra-bind': [2], - 'no-extra-boolean-cast': [2], - 'no-extra-label': [0], - 'no-fallthrough': [2], - 'no-func-assign': [2], - 'no-global-assign': [2], - 'no-implicit-coercion': [2], - 'no-implicit-globals': [0], - 'no-implied-eval': [0], // handled by @typescript-eslint/no-implied-eval - 'no-import-assign': [2], - 'no-inline-comments': [0], - 'no-inner-declarations': [2], - 'no-invalid-regexp': [2], - 'no-invalid-this': [0], - 'no-irregular-whitespace': [2], - 'no-iterator': [2], - 'no-jquery/no-ajax-events': [2], - 'no-jquery/no-ajax': [2], - 'no-jquery/no-and-self': [2], - 'no-jquery/no-animate-toggle': [2], - 'no-jquery/no-animate': [2], - 'no-jquery/no-append-html': [2], - 'no-jquery/no-attr': [2], - 'no-jquery/no-bind': [2], - 'no-jquery/no-box-model': [2], - 'no-jquery/no-browser': [2], - 'no-jquery/no-camel-case': [2], - 'no-jquery/no-class-state': [2], - 'no-jquery/no-class': [0], - 'no-jquery/no-clone': [2], - 'no-jquery/no-closest': [0], - 'no-jquery/no-constructor-attributes': [2], - 'no-jquery/no-contains': [2], - 'no-jquery/no-context-prop': [2], - 'no-jquery/no-css': [2], - 'no-jquery/no-data': [0], - 'no-jquery/no-deferred': [2], - 'no-jquery/no-delegate': [2], - 'no-jquery/no-done-fail': [2], - 'no-jquery/no-each-collection': [0], - 'no-jquery/no-each-util': [0], - 'no-jquery/no-each': [0], - 'no-jquery/no-error-shorthand': [2], - 'no-jquery/no-error': [2], - 'no-jquery/no-escape-selector': [2], - 'no-jquery/no-event-shorthand': [2], - 'no-jquery/no-extend': [2], - 'no-jquery/no-fade': [2], - 'no-jquery/no-filter': [0], - 'no-jquery/no-find-collection': [0], - 'no-jquery/no-find-util': [2], - 'no-jquery/no-find': [0], - 'no-jquery/no-fx-interval': [2], - 'no-jquery/no-fx': [2], - 'no-jquery/no-global-eval': [2], - 'no-jquery/no-global-selector': [0], - 'no-jquery/no-grep': [2], - 'no-jquery/no-has': [2], - 'no-jquery/no-hold-ready': [2], - 'no-jquery/no-html': [0], - 'no-jquery/no-in-array': [2], - 'no-jquery/no-is-array': [2], - 'no-jquery/no-is-empty-object': [2], - 'no-jquery/no-is-function': [2], - 'no-jquery/no-is-numeric': [2], - 'no-jquery/no-is-plain-object': [2], - 'no-jquery/no-is-window': [2], - 'no-jquery/no-is': [2], - 'no-jquery/no-jquery-constructor': [0], - 'no-jquery/no-live': [2], - 'no-jquery/no-load-shorthand': [2], - 'no-jquery/no-load': [2], - 'no-jquery/no-map-collection': [0], - 'no-jquery/no-map-util': [2], - 'no-jquery/no-map': [2], - 'no-jquery/no-merge': [2], - 'no-jquery/no-node-name': [2], - 'no-jquery/no-noop': [2], - 'no-jquery/no-now': [2], - 'no-jquery/no-on-ready': [2], - 'no-jquery/no-other-methods': [0], - 'no-jquery/no-other-utils': [2], - 'no-jquery/no-param': [2], - 'no-jquery/no-parent': [0], - 'no-jquery/no-parents': [2], - 'no-jquery/no-parse-html-literal': [2], - 'no-jquery/no-parse-html': [2], - 'no-jquery/no-parse-json': [2], - 'no-jquery/no-parse-xml': [2], - 'no-jquery/no-prop': [2], - 'no-jquery/no-proxy': [2], - 'no-jquery/no-ready-shorthand': [2], - 'no-jquery/no-ready': [2], - 'no-jquery/no-selector-prop': [2], - 'no-jquery/no-serialize': [2], - 'no-jquery/no-size': [2], - 'no-jquery/no-sizzle': [2], - 'no-jquery/no-slide': [2], - 'no-jquery/no-sub': [2], - 'no-jquery/no-support': [2], - 'no-jquery/no-text': [2], - 'no-jquery/no-trigger': [0], - 'no-jquery/no-trim': [2], - 'no-jquery/no-type': [2], - 'no-jquery/no-unique': [2], - 'no-jquery/no-unload-shorthand': [2], - 'no-jquery/no-val': [0], - 'no-jquery/no-visibility': [2], - 'no-jquery/no-when': [2], - 'no-jquery/no-wrap': [2], - 'no-jquery/variable-pattern': [2], - 'no-label-var': [2], - 'no-labels': [0], // handled by no-restricted-syntax - 'no-lone-blocks': [2], - 'no-lonely-if': [0], - 'no-loop-func': [0], - 'no-loss-of-precision': [2], - 'no-magic-numbers': [0], - 'no-misleading-character-class': [2], - 'no-multi-assign': [0], - 'no-multi-str': [2], - 'no-negated-condition': [0], - 'no-nested-ternary': [0], - 'no-new-func': [0], // handled by @typescript-eslint/no-implied-eval - 'no-new-native-nonconstructor': [2], - 'no-new-object': [2], - 'no-new-symbol': [2], - 'no-new-wrappers': [2], - 'no-new': [0], - 'no-nonoctal-decimal-escape': [2], - 'no-obj-calls': [2], - 'no-octal-escape': [2], - 'no-octal': [2], - 'no-param-reassign': [0], - 'no-plusplus': [0], - 'no-promise-executor-return': [0], - 'no-proto': [2], - 'no-prototype-builtins': [2], - 'no-redeclare': [0], // must be disabled for typescript overloads - 'no-regex-spaces': [2], - 'no-restricted-exports': [0], - 'no-restricted-globals': [2, 'addEventListener', 'blur', 'close', 'closed', 'confirm', 'defaultStatus', 'defaultstatus', 'error', 'event', 'external', 'find', 'focus', 'frameElement', 'frames', 'history', 'innerHeight', 'innerWidth', 'isFinite', 'isNaN', 'length', 'locationbar', 'menubar', 'moveBy', 'moveTo', 'name', 'onblur', 'onerror', 'onfocus', 'onload', 'onresize', 'onunload', 'open', 'opener', 'opera', 'outerHeight', 'outerWidth', 'pageXOffset', 'pageYOffset', 'parent', 'print', 'removeEventListener', 'resizeBy', 'resizeTo', 'screen', 'screenLeft', 'screenTop', 'screenX', 'screenY', 'scroll', 'scrollbars', 'scrollBy', 'scrollTo', 'scrollX', 'scrollY', 'status', 'statusbar', 'stop', 'toolbar', 'top'], - 'no-restricted-imports': [0], - 'no-restricted-syntax': [2, ...restrictedSyntax, {selector: 'CallExpression[callee.name="fetch"]', message: 'use modules/fetch.ts instead'}], - 'no-return-assign': [0], - 'no-script-url': [2], - 'no-self-assign': [2, {props: true}], - 'no-self-compare': [2], - 'no-sequences': [2], - 'no-setter-return': [2], - 'no-shadow-restricted-names': [2], - 'no-shadow': [0], - 'no-sparse-arrays': [2], - 'no-template-curly-in-string': [2], - 'no-ternary': [0], - 'no-this-before-super': [2], - 'no-throw-literal': [2], - 'no-undef-init': [2], - 'no-undef': [2], // it is still needed by eslint & IDE to prompt undefined names in real time - 'no-undefined': [0], - 'no-underscore-dangle': [0], - 'no-unexpected-multiline': [2], - 'no-unmodified-loop-condition': [2], - 'no-unneeded-ternary': [2], - 'no-unreachable-loop': [2], - 'no-unreachable': [2], - 'no-unsafe-finally': [2], - 'no-unsafe-negation': [2], - 'no-unused-expressions': [2], - 'no-unused-labels': [2], - 'no-unused-private-class-members': [2], - 'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars - 'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define - 'no-use-extend-native/no-use-extend-native': [2], - 'no-useless-backreference': [2], - 'no-useless-call': [2], - 'no-useless-catch': [2], - 'no-useless-computed-key': [2], - 'no-useless-concat': [2], - 'no-useless-constructor': [2], - 'no-useless-escape': [2], - 'no-useless-rename': [2], - 'no-useless-return': [2], - 'no-var': [2], - 'no-void': [2], - 'no-warning-comments': [0], - 'no-with': [0], // handled by no-restricted-syntax - 'object-shorthand': [2, 'always'], - 'one-var-declaration-per-line': [0], - 'one-var': [0], - 'operator-assignment': [2, 'always'], - 'operator-linebreak': [2, 'after'], - 'prefer-arrow-callback': [2, {allowNamedFunctions: true, allowUnboundThis: true}], - 'prefer-const': [2, {destructuring: 'all', ignoreReadBeforeAssign: true}], - 'prefer-destructuring': [0], - 'prefer-exponentiation-operator': [2], - 'prefer-named-capture-group': [0], - 'prefer-numeric-literals': [2], - 'prefer-object-has-own': [2], - 'prefer-object-spread': [2], - 'prefer-promise-reject-errors': [2, {allowEmptyReject: false}], - 'prefer-regex-literals': [2], - 'prefer-rest-params': [2], - 'prefer-spread': [2], - 'prefer-template': [2], - 'radix': [2, 'as-needed'], - 'regexp/confusing-quantifier': [2], - 'regexp/control-character-escape': [2], - 'regexp/hexadecimal-escape': [0], - 'regexp/letter-case': [0], - 'regexp/match-any': [2], - 'regexp/negation': [2], - 'regexp/no-contradiction-with-assertion': [0], - 'regexp/no-control-character': [0], - 'regexp/no-dupe-characters-character-class': [2], - 'regexp/no-dupe-disjunctions': [2], - 'regexp/no-empty-alternative': [2], - 'regexp/no-empty-capturing-group': [2], - 'regexp/no-empty-character-class': [0], - 'regexp/no-empty-group': [2], - 'regexp/no-empty-lookarounds-assertion': [2], - 'regexp/no-empty-string-literal': [2], - 'regexp/no-escape-backspace': [2], - 'regexp/no-extra-lookaround-assertions': [0], - 'regexp/no-invalid-regexp': [2], - 'regexp/no-invisible-character': [2], - 'regexp/no-lazy-ends': [2], - 'regexp/no-legacy-features': [2], - 'regexp/no-misleading-capturing-group': [0], - 'regexp/no-misleading-unicode-character': [0], - 'regexp/no-missing-g-flag': [2], - 'regexp/no-non-standard-flag': [2], - 'regexp/no-obscure-range': [2], - 'regexp/no-octal': [2], - 'regexp/no-optional-assertion': [2], - 'regexp/no-potentially-useless-backreference': [2], - 'regexp/no-standalone-backslash': [2], - 'regexp/no-super-linear-backtracking': [0], - 'regexp/no-super-linear-move': [0], - 'regexp/no-trivially-nested-assertion': [2], - 'regexp/no-trivially-nested-quantifier': [2], - 'regexp/no-unused-capturing-group': [0], - 'regexp/no-useless-assertions': [2], - 'regexp/no-useless-backreference': [2], - 'regexp/no-useless-character-class': [2], - 'regexp/no-useless-dollar-replacements': [2], - 'regexp/no-useless-escape': [2], - 'regexp/no-useless-flag': [2], - 'regexp/no-useless-lazy': [2], - 'regexp/no-useless-non-capturing-group': [2], - 'regexp/no-useless-quantifier': [2], - 'regexp/no-useless-range': [2], - 'regexp/no-useless-set-operand': [2], - 'regexp/no-useless-string-literal': [2], - 'regexp/no-useless-two-nums-quantifier': [2], - 'regexp/no-zero-quantifier': [2], - 'regexp/optimal-lookaround-quantifier': [2], - 'regexp/optimal-quantifier-concatenation': [0], - 'regexp/prefer-character-class': [0], - 'regexp/prefer-d': [0], - 'regexp/prefer-escape-replacement-dollar-char': [0], - 'regexp/prefer-lookaround': [0], - 'regexp/prefer-named-backreference': [0], - 'regexp/prefer-named-capture-group': [0], - 'regexp/prefer-named-replacement': [0], - 'regexp/prefer-plus-quantifier': [2], - 'regexp/prefer-predefined-assertion': [2], - 'regexp/prefer-quantifier': [0], - 'regexp/prefer-question-quantifier': [2], - 'regexp/prefer-range': [2], - 'regexp/prefer-regexp-exec': [2], - 'regexp/prefer-regexp-test': [2], - 'regexp/prefer-result-array-groups': [0], - 'regexp/prefer-set-operation': [2], - 'regexp/prefer-star-quantifier': [2], - 'regexp/prefer-unicode-codepoint-escapes': [2], - 'regexp/prefer-w': [0], - 'regexp/require-unicode-regexp': [0], - 'regexp/simplify-set-operations': [2], - 'regexp/sort-alternatives': [0], - 'regexp/sort-character-class-elements': [0], - 'regexp/sort-flags': [0], - 'regexp/strict': [2], - 'regexp/unicode-escape': [0], - 'regexp/use-ignore-case': [0], - 'require-atomic-updates': [0], - 'require-await': [0], // handled by @typescript-eslint/require-await - 'require-unicode-regexp': [0], - 'require-yield': [2], - 'sonarjs/cognitive-complexity': [0], - 'sonarjs/elseif-without-else': [0], - 'sonarjs/max-switch-cases': [0], - 'sonarjs/no-all-duplicated-branches': [2], - 'sonarjs/no-collapsible-if': [0], - 'sonarjs/no-collection-size-mischeck': [2], - 'sonarjs/no-duplicate-string': [0], - 'sonarjs/no-duplicated-branches': [0], - 'sonarjs/no-element-overwrite': [2], - 'sonarjs/no-empty-collection': [2], - 'sonarjs/no-extra-arguments': [2], - 'sonarjs/no-gratuitous-expressions': [2], - 'sonarjs/no-identical-conditions': [2], - 'sonarjs/no-identical-expressions': [2], - 'sonarjs/no-identical-functions': [2, 5], - 'sonarjs/no-ignored-return': [2], - 'sonarjs/no-inverted-boolean-check': [2], - 'sonarjs/no-nested-switch': [0], - 'sonarjs/no-nested-template-literals': [0], - 'sonarjs/no-redundant-boolean': [2], - 'sonarjs/no-redundant-jump': [2], - 'sonarjs/no-same-line-conditional': [2], - 'sonarjs/no-small-switch': [0], - 'sonarjs/no-unused-collection': [2], - 'sonarjs/no-use-of-empty-return-value': [2], - 'sonarjs/no-useless-catch': [2], - 'sonarjs/non-existent-operator': [2], - 'sonarjs/prefer-immediate-return': [0], - 'sonarjs/prefer-object-literal': [0], - 'sonarjs/prefer-single-boolean-return': [0], - 'sonarjs/prefer-while': [2], - 'sort-imports': [0], - 'sort-keys': [0], - 'sort-vars': [0], - 'strict': [0], - 'symbol-description': [2], - 'unicode-bom': [2, 'never'], - 'unicorn/better-regex': [0], - 'unicorn/catch-error-name': [0], - 'unicorn/consistent-destructuring': [2], - 'unicorn/consistent-empty-array-spread': [2], - 'unicorn/consistent-existence-index-check': [0], - 'unicorn/consistent-function-scoping': [0], - 'unicorn/custom-error-definition': [0], - 'unicorn/empty-brace-spaces': [2], - 'unicorn/error-message': [0], - 'unicorn/escape-case': [0], - 'unicorn/expiring-todo-comments': [0], - 'unicorn/explicit-length-check': [0], - 'unicorn/filename-case': [0], - 'unicorn/import-index': [0], - 'unicorn/import-style': [0], - 'unicorn/new-for-builtins': [2], - 'unicorn/no-abusive-eslint-disable': [0], - 'unicorn/no-anonymous-default-export': [0], - 'unicorn/no-array-callback-reference': [0], - 'unicorn/no-array-for-each': [2], - 'unicorn/no-array-method-this-argument': [2], - 'unicorn/no-array-push-push': [2], - 'unicorn/no-array-reduce': [2], - 'unicorn/no-await-expression-member': [0], - 'unicorn/no-await-in-promise-methods': [2], - 'unicorn/no-console-spaces': [0], - 'unicorn/no-document-cookie': [2], - 'unicorn/no-empty-file': [2], - 'unicorn/no-for-loop': [0], - 'unicorn/no-hex-escape': [0], - 'unicorn/no-instanceof-array': [0], - 'unicorn/no-invalid-fetch-options': [2], - 'unicorn/no-invalid-remove-event-listener': [2], - 'unicorn/no-keyword-prefix': [0], - 'unicorn/no-length-as-slice-end': [2], - 'unicorn/no-lonely-if': [2], - 'unicorn/no-magic-array-flat-depth': [0], - 'unicorn/no-negated-condition': [0], - 'unicorn/no-negation-in-equality-check': [2], - 'unicorn/no-nested-ternary': [0], - 'unicorn/no-new-array': [0], - 'unicorn/no-new-buffer': [0], - 'unicorn/no-null': [0], - 'unicorn/no-object-as-default-parameter': [0], - 'unicorn/no-process-exit': [0], - 'unicorn/no-single-promise-in-promise-methods': [2], - 'unicorn/no-static-only-class': [2], - 'unicorn/no-thenable': [2], - 'unicorn/no-this-assignment': [2], - 'unicorn/no-typeof-undefined': [2], - 'unicorn/no-unnecessary-await': [2], - 'unicorn/no-unnecessary-polyfills': [2], - 'unicorn/no-unreadable-array-destructuring': [0], - 'unicorn/no-unreadable-iife': [2], - 'unicorn/no-unused-properties': [2], - 'unicorn/no-useless-fallback-in-spread': [2], - 'unicorn/no-useless-length-check': [2], - 'unicorn/no-useless-promise-resolve-reject': [2], - 'unicorn/no-useless-spread': [2], - 'unicorn/no-useless-switch-case': [2], - 'unicorn/no-useless-undefined': [0], - 'unicorn/no-zero-fractions': [2], - 'unicorn/number-literal-case': [0], - 'unicorn/numeric-separators-style': [0], - 'unicorn/prefer-add-event-listener': [2], - 'unicorn/prefer-array-find': [2], - 'unicorn/prefer-array-flat-map': [2], - 'unicorn/prefer-array-flat': [2], - 'unicorn/prefer-array-index-of': [2], - 'unicorn/prefer-array-some': [2], - 'unicorn/prefer-at': [0], - 'unicorn/prefer-blob-reading-methods': [2], - 'unicorn/prefer-code-point': [0], - 'unicorn/prefer-date-now': [2], - 'unicorn/prefer-default-parameters': [0], - 'unicorn/prefer-dom-node-append': [2], - 'unicorn/prefer-dom-node-dataset': [0], - 'unicorn/prefer-dom-node-remove': [2], - 'unicorn/prefer-dom-node-text-content': [2], - 'unicorn/prefer-event-target': [2], - 'unicorn/prefer-export-from': [0], - 'unicorn/prefer-global-this': [0], - 'unicorn/prefer-includes': [2], - 'unicorn/prefer-json-parse-buffer': [0], - 'unicorn/prefer-keyboard-event-key': [2], - 'unicorn/prefer-logical-operator-over-ternary': [2], - 'unicorn/prefer-math-min-max': [2], - 'unicorn/prefer-math-trunc': [2], - 'unicorn/prefer-modern-dom-apis': [0], - 'unicorn/prefer-modern-math-apis': [2], - 'unicorn/prefer-module': [2], - 'unicorn/prefer-native-coercion-functions': [2], - 'unicorn/prefer-negative-index': [2], - 'unicorn/prefer-node-protocol': [2], - 'unicorn/prefer-number-properties': [0], - 'unicorn/prefer-object-from-entries': [2], - 'unicorn/prefer-object-has-own': [0], - 'unicorn/prefer-optional-catch-binding': [2], - 'unicorn/prefer-prototype-methods': [0], - 'unicorn/prefer-query-selector': [2], - 'unicorn/prefer-reflect-apply': [0], - 'unicorn/prefer-regexp-test': [2], - 'unicorn/prefer-set-has': [0], - 'unicorn/prefer-set-size': [2], - 'unicorn/prefer-spread': [0], - 'unicorn/prefer-string-raw': [0], - 'unicorn/prefer-string-replace-all': [0], - 'unicorn/prefer-string-slice': [0], - 'unicorn/prefer-string-starts-ends-with': [2], - 'unicorn/prefer-string-trim-start-end': [2], - 'unicorn/prefer-structured-clone': [2], - 'unicorn/prefer-switch': [0], - 'unicorn/prefer-ternary': [0], - 'unicorn/prefer-text-content': [2], - 'unicorn/prefer-top-level-await': [0], - 'unicorn/prefer-type-error': [0], - 'unicorn/prevent-abbreviations': [0], - 'unicorn/relative-url-style': [2], - 'unicorn/require-array-join-separator': [2], - 'unicorn/require-number-to-fixed-digits-argument': [2], - 'unicorn/require-post-message-target-origin': [0], - 'unicorn/string-content': [0], - 'unicorn/switch-case-braces': [0], - 'unicorn/template-indent': [2], - 'unicorn/text-encoding-identifier-case': [0], - 'unicorn/throw-new-error': [2], - 'use-isnan': [2], - 'valid-typeof': [2, {requireStringLiterals: true}], - 'vars-on-top': [0], - 'wc/attach-shadow-constructor': [2], - 'wc/define-tag-after-class-definition': [0], - 'wc/expose-class-on-global': [0], - 'wc/file-name-matches-element': [2], - 'wc/guard-define-call': [0], - 'wc/guard-super-call': [2], - 'wc/max-elements-per-file': [0], - 'wc/no-child-traversal-in-attributechangedcallback': [2], - 'wc/no-child-traversal-in-connectedcallback': [2], - 'wc/no-closed-shadow-root': [2], - 'wc/no-constructor-attributes': [2], - 'wc/no-constructor-params': [2], - 'wc/no-constructor': [2], - 'wc/no-customized-built-in-elements': [2], - 'wc/no-exports-with-element': [0], - 'wc/no-invalid-element-name': [2], - 'wc/no-invalid-extends': [2], - 'wc/no-method-prefixed-with-on': [2], - 'wc/no-self-class': [2], - 'wc/no-typos': [2], - 'wc/require-listener-teardown': [2], - 'wc/tag-name-matches-class': [2], - 'yoda': [2, 'never'], - }, -}; diff --git a/Makefile b/Makefile index 1fb4a40d71..637e64210a 100644 --- a/Makefile +++ b/Makefile @@ -162,7 +162,7 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST) GO_DIRS := build cmd models modules routers services tests WEB_DIRS := web_src/js web_src/css -ESLINT_FILES := web_src/js tools *.ts *.cjs tests/e2e +ESLINT_FILES := web_src/js tools *.ts tests/e2e STYLELINT_FILES := web_src/css web_src/js/components/*.vue SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.md *.yml *.yaml *.toml)) $(filter-out tools/misspellings.csv, $(wildcard tools/*)) EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini @@ -346,12 +346,12 @@ lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backen .PHONY: lint-js lint-js: node_modules ## lint js files - $(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --ext js,ts,vue $(ESLINT_FILES) + $(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES) $(NODE_VARS) pnpm exec vue-tsc .PHONY: lint-js-fix lint-js-fix: node_modules ## lint js files and fix issues - $(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --ext js,ts,vue $(ESLINT_FILES) --fix + $(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES) --fix $(NODE_VARS) pnpm exec vue-tsc .PHONY: lint-css diff --git a/assets/go-licenses.json b/assets/go-licenses.json index d645009d90..9c19080e24 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -579,11 +579,6 @@ "path": "github.com/go-webauthn/x/revoke/LICENSE", "licenseText": "Copyright (c) 2014 CloudFlare Inc.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\nRedistributions of source code must retain the above copyright notice,\nthis list of conditions and the following disclaimer.\n\nRedistributions in binary form must reproduce the above copyright notice,\nthis list of conditions and the following disclaimer in the documentation\nand/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nHOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED\nTO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" }, - { - "name": "github.com/gobwas/glob", - "path": "github.com/gobwas/glob/LICENSE", - "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2016 Sergey Kamardin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE." - }, { "name": "github.com/goccy/go-json", "path": "github.com/goccy/go-json/LICENSE", diff --git a/cmd/dump.go b/cmd/dump.go index fa135079c0..7f0b23ed98 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -265,6 +265,7 @@ func runDump(ctx context.Context, cmd *cli.Command) error { excludes = append(excludes, setting.LFS.Storage.Path) excludes = append(excludes, setting.Attachment.Storage.Path) excludes = append(excludes, setting.Packages.Storage.Path) + excludes = append(excludes, setting.RepoArchive.Storage.Path) excludes = append(excludes, setting.Log.RootPath) if err := dumper.AddRecursiveExclude("data", setting.AppDataPath, excludes); err != nil { fatal("Failed to include data directory: %v", err) diff --git a/cmd/embedded.go b/cmd/embedded.go index 1908352453..9180407fd1 100644 --- a/cmd/embedded.go +++ b/cmd/embedded.go @@ -12,6 +12,7 @@ import ( "strings" "code.gitea.io/gitea/modules/assetfs" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/options" "code.gitea.io/gitea/modules/public" @@ -19,7 +20,6 @@ import ( "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/util" - "github.com/gobwas/glob" "github.com/urfave/cli/v3" ) diff --git a/cmd/hook.go b/cmd/hook.go index b741127ca3..2f866dd396 100644 --- a/cmd/hook.go +++ b/cmd/hook.go @@ -15,6 +15,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" repo_module "code.gitea.io/gitea/modules/repository" @@ -312,7 +313,7 @@ func runHookPostReceive(ctx context.Context, c *cli.Command) error { setup(ctx, c.Bool("debug")) // First of all run update-server-info no matter what - if _, _, err := git.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil { + if _, _, err := gitcmd.NewCommand("update-server-info").RunStdString(ctx, nil); err != nil { return fmt.Errorf("failed to call 'git update-server-info': %w", err) } diff --git a/cmd/serv.go b/cmd/serv.go index 60f7fb92ff..76d8c81544 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -21,6 +21,7 @@ import ( "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/lfstransfer" "code.gitea.io/gitea/modules/log" @@ -312,30 +313,30 @@ func runServ(ctx context.Context, c *cli.Command) error { return nil } - var gitcmd *exec.Cmd - gitBinPath := filepath.Dir(git.GitExecutable) // e.g. /usr/bin - gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack + var command *exec.Cmd + gitBinPath := filepath.Dir(gitcmd.GitExecutable) // e.g. /usr/bin + gitBinVerb := filepath.Join(gitBinPath, verb) // e.g. /usr/bin/git-upload-pack if _, err := os.Stat(gitBinVerb); err != nil { // if the command "git-upload-pack" doesn't exist, try to split "git-upload-pack" to use the sub-command with git // ps: Windows only has "git.exe" in the bin path, so Windows always uses this way verbFields := strings.SplitN(verb, "-", 2) if len(verbFields) == 2 { // use git binary with the sub-command part: "C:\...\bin\git.exe", "upload-pack", ... - gitcmd = exec.CommandContext(ctx, git.GitExecutable, verbFields[1], repoPath) + command = exec.CommandContext(ctx, gitcmd.GitExecutable, verbFields[1], repoPath) } } - if gitcmd == nil { + if command == nil { // by default, use the verb (it has been checked above by allowedCommands) - gitcmd = exec.CommandContext(ctx, gitBinVerb, repoPath) + command = exec.CommandContext(ctx, gitBinVerb, repoPath) } - process.SetSysProcAttribute(gitcmd) - gitcmd.Dir = setting.RepoRootPath - gitcmd.Stdout = os.Stdout - gitcmd.Stdin = os.Stdin - gitcmd.Stderr = os.Stderr - gitcmd.Env = append(gitcmd.Env, os.Environ()...) - gitcmd.Env = append(gitcmd.Env, + process.SetSysProcAttribute(command) + command.Dir = setting.RepoRootPath + command.Stdout = os.Stdout + command.Stdin = os.Stdin + command.Stderr = os.Stderr + command.Env = append(command.Env, os.Environ()...) + command.Env = append(command.Env, repo_module.EnvRepoIsWiki+"="+strconv.FormatBool(results.IsWiki), repo_module.EnvRepoName+"="+results.RepoName, repo_module.EnvRepoUsername+"="+results.OwnerName, @@ -350,9 +351,9 @@ func runServ(ctx context.Context, c *cli.Command) error { ) // to avoid breaking, here only use the minimal environment variables for the "gitea serv" command. // it could be re-considered whether to use the same git.CommonGitCmdEnvs() as "git" command later. - gitcmd.Env = append(gitcmd.Env, git.CommonCmdServEnvs()...) + command.Env = append(command.Env, gitcmd.CommonCmdServEnvs()...) - if err = gitcmd.Run(); err != nil { + if err = command.Run(); err != nil { return fail(ctx, "Failed to execute git command", "Failed to execute git command: %v", err) } diff --git a/contrib/backport/README b/contrib/backport/README index 1e84c1bb97..466b79c6d4 100644 --- a/contrib/backport/README +++ b/contrib/backport/README @@ -11,7 +11,7 @@ The default version will read from `docs/config.yml`. You can override this using the option `--version`. The upstream branches will be fetched, using the remote `origin`. This can -be overrided using `--upstream`, and fetching can be avoided using +be overridden using `--upstream`, and fetching can be avoided using `--no-fetch`. By default the branch created will be called `backport-$PR-$VERSION`. You diff --git a/contrib/legal/privacy.html.sample b/contrib/legal/privacy.html.sample index 50972b2a3e..adb3ea7ad4 100644 --- a/contrib/legal/privacy.html.sample +++ b/contrib/legal/privacy.html.sample @@ -150,7 +150,7 @@

In general, Your Gitea Instance retains User Personal Information for as long as your account is active, or as needed to provide you service.

-

If you would like to cancel your account or delete your User Personal Information, you may do so in your user profile. We retain and use your information as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements, but barring legal requirements, we will delete your full profile (within reason) within 90 days of your request. Feel free to contact our support to request erasure of the data we process on the bassis of consent within 30 days.

+

If you would like to cancel your account or delete your User Personal Information, you may do so in your user profile. We retain and use your information as necessary to comply with our legal obligations, resolve disputes, and enforce our agreements, but barring legal requirements, we will delete your full profile (within reason) within 90 days of your request. Feel free to contact our support to request erasure of the data we process on the basis of consent within 30 days.

After an account has been deleted, certain data, such as contributions to other Users' repositories and comments in others' issues, will remain. However, we will delete or de-identify your User Personal Information, including your username and email address, from the author field of issues, pull requests, and comments by associating them with a ghost user.

diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000000..678a49647c --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,1029 @@ +import arrayFunc from 'eslint-plugin-array-func'; +import comments from '@eslint-community/eslint-plugin-eslint-comments'; +import github from 'eslint-plugin-github'; +import globals from 'globals'; +import importPlugin from 'eslint-plugin-import-x'; +import noUseExtendNative from 'eslint-plugin-no-use-extend-native'; +import playwright from 'eslint-plugin-playwright'; +import regexp from 'eslint-plugin-regexp'; +import sonarjs from 'eslint-plugin-sonarjs'; +import stylistic from '@stylistic/eslint-plugin'; +import typescriptParser from '@typescript-eslint/parser'; +import typescriptPlugin from 'typescript-eslint'; +import unicorn from 'eslint-plugin-unicorn'; +import vitest from '@vitest/eslint-plugin'; +import vue from 'eslint-plugin-vue'; +import vueScopedCss from 'eslint-plugin-vue-scoped-css'; +import wc from 'eslint-plugin-wc'; +import {defineConfig, globalIgnores} from 'eslint/config'; + +const jsExts = ['js', 'mjs', 'cjs'] as const; +const tsExts = ['ts', 'mts', 'cts'] as const; +const restrictedSyntax = ['WithStatement', 'ForInStatement', 'LabeledStatement', 'SequenceExpression']; + +export default defineConfig([ + globalIgnores([ + 'web_src/js/vendor', + 'web_src/fomantic', + 'public/assets/js', + ]), + { + files: [`**/*.{${[...jsExts, ...tsExts].join(',')}}`], + ignores: ['dist/*'], + languageOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + globals: { + ...globals.browser, + ...globals.node, + }, + parser: typescriptParser, + parserOptions: { + sourceType: 'module', + ecmaVersion: 'latest', + ecmaFeatures: { + impliedStrict: true, + }, + project: true, + }, + }, + linterOptions: { + reportUnusedDisableDirectives: 2, + }, + plugins: { + '@eslint-community/eslint-comments': comments, + // @ts-expect-error + '@stylistic': stylistic, + '@typescript-eslint': typescriptPlugin.plugin, + 'array-func': arrayFunc, + // @ts-expect-error -- https://github.com/un-ts/eslint-plugin-import-x/issues/203 + 'import-x': importPlugin, + 'no-use-extend-native': noUseExtendNative, + // @ts-expect-error + regexp, + // @ts-expect-error + sonarjs, + // @ts-expect-error + unicorn, + github, + // @ts-expect-error + wc, + }, + settings: { + 'import-x/extensions': [...jsExts, ...tsExts].map((ext) => `.${ext}`), + 'import-x/parsers': {'@typescript-eslint/parser': [...jsExts, ...tsExts].map((ext) => `.${ext}`)}, + 'import-x/resolver': {'typescript': true}, + }, + rules: { + '@eslint-community/eslint-comments/disable-enable-pair': [2], + '@eslint-community/eslint-comments/no-aggregating-enable': [2], + '@eslint-community/eslint-comments/no-duplicate-disable': [2], + '@eslint-community/eslint-comments/no-restricted-disable': [0], + '@eslint-community/eslint-comments/no-unlimited-disable': [2], + '@eslint-community/eslint-comments/no-unused-disable': [2], + '@eslint-community/eslint-comments/no-unused-enable': [2], + '@eslint-community/eslint-comments/no-use': [0], + '@eslint-community/eslint-comments/require-description': [0], + '@stylistic/array-bracket-newline': [0], + '@stylistic/array-bracket-spacing': [2, 'never'], + '@stylistic/array-element-newline': [0], + '@stylistic/arrow-parens': [2, 'always'], + '@stylistic/arrow-spacing': [2, {before: true, after: true}], + '@stylistic/block-spacing': [0], + '@stylistic/brace-style': [2, '1tbs', {allowSingleLine: true}], + '@stylistic/comma-dangle': [2, 'always-multiline'], + '@stylistic/comma-spacing': [2, {before: false, after: true}], + '@stylistic/comma-style': [2, 'last'], + '@stylistic/computed-property-spacing': [2, 'never'], + '@stylistic/dot-location': [2, 'property'], + '@stylistic/eol-last': [2], + '@stylistic/function-call-argument-newline': [0], + '@stylistic/function-call-spacing': [2, 'never'], + '@stylistic/function-paren-newline': [0], + '@stylistic/generator-star-spacing': [0], + '@stylistic/implicit-arrow-linebreak': [0], + '@stylistic/indent': [2, 2, {ignoreComments: true, SwitchCase: 1}], + '@stylistic/key-spacing': [2], + '@stylistic/keyword-spacing': [2], + '@stylistic/line-comment-position': [0], + '@stylistic/linebreak-style': [2, 'unix'], + '@stylistic/lines-around-comment': [0], + '@stylistic/lines-between-class-members': [0], + '@stylistic/max-len': [0], + '@stylistic/max-statements-per-line': [0], + '@stylistic/multiline-comment-style': [0], + '@stylistic/multiline-ternary': [0], + '@stylistic/new-parens': [2], + '@stylistic/newline-per-chained-call': [0], + '@stylistic/no-confusing-arrow': [0], + '@stylistic/no-extra-parens': [0], + '@stylistic/no-extra-semi': [2], + '@stylistic/no-floating-decimal': [0], + '@stylistic/no-mixed-operators': [0], + '@stylistic/no-mixed-spaces-and-tabs': [2], + '@stylistic/no-multi-spaces': [2, {ignoreEOLComments: true, exceptions: {Property: true}}], + '@stylistic/no-multiple-empty-lines': [2, {max: 1, maxEOF: 0, maxBOF: 0}], + '@stylistic/no-tabs': [2], + '@stylistic/no-trailing-spaces': [2], + '@stylistic/no-whitespace-before-property': [2], + '@stylistic/nonblock-statement-body-position': [2], + '@stylistic/object-curly-newline': [0], + '@stylistic/object-curly-spacing': [2, 'never'], + '@stylistic/object-property-newline': [0], + '@stylistic/one-var-declaration-per-line': [0], + '@stylistic/operator-linebreak': [2, 'after'], + '@stylistic/padded-blocks': [2, 'never'], + '@stylistic/padding-line-between-statements': [0], + '@stylistic/quote-props': [0], + '@stylistic/quotes': [2, 'single', {avoidEscape: true, allowTemplateLiterals: 'always'}], + '@stylistic/rest-spread-spacing': [2, 'never'], + '@stylistic/semi': [2, 'always', {omitLastInOneLineBlock: true}], + '@stylistic/semi-spacing': [2, {before: false, after: true}], + '@stylistic/semi-style': [2, 'last'], + '@stylistic/space-before-blocks': [2, 'always'], + '@stylistic/space-before-function-paren': [2, {anonymous: 'ignore', named: 'never', asyncArrow: 'always'}], + '@stylistic/space-in-parens': [2, 'never'], + '@stylistic/space-infix-ops': [2], + '@stylistic/space-unary-ops': [2], + '@stylistic/spaced-comment': [2, 'always'], + '@stylistic/switch-colon-spacing': [2], + '@stylistic/template-curly-spacing': [2, 'never'], + '@stylistic/template-tag-spacing': [2, 'never'], + '@stylistic/wrap-iife': [2, 'inside'], + '@stylistic/wrap-regex': [0], + '@stylistic/yield-star-spacing': [2, 'after'], + '@typescript-eslint/adjacent-overload-signatures': [0], + '@typescript-eslint/array-type': [0], + '@typescript-eslint/await-thenable': [2], + '@typescript-eslint/ban-ts-comment': [2, {'ts-expect-error': false, 'ts-ignore': true, 'ts-nocheck': false, 'ts-check': false}], + '@typescript-eslint/ban-tslint-comment': [0], + '@typescript-eslint/class-literal-property-style': [0], + '@typescript-eslint/class-methods-use-this': [0], + '@typescript-eslint/consistent-generic-constructors': [0], + '@typescript-eslint/consistent-indexed-object-style': [0], + '@typescript-eslint/consistent-return': [0], + '@typescript-eslint/consistent-type-assertions': [2, {assertionStyle: 'as', objectLiteralTypeAssertions: 'allow'}], + '@typescript-eslint/consistent-type-definitions': [2, 'type'], + '@typescript-eslint/consistent-type-exports': [2, {fixMixedExportsWithInlineTypeSpecifier: false}], + '@typescript-eslint/consistent-type-imports': [2, {prefer: 'type-imports', fixStyle: 'separate-type-imports', disallowTypeAnnotations: true}], + '@typescript-eslint/default-param-last': [0], + '@typescript-eslint/dot-notation': [0], + '@typescript-eslint/explicit-function-return-type': [0], + '@typescript-eslint/explicit-member-accessibility': [0], + '@typescript-eslint/explicit-module-boundary-types': [0], + '@typescript-eslint/init-declarations': [0], + '@typescript-eslint/max-params': [0], + '@typescript-eslint/member-ordering': [0], + '@typescript-eslint/method-signature-style': [0], + '@typescript-eslint/naming-convention': [0], + '@typescript-eslint/no-array-constructor': [2], + '@typescript-eslint/no-array-delete': [2], + '@typescript-eslint/no-base-to-string': [0], + '@typescript-eslint/no-confusing-non-null-assertion': [2], + '@typescript-eslint/no-confusing-void-expression': [0], + '@typescript-eslint/no-deprecated': [2], + '@typescript-eslint/no-dupe-class-members': [0], + '@typescript-eslint/no-duplicate-enum-values': [2], + '@typescript-eslint/no-duplicate-type-constituents': [2, {ignoreUnions: true}], + '@typescript-eslint/no-dynamic-delete': [0], + '@typescript-eslint/no-empty-function': [0], + '@typescript-eslint/no-empty-interface': [0], + '@typescript-eslint/no-empty-object-type': [2], + '@typescript-eslint/no-explicit-any': [0], + '@typescript-eslint/no-extra-non-null-assertion': [2], + '@typescript-eslint/no-extraneous-class': [0], + '@typescript-eslint/no-floating-promises': [0], + '@typescript-eslint/no-for-in-array': [2], + '@typescript-eslint/no-implied-eval': [2], + '@typescript-eslint/no-import-type-side-effects': [0], // dupe with consistent-type-imports + '@typescript-eslint/no-inferrable-types': [0], + '@typescript-eslint/no-invalid-this': [0], + '@typescript-eslint/no-invalid-void-type': [0], + '@typescript-eslint/no-loop-func': [0], + '@typescript-eslint/no-loss-of-precision': [0], + '@typescript-eslint/no-magic-numbers': [0], + '@typescript-eslint/no-meaningless-void-operator': [0], + '@typescript-eslint/no-misused-new': [2], + '@typescript-eslint/no-misused-promises': [2, {checksVoidReturn: {attributes: false, arguments: false}}], + '@typescript-eslint/no-mixed-enums': [0], + '@typescript-eslint/no-namespace': [2], + '@typescript-eslint/no-non-null-asserted-nullish-coalescing': [0], + '@typescript-eslint/no-non-null-asserted-optional-chain': [2], + '@typescript-eslint/no-non-null-assertion': [0], + '@typescript-eslint/no-redeclare': [0], + '@typescript-eslint/no-redundant-type-constituents': [2], + '@typescript-eslint/no-require-imports': [2], + '@typescript-eslint/no-restricted-imports': [0], + '@typescript-eslint/no-restricted-types': [0], + '@typescript-eslint/no-shadow': [0], + '@typescript-eslint/no-this-alias': [0], // handled by unicorn/no-this-assignment + '@typescript-eslint/no-unnecessary-boolean-literal-compare': [0], + '@typescript-eslint/no-unnecessary-condition': [0], + '@typescript-eslint/no-unnecessary-qualifier': [0], + '@typescript-eslint/no-unnecessary-template-expression': [0], + '@typescript-eslint/no-unnecessary-type-arguments': [0], + '@typescript-eslint/no-unnecessary-type-assertion': [2], + '@typescript-eslint/no-unnecessary-type-constraint': [2], + '@typescript-eslint/no-unnecessary-type-conversion': [2], + '@typescript-eslint/no-unsafe-argument': [0], + '@typescript-eslint/no-unsafe-assignment': [0], + '@typescript-eslint/no-unsafe-call': [0], + '@typescript-eslint/no-unsafe-declaration-merging': [2], + '@typescript-eslint/no-unsafe-enum-comparison': [2], + '@typescript-eslint/no-unsafe-function-type': [2], + '@typescript-eslint/no-unsafe-member-access': [0], + '@typescript-eslint/no-unsafe-return': [0], + '@typescript-eslint/no-unsafe-unary-minus': [2], + '@typescript-eslint/no-unused-expressions': [0], + '@typescript-eslint/no-unused-vars': [2, {vars: 'all', args: 'all', caughtErrors: 'all', ignoreRestSiblings: false, argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', destructuredArrayIgnorePattern: '^_'}], + '@typescript-eslint/no-use-before-define': [2, {functions: false, classes: true, variables: true, allowNamedExports: true, typedefs: false, enums: false, ignoreTypeReferences: true}], + '@typescript-eslint/no-useless-constructor': [0], + '@typescript-eslint/no-useless-empty-export': [0], + '@typescript-eslint/no-wrapper-object-types': [2], + '@typescript-eslint/non-nullable-type-assertion-style': [0], + '@typescript-eslint/only-throw-error': [2], + '@typescript-eslint/parameter-properties': [0], + '@typescript-eslint/prefer-as-const': [2], + '@typescript-eslint/prefer-destructuring': [0], + '@typescript-eslint/prefer-enum-initializers': [0], + '@typescript-eslint/prefer-find': [2], + '@typescript-eslint/prefer-for-of': [2], + '@typescript-eslint/prefer-function-type': [2], + '@typescript-eslint/prefer-includes': [2], + '@typescript-eslint/prefer-literal-enum-member': [0], + '@typescript-eslint/prefer-namespace-keyword': [0], + '@typescript-eslint/prefer-nullish-coalescing': [0], + '@typescript-eslint/prefer-optional-chain': [2, {requireNullish: true}], + '@typescript-eslint/prefer-promise-reject-errors': [0], + '@typescript-eslint/prefer-readonly': [0], + '@typescript-eslint/prefer-readonly-parameter-types': [0], + '@typescript-eslint/prefer-reduce-type-parameter': [0], + '@typescript-eslint/prefer-regexp-exec': [0], + '@typescript-eslint/prefer-return-this-type': [0], + '@typescript-eslint/prefer-string-starts-ends-with': [2, {allowSingleElementEquality: 'always'}], + '@typescript-eslint/promise-function-async': [0], + '@typescript-eslint/require-array-sort-compare': [0], + '@typescript-eslint/require-await': [0], + '@typescript-eslint/restrict-plus-operands': [2], + '@typescript-eslint/restrict-template-expressions': [0], + '@typescript-eslint/return-await': [0], + '@typescript-eslint/strict-boolean-expressions': [0], + '@typescript-eslint/switch-exhaustiveness-check': [0], + '@typescript-eslint/triple-slash-reference': [2], + '@typescript-eslint/typedef': [0], + '@typescript-eslint/unbound-method': [0], // too many false-positives + '@typescript-eslint/unified-signatures': [2], + 'accessor-pairs': [2], + 'array-callback-return': [2, {checkForEach: true}], + 'array-func/avoid-reverse': [2], + 'array-func/from-map': [2], + 'array-func/no-unnecessary-this-arg': [2], + 'array-func/prefer-array-from': [2], + 'array-func/prefer-flat-map': [0], // handled by unicorn/prefer-array-flat-map + 'array-func/prefer-flat': [0], // handled by unicorn/prefer-array-flat + 'arrow-body-style': [0], + 'block-scoped-var': [2], + 'camelcase': [0], + 'capitalized-comments': [0], + 'class-methods-use-this': [0], + 'complexity': [0], + 'consistent-return': [0], + 'consistent-this': [0], + 'constructor-super': [2], + 'curly': [0], + 'default-case-last': [2], + 'default-case': [0], + 'default-param-last': [0], + 'dot-notation': [0], + 'eqeqeq': [2], + 'for-direction': [2], + 'func-name-matching': [2], + 'func-names': [0], + 'func-style': [0], + 'getter-return': [2], + 'github/a11y-aria-label-is-well-formatted': [0], + 'github/a11y-no-title-attribute': [0], + 'github/a11y-no-visually-hidden-interactive-element': [0], + 'github/a11y-role-supports-aria-props': [0], + 'github/a11y-svg-has-accessible-name': [0], + 'github/array-foreach': [0], + 'github/async-currenttarget': [2], + 'github/async-preventdefault': [0], // https://github.com/github/eslint-plugin-github/issues/599 + 'github/authenticity-token': [0], + 'github/get-attribute': [0], + 'github/js-class-name': [0], + 'github/no-blur': [0], + 'github/no-d-none': [0], + 'github/no-dataset': [2], + 'github/no-dynamic-script-tag': [2], + 'github/no-implicit-buggy-globals': [2], + 'github/no-inner-html': [0], + 'github/no-innerText': [2], + 'github/no-then': [2], + 'github/no-useless-passive': [2], + 'github/prefer-observers': [2], + 'github/require-passive-events': [2], + 'github/unescaped-html-literal': [2], + 'grouped-accessor-pairs': [2], + 'guard-for-in': [0], + 'id-blacklist': [0], + 'id-length': [0], + 'id-match': [0], + 'import-x/consistent-type-specifier-style': [0], + 'import-x/default': [0], + 'import-x/dynamic-import-chunkname': [0], + 'import-x/export': [2], + 'import-x/exports-last': [0], + 'import-x/extensions': [2, 'always', {ignorePackages: true}], + 'import-x/first': [2], + 'import-x/group-exports': [0], + 'import-x/max-dependencies': [0], + 'import-x/named': [2], + 'import-x/namespace': [0], + 'import-x/newline-after-import': [0], + 'import-x/no-absolute-path': [0], + 'import-x/no-amd': [2], + 'import-x/no-anonymous-default-export': [0], + 'import-x/no-commonjs': [2], + 'import-x/no-cycle': [2, {ignoreExternal: true, maxDepth: 1}], + 'import-x/no-default-export': [0], + 'import-x/no-deprecated': [0], + 'import-x/no-dynamic-require': [0], + 'import-x/no-empty-named-blocks': [2], + 'import-x/no-extraneous-dependencies': [2], + 'import-x/no-import-module-exports': [0], + 'import-x/no-internal-modules': [0], + 'import-x/no-mutable-exports': [0], + 'import-x/no-named-as-default-member': [0], + 'import-x/no-named-as-default': [0], + 'import-x/no-named-default': [0], + 'import-x/no-named-export': [0], + 'import-x/no-namespace': [0], + 'import-x/no-nodejs-modules': [0], + 'import-x/no-relative-packages': [0], + 'import-x/no-relative-parent-imports': [0], + 'import-x/no-restricted-paths': [0], + 'import-x/no-self-import': [2], + 'import-x/no-unassigned-import': [0], + 'import-x/no-unresolved': [2, {commonjs: true, ignore: ['\\?.+$']}], + // 'import-x/no-unused-modules': [2, {unusedExports: true}], // not compatible with eslint 9 + 'import-x/no-useless-path-segments': [2, {commonjs: true}], + 'import-x/no-webpack-loader-syntax': [2], + 'import-x/order': [0], + 'import-x/prefer-default-export': [0], + 'import-x/unambiguous': [0], + 'init-declarations': [0], + 'line-comment-position': [0], + 'logical-assignment-operators': [0], + 'max-classes-per-file': [0], + 'max-depth': [0], + 'max-lines-per-function': [0], + 'max-lines': [0], + 'max-nested-callbacks': [0], + 'max-params': [0], + 'max-statements': [0], + 'multiline-comment-style': [0], + 'new-cap': [0], + 'no-alert': [0], + 'no-array-constructor': [0], // handled by @typescript-eslint/no-array-constructor + 'no-async-promise-executor': [0], + 'no-await-in-loop': [0], + 'no-bitwise': [0], + 'no-buffer-constructor': [0], + 'no-caller': [2], + 'no-case-declarations': [2], + 'no-class-assign': [2], + 'no-compare-neg-zero': [2], + 'no-cond-assign': [2, 'except-parens'], + 'no-console': [1, {allow: ['debug', 'info', 'warn', 'error']}], + 'no-const-assign': [2], + 'no-constant-binary-expression': [2], + 'no-constant-condition': [0], + 'no-constructor-return': [2], + 'no-continue': [0], + 'no-control-regex': [0], + 'no-debugger': [1], + 'no-delete-var': [2], + 'no-div-regex': [0], + 'no-dupe-args': [2], + 'no-dupe-class-members': [2], + 'no-dupe-else-if': [2], + 'no-dupe-keys': [2], + 'no-duplicate-case': [2], + 'no-duplicate-imports': [0], + 'no-else-return': [2], + 'no-empty-character-class': [2], + 'no-empty-function': [0], + 'no-empty-pattern': [2], + 'no-empty-static-block': [2], + 'no-empty': [2, {allowEmptyCatch: true}], + 'no-eq-null': [2], + 'no-eval': [2], + 'no-ex-assign': [2], + 'no-extend-native': [2], + 'no-extra-bind': [2], + 'no-extra-boolean-cast': [2], + 'no-extra-label': [0], + 'no-fallthrough': [2], + 'no-func-assign': [2], + 'no-global-assign': [2], + 'no-implicit-coercion': [2], + 'no-implicit-globals': [0], + 'no-implied-eval': [0], // handled by @typescript-eslint/no-implied-eval + 'no-import-assign': [2], + 'no-inline-comments': [0], + 'no-inner-declarations': [2], + 'no-invalid-regexp': [2], + 'no-invalid-this': [0], + 'no-irregular-whitespace': [2], + 'no-iterator': [2], + // 'no-jquery/no-ajax-events': [2], + // 'no-jquery/no-ajax': [2], + // 'no-jquery/no-and-self': [2], + // 'no-jquery/no-animate-toggle': [2], + // 'no-jquery/no-animate': [2], + // 'no-jquery/no-append-html': [2], + // 'no-jquery/no-attr': [2], + // 'no-jquery/no-bind': [2], + // 'no-jquery/no-box-model': [2], + // 'no-jquery/no-browser': [2], + // 'no-jquery/no-camel-case': [2], + // 'no-jquery/no-class-state': [2], + // 'no-jquery/no-class': [0], + // 'no-jquery/no-clone': [2], + // 'no-jquery/no-closest': [0], + // 'no-jquery/no-constructor-attributes': [2], + // 'no-jquery/no-contains': [2], + // 'no-jquery/no-context-prop': [2], + // 'no-jquery/no-css': [2], + // 'no-jquery/no-data': [0], + // 'no-jquery/no-deferred': [2], + // 'no-jquery/no-delegate': [2], + // 'no-jquery/no-done-fail': [2], + // 'no-jquery/no-each-collection': [0], + // 'no-jquery/no-each-util': [0], + // 'no-jquery/no-each': [0], + // 'no-jquery/no-error-shorthand': [2], + // 'no-jquery/no-error': [2], + // 'no-jquery/no-escape-selector': [2], + // 'no-jquery/no-event-shorthand': [2], + // 'no-jquery/no-extend': [2], + // 'no-jquery/no-fade': [2], + // 'no-jquery/no-filter': [0], + // 'no-jquery/no-find-collection': [0], + // 'no-jquery/no-find-util': [2], + // 'no-jquery/no-find': [0], + // 'no-jquery/no-fx-interval': [2], + // 'no-jquery/no-fx': [2], + // 'no-jquery/no-global-eval': [2], + // 'no-jquery/no-global-selector': [0], + // 'no-jquery/no-grep': [2], + // 'no-jquery/no-has': [2], + // 'no-jquery/no-hold-ready': [2], + // 'no-jquery/no-html': [0], + // 'no-jquery/no-in-array': [2], + // 'no-jquery/no-is-array': [2], + // 'no-jquery/no-is-empty-object': [2], + // 'no-jquery/no-is-function': [2], + // 'no-jquery/no-is-numeric': [2], + // 'no-jquery/no-is-plain-object': [2], + // 'no-jquery/no-is-window': [2], + // 'no-jquery/no-is': [2], + // 'no-jquery/no-jquery-constructor': [0], + // 'no-jquery/no-live': [2], + // 'no-jquery/no-load-shorthand': [2], + // 'no-jquery/no-load': [2], + // 'no-jquery/no-map-collection': [0], + // 'no-jquery/no-map-util': [2], + // 'no-jquery/no-map': [2], + // 'no-jquery/no-merge': [2], + // 'no-jquery/no-node-name': [2], + // 'no-jquery/no-noop': [2], + // 'no-jquery/no-now': [2], + // 'no-jquery/no-on-ready': [2], + // 'no-jquery/no-other-methods': [0], + // 'no-jquery/no-other-utils': [2], + // 'no-jquery/no-param': [2], + // 'no-jquery/no-parent': [0], + // 'no-jquery/no-parents': [2], + // 'no-jquery/no-parse-html-literal': [2], + // 'no-jquery/no-parse-html': [2], + // 'no-jquery/no-parse-json': [2], + // 'no-jquery/no-parse-xml': [2], + // 'no-jquery/no-prop': [2], + // 'no-jquery/no-proxy': [2], + // 'no-jquery/no-ready-shorthand': [2], + // 'no-jquery/no-ready': [2], + // 'no-jquery/no-selector-prop': [2], + // 'no-jquery/no-serialize': [2], + // 'no-jquery/no-size': [2], + // 'no-jquery/no-sizzle': [2], + // 'no-jquery/no-slide': [2], + // 'no-jquery/no-sub': [2], + // 'no-jquery/no-support': [2], + // 'no-jquery/no-text': [2], + // 'no-jquery/no-trigger': [0], + // 'no-jquery/no-trim': [2], + // 'no-jquery/no-type': [2], + // 'no-jquery/no-unique': [2], + // 'no-jquery/no-unload-shorthand': [2], + // 'no-jquery/no-val': [0], + // 'no-jquery/no-visibility': [2], + // 'no-jquery/no-when': [2], + // 'no-jquery/no-wrap': [2], + // 'no-jquery/variable-pattern': [2], + 'no-label-var': [2], + 'no-labels': [0], // handled by no-restricted-syntax + 'no-lone-blocks': [2], + 'no-lonely-if': [0], + 'no-loop-func': [0], + 'no-loss-of-precision': [2], + 'no-magic-numbers': [0], + 'no-misleading-character-class': [2], + 'no-multi-assign': [0], + 'no-multi-str': [2], + 'no-negated-condition': [0], + 'no-nested-ternary': [0], + 'no-new-func': [0], // handled by @typescript-eslint/no-implied-eval + 'no-new-native-nonconstructor': [2], + 'no-new-object': [2], + 'no-new-symbol': [2], + 'no-new-wrappers': [2], + 'no-new': [0], + 'no-nonoctal-decimal-escape': [2], + 'no-obj-calls': [2], + 'no-octal-escape': [2], + 'no-octal': [2], + 'no-param-reassign': [0], + 'no-plusplus': [0], + 'no-promise-executor-return': [0], + 'no-proto': [2], + 'no-prototype-builtins': [2], + 'no-redeclare': [0], // must be disabled for typescript overloads + 'no-regex-spaces': [2], + 'no-restricted-exports': [0], + 'no-restricted-globals': [2, 'addEventListener', 'blur', 'close', 'closed', 'confirm', 'defaultStatus', 'defaultstatus', 'error', 'event', 'external', 'find', 'focus', 'frameElement', 'frames', 'history', 'innerHeight', 'innerWidth', 'isFinite', 'isNaN', 'length', 'locationbar', 'menubar', 'moveBy', 'moveTo', 'name', 'onblur', 'onerror', 'onfocus', 'onload', 'onresize', 'onunload', 'open', 'opener', 'opera', 'outerHeight', 'outerWidth', 'pageXOffset', 'pageYOffset', 'parent', 'print', 'removeEventListener', 'resizeBy', 'resizeTo', 'screen', 'screenLeft', 'screenTop', 'screenX', 'screenY', 'scroll', 'scrollbars', 'scrollBy', 'scrollTo', 'scrollX', 'scrollY', 'status', 'statusbar', 'stop', 'toolbar', 'top'], + 'no-restricted-imports': [0], + 'no-restricted-syntax': [2, ...restrictedSyntax, {selector: 'CallExpression[callee.name="fetch"]', message: 'use modules/fetch.ts instead'}], + 'no-return-assign': [0], + 'no-script-url': [2], + 'no-self-assign': [2, {props: true}], + 'no-self-compare': [2], + 'no-sequences': [2], + 'no-setter-return': [2], + 'no-shadow-restricted-names': [2], + 'no-shadow': [0], + 'no-sparse-arrays': [2], + 'no-template-curly-in-string': [2], + 'no-ternary': [0], + 'no-this-before-super': [2], + 'no-throw-literal': [2], + 'no-undef-init': [2], + 'no-undef': [2], // it is still needed by eslint & IDE to prompt undefined names in real time + 'no-undefined': [0], + 'no-underscore-dangle': [0], + 'no-unexpected-multiline': [2], + 'no-unmodified-loop-condition': [2], + 'no-unneeded-ternary': [2], + 'no-unreachable-loop': [2], + 'no-unreachable': [2], + 'no-unsafe-finally': [2], + 'no-unsafe-negation': [2], + 'no-unused-expressions': [2], + 'no-unused-labels': [2], + 'no-unused-private-class-members': [2], + 'no-unused-vars': [0], // handled by @typescript-eslint/no-unused-vars + 'no-use-before-define': [0], // handled by @typescript-eslint/no-use-before-define + 'no-use-extend-native/no-use-extend-native': [2], + 'no-useless-backreference': [2], + 'no-useless-call': [2], + 'no-useless-catch': [2], + 'no-useless-computed-key': [2], + 'no-useless-concat': [2], + 'no-useless-constructor': [2], + 'no-useless-escape': [2], + 'no-useless-rename': [2], + 'no-useless-return': [2], + 'no-var': [2], + 'no-void': [2], + 'no-warning-comments': [0], + 'no-with': [0], // handled by no-restricted-syntax + 'object-shorthand': [2, 'always'], + 'one-var-declaration-per-line': [0], + 'one-var': [0], + 'operator-assignment': [2, 'always'], + 'operator-linebreak': [2, 'after'], + 'prefer-arrow-callback': [2, {allowNamedFunctions: true, allowUnboundThis: true}], + 'prefer-const': [2, {destructuring: 'all', ignoreReadBeforeAssign: true}], + 'prefer-destructuring': [0], + 'prefer-exponentiation-operator': [2], + 'prefer-named-capture-group': [0], + 'prefer-numeric-literals': [2], + 'prefer-object-has-own': [2], + 'prefer-object-spread': [2], + 'prefer-promise-reject-errors': [2, {allowEmptyReject: false}], + 'prefer-regex-literals': [2], + 'prefer-rest-params': [2], + 'prefer-spread': [2], + 'prefer-template': [2], + 'radix': [2, 'as-needed'], + 'regexp/confusing-quantifier': [2], + 'regexp/control-character-escape': [2], + 'regexp/hexadecimal-escape': [0], + 'regexp/letter-case': [0], + 'regexp/match-any': [2], + 'regexp/negation': [2], + 'regexp/no-contradiction-with-assertion': [0], + 'regexp/no-control-character': [0], + 'regexp/no-dupe-characters-character-class': [2], + 'regexp/no-dupe-disjunctions': [2], + 'regexp/no-empty-alternative': [2], + 'regexp/no-empty-capturing-group': [2], + 'regexp/no-empty-character-class': [0], + 'regexp/no-empty-group': [2], + 'regexp/no-empty-lookarounds-assertion': [2], + 'regexp/no-empty-string-literal': [2], + 'regexp/no-escape-backspace': [2], + 'regexp/no-extra-lookaround-assertions': [0], + 'regexp/no-invalid-regexp': [2], + 'regexp/no-invisible-character': [2], + 'regexp/no-lazy-ends': [2], + 'regexp/no-legacy-features': [2], + 'regexp/no-misleading-capturing-group': [0], + 'regexp/no-misleading-unicode-character': [0], + 'regexp/no-missing-g-flag': [2], + 'regexp/no-non-standard-flag': [2], + 'regexp/no-obscure-range': [2], + 'regexp/no-octal': [2], + 'regexp/no-optional-assertion': [2], + 'regexp/no-potentially-useless-backreference': [2], + 'regexp/no-standalone-backslash': [2], + 'regexp/no-super-linear-backtracking': [0], + 'regexp/no-super-linear-move': [0], + 'regexp/no-trivially-nested-assertion': [2], + 'regexp/no-trivially-nested-quantifier': [2], + 'regexp/no-unused-capturing-group': [0], + 'regexp/no-useless-assertions': [2], + 'regexp/no-useless-backreference': [2], + 'regexp/no-useless-character-class': [2], + 'regexp/no-useless-dollar-replacements': [2], + 'regexp/no-useless-escape': [2], + 'regexp/no-useless-flag': [2], + 'regexp/no-useless-lazy': [2], + 'regexp/no-useless-non-capturing-group': [2], + 'regexp/no-useless-quantifier': [2], + 'regexp/no-useless-range': [2], + 'regexp/no-useless-set-operand': [2], + 'regexp/no-useless-string-literal': [2], + 'regexp/no-useless-two-nums-quantifier': [2], + 'regexp/no-zero-quantifier': [2], + 'regexp/optimal-lookaround-quantifier': [2], + 'regexp/optimal-quantifier-concatenation': [0], + 'regexp/prefer-character-class': [0], + 'regexp/prefer-d': [0], + 'regexp/prefer-escape-replacement-dollar-char': [0], + 'regexp/prefer-lookaround': [0], + 'regexp/prefer-named-backreference': [0], + 'regexp/prefer-named-capture-group': [0], + 'regexp/prefer-named-replacement': [0], + 'regexp/prefer-plus-quantifier': [2], + 'regexp/prefer-predefined-assertion': [2], + 'regexp/prefer-quantifier': [0], + 'regexp/prefer-question-quantifier': [2], + 'regexp/prefer-range': [2], + 'regexp/prefer-regexp-exec': [2], + 'regexp/prefer-regexp-test': [2], + 'regexp/prefer-result-array-groups': [0], + 'regexp/prefer-set-operation': [2], + 'regexp/prefer-star-quantifier': [2], + 'regexp/prefer-unicode-codepoint-escapes': [2], + 'regexp/prefer-w': [0], + 'regexp/require-unicode-regexp': [0], + 'regexp/simplify-set-operations': [2], + 'regexp/sort-alternatives': [0], + 'regexp/sort-character-class-elements': [0], + 'regexp/sort-flags': [0], + 'regexp/strict': [2], + 'regexp/unicode-escape': [0], + 'regexp/use-ignore-case': [0], + 'require-atomic-updates': [0], + 'require-await': [0], // handled by @typescript-eslint/require-await + 'require-unicode-regexp': [0], + 'require-yield': [2], + 'sonarjs/cognitive-complexity': [0], + 'sonarjs/elseif-without-else': [0], + 'sonarjs/max-switch-cases': [0], + 'sonarjs/no-all-duplicated-branches': [2], + 'sonarjs/no-collapsible-if': [0], + 'sonarjs/no-collection-size-mischeck': [2], + 'sonarjs/no-duplicate-string': [0], + 'sonarjs/no-duplicated-branches': [0], + 'sonarjs/no-element-overwrite': [2], + 'sonarjs/no-empty-collection': [2], + 'sonarjs/no-extra-arguments': [2], + 'sonarjs/no-gratuitous-expressions': [2], + 'sonarjs/no-identical-conditions': [2], + 'sonarjs/no-identical-expressions': [2], + 'sonarjs/no-identical-functions': [2, 5], + 'sonarjs/no-ignored-return': [2], + 'sonarjs/no-inverted-boolean-check': [2], + 'sonarjs/no-nested-switch': [0], + 'sonarjs/no-nested-template-literals': [0], + 'sonarjs/no-redundant-boolean': [2], + 'sonarjs/no-redundant-jump': [2], + 'sonarjs/no-same-line-conditional': [2], + 'sonarjs/no-small-switch': [0], + 'sonarjs/no-unused-collection': [2], + 'sonarjs/no-use-of-empty-return-value': [2], + 'sonarjs/no-useless-catch': [2], + 'sonarjs/non-existent-operator': [2], + 'sonarjs/prefer-immediate-return': [0], + 'sonarjs/prefer-object-literal': [0], + 'sonarjs/prefer-single-boolean-return': [0], + 'sonarjs/prefer-while': [2], + 'sort-imports': [0], + 'sort-keys': [0], + 'sort-vars': [0], + 'strict': [0], + 'symbol-description': [2], + 'unicode-bom': [2, 'never'], + 'unicorn/better-regex': [0], + 'unicorn/catch-error-name': [0], + 'unicorn/consistent-destructuring': [2], + 'unicorn/consistent-empty-array-spread': [2], + 'unicorn/consistent-existence-index-check': [0], + 'unicorn/consistent-function-scoping': [0], + 'unicorn/custom-error-definition': [0], + 'unicorn/empty-brace-spaces': [2], + 'unicorn/error-message': [0], + 'unicorn/escape-case': [0], + 'unicorn/expiring-todo-comments': [0], + 'unicorn/explicit-length-check': [0], + 'unicorn/filename-case': [0], + 'unicorn/import-index': [0], + 'unicorn/import-style': [0], + 'unicorn/new-for-builtins': [2], + 'unicorn/no-abusive-eslint-disable': [0], + 'unicorn/no-anonymous-default-export': [0], + 'unicorn/no-array-callback-reference': [0], + 'unicorn/no-array-for-each': [2], + 'unicorn/no-array-method-this-argument': [2], + 'unicorn/no-array-push-push': [2], + 'unicorn/no-array-reduce': [2], + 'unicorn/no-await-expression-member': [0], + 'unicorn/no-await-in-promise-methods': [2], + 'unicorn/no-console-spaces': [0], + 'unicorn/no-document-cookie': [2], + 'unicorn/no-empty-file': [2], + 'unicorn/no-for-loop': [0], + 'unicorn/no-hex-escape': [0], + 'unicorn/no-instanceof-array': [0], + 'unicorn/no-invalid-fetch-options': [2], + 'unicorn/no-invalid-remove-event-listener': [2], + 'unicorn/no-keyword-prefix': [0], + 'unicorn/no-length-as-slice-end': [2], + 'unicorn/no-lonely-if': [2], + 'unicorn/no-magic-array-flat-depth': [0], + 'unicorn/no-negated-condition': [0], + 'unicorn/no-negation-in-equality-check': [2], + 'unicorn/no-nested-ternary': [0], + 'unicorn/no-new-array': [0], + 'unicorn/no-new-buffer': [0], + 'unicorn/no-null': [0], + 'unicorn/no-object-as-default-parameter': [0], + 'unicorn/no-process-exit': [0], + 'unicorn/no-single-promise-in-promise-methods': [2], + 'unicorn/no-static-only-class': [2], + 'unicorn/no-thenable': [2], + 'unicorn/no-this-assignment': [2], + 'unicorn/no-typeof-undefined': [2], + 'unicorn/no-unnecessary-await': [2], + 'unicorn/no-unnecessary-polyfills': [2], + 'unicorn/no-unreadable-array-destructuring': [0], + 'unicorn/no-unreadable-iife': [2], + 'unicorn/no-unused-properties': [2], + 'unicorn/no-useless-fallback-in-spread': [2], + 'unicorn/no-useless-length-check': [2], + 'unicorn/no-useless-promise-resolve-reject': [2], + 'unicorn/no-useless-spread': [2], + 'unicorn/no-useless-switch-case': [2], + 'unicorn/no-useless-undefined': [0], + 'unicorn/no-zero-fractions': [2], + 'unicorn/number-literal-case': [0], + 'unicorn/numeric-separators-style': [0], + 'unicorn/prefer-add-event-listener': [2], + 'unicorn/prefer-array-find': [2], + 'unicorn/prefer-array-flat-map': [2], + 'unicorn/prefer-array-flat': [2], + 'unicorn/prefer-array-index-of': [2], + 'unicorn/prefer-array-some': [2], + 'unicorn/prefer-at': [0], + 'unicorn/prefer-blob-reading-methods': [2], + 'unicorn/prefer-code-point': [0], + 'unicorn/prefer-date-now': [2], + 'unicorn/prefer-default-parameters': [0], + 'unicorn/prefer-dom-node-append': [2], + 'unicorn/prefer-dom-node-dataset': [0], + 'unicorn/prefer-dom-node-remove': [2], + 'unicorn/prefer-dom-node-text-content': [2], + 'unicorn/prefer-event-target': [2], + 'unicorn/prefer-export-from': [0], + 'unicorn/prefer-global-this': [0], + 'unicorn/prefer-includes': [2], + 'unicorn/prefer-json-parse-buffer': [0], + 'unicorn/prefer-keyboard-event-key': [2], + 'unicorn/prefer-logical-operator-over-ternary': [2], + 'unicorn/prefer-math-min-max': [2], + 'unicorn/prefer-math-trunc': [2], + 'unicorn/prefer-modern-dom-apis': [0], + 'unicorn/prefer-modern-math-apis': [2], + 'unicorn/prefer-module': [2], + 'unicorn/prefer-native-coercion-functions': [2], + 'unicorn/prefer-negative-index': [2], + 'unicorn/prefer-node-protocol': [2], + 'unicorn/prefer-number-properties': [0], + 'unicorn/prefer-object-from-entries': [2], + 'unicorn/prefer-object-has-own': [0], + 'unicorn/prefer-optional-catch-binding': [2], + 'unicorn/prefer-prototype-methods': [0], + 'unicorn/prefer-query-selector': [2], + 'unicorn/prefer-reflect-apply': [0], + 'unicorn/prefer-regexp-test': [2], + 'unicorn/prefer-set-has': [0], + 'unicorn/prefer-set-size': [2], + 'unicorn/prefer-spread': [0], + 'unicorn/prefer-string-raw': [0], + 'unicorn/prefer-string-replace-all': [0], + 'unicorn/prefer-string-slice': [0], + 'unicorn/prefer-string-starts-ends-with': [2], + 'unicorn/prefer-string-trim-start-end': [2], + 'unicorn/prefer-structured-clone': [2], + 'unicorn/prefer-switch': [0], + 'unicorn/prefer-ternary': [0], + 'unicorn/prefer-top-level-await': [0], + 'unicorn/prefer-type-error': [0], + 'unicorn/prevent-abbreviations': [0], + 'unicorn/relative-url-style': [2], + 'unicorn/require-array-join-separator': [2], + 'unicorn/require-number-to-fixed-digits-argument': [2], + 'unicorn/require-post-message-target-origin': [0], + 'unicorn/string-content': [0], + 'unicorn/switch-case-braces': [0], + 'unicorn/template-indent': [2], + 'unicorn/text-encoding-identifier-case': [0], + 'unicorn/throw-new-error': [2], + 'use-isnan': [2], + 'valid-typeof': [2, {requireStringLiterals: true}], + 'vars-on-top': [0], + 'wc/attach-shadow-constructor': [2], + 'wc/define-tag-after-class-definition': [0], + 'wc/expose-class-on-global': [0], + 'wc/file-name-matches-element': [2], + 'wc/guard-define-call': [0], + 'wc/guard-super-call': [2], + 'wc/max-elements-per-file': [0], + 'wc/no-child-traversal-in-attributechangedcallback': [2], + 'wc/no-child-traversal-in-connectedcallback': [2], + 'wc/no-closed-shadow-root': [2], + 'wc/no-constructor-attributes': [2], + 'wc/no-constructor-params': [2], + 'wc/no-constructor': [2], + 'wc/no-customized-built-in-elements': [2], + 'wc/no-exports-with-element': [0], + 'wc/no-invalid-element-name': [2], + 'wc/no-invalid-extends': [2], + 'wc/no-method-prefixed-with-on': [2], + 'wc/no-self-class': [2], + 'wc/no-typos': [2], + 'wc/require-listener-teardown': [2], + 'wc/tag-name-matches-class': [2], + 'yoda': [2, 'never'], + }, + }, + // @ts-expect-error + { + ...playwright.configs['flat/recommended'], + files: ['tests/e2e/**'], + rules: { + ...playwright.configs['flat/recommended'].rules, + }, + }, + { + files: ['**/*.vue'], + languageOptions: { + parserOptions: { + parser: '@typescript-eslint/parser', + }, + }, + extends: [ + // @ts-expect-error + vue.configs['flat/recommended'], + // @ts-expect-error + vueScopedCss.configs['flat/recommended'], + ], + rules: { + 'vue/attributes-order': [0], + 'vue/html-closing-bracket-spacing': [2, {startTag: 'never', endTag: 'never', selfClosingTag: 'never'}], + 'vue/max-attributes-per-line': [0], + 'vue/singleline-html-element-content-newline': [0], + }, + }, + { + files: ['web_src/js/modules/fetch.ts', 'web_src/js/standalone/**/*'], + rules: { + 'no-restricted-syntax': [2, ...restrictedSyntax], + }, + }, + { + files: ['**/*.test.ts', 'web_src/js/test/setup.ts'], + // @ts-expect-error - https://github.com/vitest-dev/eslint-plugin-vitest/issues/737 + plugins: {vitest}, + languageOptions: {globals: globals.vitest}, + rules: { + 'github/unescaped-html-literal': [0], + 'vitest/consistent-test-filename': [0], + 'vitest/consistent-test-it': [0], + 'vitest/expect-expect': [0], + 'vitest/max-expects': [0], + 'vitest/max-nested-describe': [0], + 'vitest/no-alias-methods': [0], + 'vitest/no-commented-out-tests': [0], + 'vitest/no-conditional-expect': [0], + 'vitest/no-conditional-in-test': [0], + 'vitest/no-conditional-tests': [0], + 'vitest/no-disabled-tests': [0], + 'vitest/no-done-callback': [0], + 'vitest/no-duplicate-hooks': [0], + 'vitest/no-focused-tests': [2], + 'vitest/no-hooks': [0], + 'vitest/no-identical-title': [2], + 'vitest/no-interpolation-in-snapshots': [0], + 'vitest/no-large-snapshots': [0], + 'vitest/no-mocks-import': [0], + 'vitest/no-restricted-matchers': [0], + 'vitest/no-restricted-vi-methods': [0], + 'vitest/no-standalone-expect': [0], + 'vitest/no-test-prefixes': [0], + 'vitest/no-test-return-statement': [0], + 'vitest/prefer-called-with': [0], + 'vitest/prefer-comparison-matcher': [0], + 'vitest/prefer-each': [0], + 'vitest/prefer-equality-matcher': [0], + 'vitest/prefer-expect-resolves': [0], + 'vitest/prefer-hooks-in-order': [0], + 'vitest/prefer-hooks-on-top': [2], + 'vitest/prefer-lowercase-title': [0], + 'vitest/prefer-mock-promise-shorthand': [0], + 'vitest/prefer-snapshot-hint': [0], + 'vitest/prefer-spy-on': [0], + 'vitest/prefer-strict-equal': [0], + 'vitest/prefer-to-be': [0], + 'vitest/prefer-to-be-falsy': [0], + 'vitest/prefer-to-be-object': [0], + 'vitest/prefer-to-be-truthy': [0], + 'vitest/prefer-to-contain': [0], + 'vitest/prefer-to-have-length': [0], + 'vitest/prefer-todo': [0], + 'vitest/require-hook': [0], + 'vitest/require-to-throw-message': [0], + 'vitest/require-top-level-describe': [0], + 'vitest/valid-describe-callback': [2], + 'vitest/valid-expect': [2], + 'vitest/valid-title': [2], + }, + }, + { + files: ['web_src/js/types.ts'], + rules: { + 'import-x/no-unused-modules': [0], + }, + }, + { + files: ['**/*.d.ts'], + rules: { + 'import-x/no-unused-modules': [0], + '@typescript-eslint/consistent-type-definitions': [0], + '@typescript-eslint/consistent-type-imports': [0], + }, + }, + { + files: ['*.config.*'], + rules: { + 'import-x/no-unused-modules': [0], + }, + }, + { + files: ['web_src/**/*', 'docs/**/*'], + languageOptions: {globals: globals.browser}, + }, + { + files: ['web_src/**/*'], + languageOptions: { + globals: { + ...globals.browser, + __webpack_public_path__: true, + process: false, // https://github.com/webpack/webpack/issues/15833 + }, + }, + }, +]); diff --git a/go.mod b/go.mod index eb871e24ae..f32c3e08ef 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,6 @@ require ( github.com/go-redsync/redsync/v4 v4.13.0 github.com/go-sql-driver/mysql v1.9.3 github.com/go-webauthn/webauthn v0.13.4 - github.com/gobwas/glob v0.2.3 github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang-jwt/jwt/v5 v5.3.0 diff --git a/go.sum b/go.sum index b69b380cfe..1853693e90 100644 --- a/go.sum +++ b/go.sum @@ -364,8 +364,6 @@ github.com/go-webauthn/webauthn v0.13.4 h1:q68qusWPcqHbg9STSxBLBHnsKaLxNO0RnVKaA github.com/go-webauthn/webauthn v0.13.4/go.mod h1:MglN6OH9ECxvhDqoq1wMoF6P6JRYDiQpC9nc5OomQmI= github.com/go-webauthn/x v0.1.24 h1:6LaWf2zzWqbyKT8IyQkhje1/1KCGhlEkMz4V1tDnt/A= github.com/go-webauthn/x v0.1.24/go.mod h1:2o5XKJ+X1AKqYKGgHdKflGnoQFQZ6flJ2IFCBKSbSOw= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= diff --git a/models/asymkey/gpg_key_commit_verification.go b/models/asymkey/gpg_key_commit_verification.go index b85374e073..375b703f7b 100644 --- a/models/asymkey/gpg_key_commit_verification.go +++ b/models/asymkey/gpg_key_commit_verification.go @@ -25,7 +25,7 @@ type CommitVerification struct { SigningUser *user_model.User // if Verified, then SigningUser is non-nil CommittingUser *user_model.User // if Verified, then CommittingUser is non-nil SigningEmail string - SigningKey *GPGKey + SigningKey *GPGKey // FIXME: need to refactor it to a new name like "SigningGPGKey", it is also used in some templates SigningSSHKey *PublicKey TrustStatus string } diff --git a/models/asymkey/key_display.go b/models/asymkey/key_display.go new file mode 100644 index 0000000000..ee17553b5b --- /dev/null +++ b/models/asymkey/key_display.go @@ -0,0 +1,37 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package asymkey + +import ( + "os" + + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +func GetDisplaySigningKey(key *git.SigningKey) string { + if key == nil || key.Format == "" { + return "" + } + + switch key.Format { + case git.SigningKeyFormatOpenPGP: + return key.KeyID + case git.SigningKeyFormatSSH: + content, err := os.ReadFile(key.KeyID) + if err != nil { + log.Error("Unable to read SSH key %s: %v", key.KeyID, err) + return "(Unable to read SSH key)" + } + display, err := CalcFingerprint(string(content)) + if err != nil { + log.Error("Unable to calculate fingerprint for SSH key %s: %v", key.KeyID, err) + return "(Unable to calculate fingerprint for SSH key)" + } + return display + } + setting.PanicInDevOrTesting("Unknown signing key format: %s", key.Format) + return "(Unknown key format)" +} diff --git a/models/db/log.go b/models/db/log.go index a9df6f541d..4f563a4df0 100644 --- a/models/db/log.go +++ b/models/db/log.go @@ -67,7 +67,7 @@ func (l *XORMLogBridge) Warn(v ...any) { l.Log(stackLevel, log.WARN, "%s", fmt.Sprint(v...)) } -// Warnf show warnning log +// Warnf show warning log func (l *XORMLogBridge) Warnf(format string, v ...any) { l.Log(stackLevel, log.WARN, format, v...) } diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index 55bbe6938c..511f7563cf 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -17,12 +17,11 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" - "github.com/gobwas/glob" - "github.com/gobwas/glob/syntax" "xorm.io/builder" ) @@ -77,7 +76,7 @@ func init() { // IsRuleNameSpecial return true if it contains special character func IsRuleNameSpecial(ruleName string) bool { for i := 0; i < len(ruleName); i++ { - if syntax.Special(ruleName[i]) { + if glob.IsSpecialByte(ruleName[i]) { return true } } diff --git a/models/git/protected_branch_list.go b/models/git/protected_branch_list.go index 16f8500672..6b282835a4 100644 --- a/models/git/protected_branch_list.go +++ b/models/git/protected_branch_list.go @@ -8,9 +8,8 @@ import ( "sort" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/optional" - - "github.com/gobwas/glob" ) type ProtectedBranchRules []*ProtectedBranch diff --git a/models/git/protected_tag.go b/models/git/protected_tag.go index 9a6646c742..95642df593 100644 --- a/models/git/protected_tag.go +++ b/models/git/protected_tag.go @@ -11,9 +11,8 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/timeutil" - - "github.com/gobwas/glob" ) // ProtectedTag struct diff --git a/models/migrations/v1_11/v111.go b/models/migrations/v1_11/v111.go index c27465f051..2634906565 100644 --- a/models/migrations/v1_11/v111.go +++ b/models/migrations/v1_11/v111.go @@ -408,7 +408,7 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error { official, err := isOfficialReviewer(sess, review.IssueID, reviewer) if err != nil { - // Branch might not be proteced or other error, ignore it. + // Branch might not be protected or other error, ignore it. continue } review.Official = official diff --git a/models/migrations/v1_12/v128.go b/models/migrations/v1_12/v128.go index d2e8b86a3d..34746dcdc4 100644 --- a/models/migrations/v1_12/v128.go +++ b/models/migrations/v1_12/v128.go @@ -12,6 +12,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -83,17 +84,17 @@ func FixMergeBase(ctx context.Context, x *xorm.Engine) error { if !pr.HasMerged { var err error - pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, gitRefName).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { var err2 error - pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err2 != nil { log.Error("Unable to get merge base for PR ID %d, Index %d in %s/%s. Error: %v & %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err, err2) continue } } } else { - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue @@ -105,9 +106,9 @@ func FixMergeBase(ctx context.Context, x *xorm.Engine) error { refs := append([]string{}, parents[1:]...) refs = append(refs, gitRefName) - cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) + cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue diff --git a/models/migrations/v1_12/v134.go b/models/migrations/v1_12/v134.go index 189d80cc52..d31cc3abdb 100644 --- a/models/migrations/v1_12/v134.go +++ b/models/migrations/v1_12/v134.go @@ -11,7 +11,7 @@ import ( "strings" "time" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -80,7 +80,7 @@ func RefixMergeBase(ctx context.Context, x *xorm.Engine) error { gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue @@ -93,9 +93,9 @@ func RefixMergeBase(ctx context.Context, x *xorm.Engine) error { // we should recalculate refs := append([]string{}, parents[1:]...) refs = append(refs, gitRefName) - cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) + cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) continue diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 7de43ecd07..678b18442e 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -348,10 +348,8 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use for _, u := range repo.Units { for _, team := range teams { - unitAccessMode := minAccessMode - if teamMode, exist := team.UnitAccessModeEx(ctx, u.Type); exist { - unitAccessMode = max(perm.unitsMode[u.Type], unitAccessMode, teamMode) - } + teamMode, _ := team.UnitAccessModeEx(ctx, u.Type) + unitAccessMode := max(perm.unitsMode[u.Type], minAccessMode, teamMode) perm.unitsMode[u.Type] = unitAccessMode } } diff --git a/models/perm/access/repo_permission_test.go b/models/perm/access/repo_permission_test.go index c8675b1ded..d81dfba288 100644 --- a/models/perm/access/repo_permission_test.go +++ b/models/perm/access/repo_permission_test.go @@ -197,4 +197,37 @@ func TestGetUserRepoPermission(t *testing.T) { assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode]) assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues]) }) + + repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // org private repo, same org as repo 32 + require.NoError(t, repo3.LoadOwner(ctx)) + require.True(t, repo3.Owner.IsOrganization()) + require.NoError(t, db.TruncateBeans(ctx, &organization.TeamUnit{}, &Access{})) // The user has access set of that repo, remove it, it is useless for our test + require.NoError(t, db.Insert(ctx, &organization.TeamRepo{OrgID: org.ID, TeamID: team.ID, RepoID: repo3.ID})) + t.Run("DoerWithNoopTeamOnPrivateRepo", func(t *testing.T) { + perm, err := GetUserRepoPermission(ctx, repo3, user) + require.NoError(t, err) + assert.Equal(t, perm_model.AccessModeNone, perm.AccessMode) + assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeCode]) + assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeIssues]) + }) + + require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeCode, AccessMode: perm_model.AccessModeNone})) + require.NoError(t, db.Insert(ctx, &organization.TeamUnit{OrgID: org.ID, TeamID: team.ID, Type: unit.TypeIssues, AccessMode: perm_model.AccessModeRead})) + t.Run("DoerWithReadIssueTeamOnPrivateRepo", func(t *testing.T) { + perm, err := GetUserRepoPermission(ctx, repo3, user) + require.NoError(t, err) + assert.Equal(t, perm_model.AccessModeNone, perm.AccessMode) + assert.Equal(t, perm_model.AccessModeNone, perm.unitsMode[unit.TypeCode]) + assert.Equal(t, perm_model.AccessModeRead, perm.unitsMode[unit.TypeIssues]) + }) + + require.NoError(t, db.Insert(ctx, repo_model.Collaboration{RepoID: repo3.ID, UserID: user.ID, Mode: perm_model.AccessModeWrite})) + require.NoError(t, db.Insert(ctx, Access{RepoID: repo3.ID, UserID: user.ID, Mode: perm_model.AccessModeWrite})) + t.Run("DoerWithReadIssueTeamAndWriteCollaboratorOnPrivateRepo", func(t *testing.T) { + perm, err := GetUserRepoPermission(ctx, repo3, user) + require.NoError(t, err) + assert.Equal(t, perm_model.AccessModeWrite, perm.AccessMode) + assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeCode]) + assert.Equal(t, perm_model.AccessModeWrite, perm.unitsMode[unit.TypeIssues]) + }) } diff --git a/models/user/setting_options.go b/models/user/setting_options.go index 7be5039329..6d37ef63d5 100644 --- a/models/user/setting_options.go +++ b/models/user/setting_options.go @@ -8,7 +8,7 @@ const ( SettingsKeyHiddenCommentTypes = "issue.hidden_comment_types" // SettingsKeyDiffWhitespaceBehavior is the setting key for whitespace behavior of diff SettingsKeyDiffWhitespaceBehavior = "diff.whitespace_behaviour" - // SettingsKeyShowOutdatedComments is the setting key wether or not to show outdated comments in PRs + // SettingsKeyShowOutdatedComments is the setting key whether or not to show outdated comments in PRs SettingsKeyShowOutdatedComments = "comment_code.show_outdated" // UserActivityPubPrivPem is user's private key diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go index 27bcafa649..5fc530b63e 100644 --- a/modules/actions/workflows.go +++ b/modules/actions/workflows.go @@ -10,11 +10,11 @@ import ( "strings" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" api "code.gitea.io/gitea/modules/structs" webhook_module "code.gitea.io/gitea/modules/webhook" - "github.com/gobwas/glob" "github.com/nektos/act/pkg/jobparser" "github.com/nektos/act/pkg/model" "github.com/nektos/act/pkg/workflowpattern" diff --git a/modules/avatar/identicon/identicon.go b/modules/avatar/identicon/identicon.go index ee92416a53..19f87da85a 100644 --- a/modules/avatar/identicon/identicon.go +++ b/modules/avatar/identicon/identicon.go @@ -70,7 +70,7 @@ func (i *Identicon) render(c, b1, b2, b1Angle, b2Angle, foreColor int) image.Ima /* # Algorithm -Origin: An image is splitted into 9 areas +Origin: An image is split into 9 areas ``` ------------- diff --git a/modules/git/attribute/batch.go b/modules/git/attribute/batch.go index 4e31fda575..9f805d55c5 100644 --- a/modules/git/attribute/batch.go +++ b/modules/git/attribute/batch.go @@ -12,6 +12,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -23,7 +24,7 @@ type BatchChecker struct { stdOut *nulSeparatedAttributeWriter ctx context.Context cancel context.CancelFunc - cmd *git.Command + cmd *gitcmd.Command } // NewBatchChecker creates a check attribute reader for the current repository and provided commit ID @@ -76,7 +77,7 @@ func NewBatchChecker(repo *git.Repository, treeish string, attributes []string) _ = lw.Close() }() stdErr := new(bytes.Buffer) - err := cmd.Run(ctx, &git.RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ Env: envs, Dir: repo.Path, Stdin: stdinReader, diff --git a/modules/git/attribute/checker.go b/modules/git/attribute/checker.go index 167b31416e..4b313adf37 100644 --- a/modules/git/attribute/checker.go +++ b/modules/git/attribute/checker.go @@ -11,12 +11,13 @@ import ( "os" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) -func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*git.Command, []string, func(), error) { +func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*gitcmd.Command, []string, func(), error) { cancel := func() {} envs := []string{"GIT_FLUSH=1"} - cmd := git.NewCommand("check-attr", "-z") + cmd := gitcmd.NewCommand("check-attr", "-z") if len(attributes) == 0 { cmd.AddArguments("--all") } @@ -70,7 +71,7 @@ func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish strin stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Env: append(os.Environ(), envs...), Dir: gitRepo.Path, Stdout: stdOut, diff --git a/modules/git/batch_reader.go b/modules/git/batch_reader.go index 7bbab76bb8..f09f4144c8 100644 --- a/modules/git/batch_reader.go +++ b/modules/git/batch_reader.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "github.com/djherbis/buffer" @@ -29,13 +30,13 @@ type WriteCloserError interface { // This is needed otherwise the git cat-file will hang for invalid repositories. func ensureValidGitRepository(ctx context.Context, repoPath string) error { stderr := strings.Builder{} - err := NewCommand("rev-parse"). - Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("rev-parse"). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stderr: &stderr, }) if err != nil { - return ConcatenateError(err, (&stderr).String()) + return gitcmd.ConcatenateError(err, (&stderr).String()) } return nil } @@ -61,8 +62,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, go func() { stderr := strings.Builder{} - err := NewCommand("cat-file", "--batch-check"). - Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("cat-file", "--batch-check"). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdin: batchStdinReader, Stdout: batchStdoutWriter, @@ -71,8 +72,8 @@ func catFileBatchCheck(ctx context.Context, repoPath string) (WriteCloserError, UseContextTimeout: true, }) if err != nil { - _ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) - _ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = batchStdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) + _ = batchStdinReader.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = batchStdoutWriter.Close() _ = batchStdinReader.Close() @@ -109,8 +110,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi go func() { stderr := strings.Builder{} - err := NewCommand("cat-file", "--batch"). - Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("cat-file", "--batch"). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdin: batchStdinReader, Stdout: batchStdoutWriter, @@ -119,8 +120,8 @@ func catFileBatch(ctx context.Context, repoPath string) (WriteCloserError, *bufi UseContextTimeout: true, }) if err != nil { - _ = batchStdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) - _ = batchStdinReader.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = batchStdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) + _ = batchStdinReader.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = batchStdoutWriter.Close() _ = batchStdinReader.Close() diff --git a/modules/git/blame.go b/modules/git/blame.go index db10df129e..50cadc41c2 100644 --- a/modules/git/blame.go +++ b/modules/git/blame.go @@ -10,6 +10,7 @@ import ( "io" "os" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) @@ -141,7 +142,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath } }() - cmd := NewCommand("blame", "--porcelain") + cmd := gitcmd.NewCommand("blame", "--porcelain") if DefaultFeatures().CheckVersionAtLeast("2.23") && !bypassBlameIgnore { ignoreRevsFileName, ignoreRevsFileCleanup, err = tryCreateBlameIgnoreRevsFile(commit) @@ -165,7 +166,7 @@ func CreateBlameReader(ctx context.Context, objectFormat ObjectFormat, repoPath go func() { stderr := bytes.Buffer{} // TODO: it doesn't work for directories (the directories shouldn't be "blamed"), and the "err" should be returned by "Read" but not by "Close" - err := cmd.Run(ctx, &RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ UseContextTimeout: true, Dir: repoPath, Stdout: stdout, diff --git a/modules/git/commit.go b/modules/git/commit.go index 0dc894d3ab..a0c5955ae8 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/util" ) @@ -87,12 +88,12 @@ func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) { // AddChanges marks local changes to be ready for commit. func AddChanges(ctx context.Context, repoPath string, all bool, files ...string) error { - cmd := NewCommand().AddArguments("add") + cmd := gitcmd.NewCommand().AddArguments("add") if all { cmd.AddArguments("--all") } cmd.AddDashesAndList(files...) - _, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) return err } @@ -106,7 +107,7 @@ type CommitChangesOptions struct { // CommitChanges commits local changes with given committer, author and message. // If author is nil, it will be the same as committer. func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptions) error { - cmd := NewCommand() + cmd := gitcmd.NewCommand() if opts.Committer != nil { cmd.AddOptionValues("-c", "user.name="+opts.Committer.Name) cmd.AddOptionValues("-c", "user.email="+opts.Committer.Email) @@ -121,7 +122,7 @@ func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptio } cmd.AddOptionFormat("--message=%s", opts.Message) - _, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) // No stderr but exit status 1 means nothing to commit. if err != nil && err.Error() == "exit status 1" { return nil @@ -131,7 +132,7 @@ func CommitChanges(ctx context.Context, repoPath string, opts CommitChangesOptio // AllCommitsCount returns count of all commits in repository func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, files ...string) (int64, error) { - cmd := NewCommand("rev-list") + cmd := gitcmd.NewCommand("rev-list") if hidePRRefs { cmd.AddArguments("--exclude=" + PullPrefix + "*") } @@ -140,7 +141,7 @@ func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, file cmd.AddDashesAndList(files...) } - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return 0, err } @@ -160,7 +161,7 @@ type CommitsCountOptions struct { // CommitsCount returns number of total commits of until given revision. func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) { - cmd := NewCommand("rev-list", "--count") + cmd := gitcmd.NewCommand("rev-list", "--count") cmd.AddDynamicArguments(opts.Revision...) @@ -172,7 +173,7 @@ func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) cmd.AddDashesAndList(opts.RelPath...) } - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: opts.RepoPath}) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: opts.RepoPath}) if err != nil { return 0, err } @@ -207,7 +208,7 @@ func (c *Commit) HasPreviousCommit(objectID ObjectID) (bool, error) { return false, nil } - _, _, err := NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path}) + _, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor").AddDynamicArguments(that, this).RunStdString(c.repo.Ctx, &gitcmd.RunOpts{Dir: c.repo.Path}) if err == nil { return true, nil } @@ -348,12 +349,12 @@ func (c *Commit) GetFileContent(filename string, limit int) (string, error) { // GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only') func (c *Commit) GetBranchName() (string, error) { - cmd := NewCommand("name-rev") + cmd := gitcmd.NewCommand("name-rev") if DefaultFeatures().CheckVersionAtLeast("2.13.0") { cmd.AddArguments("--exclude", "refs/tags/*") } cmd.AddArguments("--name-only", "--no-undefined").AddDynamicArguments(c.ID.String()) - data, _, err := cmd.RunStdString(c.repo.Ctx, &RunOpts{Dir: c.repo.Path}) + data, _, err := cmd.RunStdString(c.repo.Ctx, &gitcmd.RunOpts{Dir: c.repo.Path}) if err != nil { // handle special case where git can not describe commit if strings.Contains(err.Error(), "cannot describe") { @@ -431,14 +432,14 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi }() stderr := new(bytes.Buffer) - err := NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &RunOpts{ + err := gitcmd.NewCommand("log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: w, Stderr: stderr, }) w.Close() // Close writer to exit parsing goroutine if err != nil { - return nil, ConcatenateError(err, stderr.String()) + return nil, gitcmd.ConcatenateError(err, stderr.String()) } <-done @@ -447,7 +448,7 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi // GetFullCommitID returns full length (40) of commit ID by given short SHA in a repository. func GetFullCommitID(ctx context.Context, repoPath, shortID string) (string, error) { - commitID, _, err := NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &RunOpts{Dir: repoPath}) + commitID, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(shortID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { if strings.Contains(err.Error(), "exit status 128") { return "", ErrNotExist{shortID, ""} diff --git a/modules/git/config.go b/modules/git/config.go index 3a717908b9..2eafe971b3 100644 --- a/modules/git/config.go +++ b/modules/git/config.go @@ -11,13 +11,14 @@ import ( "runtime" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) // syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem) func syncGitConfig(ctx context.Context) (err error) { - if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil { - return fmt.Errorf("unable to prepare git home directory %s, err: %w", HomeDir(), err) + if err = os.MkdirAll(gitcmd.HomeDir(), os.ModePerm); err != nil { + return fmt.Errorf("unable to prepare git home directory %s, err: %w", gitcmd.HomeDir(), err) } // first, write user's git config options to git config file @@ -117,8 +118,8 @@ func syncGitConfig(ctx context.Context) (err error) { } func configSet(ctx context.Context, key, value string) error { - stdout, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) - if err != nil && !IsErrorExitCode(err, 1) { + stdout, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) + if err != nil && !gitcmd.IsErrorExitCode(err, 1) { return fmt.Errorf("failed to get git config %s, err: %w", key, err) } @@ -127,7 +128,7 @@ func configSet(ctx context.Context, key, value string) error { return nil } - _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to set git global config %s, err: %w", key, err) } @@ -136,14 +137,14 @@ func configSet(ctx context.Context, key, value string) error { } func configSetNonExist(ctx context.Context, key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err == nil { // already exist return nil } - if IsErrorExitCode(err, 1) { + if gitcmd.IsErrorExitCode(err, 1) { // not exist, set new config - _, _, err = NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to set git global config %s, err: %w", key, err) } @@ -154,14 +155,14 @@ func configSetNonExist(ctx context.Context, key, value string) error { } func configAddNonExist(ctx context.Context, key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) if err == nil { // already exist return nil } - if IsErrorExitCode(err, 1) { + if gitcmd.IsErrorExitCode(err, 1) { // not exist, add new config - _, _, err = NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global", "--add").AddDynamicArguments(key, value).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to add git global config %s, err: %w", key, err) } @@ -171,16 +172,16 @@ func configAddNonExist(ctx context.Context, key, value string) error { } func configUnsetAll(ctx context.Context, key, value string) error { - _, _, err := NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("config", "--global", "--get").AddDynamicArguments(key).RunStdString(ctx, nil) if err == nil { // exist, need to remove - _, _, err = NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) + _, _, err = gitcmd.NewCommand("config", "--global", "--unset-all").AddDynamicArguments(key, regexp.QuoteMeta(value)).RunStdString(ctx, nil) if err != nil { return fmt.Errorf("failed to unset git global config %s, err: %w", key, err) } return nil } - if IsErrorExitCode(err, 1) { + if gitcmd.IsErrorExitCode(err, 1) { // not exist return nil } diff --git a/modules/git/config_test.go b/modules/git/config_test.go index 911e0e0184..237feb67d5 100644 --- a/modules/git/config_test.go +++ b/modules/git/config_test.go @@ -8,13 +8,14 @@ import ( "strings" "testing" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" ) func gitConfigContains(sub string) bool { - if b, err := os.ReadFile(HomeDir() + "/.gitconfig"); err == nil { + if b, err := os.ReadFile(gitcmd.HomeDir() + "/.gitconfig"); err == nil { return strings.Contains(string(b), sub) } return false diff --git a/modules/git/diff.go b/modules/git/diff.go index 35d115be0e..d185cc9277 100644 --- a/modules/git/diff.go +++ b/modules/git/diff.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -34,8 +35,8 @@ func GetRawDiff(repo *Repository, commitID string, diffType RawDiffType, writer // GetReverseRawDiff dumps the reverse diff results of repository in given commit ID to io.Writer. func GetReverseRawDiff(ctx context.Context, repoPath, commitID string, writer io.Writer) error { stderr := new(bytes.Buffer) - cmd := NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID) - if err := cmd.Run(ctx, &RunOpts{ + cmd := gitcmd.NewCommand("show", "--pretty=format:revert %H%n", "-R").AddDynamicArguments(commitID) + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: writer, Stderr: stderr, @@ -56,7 +57,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff files = append(files, file) } - cmd := NewCommand() + cmd := gitcmd.NewCommand() switch diffType { case RawDiffNormal: if len(startCommit) != 0 { @@ -89,7 +90,7 @@ func GetRepoRawDiffForFile(repo *Repository, startCommit, endCommit string, diff } stderr := new(bytes.Buffer) - if err = cmd.Run(repo.Ctx, &RunOpts{ + if err = cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: writer, Stderr: stderr, @@ -312,8 +313,8 @@ func GetAffectedFiles(repo *Repository, branchName, oldCommitID, newCommitID str affectedFiles := make([]string, 0, 32) // Run `git diff --name-only` to get the names of the changed files - err = NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID). - Run(repo.Ctx, &RunOpts{ + err = gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(oldCommitID, newCommitID). + Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdout: stdoutWriter, diff --git a/modules/git/git.go b/modules/git/git.go index 0a2e87a2ea..161fa42196 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -9,12 +9,12 @@ import ( "errors" "fmt" "os" - "os/exec" "path/filepath" "runtime" "strings" "time" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -33,10 +33,7 @@ type Features struct { SupportCheckAttrOnBare bool // >= 2.40 } -var ( - GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization - defaultFeatures *Features -) +var defaultFeatures *Features func (f *Features) CheckVersionAtLeast(atLeast string) bool { return f.gitVersion.Compare(version.Must(version.NewVersion(atLeast))) >= 0 @@ -60,7 +57,7 @@ func DefaultFeatures() *Features { } func loadGitVersionFeatures() (*Features, error) { - stdout, _, runErr := NewCommand("version").RunStdString(context.Background(), nil) + stdout, _, runErr := gitcmd.NewCommand("version").RunStdString(context.Background(), nil) if runErr != nil { return nil, runErr } @@ -129,32 +126,6 @@ func ensureGitVersion() error { return nil } -// SetExecutablePath changes the path of git executable and checks the file permission and version. -func SetExecutablePath(path string) error { - // If path is empty, we use the default value of GitExecutable "git" to search for the location of git. - if path != "" { - GitExecutable = path - } - absPath, err := exec.LookPath(GitExecutable) - if err != nil { - return fmt.Errorf("git not found: %w", err) - } - GitExecutable = absPath - return nil -} - -// HomeDir is the home dir for git to store the global config file used by Gitea internally -func HomeDir() string { - if setting.Git.HomePath == "" { - // strict check, make sure the git module is initialized correctly. - // attention: when the git module is called in gitea sub-command (serv/hook), the log module might not obviously show messages to users/developers. - // for example: if there is gitea git hook code calling git.NewCommand before git.InitXxx, the integration test won't show the real failure reasons. - log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules") - return "" - } - return setting.Git.HomePath -} - // InitSimple initializes git module with a very simple step, no config changes, no global command arguments. // This method doesn't change anything to filesystem. At the moment, it is only used by some Gitea sub-commands. func InitSimple() error { @@ -167,10 +138,10 @@ func InitSimple() error { } if setting.Git.Timeout.Default > 0 { - defaultCommandExecutionTimeout = time.Duration(setting.Git.Timeout.Default) * time.Second + gitcmd.SetDefaultCommandExecutionTimeout(time.Duration(setting.Git.Timeout.Default) * time.Second) } - if err := SetExecutablePath(setting.Git.Path); err != nil { + if err := gitcmd.SetExecutablePath(setting.Git.Path); err != nil { return err } @@ -185,7 +156,7 @@ func InitSimple() error { // when git works with gnupg (commit signing), there should be a stable home for gnupg commands if _, ok := os.LookupEnv("GNUPGHOME"); !ok { - _ = os.Setenv("GNUPGHOME", filepath.Join(HomeDir(), ".gnupg")) + _ = os.Setenv("GNUPGHOME", filepath.Join(gitcmd.HomeDir(), ".gnupg")) } return nil } diff --git a/modules/git/command.go b/modules/git/gitcmd/command.go similarity index 99% rename from modules/git/command.go rename to modules/git/gitcmd/command.go index eeb987feb0..ed2f6fb647 100644 --- a/modules/git/command.go +++ b/modules/git/gitcmd/command.go @@ -2,7 +2,7 @@ // Copyright 2016 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package git +package gitcmd import ( "bytes" @@ -32,6 +32,10 @@ type TrustedCmdArgs []internal.CmdArg // defaultCommandExecutionTimeout default command execution timeout duration var defaultCommandExecutionTimeout = 360 * time.Second +func SetDefaultCommandExecutionTimeout(timeout time.Duration) { + defaultCommandExecutionTimeout = timeout +} + // DefaultLocale is the default LC_ALL to run git commands in. const DefaultLocale = "C" diff --git a/modules/git/command_race_test.go b/modules/git/gitcmd/command_race_test.go similarity index 98% rename from modules/git/command_race_test.go rename to modules/git/gitcmd/command_race_test.go index a6aa3a1580..aee2272808 100644 --- a/modules/git/command_race_test.go +++ b/modules/git/gitcmd/command_race_test.go @@ -3,7 +3,7 @@ //go:build race -package git +package gitcmd import ( "context" diff --git a/modules/git/command_test.go b/modules/git/gitcmd/command_test.go similarity index 83% rename from modules/git/command_test.go rename to modules/git/gitcmd/command_test.go index 85976e289e..544a97f64c 100644 --- a/modules/git/command_test.go +++ b/modules/git/gitcmd/command_test.go @@ -1,14 +1,30 @@ // Copyright 2022 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT -package git +package gitcmd import ( + "fmt" + "os" "testing" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/tempdir" + "github.com/stretchr/testify/assert" ) +func TestMain(m *testing.M) { + gitHomePath, cleanup, err := tempdir.OsTempDir("gitea-test").MkdirTempRandom("git-home") + if err != nil { + _, _ = fmt.Fprintf(os.Stderr, "unable to create temp dir: %v", err) + os.Exit(1) + } + defer cleanup() + + setting.Git.HomePath = gitHomePath +} + func TestRunWithContextStd(t *testing.T) { cmd := NewCommand("--version") stdout, stderr, err := cmd.RunStdString(t.Context(), &RunOpts{}) diff --git a/modules/git/gitcmd/env.go b/modules/git/gitcmd/env.go new file mode 100644 index 0000000000..269b51a253 --- /dev/null +++ b/modules/git/gitcmd/env.go @@ -0,0 +1,40 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitcmd + +import ( + "fmt" + "os/exec" + + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +var GitExecutable = "git" // the command name of git, will be updated to an absolute path during initialization + +// SetExecutablePath changes the path of git executable and checks the file permission and version. +func SetExecutablePath(path string) error { + // If path is empty, we use the default value of GitExecutable "git" to search for the location of git. + if path != "" { + GitExecutable = path + } + absPath, err := exec.LookPath(GitExecutable) + if err != nil { + return fmt.Errorf("git not found: %w", err) + } + GitExecutable = absPath + return nil +} + +// HomeDir is the home dir for git to store the global config file used by Gitea internally +func HomeDir() string { + if setting.Git.HomePath == "" { + // strict check, make sure the git module is initialized correctly. + // attention: when the git module is called in gitea sub-command (serv/hook), the log module might not obviously show messages to users/developers. + // for example: if there is gitea git hook code calling NewCommand before git.InitXxx, the integration test won't show the real failure reasons. + log.Fatal("Unable to init Git's HomeDir, incorrect initialization of the setting and git modules") + return "" + } + return setting.Git.HomePath +} diff --git a/modules/git/gitcmd/utils.go b/modules/git/gitcmd/utils.go new file mode 100644 index 0000000000..ee24eb6a9a --- /dev/null +++ b/modules/git/gitcmd/utils.go @@ -0,0 +1,14 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitcmd + +import "fmt" + +// ConcatenateError concatenats an error with stderr string +func ConcatenateError(err error, stderr string) error { + if len(stderr) == 0 { + return err + } + return fmt.Errorf("%w - %s", err, stderr) +} diff --git a/modules/git/grep.go b/modules/git/grep.go index 66711650c9..f5f6f12041 100644 --- a/modules/git/grep.go +++ b/modules/git/grep.go @@ -14,6 +14,7 @@ import ( "strconv" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) @@ -60,7 +61,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO 2^@repo: go-gitea/gitea */ var results []*GrepResult - cmd := NewCommand("grep", "--null", "--break", "--heading", "--line-number", "--full-name") + cmd := gitcmd.NewCommand("grep", "--null", "--break", "--heading", "--line-number", "--full-name") cmd.AddOptionValues("--context", strconv.Itoa(opts.ContextLineNumber)) switch opts.GrepMode { case GrepModeExact: @@ -83,7 +84,7 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO cmd.AddDashesAndList(opts.PathspecList...) opts.MaxResultLimit = util.IfZero(opts.MaxResultLimit, 50) stderr := bytes.Buffer{} - err = cmd.Run(ctx, &RunOpts{ + err = cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr, @@ -135,11 +136,11 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO }, }) // git grep exits by cancel (killed), usually it is caused by the limit of results - if IsErrorExitCode(err, -1) && stderr.Len() == 0 { + if gitcmd.IsErrorExitCode(err, -1) && stderr.Len() == 0 { return results, nil } // git grep exits with 1 if no results are found - if IsErrorExitCode(err, 1) && stderr.Len() == 0 { + if gitcmd.IsErrorExitCode(err, 1) && stderr.Len() == 0 { return nil, nil } if err != nil && !errors.Is(err, context.Canceled) { diff --git a/modules/git/key.go b/modules/git/key.go index 2513c048b7..8c14742f34 100644 --- a/modules/git/key.go +++ b/modules/git/key.go @@ -3,13 +3,24 @@ package git +import "code.gitea.io/gitea/modules/setting" + // Based on https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat const ( SigningKeyFormatOpenPGP = "openpgp" // for GPG keys, the expected default of git cli SigningKeyFormatSSH = "ssh" ) +// SigningKey represents an instance key info which will be used to sign git commits. +// FIXME: need to refactor it to a new name, this name conflicts with the variable names for "asymkey.GPGKey" in many places. type SigningKey struct { KeyID string Format string } + +func (s *SigningKey) String() string { + // Do not expose KeyID + // In case the key is a file path and the struct is rendered in a template, then the server path will be exposed. + setting.PanicInDevOrTesting("don't call SigningKey.String() - it exposes the KeyID which might be a local file path") + return "SigningKey:" + s.Format +} diff --git a/modules/git/log_name_status.go b/modules/git/log_name_status.go index dfdef38ef9..7a5192f58b 100644 --- a/modules/git/log_name_status.go +++ b/modules/git/log_name_status.go @@ -14,6 +14,7 @@ import ( "strings" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/git/gitcmd" "github.com/djherbis/buffer" "github.com/djherbis/nio/v3" @@ -34,7 +35,7 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p _ = stdoutWriter.Close() } - cmd := NewCommand() + cmd := gitcmd.NewCommand() cmd.AddArguments("log", "--name-status", "-c", "--format=commit%x00%H %P%x00", "--parents", "--no-renames", "-t", "-z").AddDynamicArguments(head) var files []string @@ -64,13 +65,13 @@ func LogNameStatusRepo(ctx context.Context, repository, head, treepath string, p go func() { stderr := strings.Builder{} - err := cmd.Run(ctx, &RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repository, Stdout: stdoutWriter, Stderr: &stderr, }) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) return } diff --git a/modules/git/pipeline/catfile.go b/modules/git/pipeline/catfile.go index 5ddc36cc01..ced8532e6d 100644 --- a/modules/git/pipeline/catfile.go +++ b/modules/git/pipeline/catfile.go @@ -13,7 +13,7 @@ import ( "strings" "sync" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -25,8 +25,8 @@ func CatFileBatchCheck(ctx context.Context, shasToCheckReader *io.PipeReader, ca stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("cat-file", "--batch-check") - if err := cmd.Run(ctx, &git.RunOpts{ + cmd := gitcmd.NewCommand("cat-file", "--batch-check") + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdin: shasToCheckReader, Stdout: catFileCheckWriter, @@ -43,8 +43,8 @@ func CatFileBatchCheckAllObjects(ctx context.Context, catFileCheckWriter *io.Pip stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("cat-file", "--batch-check", "--batch-all-objects") - if err := cmd.Run(ctx, &git.RunOpts{ + cmd := gitcmd.NewCommand("cat-file", "--batch-check", "--batch-all-objects") + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: catFileCheckWriter, Stderr: stderr, @@ -64,7 +64,7 @@ func CatFileBatch(ctx context.Context, shasToBatchReader *io.PipeReader, catFile stderr := new(bytes.Buffer) var errbuf strings.Builder - if err := git.NewCommand("cat-file", "--batch").Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("cat-file", "--batch").Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: catFileBatchWriter, Stdin: shasToBatchReader, diff --git a/modules/git/pipeline/lfs_nogogit.go b/modules/git/pipeline/lfs_nogogit.go index c5eed73701..d2f147854d 100644 --- a/modules/git/pipeline/lfs_nogogit.go +++ b/modules/git/pipeline/lfs_nogogit.go @@ -14,6 +14,7 @@ import ( "sync" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // FindLFSFile finds commits that contain a provided pointer file hash @@ -32,13 +33,13 @@ func FindLFSFile(repo *git.Repository, objectID git.ObjectID) ([]*LFSResult, err go func() { stderr := strings.Builder{} - err := git.NewCommand("rev-list", "--all").Run(repo.Ctx, &git.RunOpts{ + err := gitcmd.NewCommand("rev-list", "--all").Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: revListWriter, Stderr: &stderr, }) if err != nil { - _ = revListWriter.CloseWithError(git.ConcatenateError(err, (&stderr).String())) + _ = revListWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = revListWriter.Close() } diff --git a/modules/git/pipeline/namerev.go b/modules/git/pipeline/namerev.go index 06731c5051..0081f7a26d 100644 --- a/modules/git/pipeline/namerev.go +++ b/modules/git/pipeline/namerev.go @@ -11,7 +11,7 @@ import ( "strings" "sync" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // NameRevStdin runs name-rev --stdin @@ -22,7 +22,7 @@ func NameRevStdin(ctx context.Context, shasToNameReader *io.PipeReader, nameRevS stderr := new(bytes.Buffer) var errbuf strings.Builder - if err := git.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("name-rev", "--stdin", "--name-only", "--always").Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: nameRevStdinWriter, Stdin: shasToNameReader, diff --git a/modules/git/pipeline/revlist.go b/modules/git/pipeline/revlist.go index 31627a0f3a..9d4ff75434 100644 --- a/modules/git/pipeline/revlist.go +++ b/modules/git/pipeline/revlist.go @@ -12,7 +12,7 @@ import ( "strings" "sync" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -23,8 +23,8 @@ func RevListAllObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sy stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("rev-list", "--objects", "--all") - if err := cmd.Run(ctx, &git.RunOpts{ + cmd := gitcmd.NewCommand("rev-list", "--objects", "--all") + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: basePath, Stdout: revListWriter, Stderr: stderr, @@ -42,11 +42,11 @@ func RevListObjects(ctx context.Context, revListWriter *io.PipeWriter, wg *sync. defer revListWriter.Close() stderr := new(bytes.Buffer) var errbuf strings.Builder - cmd := git.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA) + cmd := gitcmd.NewCommand("rev-list", "--objects").AddDynamicArguments(headSHA) if baseSHA != "" { cmd = cmd.AddArguments("--not").AddDynamicArguments(baseSHA) } - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: revListWriter, Stderr: stderr, diff --git a/modules/git/remote.go b/modules/git/remote.go index 283d26484b..9f12142f91 100644 --- a/modules/git/remote.go +++ b/modules/git/remote.go @@ -9,19 +9,20 @@ import ( "net/url" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) // GetRemoteAddress returns remote url of git repository in the repoPath with special remote name func GetRemoteAddress(ctx context.Context, repoPath, remoteName string) (string, error) { - var cmd *Command + var cmd *gitcmd.Command if DefaultFeatures().CheckVersionAtLeast("2.7") { - cmd = NewCommand("remote", "get-url").AddDynamicArguments(remoteName) + cmd = gitcmd.NewCommand("remote", "get-url").AddDynamicArguments(remoteName) } else { - cmd = NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url") + cmd = gitcmd.NewCommand("config", "--get").AddDynamicArguments("remote." + remoteName + ".url") } - result, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + result, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return "", err } diff --git a/modules/git/repo.go b/modules/git/repo.go index 8e7b427bd0..38cb4592a0 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -17,6 +17,7 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/proxy" "code.gitea.io/gitea/modules/setting" ) @@ -40,9 +41,9 @@ func (repo *Repository) GetAllCommitsCount() (int64, error) { func (repo *Repository) ShowPrettyFormatLogToList(ctx context.Context, revisionRange string) ([]*Commit, error) { // avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git [...] -- [...]' - logs, _, err := NewCommand("log").AddArguments(prettyLogFormat). + logs, _, err := gitcmd.NewCommand("log").AddArguments(prettyLogFormat). AddDynamicArguments(revisionRange).AddArguments("--"). - RunStdBytes(ctx, &RunOpts{Dir: repo.Path}) + RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -70,7 +71,7 @@ func (repo *Repository) parsePrettyFormatLogToList(logs []byte) ([]*Commit, erro // IsRepoURLAccessible checks if given repository URL is accessible. func IsRepoURLAccessible(ctx context.Context, url string) bool { - _, _, err := NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil) + _, _, err := gitcmd.NewCommand("ls-remote", "-q", "-h").AddDynamicArguments(url, "HEAD").RunStdString(ctx, nil) return err == nil } @@ -81,7 +82,7 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma return err } - cmd := NewCommand("init") + cmd := gitcmd.NewCommand("init") if !IsValidObjectFormat(objectFormatName) { return fmt.Errorf("invalid object format: %s", objectFormatName) @@ -93,15 +94,15 @@ func InitRepository(ctx context.Context, repoPath string, bare bool, objectForma if bare { cmd.AddArguments("--bare") } - _, _, err = cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) return err } // IsEmpty Check if repository is empty. func (repo *Repository) IsEmpty() (bool, error) { var errbuf, output strings.Builder - if err := NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all"). - Run(repo.Ctx, &RunOpts{ + if err := gitcmd.NewCommand().AddOptionFormat("--git-dir=%s", repo.Path).AddArguments("rev-list", "-n", "1", "--all"). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: &output, Stderr: &errbuf, @@ -137,7 +138,7 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error { return err } - cmd := NewCommand().AddArguments("clone") + cmd := gitcmd.NewCommand().AddArguments("clone") if opts.SkipTLSVerify { cmd.AddArguments("-c", "http.sslVerify=false") } @@ -178,13 +179,13 @@ func Clone(ctx context.Context, from, to string, opts CloneRepoOptions) error { } stderr := new(bytes.Buffer) - if err = cmd.Run(ctx, &RunOpts{ + if err = cmd.Run(ctx, &gitcmd.RunOpts{ Timeout: opts.Timeout, Env: envs, Stdout: io.Discard, Stderr: stderr, }); err != nil { - return ConcatenateError(err, stderr.String()) + return gitcmd.ConcatenateError(err, stderr.String()) } return nil } @@ -201,7 +202,7 @@ type PushOptions struct { // Push pushs local commits to given remote branch. func Push(ctx context.Context, repoPath string, opts PushOptions) error { - cmd := NewCommand("push") + cmd := gitcmd.NewCommand("push") if opts.Force { cmd.AddArguments("-f") } @@ -214,7 +215,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error { } cmd.AddDashesAndList(remoteBranchArgs...) - stdout, stderr, err := cmd.RunStdString(ctx, &RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath}) + stdout, stderr, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Env: opts.Env, Timeout: opts.Timeout, Dir: repoPath}) if err != nil { if strings.Contains(stderr, "non-fast-forward") { return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err} @@ -233,8 +234,8 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error { // GetLatestCommitTime returns time for latest commit in repository (across all branches) func GetLatestCommitTime(ctx context.Context, repoPath string) (time.Time, error) { - cmd := NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)") - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + cmd := gitcmd.NewCommand("for-each-ref", "--sort=-committerdate", BranchPrefix, "--count", "1", "--format=%(committerdate)") + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return time.Time{}, err } @@ -250,9 +251,9 @@ type DivergeObject struct { // GetDivergingCommits returns the number of commits a targetBranch is ahead or behind a baseBranch func GetDivergingCommits(ctx context.Context, repoPath, baseBranch, targetBranch string) (do DivergeObject, err error) { - cmd := NewCommand("rev-list", "--count", "--left-right"). + cmd := gitcmd.NewCommand("rev-list", "--count", "--left-right"). AddDynamicArguments(baseBranch + "..." + targetBranch).AddArguments("--") - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return do, err } @@ -281,23 +282,23 @@ func (repo *Repository) CreateBundle(ctx context.Context, commit string, out io. defer cleanup() env := append(os.Environ(), "GIT_OBJECT_DIRECTORY="+filepath.Join(repo.Path, "objects")) - _, _, err = NewCommand("init", "--bare").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("init", "--bare").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } - _, _, err = NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("reset", "--soft").AddDynamicArguments(commit).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } - _, _, err = NewCommand("branch", "-m", "bundle").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("branch", "-m", "bundle").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } tmpFile := filepath.Join(tmp, "bundle") - _, _, err = NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &RunOpts{Dir: tmp, Env: env}) + _, _, err = gitcmd.NewCommand("bundle", "create").AddDynamicArguments(tmpFile, "bundle", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmp, Env: env}) if err != nil { return err } diff --git a/modules/git/repo_archive.go b/modules/git/repo_archive.go index 0b2f6f2a45..e12300345f 100644 --- a/modules/git/repo_archive.go +++ b/modules/git/repo_archive.go @@ -10,6 +10,8 @@ import ( "io" "path/filepath" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // ArchiveType archive types @@ -53,7 +55,7 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t return fmt.Errorf("unknown format: %v", format) } - cmd := NewCommand("archive") + cmd := gitcmd.NewCommand("archive") if usePrefix { cmd.AddOptionFormat("--prefix=%s", filepath.Base(strings.TrimSuffix(repo.Path, ".git"))+"/") } @@ -61,13 +63,13 @@ func (repo *Repository) CreateArchive(ctx context.Context, format ArchiveType, t cmd.AddDynamicArguments(commitID) var stderr strings.Builder - err := cmd.Run(ctx, &RunOpts{ + err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: target, Stderr: &stderr, }) if err != nil { - return ConcatenateError(err, stderr.String()) + return gitcmd.ConcatenateError(err, stderr.String()) } return nil } diff --git a/modules/git/repo_blame.go b/modules/git/repo_blame.go index 6941a76c42..04f74049aa 100644 --- a/modules/git/repo_blame.go +++ b/modules/git/repo_blame.go @@ -5,14 +5,16 @@ package git import ( "fmt" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // LineBlame returns the latest commit at the given line func (repo *Repository) LineBlame(revision, path, file string, line uint) (*Commit, error) { - res, _, err := NewCommand("blame"). + res, _, err := gitcmd.NewCommand("blame"). AddOptionFormat("-L %d,%d", line, line). AddOptionValues("-p", revision). - AddDashesAndList(file).RunStdString(repo.Ctx, &RunOpts{Dir: path}) + AddDashesAndList(file).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: path}) if err != nil { return nil, err } diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index eac2031003..5d4c05bb28 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -8,6 +8,8 @@ import ( "context" "errors" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // BranchPrefix base dir of the branch information file store on git @@ -15,7 +17,7 @@ const BranchPrefix = "refs/heads/" // IsReferenceExist returns true if given reference exists in the repository. func IsReferenceExist(ctx context.Context, repoPath, name string) bool { - _, _, err := NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &RunOpts{Dir: repoPath}) + _, _, err := gitcmd.NewCommand("show-ref", "--verify").AddDashesAndList(name).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) return err == nil } @@ -25,7 +27,7 @@ func IsBranchExist(ctx context.Context, repoPath, name string) bool { } func GetDefaultBranch(ctx context.Context, repoPath string) (string, error) { - stdout, _, err := NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &RunOpts{Dir: repoPath}) + stdout, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return "", err } @@ -43,7 +45,7 @@ type DeleteBranchOptions struct { // DeleteBranch delete a branch by name on repository. func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error { - cmd := NewCommand("branch") + cmd := gitcmd.NewCommand("branch") if opts.Force { cmd.AddArguments("-D") @@ -52,35 +54,35 @@ func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) erro } cmd.AddDashesAndList(name) - _, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // CreateBranch create a new branch func (repo *Repository) CreateBranch(branch, oldbranchOrCommit string) error { - cmd := NewCommand("branch") + cmd := gitcmd.NewCommand("branch") cmd.AddDashesAndList(branch, oldbranchOrCommit) - _, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // AddRemote adds a new remote to repository. func (repo *Repository) AddRemote(name, url string, fetch bool) error { - cmd := NewCommand("remote", "add") + cmd := gitcmd.NewCommand("remote", "add") if fetch { cmd.AddArguments("-f") } cmd.AddDynamicArguments(name, url) - _, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // RenameBranch rename a branch func (repo *Repository) RenameBranch(from, to string) error { - _, _, err := NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("branch", "-m").AddDynamicArguments(from, to).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } diff --git a/modules/git/repo_branch_nogogit.go b/modules/git/repo_branch_nogogit.go index 0d11198523..255c2974e9 100644 --- a/modules/git/repo_branch_nogogit.go +++ b/modules/git/repo_branch_nogogit.go @@ -13,6 +13,7 @@ import ( "io" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -70,25 +71,25 @@ func (repo *Repository) IsBranchExist(name string) bool { // GetBranchNames returns branches from the repository, skipping "skip" initial branches and // returning at most "limit" branches, or all branches if "limit" is 0. func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) { - return callShowRef(repo.Ctx, repo.Path, BranchPrefix, TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit) + return callShowRef(repo.Ctx, repo.Path, BranchPrefix, gitcmd.TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"}, skip, limit) } // WalkReferences walks all the references from the repository // refType should be empty, ObjectTag or ObjectBranch. All other values are equivalent to empty. func (repo *Repository) WalkReferences(refType ObjectType, skip, limit int, walkfn func(sha1, refname string) error) (int, error) { - var args TrustedCmdArgs + var args gitcmd.TrustedCmdArgs switch refType { case ObjectTag: - args = TrustedCmdArgs{TagPrefix, "--sort=-taggerdate"} + args = gitcmd.TrustedCmdArgs{TagPrefix, "--sort=-taggerdate"} case ObjectBranch: - args = TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"} + args = gitcmd.TrustedCmdArgs{BranchPrefix, "--sort=-committerdate"} } return WalkShowRef(repo.Ctx, repo.Path, args, skip, limit, walkfn) } // callShowRef return refs, if limit = 0 it will not limit -func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) { +func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs gitcmd.TrustedCmdArgs, skip, limit int) (branchNames []string, countAll int, err error) { countAll, err = WalkShowRef(ctx, repoPath, extraArgs, skip, limit, func(_, branchName string) error { branchName = strings.TrimPrefix(branchName, trimPrefix) branchNames = append(branchNames, branchName) @@ -98,7 +99,7 @@ func callShowRef(ctx context.Context, repoPath, trimPrefix string, extraArgs Tru return branchNames, countAll, err } -func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) { +func WalkShowRef(ctx context.Context, repoPath string, extraArgs gitcmd.TrustedCmdArgs, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) { stdoutReader, stdoutWriter := io.Pipe() defer func() { _ = stdoutReader.Close() @@ -107,9 +108,9 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, go func() { stderrBuilder := &strings.Builder{} - args := TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"} + args := gitcmd.TrustedCmdArgs{"for-each-ref", "--format=%(objectname) %(refname)"} args = append(args, extraArgs...) - err := NewCommand(args...).Run(ctx, &RunOpts{ + err := gitcmd.NewCommand(args...).Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: stdoutWriter, Stderr: stderrBuilder, @@ -119,7 +120,7 @@ func WalkShowRef(ctx context.Context, repoPath string, extraArgs TrustedCmdArgs, _ = stdoutWriter.Close() return } - _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String())) } else { _ = stdoutWriter.Close() } diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 4066a1ca7b..6e5911f1dd 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -12,6 +12,7 @@ import ( "strings" "code.gitea.io/gitea/modules/cache" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) @@ -59,7 +60,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com relpath = `\` + relpath } - stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).AddDynamicArguments(id.String()).AddDashesAndList(relpath).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -74,7 +75,7 @@ func (repo *Repository) getCommitByPathWithID(id ObjectID, relpath string) (*Com // GetCommitByPath returns the last commit of relative path. func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) { - stdout, _, runErr := NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("log", "-1", prettyLogFormat).AddDashesAndList(relpath).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -91,7 +92,7 @@ func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) { // commitsByRangeWithTime returns the specific page commits before current revision, with not, since, until support func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, not, since, until string) ([]*Commit, error) { - cmd := NewCommand("log"). + cmd := gitcmd.NewCommand("log"). AddOptionFormat("--skip=%d", (page-1)*pageSize). AddOptionFormat("--max-count=%d", pageSize). AddArguments(prettyLogFormat). @@ -107,7 +108,7 @@ func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, cmd.AddOptionFormat("--until=%s", until) } - stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -117,7 +118,7 @@ func (repo *Repository) commitsByRangeWithTime(id ObjectID, page, pageSize int, func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([]*Commit, error) { // add common arguments to git command - addCommonSearchArgs := func(c *Command) { + addCommonSearchArgs := func(c *gitcmd.Command) { // ignore case c.AddArguments("-i") @@ -141,7 +142,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ } // create new git log command with limit of 100 commits - cmd := NewCommand("log", "-100", prettyLogFormat).AddDynamicArguments(id.String()) + cmd := gitcmd.NewCommand("log", "-100", prettyLogFormat).AddDynamicArguments(id.String()) // pretend that all refs along with HEAD were listed on command line as // https://git-scm.com/docs/git-log#Documentation/git-log.txt---all @@ -161,7 +162,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ // search for commits matching given constraints and keywords in commit msg addCommonSearchArgs(cmd) - stdout, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -175,14 +176,14 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ // ignore anything not matching a valid sha pattern if id.Type().IsValid(v) { // create new git log command with 1 commit limit - hashCmd := NewCommand("log", "-1", prettyLogFormat) + hashCmd := gitcmd.NewCommand("log", "-1", prettyLogFormat) // add previous arguments except for --grep and --all addCommonSearchArgs(hashCmd) // add keyword as hashCmd.AddDynamicArguments(v) // search with given constraints for commit matching sha hash of v - hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + hashMatching, _, err := hashCmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil || bytes.Contains(stdout, hashMatching) { continue } @@ -197,7 +198,7 @@ func (repo *Repository) searchCommits(id ObjectID, opts SearchCommitsOptions) ([ // FileChangedBetweenCommits Returns true if the file changed between commit IDs id1 and id2 // You must ensure that id1 and id2 are valid commit ids. func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bool, error) { - stdout, _, err := NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(id1, id2).AddDashesAndList(filename).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return false, err } @@ -232,7 +233,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) }() go func() { stderr := strings.Builder{} - gitCmd := NewCommand("rev-list"). + gitCmd := gitcmd.NewCommand("rev-list"). AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize). AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize) gitCmd.AddDynamicArguments(opts.Revision) @@ -248,13 +249,13 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) } gitCmd.AddDashesAndList(opts.File) - err := gitCmd.Run(repo.Ctx, &RunOpts{ + err := gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr, }) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, (&stderr).String())) } else { _ = stdoutWriter.Close() } @@ -290,11 +291,11 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions) // FilesCountBetween return the number of files changed between two commits func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) { - stdout, _, err := NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID+"..."+endCommitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // git >= 2.28 now returns an error if startCommitID and endCommitID have become unrelated. // previously it would return the results of git diff --name-only startCommitID endCommitID so let's try that... - stdout, _, err = NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("diff", "--name-only").AddDynamicArguments(startCommitID, endCommitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } if err != nil { return 0, err @@ -308,13 +309,13 @@ func (repo *Repository) CommitsBetween(last, before *Commit) ([]*Commit, error) var stdout []byte var err error if before == nil { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } else { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated. // previously it would return the results of git rev-list before last so let's try that... - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } } if err != nil { @@ -328,22 +329,22 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in var stdout []byte var err error if before == nil { - stdout, _, err = NewCommand("rev-list"). + stdout, _, err = gitcmd.NewCommand("rev-list"). AddOptionValues("--max-count", strconv.Itoa(limit)). AddOptionValues("--skip", strconv.Itoa(skip)). - AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + AddDynamicArguments(last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } else { - stdout, _, err = NewCommand("rev-list"). + stdout, _, err = gitcmd.NewCommand("rev-list"). AddOptionValues("--max-count", strconv.Itoa(limit)). AddOptionValues("--skip", strconv.Itoa(skip)). - AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + AddDynamicArguments(before.ID.String()+".."+last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated. // previously it would return the results of git rev-list --max-count n before last so let's try that... - stdout, _, err = NewCommand("rev-list"). + stdout, _, err = gitcmd.NewCommand("rev-list"). AddOptionValues("--max-count", strconv.Itoa(limit)). AddOptionValues("--skip", strconv.Itoa(skip)). - AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + AddDynamicArguments(before.ID.String(), last.ID.String()).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } } if err != nil { @@ -358,13 +359,13 @@ func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch s var stdout []byte var err error if before == nil { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } else { - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil && strings.Contains(err.Error(), "no merge base") { // future versions of git >= 2.28 are likely to return an error if before and last have become unrelated. // previously it would return the results of git rev-list before last so let's try that... - stdout, _, err = NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err = gitcmd.NewCommand("rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) } } if err != nil { @@ -410,13 +411,13 @@ func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) { // commitsBefore the limit is depth, not total number of returned commits. func (repo *Repository) commitsBefore(id ObjectID, limit int) ([]*Commit, error) { - cmd := NewCommand("log", prettyLogFormat) + cmd := gitcmd.NewCommand("log", prettyLogFormat) if limit > 0 { cmd.AddOptionFormat("-%d", limit) } cmd.AddDynamicArguments(id.String()) - stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -453,10 +454,10 @@ func (repo *Repository) getCommitsBeforeLimit(id ObjectID, num int) ([]*Commit, func (repo *Repository) getBranches(env []string, commitID string, limit int) ([]string, error) { if DefaultFeatures().CheckVersionAtLeast("2.7.0") { - stdout, _, err := NewCommand("for-each-ref", "--format=%(refname:strip=2)"). + stdout, _, err := gitcmd.NewCommand("for-each-ref", "--format=%(refname:strip=2)"). AddOptionFormat("--count=%d", limit). AddOptionValues("--contains", commitID, BranchPrefix). - RunStdString(repo.Ctx, &RunOpts{ + RunStdString(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Env: env, }) @@ -468,7 +469,7 @@ func (repo *Repository) getBranches(env []string, commitID string, limit int) ([ return branches, nil } - stdout, _, err := NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &RunOpts{ + stdout, _, err := gitcmd.NewCommand("branch").AddOptionValues("--contains", commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Env: env, }) @@ -510,7 +511,7 @@ func (repo *Repository) GetCommitsFromIDs(commitIDs []string) []*Commit { // IsCommitInBranch check if the commit is on the branch func (repo *Repository) IsCommitInBranch(commitID, branch string) (r bool, err error) { - stdout, _, err := NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("branch", "--contains").AddDynamicArguments(commitID, branch).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return false, err } @@ -536,10 +537,10 @@ func (repo *Repository) AddLastCommitCache(cacheKey, fullName, sha string) error // GetCommitBranchStart returns the commit where the branch diverged func (repo *Repository) GetCommitBranchStart(env []string, branch, endCommitID string) (string, error) { - cmd := NewCommand("log", prettyLogFormat) + cmd := gitcmd.NewCommand("log", prettyLogFormat) cmd.AddDynamicArguments(endCommitID) - stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &RunOpts{ + stdout, _, runErr := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Env: env, }) diff --git a/modules/git/repo_commit_gogit.go b/modules/git/repo_commit_gogit.go index a88902e209..c830e52b7e 100644 --- a/modules/git/repo_commit_gogit.go +++ b/modules/git/repo_commit_gogit.go @@ -9,6 +9,8 @@ package git import ( "strings" + "code.gitea.io/gitea/modules/git/gitcmd" + "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/hash" "github.com/go-git/go-git/v5/plumbing/object" @@ -59,7 +61,7 @@ func (repo *Repository) ConvertToGitID(commitID string) (ObjectID, error) { } } - actualCommitID, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + actualCommitID, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) actualCommitID = strings.TrimSpace(actualCommitID) if err != nil { if strings.Contains(err.Error(), "unknown revision or path") || diff --git a/modules/git/repo_commit_nogogit.go b/modules/git/repo_commit_nogogit.go index 3ead3e2216..f00d407ae0 100644 --- a/modules/git/repo_commit_nogogit.go +++ b/modules/git/repo_commit_nogogit.go @@ -11,12 +11,13 @@ import ( "io" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) // ResolveReference resolves a name to a reference func (repo *Repository) ResolveReference(name string) (string, error) { - stdout, _, err := NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { if strings.Contains(err.Error(), "not a valid ref") { return "", ErrNotExist{name, ""} @@ -52,13 +53,13 @@ func (repo *Repository) GetRefCommitID(name string) (string, error) { // SetReference sets the commit ID string of given reference (e.g. branch or tag). func (repo *Repository) SetReference(name, commitID string) error { - _, _, err := NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("update-ref").AddDynamicArguments(name, commitID).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // RemoveReference removes the given reference (e.g. branch or tag). func (repo *Repository) RemoveReference(name string) error { - _, _, err := NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("update-ref", "--no-deref", "-d").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } @@ -68,7 +69,7 @@ func (repo *Repository) IsCommitExist(name string) bool { log.Error("IsCommitExist: %v", err) return false } - _, _, err := NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("cat-file", "-e").AddDynamicArguments(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err == nil } diff --git a/modules/git/repo_commitgraph.go b/modules/git/repo_commitgraph.go index 62c6378054..331c799b33 100644 --- a/modules/git/repo_commitgraph.go +++ b/modules/git/repo_commitgraph.go @@ -6,13 +6,15 @@ package git import ( "context" "fmt" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // WriteCommitGraph write commit graph to speed up repo access // this requires git v2.18 to be installed func WriteCommitGraph(ctx context.Context, repoPath string) error { if DefaultFeatures().CheckVersionAtLeast("2.18") { - if _, _, err := NewCommand("commit-graph", "write").RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil { + if _, _, err := gitcmd.NewCommand("commit-graph", "write").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil { return fmt.Errorf("unable to write commit-graph for '%s' : %w", repoPath, err) } } diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index 56251a87a0..69a7314d5c 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -16,6 +16,8 @@ import ( "regexp" "strconv" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // GetMergeBase checks and returns merge base of two branches and the reference used as base. @@ -27,13 +29,13 @@ func (repo *Repository) GetMergeBase(tmpRemote, base, head string) (string, stri if tmpRemote != "origin" { tmpBaseName := RemotePrefix + tmpRemote + "/tmp_" + base // Fetch commit into a temporary branch in order to be able to handle commits and tags - _, _, err := NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("fetch", "--no-tags").AddDynamicArguments(tmpRemote).AddDashesAndList(base+":"+tmpBaseName).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err == nil { base = tmpBaseName } } - stdout, _, err := NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("merge-base").AddDashesAndList(base, head).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return strings.TrimSpace(stdout), base, err } @@ -61,8 +63,8 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis } // avoid: ambiguous argument 'refs/a...refs/b': unknown revision or path not in the working tree. Use '--': 'git [...] -- [...]' - if err := NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--"). - Run(repo.Ctx, &RunOpts{ + if err := gitcmd.NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base+separator+head).AddArguments("--"). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -72,7 +74,7 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis // previously it would return the results of git diff -z --name-only base head so let's try that... w = &lineCountWriter{} stderr.Reset() - if err = NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &RunOpts{ + if err = gitcmd.NewCommand("diff", "-z", "--name-only").AddDynamicArguments(base, head).AddArguments("--").Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -87,13 +89,13 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis // GetDiffShortStatByCmdArgs counts number of changed files, number of additions and deletions // TODO: it can be merged with another "GetDiffShortStat" in the future -func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) { +func GetDiffShortStatByCmdArgs(ctx context.Context, repoPath string, trustedArgs gitcmd.TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) { // Now if we call: // $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875 // we get: // " 9902 files changed, 2034198 insertions(+), 298800 deletions(-)\n" - cmd := NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...) - stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}) + cmd := gitcmd.NewCommand("diff", "--shortstat").AddArguments(trustedArgs...).AddDynamicArguments(dynamicArgs...) + stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { return 0, 0, 0, err } @@ -139,8 +141,8 @@ func parseDiffStat(stdout string) (numFiles, totalAdditions, totalDeletions int, // GetDiff generates and returns patch data between given revisions, optimized for human readability func (repo *Repository) GetDiff(compareArg string, w io.Writer) error { stderr := new(bytes.Buffer) - return NewCommand("diff", "-p").AddDynamicArguments(compareArg). - Run(repo.Ctx, &RunOpts{ + return gitcmd.NewCommand("diff", "-p").AddDynamicArguments(compareArg). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -149,7 +151,7 @@ func (repo *Repository) GetDiff(compareArg string, w io.Writer) error { // GetDiffBinary generates and returns patch data between given revisions, including binary diffs. func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error { - return NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &RunOpts{ + return gitcmd.NewCommand("diff", "-p", "--binary", "--histogram").AddDynamicArguments(compareArg).Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, }) @@ -158,8 +160,8 @@ func (repo *Repository) GetDiffBinary(compareArg string, w io.Writer) error { // GetPatch generates and returns format-patch data between given revisions, able to be used with `git apply` func (repo *Repository) GetPatch(compareArg string, w io.Writer) error { stderr := new(bytes.Buffer) - return NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg). - Run(repo.Ctx, &RunOpts{ + return gitcmd.NewCommand("format-patch", "--binary", "--stdout").AddDynamicArguments(compareArg). + Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: w, Stderr: stderr, @@ -174,13 +176,13 @@ func (repo *Repository) GetFilesChangedBetween(base, head string) ([]string, err if err != nil { return nil, err } - cmd := NewCommand("diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z") + cmd := gitcmd.NewCommand("diff-tree", "--name-only", "--root", "--no-commit-id", "-r", "-z") if base == objectFormat.EmptyObjectID().String() { cmd.AddDynamicArguments(head) } else { cmd.AddDynamicArguments(base, head) } - stdout, _, err := cmd.RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/repo_gpg.go b/modules/git/repo_gpg.go index 0021a7bda7..a999d2dbc6 100644 --- a/modules/git/repo_gpg.go +++ b/modules/git/repo_gpg.go @@ -9,6 +9,7 @@ import ( "os" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/process" ) @@ -42,7 +43,7 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, Sign: true, } - value, _, _ := NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) sign, valid := ParseBool(strings.TrimSpace(value)) if !sign || !valid { gpgSettings.Sign = false @@ -50,16 +51,16 @@ func (repo *Repository) GetDefaultPublicGPGKey(forceUpdate bool) (*GPGSettings, return gpgSettings, nil } - signingKey, _, _ := NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.KeyID = strings.TrimSpace(signingKey) - format, _, _ := NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + format, _, _ := gitcmd.NewCommand("config", "--default", SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.Format = strings.TrimSpace(format) - defaultEmail, _, _ := NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + defaultEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.Email = strings.TrimSpace(defaultEmail) - defaultName, _, _ := NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + defaultName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) gpgSettings.Name = strings.TrimSpace(defaultName) if err := gpgSettings.LoadPublicKeyContent(); err != nil { diff --git a/modules/git/repo_index.go b/modules/git/repo_index.go index 4879121a41..e7b3792d95 100644 --- a/modules/git/repo_index.go +++ b/modules/git/repo_index.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) @@ -21,7 +22,7 @@ func (repo *Repository) ReadTreeToIndex(treeish string, indexFilename ...string) } if len(treeish) != objectFormat.FullLength() { - res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(treeish).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return err } @@ -41,7 +42,7 @@ func (repo *Repository) readTreeToIndex(id ObjectID, indexFilename ...string) er if len(indexFilename) > 0 { env = append(os.Environ(), "GIT_INDEX_FILE="+indexFilename[0]) } - _, _, err := NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path, Env: env}) + _, _, err := gitcmd.NewCommand("read-tree").AddDynamicArguments(id.String()).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path, Env: env}) if err != nil { return err } @@ -74,14 +75,14 @@ func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilena // EmptyIndex empties the index func (repo *Repository) EmptyIndex() error { - _, _, err := NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("read-tree", "--empty").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // LsFiles checks if the given filenames are in the index func (repo *Repository) LsFiles(filenames ...string) ([]string, error) { - cmd := NewCommand("ls-files", "-z").AddDashesAndList(filenames...) - res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + cmd := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...) + res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -99,7 +100,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error { if err != nil { return err } - cmd := NewCommand("update-index", "--remove", "-z", "--index-info") + cmd := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info") stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) buffer := new(bytes.Buffer) @@ -109,7 +110,7 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error { buffer.WriteString("0 blob " + objectFormat.EmptyObjectID().String() + "\t" + file + "\000") } } - return cmd.Run(repo.Ctx, &RunOpts{ + return cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdin: bytes.NewReader(buffer.Bytes()), Stdout: stdout, @@ -125,7 +126,7 @@ type IndexObjectInfo struct { // AddObjectsToIndex adds the provided object hashes to the index at the provided filenames func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error { - cmd := NewCommand("update-index", "--add", "--replace", "-z", "--index-info") + cmd := gitcmd.NewCommand("update-index", "--add", "--replace", "-z", "--index-info") stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) buffer := new(bytes.Buffer) @@ -133,7 +134,7 @@ func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error { // using format: mode SP type SP sha1 TAB path buffer.WriteString(object.Mode + " blob " + object.Object.String() + "\t" + object.Filename + "\000") } - return cmd.Run(repo.Ctx, &RunOpts{ + return cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdin: bytes.NewReader(buffer.Bytes()), Stdout: stdout, @@ -148,7 +149,7 @@ func (repo *Repository) AddObjectToIndex(mode string, object ObjectID, filename // WriteTree writes the current index as a tree to the object db and returns its hash func (repo *Repository) WriteTree() (*Tree, error) { - stdout, _, runErr := NewCommand("write-tree").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("write-tree").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } diff --git a/modules/git/repo_object.go b/modules/git/repo_object.go index 08e0413311..e8f6510c23 100644 --- a/modules/git/repo_object.go +++ b/modules/git/repo_object.go @@ -8,6 +8,8 @@ import ( "bytes" "io" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // ObjectType git object type @@ -66,15 +68,15 @@ func (repo *Repository) HashObject(reader io.Reader) (ObjectID, error) { } func (repo *Repository) hashObject(reader io.Reader, save bool) (string, error) { - var cmd *Command + var cmd *gitcmd.Command if save { - cmd = NewCommand("hash-object", "-w", "--stdin") + cmd = gitcmd.NewCommand("hash-object", "-w", "--stdin") } else { - cmd = NewCommand("hash-object", "--stdin") + cmd = gitcmd.NewCommand("hash-object", "--stdin") } stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) - err := cmd.Run(repo.Ctx, &RunOpts{ + err := cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdin: reader, Stdout: stdout, diff --git a/modules/git/repo_ref.go b/modules/git/repo_ref.go index 554f9f73e1..577e17c45d 100644 --- a/modules/git/repo_ref.go +++ b/modules/git/repo_ref.go @@ -7,6 +7,7 @@ import ( "context" "strings" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) @@ -18,7 +19,7 @@ func (repo *Repository) GetRefs() ([]*Reference, error) { // ListOccurrences lists all refs of the given refType the given commit appears in sorted by creation date DESC // refType should only be a literal "branch" or "tag" and nothing else func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA string) ([]string, error) { - cmd := NewCommand() + cmd := gitcmd.NewCommand() switch refType { case "branch": cmd.AddArguments("branch") @@ -27,7 +28,7 @@ func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA default: return nil, util.NewInvalidArgumentErrorf(`can only use "branch" or "tag" for refType, but got %q`, refType) } - stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := cmd.AddArguments("--no-color", "--sort=-creatordate", "--contains").AddDynamicArguments(commitSHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/repo_ref_nogogit.go b/modules/git/repo_ref_nogogit.go index 8d34713eaf..784efecc65 100644 --- a/modules/git/repo_ref_nogogit.go +++ b/modules/git/repo_ref_nogogit.go @@ -9,6 +9,8 @@ import ( "bufio" "io" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // GetRefsFiltered returns all references of the repository that matches patterm exactly or starting with. @@ -21,13 +23,13 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) { go func() { stderrBuilder := &strings.Builder{} - err := NewCommand("for-each-ref").Run(repo.Ctx, &RunOpts{ + err := gitcmd.NewCommand("for-each-ref").Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: stderrBuilder, }) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderrBuilder.String())) } else { _ = stdoutWriter.Close() } diff --git a/modules/git/repo_stats.go b/modules/git/repo_stats.go index 8c6f31c38c..22082325ef 100644 --- a/modules/git/repo_stats.go +++ b/modules/git/repo_stats.go @@ -14,6 +14,7 @@ import ( "time" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/git/gitcmd" ) // CodeActivityStats represents git statistics data @@ -40,9 +41,9 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) since := fromTime.Format(time.RFC3339) - stdout, _, runErr := NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso"). + stdout, _, runErr := gitcmd.NewCommand("rev-list", "--count", "--no-merges", "--branches=*", "--date=iso"). AddOptionFormat("--since=%s", since). - RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if runErr != nil { return nil, runErr } @@ -62,7 +63,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) _ = stdoutWriter.Close() }() - gitCmd := NewCommand("log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso"). + gitCmd := gitcmd.NewCommand("log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso"). AddOptionFormat("--since=%s", since) if len(branch) == 0 { gitCmd.AddArguments("--branches=*") @@ -71,7 +72,7 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string) } stderr := new(strings.Builder) - err = gitCmd.Run(repo.Ctx, &RunOpts{ + err = gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{ Env: []string{}, Dir: repo.Path, Stdout: stdoutWriter, diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index c8d72eee02..0cb0932459 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -10,6 +10,7 @@ import ( "strings" "code.gitea.io/gitea/modules/git/foreachref" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/util" ) @@ -18,13 +19,13 @@ const TagPrefix = "refs/tags/" // CreateTag create one tag in the repository func (repo *Repository) CreateTag(name, revision string) error { - _, _, err := NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("tag").AddDashesAndList(name, revision).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } // CreateAnnotatedTag create one annotated tag in the repository func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error { - _, _, err := NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + _, _, err := gitcmd.NewCommand("tag", "-a", "-m").AddDynamicArguments(message).AddDashesAndList(name, revision).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) return err } @@ -34,7 +35,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) { return "", fmt.Errorf("SHA is too short: %s", sha) } - stdout, _, err := NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("show-ref", "--tags", "-d").RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return "", err } @@ -57,7 +58,7 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) { // GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA) func (repo *Repository) GetTagID(name string) (string, error) { - stdout, _, err := NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + stdout, _, err := gitcmd.NewCommand("show-ref", "--tags").AddDashesAndList(name).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return "", err } @@ -114,14 +115,14 @@ func (repo *Repository) GetTagInfos(page, pageSize int) ([]*Tag, int, error) { defer stdoutReader.Close() defer stdoutWriter.Close() stderr := strings.Builder{} - rc := &RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr} + rc := &gitcmd.RunOpts{Dir: repo.Path, Stdout: stdoutWriter, Stderr: &stderr} go func() { - err := NewCommand("for-each-ref"). + err := gitcmd.NewCommand("for-each-ref"). AddOptionFormat("--format=%s", forEachRefFmt.Flag()). AddArguments("--sort", "-*creatordate", "refs/tags").Run(repo.Ctx, rc) if err != nil { - _ = stdoutWriter.CloseWithError(ConcatenateError(err, stderr.String())) + _ = stdoutWriter.CloseWithError(gitcmd.ConcatenateError(err, stderr.String())) } else { _ = stdoutWriter.Close() } diff --git a/modules/git/repo_tree.go b/modules/git/repo_tree.go index 309a73d759..1d8c940951 100644 --- a/modules/git/repo_tree.go +++ b/modules/git/repo_tree.go @@ -9,6 +9,8 @@ import ( "os" "strings" "time" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // CommitTreeOpts represents the possible options to CommitTree @@ -33,7 +35,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt "GIT_COMMITTER_EMAIL="+committer.Email, "GIT_COMMITTER_DATE="+commitTimeStr, ) - cmd := NewCommand("commit-tree").AddDynamicArguments(tree.ID.String()) + cmd := gitcmd.NewCommand("commit-tree").AddDynamicArguments(tree.ID.String()) for _, parent := range opts.Parents { cmd.AddArguments("-p").AddDynamicArguments(parent) @@ -58,7 +60,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) - err := cmd.Run(repo.Ctx, &RunOpts{ + err := cmd.Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdin: messageBytes, @@ -66,7 +68,7 @@ func (repo *Repository) CommitTree(author, committer *Signature, tree *Tree, opt Stderr: stderr, }) if err != nil { - return nil, ConcatenateError(err, stderr.String()) + return nil, gitcmd.ConcatenateError(err, stderr.String()) } return NewIDFromString(strings.TrimSpace(stdout.String())) } diff --git a/modules/git/repo_tree_gogit.go b/modules/git/repo_tree_gogit.go index f77cd83612..40524d0c34 100644 --- a/modules/git/repo_tree_gogit.go +++ b/modules/git/repo_tree_gogit.go @@ -9,6 +9,8 @@ package git import ( "errors" + "code.gitea.io/gitea/modules/git/gitcmd" + "github.com/go-git/go-git/v5/plumbing" ) @@ -36,7 +38,7 @@ func (repo *Repository) GetTree(idStr string) (*Tree, error) { } if len(idStr) != objectFormat.FullLength() { - res, _, err := NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + res, _, err := gitcmd.NewCommand("rev-parse", "--verify").AddDynamicArguments(idStr).RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 31a32f1a9e..58824adc82 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -9,6 +9,7 @@ import ( "fmt" "os" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -24,7 +25,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul if err != nil { return nil, err } - opts := &RunOpts{ + opts := &gitcmd.RunOpts{ Dir: repoPath, Stdout: stdoutWriter, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { @@ -45,7 +46,7 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul return scanner.Err() }, } - err = NewCommand("ls-tree", "-r", "--", "HEAD").Run(ctx, opts) + err = gitcmd.NewCommand("ls-tree", "-r", "--", "HEAD").Run(ctx, opts) if err != nil { return nil, fmt.Errorf("GetTemplateSubmoduleCommits: error running git ls-tree: %v", err) } @@ -56,8 +57,8 @@ func GetTemplateSubmoduleCommits(ctx context.Context, repoPath string) (submodul // It is only for generating new repos based on existing template, requires the .gitmodules file to be already present in the work dir. func AddTemplateSubmoduleIndexes(ctx context.Context, repoPath string, submodules []TemplateSubmoduleCommit) error { for _, submodule := range submodules { - cmd := NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path) - if stdout, _, err := cmd.RunStdString(ctx, &RunOpts{Dir: repoPath}); err != nil { + cmd := gitcmd.NewCommand("update-index", "--add", "--cacheinfo", "160000").AddDynamicArguments(submodule.Commit, submodule.Path) + if stdout, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil { log.Error("Unable to add %s as submodule to repo %s: stdout %s\nError: %v", submodule.Path, repoPath, stdout, err) return err } diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go index 55ac0971a5..d2df8b2a91 100644 --- a/modules/git/submodule_test.go +++ b/modules/git/submodule_test.go @@ -8,6 +8,8 @@ import ( "path/filepath" "testing" + "code.gitea.io/gitea/modules/git/gitcmd" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -30,14 +32,14 @@ func TestAddTemplateSubmoduleIndexes(t *testing.T) { ctx := t.Context() tmpDir := t.TempDir() var err error - _, _, err = NewCommand("init").RunStdString(ctx, &RunOpts{Dir: tmpDir}) + _, _, err = gitcmd.NewCommand("init").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir}) require.NoError(t, err) _ = os.Mkdir(filepath.Join(tmpDir, "new-dir"), 0o755) err = AddTemplateSubmoduleIndexes(ctx, tmpDir, []TemplateSubmoduleCommit{{Path: "new-dir", Commit: "1234567890123456789012345678901234567890"}}) require.NoError(t, err) - _, _, err = NewCommand("add", "--all").RunStdString(ctx, &RunOpts{Dir: tmpDir}) + _, _, err = gitcmd.NewCommand("add", "--all").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir}) require.NoError(t, err) - _, _, err = NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &RunOpts{Dir: tmpDir}) + _, _, err = gitcmd.NewCommand("-c", "user.name=a", "-c", "user.email=b", "commit", "-m=test").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir}) require.NoError(t, err) submodules, err := GetTemplateSubmoduleCommits(t.Context(), tmpDir) require.NoError(t, err) diff --git a/modules/git/tree.go b/modules/git/tree.go index 38fb45f3b1..a8c4929c7c 100644 --- a/modules/git/tree.go +++ b/modules/git/tree.go @@ -7,6 +7,8 @@ package git import ( "bytes" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // NewTree create a new tree according the repository and tree id @@ -48,10 +50,10 @@ func (t *Tree) SubTree(rpath string) (*Tree, error) { // LsTree checks if the given filenames are in the tree func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error) { - cmd := NewCommand("ls-tree", "-z", "--name-only"). + cmd := gitcmd.NewCommand("ls-tree", "-z", "--name-only"). AddDashesAndList(append([]string{ref}, filenames...)...) - res, _, err := cmd.RunStdBytes(repo.Ctx, &RunOpts{Dir: repo.Path}) + res, _, err := cmd.RunStdBytes(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } @@ -65,9 +67,9 @@ func (repo *Repository) LsTree(ref string, filenames ...string) ([]string, error // GetTreePathLatestCommit returns the latest commit of a tree path func (repo *Repository) GetTreePathLatestCommit(refName, treePath string) (*Commit, error) { - stdout, _, err := NewCommand("rev-list", "-1"). + stdout, _, err := gitcmd.NewCommand("rev-list", "-1"). AddDynamicArguments(refName).AddDashesAndList(treePath). - RunStdString(repo.Ctx, &RunOpts{Dir: repo.Path}) + RunStdString(repo.Ctx, &gitcmd.RunOpts{Dir: repo.Path}) if err != nil { return nil, err } diff --git a/modules/git/tree_nogogit.go b/modules/git/tree_nogogit.go index f88788418e..045d78c42c 100644 --- a/modules/git/tree_nogogit.go +++ b/modules/git/tree_nogogit.go @@ -8,6 +8,8 @@ package git import ( "io" "strings" + + "code.gitea.io/gitea/modules/git/gitcmd" ) // Tree represents a flat directory listing. @@ -70,7 +72,7 @@ func (t *Tree) ListEntries() (Entries, error) { } } - stdout, _, runErr := NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path}) + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-l").AddDynamicArguments(t.ID.String()).RunStdBytes(t.repo.Ctx, &gitcmd.RunOpts{Dir: t.repo.Path}) if runErr != nil { if strings.Contains(runErr.Error(), "fatal: Not a valid object name") || strings.Contains(runErr.Error(), "fatal: not a tree object") { return nil, ErrNotExist{ @@ -91,15 +93,15 @@ func (t *Tree) ListEntries() (Entries, error) { // listEntriesRecursive returns all entries of current tree recursively including all subtrees // extraArgs could be "-l" to get the size, which is slower -func (t *Tree) listEntriesRecursive(extraArgs TrustedCmdArgs) (Entries, error) { +func (t *Tree) listEntriesRecursive(extraArgs gitcmd.TrustedCmdArgs) (Entries, error) { if t.entriesRecursiveParsed { return t.entriesRecursive, nil } - stdout, _, runErr := NewCommand("ls-tree", "-t", "-r"). + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "-t", "-r"). AddArguments(extraArgs...). AddDynamicArguments(t.ID.String()). - RunStdBytes(t.repo.Ctx, &RunOpts{Dir: t.repo.Path}) + RunStdBytes(t.repo.Ctx, &gitcmd.RunOpts{Dir: t.repo.Path}) if runErr != nil { return nil, runErr } @@ -120,5 +122,5 @@ func (t *Tree) ListEntriesRecursiveFast() (Entries, error) { // ListEntriesRecursiveWithSize returns all entries of current tree recursively including all subtrees, with size func (t *Tree) ListEntriesRecursiveWithSize() (Entries, error) { - return t.listEntriesRecursive(TrustedCmdArgs{"--long"}) + return t.listEntriesRecursive(gitcmd.TrustedCmdArgs{"--long"}) } diff --git a/modules/git/utils.go b/modules/git/utils.go index e2bdf7866b..b5f188904a 100644 --- a/modules/git/utils.go +++ b/modules/git/utils.go @@ -6,7 +6,6 @@ package git import ( "crypto/sha1" "encoding/hex" - "fmt" "io" "strconv" "strings" @@ -42,14 +41,6 @@ func (oc *ObjectCache[T]) Get(id string) (T, bool) { return obj, has } -// ConcatenateError concatenats an error with stderr string -func ConcatenateError(err error, stderr string) error { - if len(stderr) == 0 { - return err - } - return fmt.Errorf("%w - %s", err, stderr) -} - // ParseBool returns the boolean value represented by the string as per git's git_config_bool // true will be returned for the result if the string is empty, but valid will be false. // "true", "yes", "on" are all true, true diff --git a/modules/gitrepo/branch.go b/modules/gitrepo/branch.go index d7857819e4..4d571f583d 100644 --- a/modules/gitrepo/branch.go +++ b/modules/gitrepo/branch.go @@ -7,6 +7,7 @@ import ( "context" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // GetBranchesByPath returns a branch by its path @@ -33,9 +34,9 @@ func GetBranchCommitID(ctx context.Context, repo Repository, branch string) (str // SetDefaultBranch sets default branch of repository. func SetDefaultBranch(ctx context.Context, repo Repository, name string) error { - _, _, err := git.NewCommand("symbolic-ref", "HEAD"). + _, _, err := gitcmd.NewCommand("symbolic-ref", "HEAD"). AddDynamicArguments(git.BranchPrefix+name). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err } diff --git a/modules/gitrepo/config.go b/modules/gitrepo/config.go index 84ef1eadf6..c028c6afe8 100644 --- a/modules/gitrepo/config.go +++ b/modules/gitrepo/config.go @@ -7,14 +7,14 @@ import ( "context" "strings" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/globallock" ) func GitConfigGet(ctx context.Context, repo Repository, key string) (string, error) { - result, _, err := git.NewCommand("config", "--get"). + result, _, err := gitcmd.NewCommand("config", "--get"). AddDynamicArguments(key). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) if err != nil { return "", err } @@ -28,9 +28,9 @@ func getRepoConfigLockKey(repoStoragePath string) string { // GitConfigAdd add a git configuration key to a specific value for the given repository. func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error { return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error { - _, _, err := git.NewCommand("config", "--add"). + _, _, err := gitcmd.NewCommand("config", "--add"). AddDynamicArguments(key, value). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } @@ -40,9 +40,9 @@ func GitConfigAdd(ctx context.Context, repo Repository, key, value string) error // If the key exists, it will be updated to the new value. func GitConfigSet(ctx context.Context, repo Repository, key, value string) error { return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error { - _, _, err := git.NewCommand("config"). + _, _, err := gitcmd.NewCommand("config"). AddDynamicArguments(key, value). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } diff --git a/modules/gitrepo/fsck.go b/modules/gitrepo/fsck.go index bcec6aa03f..ffccff28a9 100644 --- a/modules/gitrepo/fsck.go +++ b/modules/gitrepo/fsck.go @@ -7,10 +7,10 @@ import ( "context" "time" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" ) // Fsck verifies the connectivity and validity of the objects in the database -func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args git.TrustedCmdArgs) error { - return git.NewCommand("fsck").AddArguments(args...).Run(ctx, &git.RunOpts{Timeout: timeout, Dir: repoPath(repo)}) +func Fsck(ctx context.Context, repo Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { + return gitcmd.NewCommand("fsck").AddArguments(args...).Run(ctx, &gitcmd.RunOpts{Timeout: timeout, Dir: repoPath(repo)}) } diff --git a/modules/gitrepo/remote.go b/modules/gitrepo/remote.go index ba32c2a1d8..20d3cd21da 100644 --- a/modules/gitrepo/remote.go +++ b/modules/gitrepo/remote.go @@ -10,6 +10,7 @@ import ( "time" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" giturl "code.gitea.io/gitea/modules/git/url" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/util" @@ -24,7 +25,7 @@ const ( func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL string, options ...RemoteOption) error { return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error { - cmd := git.NewCommand("remote", "add") + cmd := gitcmd.NewCommand("remote", "add") if len(options) > 0 { switch options[0] { case RemoteOptionMirrorPush: @@ -37,15 +38,15 @@ func GitRemoteAdd(ctx context.Context, repo Repository, remoteName, remoteURL st } _, _, err := cmd. AddDynamicArguments(remoteName, remoteURL). - RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } func GitRemoteRemove(ctx context.Context, repo Repository, remoteName string) error { return globallock.LockAndDo(ctx, getRepoConfigLockKey(repo.RelativePath()), func(ctx context.Context) error { - cmd := git.NewCommand("remote", "rm").AddDynamicArguments(remoteName) - _, _, err := cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath(repo)}) + cmd := gitcmd.NewCommand("remote", "rm").AddDynamicArguments(remoteName) + _, _, err := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) return err }) } @@ -64,8 +65,8 @@ func GitRemoteGetURL(ctx context.Context, repo Repository, remoteName string) (* // GitRemotePrune prunes the remote branches that no longer exist in the remote repository. func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error { - return git.NewCommand("remote", "prune").AddDynamicArguments(remoteName). - Run(ctx, &git.RunOpts{ + return gitcmd.NewCommand("remote", "prune").AddDynamicArguments(remoteName). + Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath(repo), Stdout: stdout, @@ -75,8 +76,8 @@ func GitRemotePrune(ctx context.Context, repo Repository, remoteName string, tim // GitRemoteUpdatePrune updates the remote branches and prunes the ones that no longer exist in the remote repository. func GitRemoteUpdatePrune(ctx context.Context, repo Repository, remoteName string, timeout time.Duration, stdout, stderr io.Writer) error { - return git.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName). - Run(ctx, &git.RunOpts{ + return gitcmd.NewCommand("remote", "update", "--prune").AddDynamicArguments(remoteName). + Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath(repo), Stdout: stdout, diff --git a/modules/glob/glob.go b/modules/glob/glob.go new file mode 100644 index 0000000000..d4ca77e2ee --- /dev/null +++ b/modules/glob/glob.go @@ -0,0 +1,184 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package glob + +import ( + "errors" + "fmt" + "regexp" + + "code.gitea.io/gitea/modules/util" +) + +// Reference: https://github.com/gobwas/glob/blob/master/glob.go + +type Glob interface { + Match(string) bool +} + +type globCompiler struct { + nonSeparatorChars string + globPattern []rune + regexpPattern string + regexp *regexp.Regexp + pos int +} + +// compileChars compiles character class patterns like [abc] or [!abc] +func (g *globCompiler) compileChars() (string, error) { + result := "" + if g.pos < len(g.globPattern) && g.globPattern[g.pos] == '!' { + g.pos++ + result += "^" + } + + for g.pos < len(g.globPattern) { + c := g.globPattern[g.pos] + g.pos++ + + if c == ']' { + return "[" + result + "]", nil + } + + if c == '\\' { + if g.pos >= len(g.globPattern) { + return "", errors.New("unterminated character class escape") + } + result += "\\" + string(g.globPattern[g.pos]) + g.pos++ + } else { + result += string(c) + } + } + + return "", errors.New("unterminated character class") +} + +// compile compiles the glob pattern into a regular expression +func (g *globCompiler) compile(subPattern bool) (string, error) { + result := "" + + for g.pos < len(g.globPattern) { + c := g.globPattern[g.pos] + g.pos++ + + if subPattern && c == '}' { + return "(" + result + ")", nil + } + + switch c { + case '*': + if g.pos < len(g.globPattern) && g.globPattern[g.pos] == '*' { + g.pos++ + result += ".*" // match any sequence of characters + } else { + result += g.nonSeparatorChars + "*" // match any sequence of non-separator characters + } + case '?': + result += g.nonSeparatorChars // match any single non-separator character + case '[': + chars, err := g.compileChars() + if err != nil { + return "", err + } + result += chars + case '{': + subResult, err := g.compile(true) + if err != nil { + return "", err + } + result += subResult + case ',': + if subPattern { + result += "|" + } else { + result += "," + } + case '\\': + if g.pos >= len(g.globPattern) { + return "", errors.New("no character to escape") + } + result += "\\" + string(g.globPattern[g.pos]) + g.pos++ + case '.', '+', '^', '$', '(', ')', '|': + result += "\\" + string(c) // escape regexp special characters + default: + result += string(c) + } + } + + return result, nil +} + +func newGlobCompiler(pattern string, separators ...rune) (Glob, error) { + g := &globCompiler{globPattern: []rune(pattern)} + + // Escape separators for use in character class + escapedSeparators := regexp.QuoteMeta(string(separators)) + if escapedSeparators != "" { + g.nonSeparatorChars = "[^" + escapedSeparators + "]" + } else { + g.nonSeparatorChars = "." + } + + compiled, err := g.compile(false) + if err != nil { + return nil, err + } + + g.regexpPattern = "^" + compiled + "$" + + regex, err := regexp.Compile(g.regexpPattern) + if err != nil { + return nil, fmt.Errorf("failed to compile regexp: %w", err) + } + + g.regexp = regex + return g, nil +} + +func (g *globCompiler) Match(s string) bool { + return g.regexp.MatchString(s) +} + +func Compile(pattern string, separators ...rune) (Glob, error) { + return newGlobCompiler(pattern, separators...) +} + +func MustCompile(pattern string, separators ...rune) Glob { + g, err := Compile(pattern, separators...) + if err != nil { + panic(err) + } + return g +} + +func IsSpecialByte(c byte) bool { + return c == '*' || c == '?' || c == '\\' || c == '[' || c == ']' || c == '{' || c == '}' +} + +// QuoteMeta returns a string that quotes all glob pattern meta characters +// inside the argument text; For example, QuoteMeta(`{foo*}`) returns `\[foo\*\]`. +// Reference: https://github.com/gobwas/glob/blob/master/glob.go +func QuoteMeta(s string) string { + pos := 0 + for pos < len(s) && !IsSpecialByte(s[pos]) { + pos++ + } + if pos == len(s) { + return s + } + b := make([]byte, pos+2*(len(s)-pos)) + copy(b, s[0:pos]) + to := pos + for ; pos < len(s); pos++ { + if IsSpecialByte(s[pos]) { + b[to] = '\\' + to++ + } + b[to] = s[pos] + to++ + } + return util.UnsafeBytesToString(b[0:to]) +} diff --git a/modules/glob/glob_test.go b/modules/glob/glob_test.go new file mode 100644 index 0000000000..8467895252 --- /dev/null +++ b/modules/glob/glob_test.go @@ -0,0 +1,208 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// Copyright (c) 2016 Sergey Kamardin +// SPDX-License-Identifier: MIT +// +//nolint:revive // the code is from gobwas/glob +package glob + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +// Reference: https://github.com/gobwas/glob/blob/master/glob_test.go + +const ( + pattern_all = "[a-z][!a-x]*cat*[h][!b]*eyes*" + regexp_all = `^[a-z][^a-x].*cat.*[h][^b].*eyes.*$` + fixture_all_match = "my cat has very bright eyes" + fixture_all_mismatch = "my dog has very bright eyes" + + pattern_plain = "google.com" + regexp_plain = `^google\.com$` + fixture_plain_match = "google.com" + fixture_plain_mismatch = "gobwas.com" + + pattern_multiple = "https://*.google.*" + regexp_multiple = `^https:\/\/.*\.google\..*$` + fixture_multiple_match = "https://account.google.com" + fixture_multiple_mismatch = "https://google.com" + + pattern_alternatives = "{https://*.google.*,*yandex.*,*yahoo.*,*mail.ru}" + regexp_alternatives = `^(https:\/\/.*\.google\..*|.*yandex\..*|.*yahoo\..*|.*mail\.ru)$` + fixture_alternatives_match = "http://yahoo.com" + fixture_alternatives_mismatch = "http://google.com" + + pattern_alternatives_suffix = "{https://*gobwas.com,http://exclude.gobwas.com}" + regexp_alternatives_suffix = `^(https:\/\/.*gobwas\.com|http://exclude.gobwas.com)$` + fixture_alternatives_suffix_first_match = "https://safe.gobwas.com" + fixture_alternatives_suffix_first_mismatch = "http://safe.gobwas.com" + fixture_alternatives_suffix_second = "http://exclude.gobwas.com" + + pattern_prefix = "abc*" + regexp_prefix = `^abc.*$` + pattern_suffix = "*def" + regexp_suffix = `^.*def$` + pattern_prefix_suffix = "ab*ef" + regexp_prefix_suffix = `^ab.*ef$` + fixture_prefix_suffix_match = "abcdef" + fixture_prefix_suffix_mismatch = "af" + + pattern_alternatives_combine_lite = "{abc*def,abc?def,abc[zte]def}" + regexp_alternatives_combine_lite = `^(abc.*def|abc.def|abc[zte]def)$` + fixture_alternatives_combine_lite = "abczdef" + + pattern_alternatives_combine_hard = "{abc*[a-c]def,abc?[d-g]def,abc[zte]?def}" + regexp_alternatives_combine_hard = `^(abc.*[a-c]def|abc.[d-g]def|abc[zte].def)$` + fixture_alternatives_combine_hard = "abczqdef" +) + +type test struct { + pattern, match string + should bool + delimiters []rune +} + +func glob(s bool, p, m string, d ...rune) test { + return test{p, m, s, d} +} + +func TestGlob(t *testing.T) { + for _, test := range []test{ + glob(true, "* ?at * eyes", "my cat has very bright eyes"), + + glob(true, "", ""), + glob(false, "", "b"), + + glob(true, "*ä", "åä"), + glob(true, "abc", "abc"), + glob(true, "a*c", "abc"), + glob(true, "a*c", "a12345c"), + glob(true, "a?c", "a1c"), + glob(true, "a.b", "a.b", '.'), + glob(true, "a.*", "a.b", '.'), + glob(true, "a.**", "a.b.c", '.'), + glob(true, "a.?.c", "a.b.c", '.'), + glob(true, "a.?.?", "a.b.c", '.'), + glob(true, "?at", "cat"), + glob(true, "?at", "fat"), + glob(true, "*", "abc"), + glob(true, `\*`, "*"), + glob(true, "**", "a.b.c", '.'), + + glob(false, "?at", "at"), + glob(false, "?at", "fat", 'f'), + glob(false, "a.*", "a.b.c", '.'), + glob(false, "a.?.c", "a.bb.c", '.'), + glob(false, "*", "a.b.c", '.'), + + glob(true, "*test", "this is a test"), + glob(true, "this*", "this is a test"), + glob(true, "*is *", "this is a test"), + glob(true, "*is*a*", "this is a test"), + glob(true, "**test**", "this is a test"), + glob(true, "**is**a***test*", "this is a test"), + + glob(false, "*is", "this is a test"), + glob(false, "*no*", "this is a test"), + glob(true, "[!a]*", "this is a test3"), + + glob(true, "*abc", "abcabc"), + glob(true, "**abc", "abcabc"), + glob(true, "???", "abc"), + glob(true, "?*?", "abc"), + glob(true, "?*?", "ac"), + glob(false, "sta", "stagnation"), + glob(true, "sta*", "stagnation"), + glob(false, "sta?", "stagnation"), + glob(false, "sta?n", "stagnation"), + + glob(true, "{abc,def}ghi", "defghi"), + glob(true, "{abc,abcd}a", "abcda"), + glob(true, "{a,ab}{bc,f}", "abc"), + glob(true, "{*,**}{a,b}", "ab"), + glob(false, "{*,**}{a,b}", "ac"), + + glob(true, "/{rate,[a-z][a-z][a-z]}*", "/rate"), + glob(true, "/{rate,[0-9][0-9][0-9]}*", "/rate"), + glob(true, "/{rate,[a-z][a-z][a-z]}*", "/usd"), + + glob(true, "{*.google.*,*.yandex.*}", "www.google.com", '.'), + glob(true, "{*.google.*,*.yandex.*}", "www.yandex.com", '.'), + glob(false, "{*.google.*,*.yandex.*}", "yandex.com", '.'), + glob(false, "{*.google.*,*.yandex.*}", "google.com", '.'), + + glob(true, "{*.google.*,yandex.*}", "www.google.com", '.'), + glob(true, "{*.google.*,yandex.*}", "yandex.com", '.'), + glob(false, "{*.google.*,yandex.*}", "www.yandex.com", '.'), + glob(false, "{*.google.*,yandex.*}", "google.com", '.'), + + glob(true, "*//{,*.}example.com", "https://www.example.com"), + glob(true, "*//{,*.}example.com", "http://example.com"), + glob(false, "*//{,*.}example.com", "http://example.com.net"), + + glob(true, pattern_all, fixture_all_match), + glob(false, pattern_all, fixture_all_mismatch), + + glob(true, pattern_plain, fixture_plain_match), + glob(false, pattern_plain, fixture_plain_mismatch), + + glob(true, pattern_multiple, fixture_multiple_match), + glob(false, pattern_multiple, fixture_multiple_mismatch), + + glob(true, pattern_alternatives, fixture_alternatives_match), + glob(false, pattern_alternatives, fixture_alternatives_mismatch), + + glob(true, pattern_alternatives_suffix, fixture_alternatives_suffix_first_match), + glob(false, pattern_alternatives_suffix, fixture_alternatives_suffix_first_mismatch), + glob(true, pattern_alternatives_suffix, fixture_alternatives_suffix_second), + + glob(true, pattern_alternatives_combine_hard, fixture_alternatives_combine_hard), + + glob(true, pattern_alternatives_combine_lite, fixture_alternatives_combine_lite), + + glob(true, pattern_prefix, fixture_prefix_suffix_match), + glob(false, pattern_prefix, fixture_prefix_suffix_mismatch), + + glob(true, pattern_suffix, fixture_prefix_suffix_match), + glob(false, pattern_suffix, fixture_prefix_suffix_mismatch), + + glob(true, pattern_prefix_suffix, fixture_prefix_suffix_match), + glob(false, pattern_prefix_suffix, fixture_prefix_suffix_mismatch), + } { + g, err := Compile(test.pattern, test.delimiters...) + require.NoError(t, err) + result := g.Match(test.match) + assert.Equal(t, test.should, result, "pattern %q matching %q should be %v but got %v, compiled=%s", test.pattern, test.match, test.should, result, g.(*globCompiler).regexpPattern) + } +} + +func TestQuoteMeta(t *testing.T) { + for id, test := range []struct { + in, out string + }{ + { + in: `[foo*]`, + out: `\[foo\*\]`, + }, + { + in: `{foo*}`, + out: `\{foo\*\}`, + }, + { + in: `*?\[]{}`, + out: `\*\?\\\[\]\{\}`, + }, + { + in: `some text and *?\[]{}`, + out: `some text and \*\?\\\[\]\{\}`, + }, + } { + act := QuoteMeta(test.in) + assert.Equal(t, test.out, act, "QuoteMeta(%q)", test.in) + _, err := Compile(act) + assert.NoError(t, err, "#%d _, err := Compile(QuoteMeta(%q) = %q); err = %q", id, test.in, act, err) + } +} diff --git a/modules/indexer/code/bleve/bleve.go b/modules/indexer/code/bleve/bleve.go index 70f0995a01..c233f491e3 100644 --- a/modules/indexer/code/bleve/bleve.go +++ b/modules/indexer/code/bleve/bleve.go @@ -16,6 +16,7 @@ import ( "code.gitea.io/gitea/modules/analyze" "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/indexer" path_filter "code.gitea.io/gitea/modules/indexer/code/bleve/token/path" "code.gitea.io/gitea/modules/indexer/code/internal" @@ -162,7 +163,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro var err error if !update.Sized { var stdout string - stdout, _, err = git.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err = gitcmd.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return err } diff --git a/modules/indexer/code/elasticsearch/elasticsearch.go b/modules/indexer/code/elasticsearch/elasticsearch.go index f925ce396a..b08d837a2a 100644 --- a/modules/indexer/code/elasticsearch/elasticsearch.go +++ b/modules/indexer/code/elasticsearch/elasticsearch.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/analyze" "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/indexer" "code.gitea.io/gitea/modules/indexer/code/internal" indexer_internal "code.gitea.io/gitea/modules/indexer/internal" @@ -147,7 +148,7 @@ func (b *Indexer) addUpdate(ctx context.Context, batchWriter git.WriteCloserErro var err error if !update.Sized { var stdout string - stdout, _, err = git.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err = gitcmd.NewCommand("cat-file", "-s").AddDynamicArguments(update.BlobSha).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return nil, err } @@ -250,7 +251,7 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st func (b *Indexer) Delete(ctx context.Context, repoID int64) error { if err := b.doDelete(ctx, repoID); err != nil { // Maybe there is a conflict during the delete operation, so we should retry after a refresh - log.Warn("Deletion of entries of repo %v within index %v was erroneus. Trying to refresh index before trying again", repoID, b.inner.VersionedIndexName(), err) + log.Warn("Deletion of entries of repo %v within index %v was erroneous. Trying to refresh index before trying again", repoID, b.inner.VersionedIndexName(), err) if err := b.refreshIndex(ctx); err != nil { return err } diff --git a/modules/indexer/code/git.go b/modules/indexer/code/git.go index 41bc74e6ec..f1513d66b0 100644 --- a/modules/indexer/code/git.go +++ b/modules/indexer/code/git.go @@ -10,13 +10,14 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/indexer/code/internal" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) func getDefaultBranchSha(ctx context.Context, repo *repo_model.Repository) (string, error) { - stdout, _, err := git.NewCommand("show-ref", "-s").AddDynamicArguments(git.BranchPrefix+repo.DefaultBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err := gitcmd.NewCommand("show-ref", "-s").AddDynamicArguments(git.BranchPrefix+repo.DefaultBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return "", err } @@ -32,8 +33,8 @@ func getRepoChanges(ctx context.Context, repo *repo_model.Repository, revision s needGenesis := len(status.CommitSha) == 0 if !needGenesis { - hasAncestorCmd := git.NewCommand("merge-base").AddDynamicArguments(status.CommitSha, revision) - stdout, _, _ := hasAncestorCmd.RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + hasAncestorCmd := gitcmd.NewCommand("merge-base").AddDynamicArguments(status.CommitSha, revision) + stdout, _, _ := hasAncestorCmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) needGenesis = len(stdout) == 0 } @@ -86,7 +87,7 @@ func parseGitLsTreeOutput(stdout []byte) ([]internal.FileUpdate, error) { // genesisChanges get changes to add repo to the indexer for the first time func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { var changes internal.RepoChanges - stdout, _, runErr := git.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, runErr := gitcmd.NewCommand("ls-tree", "--full-tree", "-l", "-r").AddDynamicArguments(revision).RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if runErr != nil { return nil, runErr } @@ -98,8 +99,8 @@ func genesisChanges(ctx context.Context, repo *repo_model.Repository, revision s // nonGenesisChanges get changes since the previous indexer update func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revision string) (*internal.RepoChanges, error) { - diffCmd := git.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision) - stdout, _, runErr := diffCmd.RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + diffCmd := gitcmd.NewCommand("diff", "--name-status").AddDynamicArguments(repo.CodeIndexerStatus.CommitSha, revision) + stdout, _, runErr := diffCmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if runErr != nil { // previous commit sha may have been removed by a force push, so // try rebuilding from scratch @@ -115,9 +116,9 @@ func nonGenesisChanges(ctx context.Context, repo *repo_model.Repository, revisio updatedFilenames := make([]string, 0, 10) updateChanges := func() error { - cmd := git.NewCommand("ls-tree", "--full-tree", "-l").AddDynamicArguments(revision). + cmd := gitcmd.NewCommand("ls-tree", "--full-tree", "-l").AddDynamicArguments(revision). AddDashesAndList(updatedFilenames...) - lsTreeStdout, _, err := cmd.RunStdBytes(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + lsTreeStdout, _, err := cmd.RunStdBytes(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { return err } diff --git a/modules/indexer/code/indexer_test.go b/modules/indexer/code/indexer_test.go index 78fea22f10..a884ab733a 100644 --- a/modules/indexer/code/indexer_test.go +++ b/modules/indexer/code/indexer_test.go @@ -134,7 +134,7 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) { }, }, // Search for matches on both the contents and the filenames within the repo '62'. - // This scenario yields two results: the first result is baed on the file (cucumber.md) while the second is based on the contents + // This scenario yields two results: the first result is based on the file (cucumber.md) while the second is based on the contents { RepoIDs: []int64{62}, Keyword: "cucumber", diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index 8f25c84b76..bbc78aecbe 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -28,7 +28,7 @@ import ( ) // IndexerMetadata is used to send data to the queue, so it contains only the ids. -// It may look weired, because it has to be compatible with the old queue data format. +// It may look weird, because it has to be compatible with the old queue data format. // If the IsDelete flag is true, the IDs specify the issues to delete from the index without querying the database. // If the IsDelete flag is false, the ID specify the issue to index, so Indexer will query the database to get the issue data. // It should be noted that if the id is not existing in the database, it's index will be deleted too even if IsDelete is false. diff --git a/modules/markup/render_link.go b/modules/markup/render_link.go index 046544ce81..9cc83095ff 100644 --- a/modules/markup/render_link.go +++ b/modules/markup/render_link.go @@ -18,7 +18,7 @@ func resolveLinkRelative(ctx context.Context, base, cur, link string, absolute b } if strings.HasPrefix(link, "/") { if strings.HasPrefix(link, base) && strings.Count(base, "/") >= 4 { - // a trick to tolerate that some users were using absolut paths (the old gitea's behavior) + // a trick to tolerate that some users were using absolute paths (the old gitea's behavior) finalLink = link } else { finalLink = util.URLJoin(base, "./", link) diff --git a/modules/proxy/proxy.go b/modules/proxy/proxy.go index 1a6bdad7fb..f8843316aa 100644 --- a/modules/proxy/proxy.go +++ b/modules/proxy/proxy.go @@ -10,10 +10,9 @@ import ( "strings" "sync" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" - - "github.com/gobwas/glob" ) var ( diff --git a/modules/queue/queue.go b/modules/queue/queue.go index 577fd4d498..56835014a5 100644 --- a/modules/queue/queue.go +++ b/modules/queue/queue.go @@ -22,7 +22,7 @@ // // 4. Handler (represented by HandlerFuncT type): // - It's the function responsible for processing items. Each active worker will call it. -// - If an item or some items are not psuccessfully rocessed, the handler could return them as "unhandled items". +// - If an item or some items are not successfully processed, the handler could return them as "unhandled items". // In such scenarios, the queue system ensures these unhandled items are returned to the base queue after a brief delay. // This mechanism is particularly beneficial in cases where the processing entity (like a document indexer) is // temporarily unavailable. It ensures that no item is skipped or lost due to transient failures in the processing diff --git a/modules/setting/glob.go b/modules/setting/glob.go index 8f1d24dea4..cc76a02077 100644 --- a/modules/setting/glob.go +++ b/modules/setting/glob.go @@ -3,7 +3,7 @@ package setting -import "github.com/gobwas/glob" +import "code.gitea.io/gitea/modules/glob" type GlobMatcher struct { compiledGlob glob.Glob diff --git a/modules/setting/service.go b/modules/setting/service.go index b1b9fedd62..e652c13c9c 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -9,10 +9,9 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" - - "github.com/gobwas/glob" ) // enumerates all the types of captchas diff --git a/modules/setting/service_test.go b/modules/setting/service_test.go index 73736b793a..fad1542741 100644 --- a/modules/setting/service_test.go +++ b/modules/setting/service_test.go @@ -6,10 +6,10 @@ package setting import ( "testing" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" - "github.com/gobwas/glob" "github.com/stretchr/testify/assert" ) diff --git a/modules/structs/issue.go b/modules/structs/issue.go index 322ac1e4ca..2540481d0f 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -17,7 +17,7 @@ import ( type StateType string const ( - // StateOpen pr is opend + // StateOpen pr is opened StateOpen StateType = "open" // StateClosed pr is closed StateClosed StateType = "closed" @@ -76,6 +76,8 @@ type Issue struct { // swagger:strfmt date-time Deadline *time.Time `json:"due_date"` + TimeEstimate int64 `json:"time_estimate"` + PullRequest *PullRequestMeta `json:"pull_request"` Repo *RepositoryMeta `json:"repository"` diff --git a/modules/structs/repo.go b/modules/structs/repo.go index e82a6dc25e..c1c85837fc 100644 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -319,7 +319,7 @@ const ( ) // Name represents the service type's name -// WARNNING: the name have to be equal to that on goth's library +// WARNING: the name has to be equal to that on goth's library func (gt GitServiceType) Name() string { return strings.ToLower(gt.Title()) } diff --git a/modules/structs/user.go b/modules/structs/user.go index 89349cda2c..90dbcff25c 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -61,7 +61,7 @@ type User struct { // MarshalJSON implements the json.Marshaler interface for User, adding field(s) for backward compatibility func (u User) MarshalJSON() ([]byte, error) { - // Re-declaring User to avoid recursion + // Redeclaring User to avoid recursion type shadow User return json.Marshal(struct { shadow diff --git a/modules/typesniffer/typesniffer_test.go b/modules/typesniffer/typesniffer_test.go index a0c824b912..ad3f78afdc 100644 --- a/modules/typesniffer/typesniffer_test.go +++ b/modules/typesniffer/typesniffer_test.go @@ -48,12 +48,12 @@ func TestIsSvgImage(t *testing.T) { `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `)).IsSvgImage()) assert.True(t, DetectContentType([]byte(` - `)).IsSvgImage()) diff --git a/modules/validation/binding.go b/modules/validation/binding.go index 75190e31e1..335f248ead 100644 --- a/modules/validation/binding.go +++ b/modules/validation/binding.go @@ -10,10 +10,10 @@ import ( "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/util" "gitea.com/go-chi/binding" - "github.com/gobwas/glob" ) const ( diff --git a/modules/validation/glob_pattern_test.go b/modules/validation/glob_pattern_test.go index 7f3e609acf..80cf035ca6 100644 --- a/modules/validation/glob_pattern_test.go +++ b/modules/validation/glob_pattern_test.go @@ -6,8 +6,9 @@ package validation import ( "testing" + "code.gitea.io/gitea/modules/glob" + "gitea.com/go-chi/binding" - "github.com/gobwas/glob" ) func getGlobPatternErrorString(pattern string) string { diff --git a/modules/validation/helpers.go b/modules/validation/helpers.go index ba383ba195..051330e439 100644 --- a/modules/validation/helpers.go +++ b/modules/validation/helpers.go @@ -11,9 +11,8 @@ import ( "strings" "sync" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/setting" - - "github.com/gobwas/glob" ) type globalVarsStruct struct { diff --git a/options/gitignore/Gradle b/options/gitignore/Gradle index a5b111377b..f93fdf4442 100644 --- a/options/gitignore/Gradle +++ b/options/gitignore/Gradle @@ -8,7 +8,7 @@ gradle-app.setting # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar -# Avoid ignore Gradle wrappper properties +# Avoid ignore Gradle wrapper properties !gradle-wrapper.properties # Cache of project diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index ffac68e262..cc92f2e626 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -3425,7 +3425,6 @@ swift.install=Přidejte balíček do svého Package.swift souboru: swift.install2=a spustit následující příkaz: vagrant.install=Pro přidání Vagrant box spusťte následující příkaz: settings.link=Propojit tento balíček s repozitářem -settings.link.description=Pokud propojíte balíček s repozitářem, je tento balíček uveden v seznamu balíčků repozitáře. settings.link.select=Vybrat repozitář settings.link.button=Aktualizovat odkaz na repozitář settings.link.success=Odkaz na repozitář byl úspěšně aktualizován. diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 8c0731edd9..dae7275f82 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -3475,7 +3475,6 @@ swift.install=Füge das Paket deiner Package.swift Datei hinzu: swift.install2=und führe den folgenden Befehl aus: vagrant.install=Um eine Vagrant-Box hinzuzufügen, führe den folgenden Befehl aus: settings.link=Dieses Paket einem Repository zuweisen -settings.link.description=Wenn du ein Paket mit einem Repository verknüpfst, wird es in der Paketliste des Repositories angezeigt. settings.link.select=Repository auswählen settings.link.button=Repository-Link aktualisieren settings.link.success=Repository-Link wurde erfolgreich aktualisiert. diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 60876b1ab0..42b23dea05 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -3133,7 +3133,6 @@ swift.install=Προσθέστε το πακέτο στο αρχείο Pac swift.install2=και εκτελέστε την ακόλουθη εντολή: vagrant.install=Για προσθήκη ενός κυτίου Vagrant, εκτελέστε την ακόλουθη εντολή: settings.link=Σύνδεση αυτού του πακέτου με ένα αποθετήριο -settings.link.description=Εάν συνδέσετε ένα πακέτο με ένα αποθετήριο, το πακέτο περιλαμβάνεται στη λίστα πακέτων του αποθετηρίου. settings.link.select=Επιλογή Αποθετηρίου settings.link.button=Ενημέρωση Συνδέσμου Αποθετηρίου settings.link.success=Ο σύνδεσμος αποθετηρίου ενημερώθηκε επιτυχώς. diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index a974b17225..b3eb7b1f4a 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3729,11 +3729,14 @@ swift.install = Add the package in your Package.swift file: swift.install2 = and run the following command: vagrant.install = To add a Vagrant box, run the following command: settings.link = Link this package to a repository -settings.link.description = If you link a package with a repository, the package is listed in the repository's package list. +settings.link.description = If you link a package with a repository, the package will appear in the repository's package list. Only repositories under the same owner can be linked. Leaving the field empty will remove the link. settings.link.select = Select Repository settings.link.button = Update Repository Link settings.link.success = Repository link was successfully updated. settings.link.error = Failed to update repository link. +settings.link.repo_not_found = Repository %s not found. +settings.unlink.error = Failed to remove repository link. +settings.unlink.success = Repository link was successfully removed. settings.delete = Delete package settings.delete.description = Deleting a package is permanent and cannot be undone. settings.delete.notice = You are about to delete %s (%s). This operation is irreversible, are you sure? diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 882a06330a..ffacb46b19 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -3113,7 +3113,6 @@ swift.install=Añade el paquete en tu archivo Package.swift: swift.install2=y ejecuta el siguiente comando: vagrant.install=Para añadir un paquete Vagrant, ejecuta el siguiente comando: settings.link=Vincular este paquete a un repositorio -settings.link.description=Si enlaza un paquete con un repositorio, el paquete se enumera en la lista de paquetes del repositorio. settings.link.select=Seleccionar repositorio settings.link.button=Actualizar enlace de repositorio settings.link.success=El enlace del repositorio se ha actualizado correctamente. diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index adf349e9d8..5814de64ca 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -3729,7 +3729,6 @@ swift.install=Ajoutez le paquet dans votre fichier Package.swift: swift.install2=et exécutez la commande suivante : vagrant.install=Pour ajouter une machine Vagrant, exécutez la commande suivante : settings.link=Lier ce paquet à un dépôt -settings.link.description=Si vous liez un paquet à dépôt, le paquet sera inclus dans sa liste des paquets. settings.link.select=Sélectionner un dépôt settings.link.button=Actualiser le lien du dépôt settings.link.success=Le lien du dépôt a été mis à jour avec succès. diff --git a/options/locale/locale_ga-IE.ini b/options/locale/locale_ga-IE.ini index ae8068ea10..b5b05209e5 100644 --- a/options/locale/locale_ga-IE.ini +++ b/options/locale/locale_ga-IE.ini @@ -3729,11 +3729,14 @@ swift.install=Cuir an pacáiste i do chomhad Package.swift: swift.install2=agus reáchtáil an t-ordú seo a leanas: vagrant.install=Chun bosca Vagrant a chur leis, reáchtáil an t-ordú seo a leanas: settings.link=Nasc an pacáiste seo le stóras -settings.link.description=Má nascann tú pacáiste le stóras, liostaítear an pacáiste i liosta pacáistí an stórais. +settings.link.description=Má nascann tú pacáiste le stórlann, beidh an pacáiste le feiceáil i liosta pacáistí an stórlainne. Ní féidir ach stórlanna faoin úinéir céanna a nascadh. Má fhágtar an réimse folamh, bainfear an nasc. settings.link.select=Roghnaigh Stóras settings.link.button=Nuashonraigh Nasc Stórais settings.link.success=D'éirigh le nasc an stórais a nuashonrú. settings.link.error=Theip ar an nasc stóras a nuashonrú. +settings.link.repo_not_found=Níor aimsíodh an stóras %s. +settings.unlink.error=Theip ar nasc an stórais a bhaint. +settings.unlink.success=Baineadh an nasc chuig an stóras go rathúil. settings.delete=Scrios pacáiste settings.delete.description=Tá pacáiste a scriosadh buan agus ní féidir é a chur ar ais. settings.delete.notice=Tá tú ar tí %s (%s) a scriosadh. Tá an oibríocht seo dochúlaithe, an bhfuil tú cinnte? diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index 2519688d08..31aebff2d6 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -2667,7 +2667,6 @@ rubygems.dependencies.development=Dipendenze Di Sviluppo rubygems.required.ruby=Richiede la versione di Ruby rubygems.required.rubygems=Richiede la versione RubyGem settings.link=Collega questo pacchetto a un repository -settings.link.description=Se si collega un pacchetto a un repository, il pacchetto è elencato nell'elenco dei pacchetti del repository. settings.link.select=Seleziona Repository settings.link.button=Aggiorna Collegamento Repository settings.link.success=Il link del repository è stato aggiornato correttamente. diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 14a4825c40..3b3083d8c6 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -3722,7 +3722,6 @@ swift.install=あなたの Package.swift ファイルにパッケ swift.install2=そして次のコマンドを実行します: vagrant.install=Vagrant ボックスを追加するには、次のコマンドを実行します。 settings.link=このパッケージをリポジトリにリンク -settings.link.description=パッケージをリポジトリにリンクすると、リポジトリのパッケージリストに表示されるようになります。 settings.link.select=リポジトリを選択 settings.link.button=リポジトリのリンクを更新 settings.link.success=リポジトリのリンクが正常に更新されました。 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 0ec540104f..9c8f47534b 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -3134,7 +3134,6 @@ swift.install=Pievienojiet pakotni savā Package.swift failā: swift.install2=un izpildiet sekojošu komandu: vagrant.install=Lai pievienotu Vagrant kasti, izpildiet sekojošu komandu: settings.link=Piesaistīt pakotni šim repozitorijam -settings.link.description=Sasaistot pakotni ar repozitoriju, tā tiks attēlota repozitorija pakotņu sarakstā. settings.link.select=Norādiet repozitoriju settings.link.button=Atjaunot repozitorija saiti settings.link.success=Repozitorija saite tika veiksmīgi atjaunota. diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 4232562994..b457ecc800 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -1103,9 +1103,9 @@ delete_preexisting_success=Arquivos órfãos excluídos em %s blame_prior=Ver a responsabilização anterior a esta modificação -transfer.accept=Aceitar transferência +transfer.accept=Aceitar Transferência transfer.accept_desc=`Transferir para "%s"` -transfer.reject=Rejeitar transferência +transfer.reject=Rejeitar Transferência transfer.reject_desc=`Cancelar a transferência para "%s"` transfer.no_permission_to_accept=Você não tem permissão para aceitar essa transferência. transfer.no_permission_to_reject=Você não tem permissão para rejeitar essa transferência. @@ -1118,14 +1118,14 @@ desc.internal=Interno desc.archived=Arquivado desc.sha256=SHA256 -template.items=Itens do modelo +template.items=Itens do Modelo template.git_content=Conteúdo Git (Branch padrão) template.git_hooks=Hooks do Git template.git_hooks_tooltip=Atualmente você não pode modificar ou remover os Git Hooks adicionados. Selecione isso apenas se você confia no repositório modelo. template.webhooks=Webhooks template.topics=Tópicos template.avatar=Avatar -template.issue_labels=Etiquetas de issue +template.issue_labels=Etiquetas de Issue template.one_item=Deve-se selecionar pelo menos um item de modelo template.invalid=Deve-se selecionar um repositório de modelo @@ -1363,7 +1363,7 @@ commits.no_commits=Nenhum commit em comum. "%s" e "%s" tem históricos completam commits.nothing_to_compare=Estes branches são iguais. commits.search.tooltip=Você pode prefixar as palavras-chave com "author:" (autor da mudança), "committer:" (autor do commit), "after:" (depois) ou "before:" (antes). Por exemplo: "revert author:Ana before:2019-01-13".\ commits.search_branch=Este Branch -commits.search_all=Todos os branches +commits.search_all=Todos os Branches commits.author=Autor commits.message=Mensagem commits.date=Data @@ -1931,24 +1931,24 @@ ext_wiki=Acesso a Wiki Externo ext_wiki.desc=Link para uma wiki externa. wiki=Wiki -wiki.welcome=Bem-vindo a wiki. +wiki.welcome=Bem-vindo a Wiki. wiki.welcome_desc=A wiki permite que você escreva e compartilhe a documentação com os colaboradores. wiki.desc=Escrever e compartilhar a documentação com os colaboradores. -wiki.create_first_page=Criar a primeira página +wiki.create_first_page=Criar a Primeira Página wiki.page=Página wiki.filter_page=Filtrar página wiki.new_page=Página wiki.page_title=Título da página wiki.page_content=Conteúdo wiki.default_commit_message=Escreva uma nota sobre a atualização nesta página (opcional). -wiki.save_page=Salvar página +wiki.save_page=Salvar Página wiki.last_commit_info=%s editou esta página %s wiki.edit_page_button=Editar -wiki.new_page_button=Nova página -wiki.file_revision=Revisão de página +wiki.new_page_button=Nova Página +wiki.file_revision=Revisão de Página wiki.wiki_page_revisions=Revisões de página Wiki wiki.back_to_wiki=Voltar para página Wiki -wiki.delete_page_button=Excluir página +wiki.delete_page_button=Excluir Página wiki.delete_page_notice_1=A exclusão da página de wiki "%s" não pode ser desfeita. Continuar? wiki.page_already_exists=Uma página de wiki com o mesmo nome já existe. wiki.reserved_page=O nome da página da wiki "%s" está reservado. @@ -2042,7 +2042,7 @@ settings.collaboration.undefined=Indefinido settings.hooks=Webhooks settings.githooks=Hooks do Git settings.basic_settings=Configurações Básicas -settings.mirror_settings=Opções de espelhamento +settings.mirror_settings=Opções de Espelhamento settings.mirror_settings.docs=Configure o seu repositório para sincronizar automaticamente commits, tags e branches de outro repositório. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=No momento, isso só pode ser feito no menu "Nova migração". Para obter mais informações, consulte: settings.mirror_settings.docs.can_still_use=Embora não seja possível modificar os espelhos existentes ou criar novos espelhos, você ainda pode usar o espelho existente. @@ -2057,25 +2057,25 @@ settings.mirror_settings.push_mirror.remote_url=URL do repositório do Git remot settings.mirror_settings.push_mirror.add=Adicionar Espelho de Push settings.mirror_settings.push_mirror.edit_sync_time=Editar intervalo de sincronização de espelhos -settings.sync_mirror=Sincronizar agora +settings.sync_mirror=Sincronizar Agora settings.site=Site -settings.update_settings=Atualizar configurações -settings.update_mirror_settings=Atualizar espelho -settings.branches.switch_default_branch=Alterar +settings.update_settings=Atualizar Configurações +settings.update_mirror_settings=Atualizar Configurações de Espelhamento +settings.branches.switch_default_branch=Alterar Branch Padrão settings.branches.update_default_branch=Atualizar Branch Padrão settings.branches.add_new_rule=Adicionar Nova Regra -settings.advanced_settings=Configurações avançadas -settings.wiki_desc=Habilitar a wiki do repositório -settings.use_internal_wiki=Usar a wiki nativa +settings.advanced_settings=Configurações Avançadas +settings.wiki_desc=Habilitar a Wiki do Repositório +settings.use_internal_wiki=Usar a Wiki Nativa settings.default_wiki_branch_name=Nome Padrão do Branch da Wiki -settings.use_external_wiki=Usar wiki externa -settings.external_wiki_url=URL externa da wiki +settings.use_external_wiki=Usar Wiki Externa +settings.external_wiki_url=URL Externa da Wiki settings.external_wiki_url_error=A URL da wiki externa não é válida. settings.external_wiki_url_desc=Visitantes são redirecionados para a URL da wiki externa ao clicar na aba da wiki. settings.issues_desc=Habilitar Issue Tracker para o Repositório settings.use_internal_issue_tracker=Usar o issue tracker nativo settings.use_external_issue_tracker=Usar issue tracker externo -settings.external_tracker_url=URL do issue tracker externo +settings.external_tracker_url=URL do Issue Tracker Externo settings.external_tracker_url_error=A URL do issue tracker externo não é válida. settings.external_tracker_url_desc=Visitantes são redirecionados para a URL do issue tracker externo ao clicar na aba de issues. settings.tracker_url_format=Formato de URL do issue tracker externo @@ -2099,29 +2099,29 @@ settings.releases_desc=Habilitar versões do Repositório settings.packages_desc=Habilitar Registro de Pacotes de Repositório settings.projects_desc=Habilitar Projetos settings.projects_mode_all=Todos os projetos -settings.actions_desc=Habilitar ações do repositório -settings.admin_settings=Configurações do administrador +settings.actions_desc=Habilitar Ações do Repositório +settings.admin_settings=Configurações do Administrador settings.admin_enable_health_check=Habilitar verificações de integridade (git fsck) no repositório -settings.admin_code_indexer=Indexador de código +settings.admin_code_indexer=Indexador de Código settings.admin_stats_indexer=Indexador de Estatísticas do Código settings.admin_indexer_commit_sha=Último SHA indexado settings.admin_indexer_unindexed=Não indexado settings.reindex_button=Adicionar à fila de reindexação settings.reindex_requested=Reindexação Requisitada settings.admin_enable_close_issues_via_commit_in_any_branch=Fechar issue via commit em um branch não padrão -settings.danger_zone=Zona de perigo +settings.danger_zone=Zona de Perigo settings.new_owner_has_same_repo=O novo proprietário já tem um repositório com o mesmo nome. Por favor, escolha outro nome. settings.convert=Converter para repositório tradicional settings.convert_desc=Você pode converter este espelhamento em um repositório tradicional. Esta ação não pode ser revertida. settings.convert_notices_1=Esta operação vai converter este espelhamento em um repositório tradicional. Esta ação não pode ser desfeita. -settings.convert_confirm=Converter o repositório +settings.convert_confirm=Converter o Repositório settings.convert_succeed=O espelhamento foi convertido em um repositório tradicional. settings.convert_fork=Converter Para Um Repositório Normal settings.convert_fork_desc=Você pode converter este fork em um repositório normal. Esta ação não pode ser desfeita. settings.convert_fork_notices_1=Esta operação irá converter o fork em um repositório normal e não pode ser desfeita. -settings.convert_fork_confirm=Converter repositório +settings.convert_fork_confirm=Converter Repositório settings.convert_fork_succeed=O fork foi convertido em um repositório normal. -settings.transfer=Transferir propriedade +settings.transfer=Transferir Propriedade settings.transfer.rejected=A transferência do repositório foi rejeitada. settings.transfer.success=A transferência do repositório foi bem sucedida. settings.transfer_abort=Cancelar transferência @@ -2132,7 +2132,7 @@ settings.transfer_form_title=Digite o nome do repositório para confirmar: settings.transfer_notices_1=- Você perderá o acesso ao repositório se transferir para um usuário individual. settings.transfer_notices_2=- Você manterá acesso ao repositório se transferi-lo para uma organização que você também é proprietário. settings.transfer_notices_3=- Se o repositório for privado e for transferido para um usuário individual, esta ação certifica que o usuário tem pelo menos permissão de leitura (e altera as permissões se necessário). -settings.transfer_owner=Novo proprietário +settings.transfer_owner=Novo Proprietário settings.transfer_perform=Executar Transferência settings.transfer_started=`Este repositório foi marcado para transferência e aguarda a confirmação de "%s"` settings.transfer_succeed=O repositório foi transferido. @@ -2145,7 +2145,7 @@ settings.trust_model.collaborator.long=Colaborador: Confiar em assinaturas feita settings.trust_model.committer=Committer settings.trust_model.collaboratorcommitter=Colaborador+Commiter settings.trust_model.collaboratorcommitter.long=Colaborador+Committer: Confiar na assinatura dos colaboradores que correspondem ao autor do commit -settings.wiki_delete=Excluir dados da wiki +settings.wiki_delete=Excluir Dados da Wiki settings.wiki_delete_desc=A exclusão de dados da wiki é permanente e não pode ser desfeita. settings.wiki_delete_notices_1=- Isso excluirá e desabilitará permanentemente a wiki do repositório %s. settings.confirm_wiki_delete=Excluir Dados da Wiki @@ -2156,14 +2156,14 @@ settings.delete_notices_1=- Esta operação NÃO PODERÁ ser de settings.delete_notices_fork_1=- Forks deste repositório se tornarão independentes após a exclusão. settings.deletion_success=O repositório foi excluído. settings.update_settings_success=As configurações do repositório foram atualizadas. -settings.confirm_delete=Excluir repositório -settings.add_collaborator=Adicionar colaborador +settings.confirm_delete=Excluir Repositório +settings.add_collaborator=Adicionar Colaborador settings.add_collaborator_success=O colaborador foi adicionado. settings.add_collaborator_inactive_user=Não é possível adicionar um usuário inativo como colaborador. settings.add_collaborator_owner=Não é possível adicionar um proprietário como um colaborador. settings.add_collaborator_duplicate=O colaborador já está adicionado a este repositório. settings.delete_collaborator=Remover -settings.collaborator_deletion=Remover colaborador +settings.collaborator_deletion=Remover Colaborador settings.collaborator_deletion_desc=A exclusão de um colaborador irá revogar o acesso a este repositório. Continuar? settings.remove_collaborator_success=O colaborador foi removido. settings.org_not_allowed_to_be_collaborator=Organizações não podem ser adicionadas como um colaborador. @@ -2174,10 +2174,10 @@ settings.add_team=Adicionar Equipe settings.add_team_duplicate=A equipe já tem o repositório settings.delete_team_tip=Esta equipe tem acesso a todos os repositórios e não pode ser removida settings.remove_team_success=O acesso da equipe ao repositório foi removido. -settings.add_webhook=Adicionar webhook +settings.add_webhook=Adicionar Webhook settings.add_webhook.invalid_channel_name=Nome do canal no webhook não pode estar em branco e não pode conter somente o caractere #. settings.hooks_desc=Webhooks automaticamente fazem requisições de HTTP POST para um servidor quando acionados determinados eventos de Gitea. Leia mais no guia de webhooks. -settings.webhook_deletion=Remover webhook +settings.webhook_deletion=Remover Webhook settings.webhook_deletion_desc=A exclusão de um webhook exclui suas configurações e o histórico de entrega. Continuar? settings.webhook_deletion_success=O webhook foi removido. settings.webhook.test_delivery=Testar Evento de Push @@ -2194,7 +2194,7 @@ settings.githook_name=Nome do Hook settings.githook_content=Conteúdo do Hook settings.update_githook=Atualizar Hook settings.add_webhook_desc=Gitea enviará requisições POST com um tipo de conteúdo especificado para a URL de destino. Leia mais no guia de webhooks. -settings.payload_url=URL de destino +settings.payload_url=URL de Destino settings.http_method=Método HTTP settings.content_type=Tipo de conteúdo POST settings.secret=Senha @@ -2204,9 +2204,9 @@ settings.slack_color=Cor settings.discord_username=Nome de usuário settings.discord_icon_url=URL do ícone settings.event_desc=Acionado em: -settings.event_push_only=Eventos de push -settings.event_send_everything=Todos os eventos -settings.event_choose=Eventos personalizados... +settings.event_push_only=Eventos de Push +settings.event_send_everything=Todos os Eventos +settings.event_choose=Eventos Personalizados… settings.event_header_repository=Eventos do Repositório settings.event_create=Criar settings.event_create_desc=Branch ou tag criado. @@ -2232,10 +2232,10 @@ settings.event_issue_label=Issue Rotulada settings.event_issue_label_desc=Rótulos da issue atualizados ou removidos. settings.event_issue_milestone=Marco Atribuído à Issue settings.event_issue_milestone_desc=Marco atribuído ou desatribuído à Issue. -settings.event_issue_comment=Comentário da issue +settings.event_issue_comment=Comentário da Issue settings.event_issue_comment_desc=Comentário da issue criado, editado ou excluído. settings.event_header_pull_request=Eventos de Pull Request -settings.event_pull_request=Pull request +settings.event_pull_request=Pull Request settings.event_pull_request_desc=Pull request aberto, fechado, reaberto, editado ou excluído. settings.event_pull_request_assign=Pull Request Atribuído settings.event_pull_request_assign_desc=Pull request atribuído ou desatribuído. @@ -2257,9 +2257,9 @@ settings.authorization_header_desc=Será incluído como header de autorização settings.active=Ativo settings.active_helper=Informações sobre eventos disparados serão enviadas para esta URL do webhook. settings.add_hook_success=O webhook foi adicionado. -settings.update_webhook=Atualizar webhook +settings.update_webhook=Atualizar Webhook settings.update_hook_success=O webhook foi atualizado. -settings.delete_webhook=Remover webhook +settings.delete_webhook=Remover Webhook settings.recent_deliveries=Entregas Recentes settings.hook_type=Tipo de Hook settings.slack_token=Token @@ -2285,14 +2285,14 @@ settings.packagist_package_url=URL do pacote do Packagist settings.deploy_keys=Chaves de Deploy settings.add_deploy_key=Nova Chave de Deploy settings.deploy_key_desc=As chaves de deploy possuem somente acesso de leitura (pull) ao repositório. -settings.is_writable=Habilitar acesso de escrita +settings.is_writable=Habilitar Acesso de Escrita settings.is_writable_info=Permitir que esta chave de deploy faça push para o repositório. settings.no_deploy_keys=Não há nenhuma chave de deploy ainda. settings.title=Título settings.deploy_key_content=Conteúdo da chave settings.key_been_used=Uma chave de deploy com conteúdo idêntico já está em uso. settings.key_name_used=Uma chave de deploy já existe com esse mesmo nome. -settings.deploy_key_deletion=Remover chave de deploy +settings.deploy_key_deletion=Remover Chave de Deploy settings.deploy_key_deletion_desc=A exclusão de uma chave de deploy irá revogar o seu acesso a este repositório. Continuar? settings.deploy_key_deletion_success=A chave de deploy foi removida. settings.branches=Branches @@ -2304,15 +2304,15 @@ settings.protected_branch_can_push_yes=Você pode fazer push settings.protected_branch_can_push_no=Você não pode fazer push settings.protect_this_branch=Habilitar Proteção de Branch settings.protect_this_branch_desc=Previne a exclusão e restringe o merge e push para o branch. -settings.protect_disable_push=Desabilitar push +settings.protect_disable_push=Desabilitar Push settings.protect_disable_push_desc=Nenhum push será permitido neste branch. settings.protect_disable_force_push=Desativar Push Forçado settings.protect_disable_force_push_desc=Nenhum push forçado será permitido para este branch. settings.protect_enable_push=Habilitar Push settings.protect_enable_push_desc=Qualquer pessoa com acesso de escrita terá permissão para realizar push neste branch (mas não forçar o push). settings.protect_enable_force_push_all=Ativar Push Forçado -settings.protect_enable_merge=Permitir merge -settings.protect_check_status_contexts=Habilitar verificação de status +settings.protect_enable_merge=Permitir Merge +settings.protect_check_status_contexts=Habilitar Verificação de Status settings.protect_check_status_contexts_list=Verificações de status encontradas na última semana para este repositório settings.protect_required_approvals=Aprovações necessárias: settings.dismiss_stale_approvals=Descartar aprovações obsoletas @@ -2350,7 +2350,7 @@ settings.tags.protection.allowed=Permitido settings.tags.protection.allowed.users=Usuários permitidos settings.tags.protection.allowed.teams=Equipes permitidas settings.tags.protection.allowed.noone=Ninguém -settings.tags.protection.create=Proteger tag +settings.tags.protection.create=Proteger Tag settings.tags.protection.none=Não há tags protegidas. settings.bot_token=Token do Bot settings.chat_id=ID do Chat @@ -2359,7 +2359,7 @@ settings.matrix.room_id=ID da Sala settings.matrix.message_type=Tipo de Mensagem settings.visibility.private.button=Tornar Privado settings.visibility.public.button=Tornar Público -settings.archive.button=Arquivar repositório +settings.archive.button=Arquivar Repositório settings.archive.header=Arquivar Este Repositório settings.archive.success=O repositório foi arquivado com sucesso. settings.archive.error=Um erro ocorreu enquanto estava sendo arquivado o repositório. Veja o log para mais detalhes. @@ -2384,12 +2384,12 @@ settings.lfs_invalid_locking_path=Caminho inválido: %s settings.lfs_invalid_lock_directory=Não é possível bloquear o diretório: %s settings.lfs_lock_already_exists=O bloqueio já existe: %s settings.lfs_lock=Bloqueio -settings.lfs_locks_no_locks=Sem bloqueios +settings.lfs_locks_no_locks=Sem Bloqueios settings.lfs_lock_file_no_exist=Arquivo bloqueado não existe no branch padrão -settings.lfs_force_unlock=Forçar desbloqueio +settings.lfs_force_unlock=Forçar Desbloqueio settings.lfs_pointers.sha=SHA Blob settings.lfs_pointers.oid=OID -settings.lfs_pointers.inRepo=No repositório +settings.lfs_pointers.inRepo=No Repositório settings.lfs_pointers.exists=Existe na loja settings.lfs_pointers.accessible=Acessível ao Usuário settings.lfs_pointers.associateAccessible=Associar %d OIDs acessíveis @@ -2479,7 +2479,7 @@ release.tag_helper_existing=Tag existente. release.title=Título da versão release.title_empty=O título não pode estar em branco. release.message=Descreva esta versão -release.prerelease_desc=Marcar como pré-lançamento +release.prerelease_desc=Marcar como Pré-lançamento release.prerelease_helper=Marcar esta versão como inadequada para uso em produção. release.cancel=Cancelar release.publish=Publicar Versão @@ -3381,7 +3381,6 @@ swift.install=Adicione o pacote em seu arquivo Package.swift: swift.install2=e execute o seguinte comando: vagrant.install=Para adicionar uma Vagrant box, execute o seguinte comando: settings.link=Vincular este pacote a um repositório -settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório. settings.link.select=Selecionar Repositório settings.link.button=Atualizar Link do Repositório settings.link.success=Link do repositório foi atualizado com sucesso. diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index c16677151c..9e648b6602 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -3599,7 +3599,7 @@ no_subscriptions=Sem subscrições default_key=Assinado com a chave padrão error.extract_sign=Falhou ao extrair a assinatura error.generate_hash=Falhou ao gerar o hash do cometimento -error.no_committer_account=Não existe qualquer conta ligada ao endereço de email de quem cometeu +error.no_committer_account=Não existe qualquer conta vinculada ao endereço de email de quem cometeu error.no_gpg_keys_found=Não foi encontrada uma chave conhecida para esta assinatura, na base de dados error.not_signed_commit=Não é um cometimento assinado error.failed_retrieval_gpg_keys=Falhou ao obter uma chave ligada à conta de quem cometeu @@ -3617,7 +3617,7 @@ desc=Gerir pacotes do repositório. empty=Ainda não há pacotes. no_metadata=Sem metadados. empty.documentation=Para obter mais informação sobre o registo de pacotes, veja a documentação. -empty.repo=Carregou um pacote mas este não é apresentado aqui? Vá às configurações do pacote e ligue-o a este repositório. +empty.repo=Carregou um pacote mas este não é apresentado aqui? Vá às configurações do pacote e vincule-o a este repositório. registry.documentation=Para mais informação sobre o registo %s, veja a documentação. filter.type=Tipo filter.type.all=Todos @@ -3729,11 +3729,14 @@ swift.install=Adicione o pacote no seu ficheiro Package.swift: swift.install2=e execute o seguinte comando: vagrant.install=Para adicionar uma máquina virtual Vagrant, execute o seguinte comando: settings.link=Vincular este pacote a um repositório -settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório. +settings.link.description=Se você vincular um pacote a um repositório, o pacote será listado na lista de pacotes do repositório. Apenas os repositórios do mesmo dono podem ser vinculados. Deixar o campo em branco irá remover o vínculo. settings.link.select=Escolha o repositório settings.link.button=Modificar vínculo ao repositório -settings.link.success=A ligação ao repositório foi modificada com sucesso. +settings.link.success=O vínculo ao repositório foi modificado com sucesso. settings.link.error=Falhou a modificação do vínculo ao repositório. +settings.link.repo_not_found=O repositório %s não foi encontrado. +settings.unlink.error=Falhou a remoção do vínculo ao repositório. +settings.unlink.success=O vínculo ao repositório foi removido com sucesso. settings.delete=Eliminar pacote settings.delete.description=Eliminar o pacote é permanente e não pode ser desfeito. settings.delete.notice=Está prestes a eliminar %s (%s). Esta operação é irreversível. Tem a certeza? diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 47aace9614..6da0eea91c 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -3083,7 +3083,6 @@ swift.install=Добавьте пакет в свой файл Package.swi swift.install2=и запустите следующую команду: vagrant.install=Чтобы добавить бокс Vagrant, выполните следующую команду: settings.link=Связать этот пакет с репозиторием -settings.link.description=Если связать пакет с репозиторием, он добавится в список пакетов репозитория. settings.link.select=Выберите репозиторий settings.link.button=Обновить ссылку на репозиторий settings.link.success=Связь с репозиторием успешно обновлена. diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index 8b0e1aced2..a3ae736f67 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -3418,7 +3418,6 @@ swift.install=Paketi Package.swift dosyanıza ekleyin: swift.install2=ve şu komutu çalıştırın: vagrant.install=Vagrant paketi eklemek için aşağıdaki komutu çalıştırın: settings.link=Bu paketi bir depoya bağlayın -settings.link.description=Eğer bir paketi bir depoya bağlarsanız, paket deponun paket listesinde listelenecektir. settings.link.select=Depo Seç settings.link.button=Depo Bağlantısını Güncelle settings.link.success=Depo bağlantısı başarıyla güncellendi. diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index 85a9982d00..1849d5d378 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -3290,7 +3290,6 @@ swift.install=Додайте пакет у ваш файл Package.swiftPackage.swift 文件中添加该包: swift.install2=并运行以下命令: vagrant.install=若要添加一个 Vagrant box,请运行以下命令: settings.link=将此软件包链接到仓库 -settings.link.description=如果您将一个软件包与一个仓库链接起来,软件包将显示在仓库的软件包列表中。 settings.link.select=选择仓库 settings.link.button=更新仓库链接 settings.link.success=仓库链接已成功更新。 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index c82987ed73..c1879203f7 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -3397,7 +3397,6 @@ swift.install=將此套件加入您的 Package.swift 檔: swift.install2=並執行下列命令: vagrant.install=執行下列命令以新增 Vagrant box: settings.link=連結此套件到儲存庫 -settings.link.description=如果您將套件連結到儲存庫,該套件會顯示在儲存庫的套件清單。 settings.link.select=選擇儲存庫 settings.link.button=更新儲存庫連結 settings.link.success=儲存庫連結更新成功。 diff --git a/package.json b/package.json index 5fe8e70c3f..0b2ce03354 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@citation-js/plugin-csl": "0.7.18", "@citation-js/plugin-software-formats": "0.6.1", "@github/markdown-toolbar-element": "2.2.3", + "@github/paste-markdown": "1.5.3", "@github/relative-time-element": "4.4.8", "@github/text-expander-element": "2.9.2", "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", @@ -18,7 +19,7 @@ "@resvg/resvg-wasm": "2.6.2", "@silverwind/vue3-calendar-heatmap": "2.0.6", "@techknowlogick/license-checker-webpack-plugin": "0.3.0", - "add-asset-webpack-plugin": "3.0.0", + "add-asset-webpack-plugin": "3.1.1", "ansi_up": "6.0.6", "asciinema-player": "3.10.0", "chart.js": "4.5.0", @@ -37,7 +38,6 @@ "katex": "0.16.22", "mermaid": "11.11.0", "mini-css-extract-plugin": "2.9.4", - "minimatch": "10.0.3", "monaco-editor": "0.53.0", "monaco-editor-webpack-plugin": "7.1.0", "online-3d-viewer": "0.16.0", @@ -45,7 +45,6 @@ "perfect-debounce": "2.0.0", "postcss": "8.5.6", "postcss-loader": "8.2.0", - "postcss-nesting": "13.0.2", "sortablejs": "1.15.6", "swagger-ui-dist": "5.29.0", "tailwindcss": "3.4.17", @@ -69,37 +68,35 @@ "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", "@playwright/test": "1.55.0", "@stoplight/spectral-cli": "6.15.0", - "@stylistic/eslint-plugin-js": "3.1.0", + "@stylistic/eslint-plugin": "5.3.1", "@stylistic/stylelint-plugin": "4.0.0", "@types/codemirror": "5.60.16", "@types/dropzone": "5.7.9", "@types/jquery": "3.5.33", "@types/katex": "0.16.7", - "@types/license-checker-webpack-plugin": "0.2.5", "@types/pdfobject": "2.2.5", "@types/sortablejs": "1.15.8", "@types/swagger-ui-dist": "3.30.6", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/toastify-js": "1.12.4", - "@typescript-eslint/eslint-plugin": "8.43.0", "@typescript-eslint/parser": "8.43.0", "@vitejs/plugin-vue": "6.0.1", "@vitest/eslint-plugin": "1.3.9", - "eslint": "8.57.0", + "eslint": "9.35.0", "eslint-import-resolver-typescript": "4.4.4", - "eslint-plugin-array-func": "4.0.0", - "eslint-plugin-github": "5.0.2", + "eslint-plugin-array-func": "5.0.2", + "eslint-plugin-github": "6.0.0", "eslint-plugin-import-x": "4.16.1", - "eslint-plugin-no-jquery": "3.1.1", - "eslint-plugin-no-use-extend-native": "0.5.0", + "eslint-plugin-no-use-extend-native": "0.7.2", "eslint-plugin-playwright": "2.2.2", "eslint-plugin-regexp": "2.10.0", "eslint-plugin-sonarjs": "3.0.5", - "eslint-plugin-unicorn": "56.0.1", + "eslint-plugin-unicorn": "61.0.2", "eslint-plugin-vue": "10.4.0", "eslint-plugin-vue-scoped-css": "2.12.0", "eslint-plugin-wc": "3.0.1", + "globals": "16.4.0", "happy-dom": "18.0.1", "markdownlint-cli": "0.45.0", "material-icon-theme": "5.27.0", @@ -111,7 +108,7 @@ "stylelint-declaration-strict-value": "1.10.11", "stylelint-value-no-unknown-custom-properties": "6.0.1", "svgo": "4.0.0", - "type-fest": "4.41.0", + "typescript-eslint": "8.43.0", "updates": "16.7.0", "vite-string-plugin": "1.4.6", "vitest": "3.2.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 83a31ce8ad..5d40acd101 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: '@github/markdown-toolbar-element': specifier: 2.2.3 version: 2.2.3 + '@github/paste-markdown': + specifier: 1.5.3 + version: 1.5.3 '@github/relative-time-element': specifier: 4.4.8 version: 4.4.8 @@ -63,8 +66,8 @@ importers: specifier: 0.3.0 version: 0.3.0(webpack@5.101.3) add-asset-webpack-plugin: - specifier: 3.0.0 - version: 3.0.0(webpack@5.101.3) + specifier: 3.1.1 + version: 3.1.1(webpack@5.101.3) ansi_up: specifier: 6.0.6 version: 6.0.6 @@ -119,9 +122,6 @@ importers: mini-css-extract-plugin: specifier: 2.9.4 version: 2.9.4(webpack@5.101.3) - minimatch: - specifier: 10.0.3 - version: 10.0.3 monaco-editor: specifier: 0.53.0 version: 0.53.0 @@ -143,9 +143,6 @@ importers: postcss-loader: specifier: 8.2.0 version: 8.2.0(postcss@8.5.6)(typescript@5.9.2)(webpack@5.101.3) - postcss-nesting: - specifier: 13.0.2 - version: 13.0.2(postcss@8.5.6) sortablejs: specifier: 1.15.6 version: 1.15.6 @@ -203,16 +200,16 @@ importers: devDependencies: '@eslint-community/eslint-plugin-eslint-comments': specifier: 4.5.0 - version: 4.5.0(eslint@8.57.0) + version: 4.5.0(eslint@9.35.0(jiti@2.5.1)) '@playwright/test': specifier: 1.55.0 version: 1.55.0 '@stoplight/spectral-cli': specifier: 6.15.0 version: 6.15.0 - '@stylistic/eslint-plugin-js': - specifier: 3.1.0 - version: 3.1.0(eslint@8.57.0) + '@stylistic/eslint-plugin': + specifier: 5.3.1 + version: 5.3.1(eslint@9.35.0(jiti@2.5.1)) '@stylistic/stylelint-plugin': specifier: 4.0.0 version: 4.0.0(stylelint@16.24.0(typescript@5.9.2)) @@ -228,9 +225,6 @@ importers: '@types/katex': specifier: 0.16.7 version: 0.16.7 - '@types/license-checker-webpack-plugin': - specifier: 0.2.5 - version: 0.2.5 '@types/pdfobject': specifier: 2.2.5 version: 2.2.5 @@ -249,60 +243,57 @@ importers: '@types/toastify-js': specifier: 1.12.4 version: 1.12.4 - '@typescript-eslint/eslint-plugin': - specifier: 8.43.0 - version: 8.43.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.43.0 - version: 8.43.0(eslint@8.57.0)(typescript@5.9.2) + version: 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) '@vitejs/plugin-vue': specifier: 6.0.1 version: 6.0.1(vite@7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))(vue@3.5.21(typescript@5.9.2)) '@vitest/eslint-plugin': specifier: 1.3.9 - version: 1.3.9(eslint@8.57.0)(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) + version: 1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)) eslint: - specifier: 8.57.0 - version: 8.57.0 + specifier: 9.35.0 + version: 9.35.0(jiti@2.5.1) eslint-import-resolver-typescript: specifier: 4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0))(eslint-plugin-import@2.32.0)(eslint@8.57.0) + version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-array-func: - specifier: 4.0.0 - version: 4.0.0(eslint@8.57.0) - eslint-plugin-github: specifier: 5.0.2 - version: 5.0.2(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0)(typescript@5.9.2) + version: 5.0.2(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-github: + specifier: 6.0.0 + version: 6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-import-x: specifier: 4.16.1 - version: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - eslint-plugin-no-jquery: - specifier: 3.1.1 - version: 3.1.1(eslint@8.57.0) + version: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-no-use-extend-native: - specifier: 0.5.0 - version: 0.5.0 + specifier: 0.7.2 + version: 0.7.2(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-playwright: specifier: 2.2.2 - version: 2.2.2(eslint@8.57.0) + version: 2.2.2(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-regexp: specifier: 2.10.0 - version: 2.10.0(eslint@8.57.0) + version: 2.10.0(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-sonarjs: specifier: 3.0.5 - version: 3.0.5(eslint@8.57.0) + version: 3.0.5(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-unicorn: - specifier: 56.0.1 - version: 56.0.1(eslint@8.57.0) + specifier: 61.0.2 + version: 61.0.2(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-vue: specifier: 10.4.0 - version: 10.4.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0)) + version: 10.4.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))) eslint-plugin-vue-scoped-css: specifier: 2.12.0 - version: 2.12.0(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0)) + version: 2.12.0(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))) eslint-plugin-wc: specifier: 3.0.1 - version: 3.0.1(eslint@8.57.0) + version: 3.0.1(eslint@9.35.0(jiti@2.5.1)) + globals: + specifier: 16.4.0 + version: 16.4.0 happy-dom: specifier: 18.0.1 version: 18.0.1 @@ -336,9 +327,9 @@ importers: svgo: specifier: 4.0.0 version: 4.0.0 - type-fest: - specifier: 4.41.0 - version: 4.41.0 + typescript-eslint: + specifier: 8.43.0 + version: 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) updates: specifier: 16.7.0 version: 16.7.0 @@ -475,12 +466,6 @@ packages: '@csstools/css-parser-algorithms': ^3.0.5 '@csstools/css-tokenizer': ^3.0.4 - '@csstools/selector-resolve-nested@3.1.0': - resolution: {integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==} - engines: {node: '>=18'} - peerDependencies: - postcss-selector-parser: ^7.0.0 - '@csstools/selector-specificity@5.0.0': resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} engines: {node: '>=18'} @@ -675,13 +660,42 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/compat@1.3.2': + resolution: {integrity: sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.40 || 9 + peerDependenciesMeta: + eslint: + optional: true - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.35.0': + resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@github/browserslist-config@1.0.0': resolution: {integrity: sha512-gIhjdJp/c2beaIWWIlsXdqXVRUz3r2BxBCpfz/F3JXHvSAQ1paMYjLH+maEATtENg+k5eLV7gA+9yPp762ieuw==} @@ -692,24 +706,30 @@ packages: '@github/markdown-toolbar-element@2.2.3': resolution: {integrity: sha512-AlquKGee+IWiAMYVB0xyHFZRMnu4n3X4HTvJHu79GiVJ1ojTukCWyxMlF5NMsecoLcBKsuBhx3QPv2vkE/zQ0A==} + '@github/paste-markdown@1.5.3': + resolution: {integrity: sha512-PzZ1b3PaqBzYqbT4fwKEhiORf38h2OcGp2+JdXNNM7inZ7egaSmfmhyNkQILpqWfS0AYtRS3CDq6z03eZ8yOMQ==} + '@github/relative-time-element@4.4.8': resolution: {integrity: sha512-FSLYm6F3TSQnqHE1EMQUVVgi2XjbCvsESwwXfugHFpBnhyF1uhJOtu0Psp/BB/qqazfdkk7f5fVcu7WuXl3t8Q==} '@github/text-expander-element@2.9.2': resolution: {integrity: sha512-XY8EUMqM4GAloNxXNA1Py1ny+engWwYntbgsnpstQN4piaTI9rIlfYldyd0nnPXhxjGCVqHPmP6yg17Q0/n9Vg==} - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - deprecated: Use @eslint/config-array instead + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - '@humanwhocodes/object-schema@2.0.3': - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - deprecated: Use @eslint/object-schema instead + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -1116,11 +1136,11 @@ packages: resolution: {integrity: sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w==} engines: {node: '>=10.8'} - '@stylistic/eslint-plugin-js@3.1.0': - resolution: {integrity: sha512-lQktsOiCr8S6StG29C5fzXYxLOD6ID1rp4j6TRS+E/qY1xd59Fm7dy5qm9UauJIEoSTlYx6yGsCHYh5UkgXPyg==} + '@stylistic/eslint-plugin@5.3.1': + resolution: {integrity: sha512-Ykums1VYonM0TgkD0VteVq9mrlO2FhF48MDJnPyv3MktIB2ydtuhlO0AfWm7xnW1kyf5bjOqA6xc7JjviuVTxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: '>=8.40.0' + eslint: '>=9.0.0' '@stylistic/stylelint-plugin@4.0.0': resolution: {integrity: sha512-CFwt3K4Y/7bygNCLCQ8Sy4Hzgbhxq3BsNW0FIuYxl17HD3ywptm54ocyeiLVRrk5jtz1Zwks7Xr9eiZt8SWHAw==} @@ -1280,9 +1300,6 @@ packages: '@types/katex@0.16.7': resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} - '@types/license-checker-webpack-plugin@0.2.5': - resolution: {integrity: sha512-raj3YPZxjkDlRrJJUq6So+C9i/fqYxUtVZzlXxm6bwwXONOnTHvGCfYmbQhzsHJneiJdlR6mMH76/bvWbZZN8Q==} - '@types/markdown-escape@1.1.3': resolution: {integrity: sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw==} @@ -1298,9 +1315,6 @@ packages: '@types/node@24.3.1': resolution: {integrity: sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==} - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/pdfobject@2.2.5': resolution: {integrity: sha512-7gD5tqc/RUDq0PyoLemL0vEHxBYi+zY0WVaFAx/Y0jBsXFgot1vB9No1GhDZGwRGJMCIZbgAb74QG9MTyTNU/g==} @@ -1313,15 +1327,9 @@ packages: '@types/sortablejs@1.15.8': resolution: {integrity: sha512-b79830lW+RZfwaztgs1aVPgbasJ8e7AXtZYHTELNXZPsERt4ymJdjV4OccDbHQAvHrCcFpbF78jkm0R6h/pZVg==} - '@types/source-list-map@0.1.6': - resolution: {integrity: sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==} - '@types/swagger-ui-dist@3.30.6': resolution: {integrity: sha512-FVxN7wjLYRtJsZBscOcOcf8oR++m38vbUFjT33Mr9HBuasX9bRDrJsp7iwixcOtKSHEEa2B7o2+4wEiXqC+Ebw==} - '@types/tapable@1.0.12': - resolution: {integrity: sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==} - '@types/tern@0.23.9': resolution: {integrity: sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==} @@ -1340,21 +1348,12 @@ packages: '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - '@types/uglify-js@3.17.5': - resolution: {integrity: sha512-TU+fZFBTBcXj/GpDpDaBmgWk/gn96kMZ+uocaFUlV2f8a6WdMzzI44QBCmGcCiYR0Y6ZlNRiyUyKKt5nl/lbzQ==} - '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} '@types/urijs@1.19.25': resolution: {integrity: sha512-XOfUup9r3Y06nFAZh3WvO0rBU4OtlfPB/vgxpjg+NRdGU6CN6djdc6OEiH+PcqHCY6eFLo9Ista73uarf4gnBg==} - '@types/webpack-sources@3.2.3': - resolution: {integrity: sha512-4nZOdMwSPHZ4pTEZzSp0AsTM4K7Qmu40UKW4tJDiOVs20UzYF9l+qUe4s0ftfN0pin06n+5cWWDJXH+sbhAiDw==} - - '@types/webpack@4.41.40': - resolution: {integrity: sha512-u6kMFSBM9HcoTpUXnL6mt2HSzftqb3JgYV6oxIgL2dl6sX6aCa5k6SOkzv5DuZjBTPUE/dJltKtwwuqrkZHpfw==} - '@types/whatwg-mimetype@3.0.2': resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==} @@ -1417,9 +1416,6 @@ packages: resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - '@unrs/resolver-binding-android-arm-eabi@1.11.1': resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} cpu: [arm] @@ -1708,11 +1704,14 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - add-asset-webpack-plugin@3.0.0: - resolution: {integrity: sha512-mg6nL4E+dNZPQfTc/A4xcOYsIxCN7Cuy9OScZsjI9qOYPiJeFZfsYcdoYlqcNNQEC4w8yNwArhD1Gm+G1iWrNg==} + add-asset-webpack-plugin@3.1.1: + resolution: {integrity: sha512-0WexE8uFq2hkC/rc+zVY8Hf5cKj/UwuBa0GSDKfCiKh6rrw/e7PYDgdxz1syHXIthTRlgt5q2vLvBIWcWtAvIQ==} engines: {node: '>=18'} peerDependencies: webpack: '>=5' + peerDependenciesMeta: + webpack: + optional: true ajv-draft-04@1.0.0: resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} @@ -1875,6 +1874,10 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} + builtin-modules@5.0.0: + resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} + engines: {node: '>=18.20'} + builtins@1.0.3: resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} @@ -1908,6 +1911,9 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + character-entities-legacy@3.0.0: resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} @@ -2352,10 +2358,6 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dom-input-range@2.0.1: resolution: {integrity: sha512-UMGnuQlEepIPCju5NrPe+8y52B+pRvSjIaSPW92KpukoDGSEVkI2iaCR4HxK7K6C7zmVsWE8PEjCYZaJMr3vpg==} @@ -2503,11 +2505,11 @@ packages: eslint-import-resolver-webpack: optional: true - eslint-plugin-array-func@4.0.0: - resolution: {integrity: sha512-p3NY2idNIvgmQLF2/62ZskYt8gOuUgQ51smRc3Lh7FtSozpNc2sg+lniz9VaCagLZHEZTl8qGJKqE7xy8O/D/g==} + eslint-plugin-array-func@5.0.2: + resolution: {integrity: sha512-iyLex2+pTcxHZ6OLL80oMy+CtffpJ9j6A/57VQi1VN5bK1IS/0o+mWvezDHeAlwXjn6ksRO9L5SGU329BBuY8A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: '>=8.40.0' + eslint: '>=8.51.0' eslint-plugin-escompat@3.11.4: resolution: {integrity: sha512-j0ywwNnIufshOzgAu+PfIig1c7VRClKSNKzpniMT2vXQ4leL5q+e/SpMFQU0nrdL2WFFM44XmhSuwmxb3G0CJg==} @@ -2525,11 +2527,11 @@ packages: peerDependencies: eslint: '*' - eslint-plugin-github@5.0.2: - resolution: {integrity: sha512-nMdzWJQ5CimjQDY6SFeJ0KIXuNFf0dgDWEd4eP3UWfuTuP/dXcZJDg7MQRvAFt743T1zUi4+/HdOihfu8xJkLA==} + eslint-plugin-github@6.0.0: + resolution: {integrity: sha512-J8MvUoiR/TU/Y9NnEmg1AnbvMUj9R6IO260z47zymMLLvso7B4c80IKjd8diqmqtSmeXXlbIus4i0SvK84flag==} hasBin: true peerDependencies: - eslint: ^8.0.1 + eslint: ^8 || ^9 eslint-plugin-i18n-text@1.0.1: resolution: {integrity: sha512-3G3UetST6rdqhqW9SfcfzNYMpQXS7wNkJvp6dsXnjzGiku6Iu5hl3B0kmk6lIcFPwYjhQIY+tXVRtK9TlGT7RA==} @@ -2565,18 +2567,15 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - eslint-plugin-no-jquery@3.1.1: - resolution: {integrity: sha512-LTLO3jH/Tjr1pmxCEqtV6qmt+OChv8La4fwgG470JRpgxyFF4NOzoC9CRy92GIWD3Yjl0qLEgPmD2FLQWcNEjg==} - peerDependencies: - eslint: '>=8.0.0' - eslint-plugin-no-only-tests@3.3.0: resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==} engines: {node: '>=5.0.0'} - eslint-plugin-no-use-extend-native@0.5.0: - resolution: {integrity: sha512-dBNjs8hor8rJgeXLH4HTut5eD3RGWf9JUsadIfuL7UosVQ/dnvOKwxEcRrXrFxrMZ8llUVWT+hOimxJABsAUzQ==} - engines: {node: '>=6.0.0'} + eslint-plugin-no-use-extend-native@0.7.2: + resolution: {integrity: sha512-hUBlwaTXIO1GzTwPT6pAjvYwmSHe4XduDhAiQvur4RUujmBUFjd8Nb2+e7WQdsQ+nGHWGRlogcUWXJRGqizTWw==} + engines: {node: '>=18.18.0'} + peerDependencies: + eslint: ^9.3.0 eslint-plugin-playwright@2.2.2: resolution: {integrity: sha512-j0jKpndIPOXRRP9uMkwb9l/nSmModOU3452nrFdgFJoEv/435J1onk8+aITzjDW8DfypxgmVaDMdmVIa6F7I0w==} @@ -2609,11 +2608,11 @@ packages: peerDependencies: eslint: ^8.0.0 || ^9.0.0 - eslint-plugin-unicorn@56.0.1: - resolution: {integrity: sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==} - engines: {node: '>=18.18'} + eslint-plugin-unicorn@61.0.2: + resolution: {integrity: sha512-zLihukvneYT7f74GNbVJXfWIiNQmkc/a9vYBTE4qPkQZswolWNdu+Wsp9sIXno1JOzdn6OUwLPd19ekXVkahRA==} + engines: {node: ^20.10.0 || >=21.0.0} peerDependencies: - eslint: '>=8.56.0' + eslint: '>=9.29.0' eslint-plugin-vue-scoped-css@2.12.0: resolution: {integrity: sha512-gEbuvYetNbsPA0IsmERFkVC2/vOHCInfFekNSOsAxWI/7C/bc8PoLal+fRibWfnzWryY6iL8YoluMtrEqWRj1A==} @@ -2646,10 +2645,6 @@ packages: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} - eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2662,20 +2657,20 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + eslint@9.35.0: + resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -2774,14 +2769,18 @@ packages: file-entry-cache@10.1.4: resolution: {integrity: sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA==} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up-simple@1.0.1: + resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} + engines: {node: '>=18'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -2790,9 +2789,9 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} flat-cache@6.1.13: resolution: {integrity: sha512-gmtS2PaUjSPa4zjObEIn4WWliKyZzYljgxODBfxugpK6q6HU9ClXzgCJ+nlcPKY9Bt090ypTOLIFWkV0jbKFjw==} @@ -2836,9 +2835,9 @@ packages: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} - get-set-props@0.1.0: - resolution: {integrity: sha512-7oKuKzAGKj0ag+eWZwcGw2fjiZ78tXnXQoBgY0aU7ZOxTu4bB7hSuQSDgtKy978EDH062P5FmD2EWiDpQS9K9Q==} - engines: {node: '>=0.10.0'} + get-set-props@0.2.0: + resolution: {integrity: sha512-YCmOj+4YAeEB5Dd9jfp6ETdejMet4zSxXjNkgaa4npBEKRI9uDOGB5MmAdAgi2OoFGAKshYhCbmLq2DS03CgVA==} + engines: {node: '>=18.0.0'} get-source@2.0.12: resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} @@ -2882,10 +2881,18 @@ packages: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + globals@15.15.0: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -2924,9 +2931,6 @@ packages: hookified@1.12.0: resolution: {integrity: sha512-hMr1Y9TCLshScrBbV2QxJ9BROddxZ12MX9KsCtuGGy/3SmmN5H1PllKerrVlSotur9dlE8hmUKAOSa3WDzsZmQ==} - hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - hpagent@1.2.0: resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} engines: {node: '>=14'} @@ -2981,9 +2985,9 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} + indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} @@ -3026,9 +3030,9 @@ packages: is-buffer@1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - is-builtin-module@3.2.1: - resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} - engines: {node: '>=6'} + is-builtin-module@5.0.0: + resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} + engines: {node: '>=18.20'} is-bun-module@2.0.0: resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} @@ -3044,8 +3048,9 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-get-set-prop@1.0.0: - resolution: {integrity: sha512-DvAYZ1ZgGUz4lzxKMPYlt08qAUqyG9ckSg2pIjfvcQ7+pkVNUHk8yVLXOnCLe5WKXhLop8oorWFBJHpwWQpszQ==} + is-get-set-prop@2.0.0: + resolution: {integrity: sha512-C32bqXfHJfRwa0U5UIMqSGziZhALszXDJZ8n8mz8WZ6c6V7oYGHEWwJvftliBswypY3P3EQqdY5lpDSEKvTS1Q==} + engines: {node: '> 18.0.0'} is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} @@ -3054,19 +3059,17 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - is-js-type@2.0.0: - resolution: {integrity: sha512-Aj13l47+uyTjlQNHtXBV8Cji3jb037vxwMWCgopRR8h6xocgBGW3qG8qGlIOEmbXQtkKShKuBM9e8AA1OeQ+xw==} + is-js-type@3.0.0: + resolution: {integrity: sha512-IbPf3g3vxm1D902xaBaYp2TUHiXZWwWRu5bM9hgKN9oAQcFaKALV6Gd13PGhXjKE5u2n8s1PhLhdke/E1fchxQ==} + engines: {node: '>=18.0.0'} is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-obj-prop@1.0.0: - resolution: {integrity: sha512-5Idb61slRlJlsAzi0Wsfwbp+zZY+9LXKUAZpvT/1ySw+NxKLRWfa0Bzj+wXI3fX5O9hiddm5c3DAaRSNP/yl2w==} - - is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} + is-obj-prop@2.0.0: + resolution: {integrity: sha512-2/VFrbzXSZVJIscazpxoB+pOQx2jBOAAL9Gui4cRKxflznUNBpsr8IDvBA4UGol3e40sltLNiY3qnZv/7qSUxA==} + engines: {node: '>=18.0.0'} is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} @@ -3079,8 +3082,9 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - is-proto-prop@2.0.0: - resolution: {integrity: sha512-jl3NbQ/fGLv5Jhan4uX+Ge9ohnemqyblWVVCpAvtTQzNFvV2xhJq+esnkIbYQ9F1nITXoLfDDQLp7LBw/zzncg==} + is-proto-prop@3.0.1: + resolution: {integrity: sha512-S8xSxNMGJO4eZD86kO46zrq2gLIhA+rN9443lQEvt8Mz/l8cxk72p/AWFmofY6uL9g9ILD6cXW6j8QQj4F3Hcw==} + engines: {node: '>=18.0.0'} is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} @@ -3126,9 +3130,9 @@ packages: js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-types@1.0.0: - resolution: {integrity: sha512-bfwqBW9cC/Lp7xcRpug7YrXm0IVw+T9e3g4mCYnv0Pjr3zIzU9PCQElYU9oSGAWzXlbdl9X5SAMPejO9sxkeUw==} - engines: {node: '>=0.10.0'} + js-types@4.0.0: + resolution: {integrity: sha512-/c+n06zvqFQGxdz1BbElF7S3nEghjNchLN1TjQnk2j10HYDaUc57rcvl6BbnziTx8NQmrg0JOs/iwRpvcYaxjQ==} + engines: {node: '>=18.20'} js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} @@ -3142,8 +3146,9 @@ packages: resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} engines: {node: '>= 10.16.0'} - jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} hasBin: true jsesc@3.1.0: @@ -3319,9 +3324,9 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lowercase-keys@1.0.1: - resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==} - engines: {node: '>=0.10.0'} + lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -3479,10 +3484,6 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - mini-css-extract-plugin@2.9.4: resolution: {integrity: sha512-ZWYT7ln73Hptxqxk2DxPU9MmapXRhxkJD6tkSR04dnQxm8BGu2hzgKLugK5yySD97u/8yy7Ma7E76k9ZdvtjkQ==} engines: {node: '>= 12.13.0'} @@ -3584,9 +3585,6 @@ packages: engines: {node: '>=12.4.0'} hasBin: true - normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -3594,9 +3592,9 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - obj-props@1.4.0: - resolution: {integrity: sha512-p7p/7ltzPDiBs6DqxOrIbtRdwxxVRBj5ROukeNb9RgA+fawhrz5n2hpNz8DDmYR//tviJSj7nUnlppGmONkjiQ==} - engines: {node: '>=0.10.0'} + obj-props@2.0.0: + resolution: {integrity: sha512-Q/uLAAfjdhrzQWN2czRNh3fDCgXjh7yRIkdHjDgIHTwpFP0BsshxTA3HRNffHR7Iw/XGTH30u8vdMXQ+079urA==} + engines: {node: '>=18.0.0'} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -3823,12 +3821,6 @@ packages: peerDependencies: postcss: ^8.2.14 - postcss-nesting@13.0.2: - resolution: {integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==} - engines: {node: '>=18'} - peerDependencies: - postcss: ^8.4 - postcss-resolve-nested-selector@0.1.6: resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==} @@ -3885,9 +3877,9 @@ packages: printable-characters@1.0.42: resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} - proto-props@2.0.0: - resolution: {integrity: sha512-2yma2tog9VaRZY2mn3Wq51uiSW4NcPYT1cQdBagwyrznrilKSZwIZ0UG3ZPL/mx+axEns0hE35T5ufOYZXEnBQ==} - engines: {node: '>=4'} + prototype-properties@5.0.0: + resolution: {integrity: sha512-uCWE2QqnGlwvvJXTwiHTPTyHE62+zORO5hpFWhAwBGDtEtTmNZZleNLJDoFsqHCL4p/CeAP2Q1uMKFUKALuRGQ==} + engines: {node: '>=18.20'} punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} @@ -3909,14 +3901,6 @@ packages: read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} - read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - - read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -3937,8 +3921,8 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true - regjsparser@0.10.0: - resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true rename-keys@1.2.0: @@ -3981,11 +3965,6 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} @@ -4029,10 +4008,6 @@ packages: resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} engines: {node: ^14.0.0 || >=16.0.0} - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -4125,9 +4100,6 @@ packages: spdx-compare@1.0.0: resolution: {integrity: sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==} - spdx-correct@3.2.0: - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} - spdx-exceptions@2.5.0: resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} @@ -4183,9 +4155,9 @@ packages: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} + strip-indent@4.1.0: + resolution: {integrity: sha512-OA95x+JPmL7kc7zCu+e+TeYxEiaIyndRx0OrBcK2QPPH09oAndr2ALvymxWA+Lx1PYYvFUm4O63pRkdJAaW96w==} + engines: {node: '>=12'} strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} @@ -4407,17 +4379,12 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - - type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} + typescript-eslint@8.43.0: + resolution: {integrity: sha512-FyRGJKUGvcFekRRcBKFBlAhnp4Ng8rhe8tuvvkR9OiU0gfd4vyvTRQHEckO6VDlH57jbeUQem2IpqPq9kLJH+w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' typescript@5.9.2: resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} @@ -4477,9 +4444,6 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validate-npm-package-name@3.0.0: resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} @@ -4874,10 +4838,6 @@ snapshots: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 - '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.0)': - dependencies: - postcss-selector-parser: 7.1.0 - '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': dependencies: postcss-selector-parser: 7.1.0 @@ -4980,25 +4940,43 @@ snapshots: '@esbuild/win32-x64@0.25.9': optional: true - '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@8.57.0)': + '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.35.0(jiti@2.5.1))': dependencies: escape-string-regexp: 4.0.0 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) ignore: 5.3.2 - '@eslint-community/eslint-utils@4.9.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.35.0(jiti@2.5.1))': dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/eslintrc@2.1.4': + '@eslint/compat@1.3.2(eslint@9.35.0(jiti@2.5.1))': + optionalDependencies: + eslint: 9.35.0(jiti@2.5.1) + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.1 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.1': {} + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.4.1 - espree: 9.6.1 - globals: 13.24.0 + espree: 10.4.0 + globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 js-yaml: 4.1.0 @@ -5007,7 +4985,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.57.0': {} + '@eslint/js@9.35.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.5': + dependencies: + '@eslint/core': 0.15.2 + levn: 0.4.1 '@github/browserslist-config@1.0.0': {} @@ -5015,6 +5000,8 @@ snapshots: '@github/markdown-toolbar-element@2.2.3': {} + '@github/paste-markdown@1.5.3': {} + '@github/relative-time-element@4.4.8': {} '@github/text-expander-element@2.9.2': @@ -5022,17 +5009,16 @@ snapshots: '@github/combobox-nav': 2.3.1 dom-input-range: 2.0.1 - '@humanwhocodes/config-array@0.11.14': + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.4.1 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 '@humanwhocodes/module-importer@1.0.1': {} - '@humanwhocodes/object-schema@2.0.3': {} + '@humanwhocodes/retry@0.4.3': {} '@iconify/types@2.0.0': {} @@ -5552,11 +5538,15 @@ snapshots: '@stoplight/yaml-ast-parser': 0.0.50 tslib: 2.8.1 - '@stylistic/eslint-plugin-js@3.1.0(eslint@8.57.0)': + '@stylistic/eslint-plugin@5.3.1(eslint@9.35.0(jiti@2.5.1))': dependencies: - eslint: 8.57.0 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + '@typescript-eslint/types': 8.43.0 + eslint: 9.35.0(jiti@2.5.1) eslint-visitor-keys: 4.2.1 espree: 10.4.0 + estraverse: 5.3.0 + picomatch: 4.0.3 '@stylistic/stylelint-plugin@4.0.0(stylelint@16.24.0(typescript@5.9.2))': dependencies: @@ -5756,10 +5746,6 @@ snapshots: '@types/katex@0.16.7': {} - '@types/license-checker-webpack-plugin@0.2.5': - dependencies: - '@types/webpack': 4.41.40 - '@types/markdown-escape@1.1.3': {} '@types/marked@4.3.2': {} @@ -5774,8 +5760,6 @@ snapshots: dependencies: undici-types: 7.10.0 - '@types/normalize-package-data@2.4.4': {} - '@types/pdfobject@2.2.5': {} '@types/sarif@2.1.7': {} @@ -5784,12 +5768,8 @@ snapshots: '@types/sortablejs@1.15.8': {} - '@types/source-list-map@0.1.6': {} - '@types/swagger-ui-dist@3.30.6': {} - '@types/tapable@1.0.12': {} - '@types/tern@0.23.9': dependencies: '@types/estree': 1.0.8 @@ -5805,40 +5785,21 @@ snapshots: '@types/trusted-types@2.0.7': optional: true - '@types/uglify-js@3.17.5': - dependencies: - source-map: 0.6.1 - '@types/unist@2.0.11': {} '@types/urijs@1.19.25': {} - '@types/webpack-sources@3.2.3': - dependencies: - '@types/node': 24.3.1 - '@types/source-list-map': 0.1.6 - source-map: 0.7.6 - - '@types/webpack@4.41.40': - dependencies: - '@types/node': 24.3.1 - '@types/tapable': 1.0.12 - '@types/uglify-js': 3.17.5 - '@types/webpack-sources': 3.2.3 - anymatch: 3.1.3 - source-map: 0.6.1 - '@types/whatwg-mimetype@3.0.2': {} - '@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/type-utils': 8.43.0(eslint@8.57.0)(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/type-utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.43.0 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -5847,14 +5808,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2)': + '@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/scope-manager': 8.43.0 '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.43.0 debug: 4.4.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -5877,13 +5838,13 @@ snapshots: dependencies: typescript: 5.9.2 - '@typescript-eslint/type-utils@8.43.0(eslint@8.57.0)(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) debug: 4.4.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: @@ -5907,13 +5868,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2)': + '@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) '@typescript-eslint/scope-manager': 8.43.0 '@typescript-eslint/types': 8.43.0 '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -5923,8 +5884,6 @@ snapshots: '@typescript-eslint/types': 8.43.0 eslint-visitor-keys: 4.2.1 - '@ungap/structured-clone@1.3.0': {} - '@unrs/resolver-binding-android-arm-eabi@1.11.1': optional: true @@ -5990,11 +5949,11 @@ snapshots: vite: 7.1.5(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) vue: 3.5.21(typescript@5.9.2) - '@vitest/eslint-plugin@1.3.9(eslint@8.57.0)(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': + '@vitest/eslint-plugin@1.3.9(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))': dependencies: '@typescript-eslint/scope-manager': 8.43.0 - '@typescript-eslint/utils': 8.43.0(eslint@8.57.0)(typescript@5.9.2) - eslint: 8.57.0 + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) optionalDependencies: typescript: 5.9.2 vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.1)(happy-dom@18.0.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1) @@ -6236,8 +6195,8 @@ snapshots: acorn@8.15.0: {} - add-asset-webpack-plugin@3.0.0(webpack@5.101.3): - dependencies: + add-asset-webpack-plugin@3.1.1(webpack@5.101.3): + optionalDependencies: webpack: 5.101.3(webpack-cli@6.0.1) ajv-draft-04@1.0.0(ajv@8.17.1): @@ -6370,6 +6329,8 @@ snapshots: builtin-modules@3.3.0: {} + builtin-modules@5.0.0: {} + builtins@1.0.3: {} bytes@3.1.2: {} @@ -6400,6 +6361,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + change-case@5.4.4: {} + character-entities-legacy@3.0.0: {} character-entities@2.0.2: {} @@ -6842,10 +6805,6 @@ snapshots: dependencies: esutils: 2.0.3 - doctrine@3.0.0: - dependencies: - esutils: 2.0.3 - dom-input-range@2.0.1: {} dom-serializer@2.0.0: @@ -6955,14 +6914,14 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-compat-utils@0.6.5(eslint@8.57.0): + eslint-compat-utils@0.6.5(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) semver: 7.7.2 - eslint-config-prettier@10.1.8(eslint@8.57.0): + eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) eslint-import-context@0.1.9(unrs-resolver@1.11.1): dependencies: @@ -6979,10 +6938,10 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0))(eslint-plugin-import@2.32.0)(eslint@8.57.0): + eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)): dependencies: debug: 4.4.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) get-tsconfig: 4.10.1 is-bun-module: 2.0.0 @@ -6990,82 +6949,87 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0) - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2) - eslint: 8.57.0 + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0))(eslint-plugin-import@2.32.0)(eslint@8.57.0) + eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)))(eslint-plugin-import@2.32.0)(eslint@9.35.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-plugin-array-func@4.0.0(eslint@8.57.0): + eslint-plugin-array-func@5.0.2(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) - eslint-plugin-escompat@3.11.4(eslint@8.57.0): + eslint-plugin-escompat@3.11.4(eslint@9.35.0(jiti@2.5.1)): dependencies: browserslist: 4.25.4 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) - eslint-plugin-eslint-comments@3.2.0(eslint@8.57.0): + eslint-plugin-eslint-comments@3.2.0(eslint@9.35.0(jiti@2.5.1)): dependencies: escape-string-regexp: 1.0.5 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) ignore: 5.3.2 - eslint-plugin-filenames@1.3.2(eslint@8.57.0): + eslint-plugin-filenames@1.3.2(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) lodash.camelcase: 4.3.0 lodash.kebabcase: 4.1.1 lodash.snakecase: 4.1.1 lodash.upperfirst: 4.3.1 - eslint-plugin-github@5.0.2(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0)(typescript@5.9.2): + eslint-plugin-github@6.0.0(@types/eslint@9.6.1)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)): dependencies: + '@eslint/compat': 1.3.2(eslint@9.35.0(jiti@2.5.1)) + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.35.0 '@github/browserslist-config': 1.0.0 - '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(typescript@5.9.2) - '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) aria-query: 5.3.2 - eslint: 8.57.0 - eslint-config-prettier: 10.1.8(eslint@8.57.0) - eslint-plugin-escompat: 3.11.4(eslint@8.57.0) - eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) - eslint-plugin-filenames: 1.3.2(eslint@8.57.0) - eslint-plugin-i18n-text: 1.0.1(eslint@8.57.0) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0) - eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) + eslint: 9.35.0(jiti@2.5.1) + eslint-config-prettier: 10.1.8(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-escompat: 3.11.4(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-eslint-comments: 3.2.0(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-filenames: 1.3.2(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-i18n-text: 1.0.1(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.35.0(jiti@2.5.1)) eslint-plugin-no-only-tests: 3.3.0 - eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@8.57.0))(eslint@8.57.0)(prettier@3.6.2) + eslint-plugin-prettier: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(prettier@3.6.2) eslint-rule-documentation: 1.0.23 + globals: 16.4.0 jsx-ast-utils: 3.3.5 prettier: 3.6.2 svg-element-attributes: 1.3.1 + typescript: 5.9.2 + typescript-eslint: 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) transitivePeerDependencies: - '@types/eslint' - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - - typescript - eslint-plugin-i18n-text@1.0.1(eslint@8.57.0): + eslint-plugin-i18n-text@1.0.1(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.35.0(jiti@2.5.1)): dependencies: '@typescript-eslint/types': 8.43.0 comment-parser: 1.4.1 debug: 4.4.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) eslint-import-context: 0.1.9(unrs-resolver@1.11.1) is-glob: 4.0.3 minimatch: 10.0.3 @@ -7073,12 +7037,12 @@ snapshots: stable-hash-x: 0.2.0 unrs-resolver: 1.11.1 optionalDependencies: - '@typescript-eslint/utils': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)): dependencies: '@rtsao/scc': 1.1.0 array-includes: '@nolyfill/array-includes@1.0.44' @@ -7087,9 +7051,9 @@ snapshots: array.prototype.flatmap: '@nolyfill/array.prototype.flatmap@1.0.44' debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0(jiti@2.5.1)) hasown: '@nolyfill/hasown@1.0.44' is-core-module: '@nolyfill/is-core-module@1.0.39' is-glob: 4.0.3 @@ -7101,13 +7065,13 @@ snapshots: string.prototype.trimend: '@nolyfill/string.prototype.trimend@1.0.44' tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.0): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.35.0(jiti@2.5.1)): dependencies: aria-query: 5.3.2 array-includes: '@nolyfill/array-includes@1.0.44' @@ -7117,7 +7081,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) hasown: '@nolyfill/hasown@1.0.44' jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -7126,51 +7090,48 @@ snapshots: safe-regex-test: '@nolyfill/safe-regex-test@1.0.44' string.prototype.includes: '@nolyfill/string.prototype.includes@1.0.44' - eslint-plugin-no-jquery@3.1.1(eslint@8.57.0): - dependencies: - eslint: 8.57.0 - eslint-plugin-no-only-tests@3.3.0: {} - eslint-plugin-no-use-extend-native@0.5.0: + eslint-plugin-no-use-extend-native@0.7.2(eslint@9.35.0(jiti@2.5.1)): dependencies: - is-get-set-prop: 1.0.0 - is-js-type: 2.0.0 - is-obj-prop: 1.0.0 - is-proto-prop: 2.0.0 + eslint: 9.35.0(jiti@2.5.1) + is-get-set-prop: 2.0.0 + is-js-type: 3.0.0 + is-obj-prop: 2.0.0 + is-proto-prop: 3.0.1 - eslint-plugin-playwright@2.2.2(eslint@8.57.0): + eslint-plugin-playwright@2.2.2(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) globals: 13.24.0 - eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@8.57.0))(eslint@8.57.0)(prettier@3.6.2): + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.35.0(jiti@2.5.1)))(eslint@9.35.0(jiti@2.5.1))(prettier@3.6.2): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@8.57.0) + eslint-config-prettier: 10.1.8(eslint@9.35.0(jiti@2.5.1)) - eslint-plugin-regexp@2.10.0(eslint@8.57.0): + eslint-plugin-regexp@2.10.0(eslint@9.35.0(jiti@2.5.1)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.12.1 comment-parser: 1.4.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) jsdoc-type-pratt-parser: 4.8.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-sonarjs@3.0.5(eslint@8.57.0): + eslint-plugin-sonarjs@3.0.5(eslint@9.35.0(jiti@2.5.1)): dependencies: '@eslint-community/regexpp': 4.12.1 builtin-modules: 3.3.0 bytes: 3.1.2 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) functional-red-black-tree: 1.0.1 jsx-ast-utils-x: 0.1.0 lodash.merge: 4.6.2 @@ -7179,57 +7140,59 @@ snapshots: semver: 7.7.2 typescript: 5.9.2 - eslint-plugin-unicorn@56.0.1(eslint@8.57.0): + eslint-plugin-unicorn@61.0.2(eslint@9.35.0(jiti@2.5.1)): dependencies: '@babel/helper-validator-identifier': 7.27.1 - '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint/plugin-kit': 0.3.5 + change-case: 5.4.4 ci-info: 4.3.0 clean-regexp: 1.0.0 core-js-compat: 3.45.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) esquery: 1.6.0 - globals: 15.15.0 - indent-string: 4.0.0 - is-builtin-module: 3.2.1 + find-up-simple: 1.0.1 + globals: 16.4.0 + indent-string: 5.0.0 + is-builtin-module: 5.0.0 jsesc: 3.1.0 pluralize: 8.0.0 - read-pkg-up: 7.0.1 regexp-tree: 0.1.27 - regjsparser: 0.10.0 + regjsparser: 0.12.0 semver: 7.7.2 - strip-indent: 3.0.0 + strip-indent: 4.1.0 - eslint-plugin-vue-scoped-css@2.12.0(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0)): + eslint-plugin-vue-scoped-css@2.12.0(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0) - eslint: 8.57.0 - eslint-compat-utils: 0.6.5(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + eslint: 9.35.0(jiti@2.5.1) + eslint-compat-utils: 0.6.5(eslint@9.35.0(jiti@2.5.1)) lodash: 4.17.21 postcss: 8.5.6 postcss-safe-parser: 6.0.0(postcss@8.5.6) postcss-scss: 4.0.9(postcss@8.5.6) postcss-selector-parser: 7.1.0 postcss-styl: 0.12.3 - vue-eslint-parser: 10.2.0(eslint@8.57.0) + vue-eslint-parser: 10.2.0(eslint@9.35.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-plugin-vue@10.4.0(@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0)): + eslint-plugin-vue@10.4.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1))): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0) - eslint: 8.57.0 + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + eslint: 9.35.0(jiti@2.5.1) natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 semver: 7.7.2 - vue-eslint-parser: 10.2.0(eslint@8.57.0) + vue-eslint-parser: 10.2.0(eslint@9.35.0(jiti@2.5.1)) xml-name-validator: 4.0.0 optionalDependencies: - '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) - eslint-plugin-wc@3.0.1(eslint@8.57.0): + eslint-plugin-wc@3.0.1(eslint@9.35.0(jiti@2.5.1)): dependencies: - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) is-valid-element-name: 1.0.0 js-levenshtein-esm: 2.0.0 @@ -7240,11 +7203,6 @@ snapshots: esrecurse: 4.3.0 estraverse: 4.3.0 - eslint-scope@7.2.2: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -7254,46 +7212,45 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@8.57.0: + eslint@9.35.0(jiti@2.5.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.12.1 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.35.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.3.0 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.1 - doctrine: 3.0.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.24.0 - graphemer: 1.4.0 ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 - strip-ansi: 6.0.1 - text-table: 0.2.0 + optionalDependencies: + jiti: 2.5.1 transitivePeerDependencies: - supports-color @@ -7303,12 +7260,6 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.15.0) eslint-visitor-keys: 4.2.1 - espree@9.6.1: - dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) - eslint-visitor-keys: 3.4.3 - esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -7391,14 +7342,16 @@ snapshots: dependencies: flat-cache: 6.1.13 - file-entry-cache@6.0.1: + file-entry-cache@8.0.0: dependencies: - flat-cache: 3.2.0 + flat-cache: 4.0.1 fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 + find-up-simple@1.0.1: {} + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -7409,11 +7362,10 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@3.2.0: + flat-cache@4.0.1: dependencies: flatted: 3.3.3 keyv: 4.5.4 - rimraf: 3.0.2 flat-cache@6.1.13: dependencies: @@ -7450,7 +7402,7 @@ snapshots: get-east-asian-width@1.4.0: {} - get-set-props@0.1.0: {} + get-set-props@0.2.0: {} get-source@2.0.12: dependencies: @@ -7512,8 +7464,12 @@ snapshots: dependencies: type-fest: 0.20.2 + globals@14.0.0: {} + globals@15.15.0: {} + globals@16.4.0: {} + globby@11.1.0: dependencies: array-union: 2.1.0 @@ -7547,8 +7503,6 @@ snapshots: hookified@1.12.0: {} - hosted-git-info@2.8.9: {} - hpagent@1.2.0: {} html-tags@3.3.1: {} @@ -7592,7 +7546,7 @@ snapshots: imurmurhash@0.1.4: {} - indent-string@4.0.0: {} + indent-string@5.0.0: {} inflight@1.0.6: dependencies: @@ -7626,9 +7580,9 @@ snapshots: is-buffer@1.1.6: {} - is-builtin-module@3.2.1: + is-builtin-module@5.0.0: dependencies: - builtin-modules: 3.3.0 + builtin-modules: 5.0.0 is-bun-module@2.0.0: dependencies: @@ -7640,10 +7594,10 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-get-set-prop@1.0.0: + is-get-set-prop@2.0.0: dependencies: - get-set-props: 0.1.0 - lowercase-keys: 1.0.1 + get-set-props: 0.2.0 + lowercase-keys: 3.0.0 is-glob@4.0.3: dependencies: @@ -7651,18 +7605,16 @@ snapshots: is-hexadecimal@2.0.1: {} - is-js-type@2.0.0: + is-js-type@3.0.0: dependencies: - js-types: 1.0.0 + js-types: 4.0.0 is-number@7.0.0: {} - is-obj-prop@1.0.0: + is-obj-prop@2.0.0: dependencies: - lowercase-keys: 1.0.1 - obj-props: 1.4.0 - - is-path-inside@3.0.3: {} + lowercase-keys: 3.0.0 + obj-props: 2.0.0 is-plain-object@2.0.4: dependencies: @@ -7672,10 +7624,10 @@ snapshots: is-potential-custom-element-name@1.0.1: {} - is-proto-prop@2.0.0: + is-proto-prop@3.0.1: dependencies: - lowercase-keys: 1.0.1 - proto-props: 2.0.0 + lowercase-keys: 3.0.0 + prototype-properties: 5.0.0 is-reference@1.2.1: dependencies: @@ -7717,7 +7669,7 @@ snapshots: js-tokens@9.0.1: {} - js-types@1.0.0: {} + js-types@4.0.0: {} js-yaml@4.1.0: dependencies: @@ -7727,7 +7679,7 @@ snapshots: jsep@1.4.0: {} - jsesc@0.5.0: {} + jsesc@3.0.2: {} jsesc@3.1.0: {} @@ -7877,7 +7829,7 @@ snapshots: loupe@3.2.1: {} - lowercase-keys@1.0.1: {} + lowercase-keys@3.0.0: {} lru-cache@10.4.3: {} @@ -8164,8 +8116,6 @@ snapshots: dependencies: mime-db: 1.52.0 - min-indent@1.0.1: {} - mini-css-extract-plugin@2.9.4(webpack@5.101.3): dependencies: schema-utils: 4.3.2 @@ -8254,20 +8204,13 @@ snapshots: nolyfill@1.0.44: {} - normalize-package-data@2.5.0: - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.10 - semver: 5.7.2 - validate-npm-package-license: 3.0.4 - normalize-path@3.0.0: {} nth-check@2.1.1: dependencies: boolbase: 1.0.0 - obj-props@1.4.0: {} + obj-props@2.0.0: {} object-assign@4.1.1: {} @@ -8475,13 +8418,6 @@ snapshots: postcss: 8.5.6 postcss-selector-parser: 6.1.2 - postcss-nesting@13.0.2(postcss@8.5.6): - dependencies: - '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.0) - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) - postcss: 8.5.6 - postcss-selector-parser: 7.1.0 - postcss-resolve-nested-selector@0.1.6: {} postcss-safe-parser@6.0.0(postcss@8.5.6): @@ -8534,7 +8470,7 @@ snapshots: printable-characters@1.0.42: {} - proto-props@2.0.0: {} + prototype-properties@5.0.0: {} punycode.js@2.3.1: {} @@ -8552,19 +8488,6 @@ snapshots: dependencies: pify: 2.3.0 - read-pkg-up@7.0.1: - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - - read-pkg@5.2.0: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -8584,9 +8507,9 @@ snapshots: regexp-tree@0.1.27: {} - regjsparser@0.10.0: + regjsparser@0.12.0: dependencies: - jsesc: 0.5.0 + jsesc: 3.0.2 rename-keys@1.2.0: {} @@ -8614,10 +8537,6 @@ snapshots: reusify@1.1.0: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - robust-predicates@3.0.2: {} rollup@2.79.2: @@ -8690,8 +8609,6 @@ snapshots: refa: 0.12.1 regexp-ast-analysis: 0.7.1 - semver@5.7.2: {} - semver@6.3.1: {} semver@7.7.2: {} @@ -8768,11 +8685,6 @@ snapshots: spdx-expression-parse: 3.0.1 spdx-ranges: 2.1.1 - spdx-correct@3.2.0: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 - spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: @@ -8833,9 +8745,7 @@ snapshots: strip-bom@3.0.0: {} - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 + strip-indent@4.1.0: {} strip-json-comments@3.1.1: {} @@ -9106,11 +9016,16 @@ snapshots: type-fest@0.20.2: {} - type-fest@0.6.0: {} - - type-fest@0.8.1: {} - - type-fest@4.41.0: {} + typescript-eslint@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.43.0(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color typescript@5.9.2: {} @@ -9172,11 +9087,6 @@ snapshots: uuid@11.1.0: {} - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.2.0 - spdx-expression-parse: 3.0.1 - validate-npm-package-name@3.0.0: dependencies: builtins: 1.0.3 @@ -9295,10 +9205,10 @@ snapshots: chart.js: 4.5.0 vue: 3.5.21(typescript@5.9.2) - vue-eslint-parser@10.2.0(eslint@8.57.0): + vue-eslint-parser@10.2.0(eslint@9.35.0(jiti@2.5.1)): dependencies: debug: 4.4.1 - eslint: 8.57.0 + eslint: 9.35.0(jiti@2.5.1) eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 diff --git a/routers/api/actions/runner/runner.go b/routers/api/actions/runner/runner.go index ce8137592d..55ba7862a9 100644 --- a/routers/api/actions/runner/runner.go +++ b/routers/api/actions/runner/runner.go @@ -157,7 +157,7 @@ func (s *Service) FetchTask( if tasksVersion != latestVersion { // if the task version in request is not equal to the version in db, - // it means there may still be some tasks not be assgined. + // it means there may still be some tasks that haven't been assigned. // try to pick a task for the runner that send the request. if t, ok, err := actions_service.PickTask(ctx, runner); err != nil { log.Error("pick task failed: %v", err) diff --git a/routers/init.go b/routers/init.go index 2281260a6f..6cd85728c2 100644 --- a/routers/init.go +++ b/routers/init.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/eventsource" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" @@ -114,7 +115,7 @@ func InitWebInstallPage(ctx context.Context) { // InitWebInstalled is for the global configuration of an installed instance func InitWebInstalled(ctx context.Context) { mustInit(git.InitFull) - log.Info("Git version: %s (home: %s)", git.DefaultFeatures().VersionInfo(), git.HomeDir()) + log.Info("Git version: %s (home: %s)", git.DefaultFeatures().VersionInfo(), gitcmd.HomeDir()) if !git.DefaultFeatures().SupportHashSha256 { log.Warn("sha256 hash support is disabled - requires Git >= 2.42." + util.Iif(git.DefaultFeatures().UsingGogit, " Gogit is currently unsupported.", "")) } diff --git a/routers/private/hook_pre_receive.go b/routers/private/hook_pre_receive.go index dd9d0bc15e..99a0b450d7 100644 --- a/routers/private/hook_pre_receive.go +++ b/routers/private/hook_pre_receive.go @@ -17,6 +17,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" @@ -188,7 +189,7 @@ func preReceiveBranch(ctx *preReceiveContext, oldCommitID, newCommitID string, r // 2. Disallow force pushes to protected branches if oldCommitID != objectFormat.EmptyObjectID().String() { - output, _, err := git.NewCommand("rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath(), Env: ctx.env}) + output, _, err := gitcmd.NewCommand("rev-list", "--max-count=1").AddDynamicArguments(oldCommitID, "^"+newCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath(), Env: ctx.env}) if err != nil { log.Error("Unable to detect force push between: %s and %s in %-v Error: %v", oldCommitID, newCommitID, repo, err) ctx.JSON(http.StatusInternalServerError, private.Response{ diff --git a/routers/private/hook_verification.go b/routers/private/hook_verification.go index 57d0964ead..a69c3b04eb 100644 --- a/routers/private/hook_verification.go +++ b/routers/private/hook_verification.go @@ -10,6 +10,7 @@ import ( "os" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" asymkey_service "code.gitea.io/gitea/services/asymkey" ) @@ -27,18 +28,18 @@ func verifyCommits(oldCommitID, newCommitID string, repo *git.Repository, env [] _ = stdoutWriter.Close() }() - var command *git.Command + var command *gitcmd.Command objectFormat, _ := repo.GetObjectFormat() if oldCommitID == objectFormat.EmptyObjectID().String() { // When creating a new branch, the oldCommitID is empty, by using "newCommitID --not --all": // List commits that are reachable by following the newCommitID, exclude "all" existing heads/tags commits // So, it only lists the new commits received, doesn't list the commits already present in the receiving repository - command = git.NewCommand("rev-list").AddDynamicArguments(newCommitID).AddArguments("--not", "--all") + command = gitcmd.NewCommand("rev-list").AddDynamicArguments(newCommitID).AddArguments("--not", "--all") } else { - command = git.NewCommand("rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID) + command = gitcmd.NewCommand("rev-list").AddDynamicArguments(oldCommitID + "..." + newCommitID) } // This is safe as force pushes are already forbidden - err = command.Run(repo.Ctx, &git.RunOpts{ + err = command.Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdout: stdoutWriter, @@ -84,8 +85,8 @@ func readAndVerifyCommit(sha string, repo *git.Repository, env []string) error { commitID := git.MustIDFromString(sha) - return git.NewCommand("cat-file", "commit").AddDynamicArguments(sha). - Run(repo.Ctx, &git.RunOpts{ + return gitcmd.NewCommand("cat-file", "commit").AddDynamicArguments(sha). + Run(repo.Ctx, &gitcmd.RunOpts{ Env: env, Dir: repo.Path, Stdout: stdoutWriter, diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index a7084bf0ae..2e56f6934a 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -28,6 +28,7 @@ import ( csv_module "code.gitea.io/gitea/modules/csv" "code.gitea.io/gitea/modules/fileicon" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup" @@ -569,7 +570,7 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo { func PrepareCompareDiff( ctx *context.Context, ci *common.CompareInfo, - whitespaceBehavior git.TrustedCmdArgs, + whitespaceBehavior gitcmd.TrustedCmdArgs, ) (nothingToCompare bool) { repo := ctx.Repo.Repository headCommitID := ci.CompareInfo.HeadCommitID diff --git a/routers/web/repo/githttp.go b/routers/web/repo/githttp.go index deb3ae4f3a..ab649b6f15 100644 --- a/routers/web/repo/githttp.go +++ b/routers/web/repo/githttp.go @@ -26,6 +26,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -315,7 +316,7 @@ func dummyInfoRefs(ctx *context.Context) { return } - refs, _, err := git.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &git.RunOpts{Dir: tmpDir}) + refs, _, err := gitcmd.NewCommand("receive-pack", "--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &gitcmd.RunOpts{Dir: tmpDir}) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } @@ -393,12 +394,12 @@ func (h *serviceHandler) sendFile(ctx *context.Context, contentType, file string // one or more key=value pairs separated by colons var safeGitProtocolHeader = regexp.MustCompile(`^[0-9a-zA-Z]+=[0-9a-zA-Z]+(:[0-9a-zA-Z]+=[0-9a-zA-Z]+)*$`) -func prepareGitCmdWithAllowedService(service string) (*git.Command, error) { +func prepareGitCmdWithAllowedService(service string) (*gitcmd.Command, error) { if service == "receive-pack" { - return git.NewCommand("receive-pack"), nil + return gitcmd.NewCommand("receive-pack"), nil } if service == "upload-pack" { - return git.NewCommand("upload-pack"), nil + return gitcmd.NewCommand("upload-pack"), nil } return nil, fmt.Errorf("service %q is not allowed", service) @@ -448,7 +449,7 @@ func serviceRPC(ctx *context.Context, h *serviceHandler, service string) { var stderr bytes.Buffer cmd.AddArguments("--stateless-rpc").AddDynamicArguments(h.getRepoDir()) - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: h.getRepoDir(), Env: append(os.Environ(), h.environ...), Stdout: ctx.Resp, @@ -488,7 +489,7 @@ func getServiceType(ctx *context.Context) string { } func updateServerInfo(ctx gocontext.Context, dir string) []byte { - out, _, err := git.NewCommand("update-server-info").RunStdBytes(ctx, &git.RunOpts{Dir: dir}) + out, _, err := gitcmd.NewCommand("update-server-info").RunStdBytes(ctx, &gitcmd.RunOpts{Dir: dir}) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(out))) } @@ -518,7 +519,7 @@ func GetInfoRefs(ctx *context.Context) { } h.environ = append(os.Environ(), h.environ...) - refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &git.RunOpts{Env: h.environ, Dir: h.getRepoDir()}) + refs, _, err := cmd.AddArguments("--stateless-rpc", "--advertise-refs", ".").RunStdBytes(ctx, &gitcmd.RunOpts{Env: h.environ, Dir: h.getRepoDir()}) if err != nil { log.Error(fmt.Sprintf("%v - %s", err, string(refs))) } diff --git a/routers/web/repo/issue_view.go b/routers/web/repo/issue_view.go index d0064e763e..d9f6c33e3f 100644 --- a/routers/web/repo/issue_view.go +++ b/routers/web/repo/issue_view.go @@ -12,6 +12,7 @@ import ( "strconv" activities_model "code.gitea.io/gitea/models/activities" + asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" @@ -494,7 +495,7 @@ func preparePullViewSigning(ctx *context.Context, issue *issues_model.Issue) { if ctx.Doer != nil { sign, key, _, err := asymkey_service.SignMerge(ctx, pull, ctx.Doer, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitHeadRefName()) ctx.Data["WillSign"] = sign - ctx.Data["SigningKey"] = key + ctx.Data["SigningKeyMergeDisplay"] = asymkey_model.GetDisplaySigningKey(key) if err != nil { if asymkey_service.IsErrWontSign(err) { ctx.Data["WontSignReason"] = err.(*asymkey_service.ErrWontSign).Reason diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 83aaf75363..c9ea836899 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -26,7 +26,9 @@ import ( "code.gitea.io/gitea/modules/emoji" "code.gitea.io/gitea/modules/fileicon" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" issue_template "code.gitea.io/gitea/modules/issue/template" "code.gitea.io/gitea/modules/log" @@ -46,8 +48,6 @@ import ( pull_service "code.gitea.io/gitea/services/pull" repo_service "code.gitea.io/gitea/services/repository" user_service "code.gitea.io/gitea/services/user" - - "github.com/gobwas/glob" ) const ( @@ -234,7 +234,7 @@ func GetMergedBaseCommitID(ctx *context.Context, issue *issues_model.Issue) stri } if commitSHA != "" { // Get immediate parent of the first commit in the patch, grab history back - parentCommit, _, err = git.NewCommand("rev-list", "-1", "--skip=1").AddDynamicArguments(commitSHA).RunStdString(ctx, &git.RunOpts{Dir: ctx.Repo.GitRepo.Path}) + parentCommit, _, err = gitcmd.NewCommand("rev-list", "-1", "--skip=1").AddDynamicArguments(commitSHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: ctx.Repo.GitRepo.Path}) if err == nil { parentCommit = strings.TrimSpace(parentCommit) } diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index 0eea5e3f34..152f67550c 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -19,6 +19,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/routers/web/repo" @@ -26,8 +27,6 @@ import ( "code.gitea.io/gitea/services/forms" pull_service "code.gitea.io/gitea/services/pull" "code.gitea.io/gitea/services/repository" - - "github.com/gobwas/glob" ) const ( diff --git a/routers/web/user/package.go b/routers/web/user/package.go index d130d1dca1..924a10041b 100644 --- a/routers/web/user/package.go +++ b/routers/web/user/package.go @@ -431,74 +431,81 @@ func PackageSettings(ctx *context.Context) { ctx.Data["Title"] = pd.Package.Name ctx.Data["IsPackagesPage"] = true ctx.Data["PackageDescriptor"] = pd - - repos, _, _ := repo_model.GetUserRepositories(ctx, repo_model.SearchRepoOptions{ - Actor: pd.Owner, - Private: true, - }) - ctx.Data["Repos"] = repos ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin() + if pd.Package.RepoID > 0 { + repo, err := repo_model.GetRepositoryByID(ctx, pd.Package.RepoID) + if err != nil { + ctx.ServerError("GetRepositoryByID", err) + return + } + ctx.Data["LinkedRepoName"] = repo.Name + } + ctx.HTML(http.StatusOK, tplPackagesSettings) } // PackageSettingsPost updates the package settings func PackageSettingsPost(ctx *context.Context) { - pd := ctx.Package.Descriptor - form := web.GetForm(ctx).(*forms.PackageSettingForm) switch form.Action { case "link": - success := func() bool { - repoID := int64(0) - if form.RepoID != 0 { - repo, err := repo_model.GetRepositoryByID(ctx, form.RepoID) - if err != nil { - log.Error("Error getting repository: %v", err) - return false - } - - if repo.OwnerID != pd.Owner.ID { - return false - } - - repoID = repo.ID - } - - if err := packages_model.SetRepositoryLink(ctx, pd.Package.ID, repoID); err != nil { - log.Error("Error updating package: %v", err) - return false - } - - return true - }() - - if success { - ctx.Flash.Success(ctx.Tr("packages.settings.link.success")) - } else { - ctx.Flash.Error(ctx.Tr("packages.settings.link.error")) - } - - ctx.Redirect(ctx.Link) - return + packageSettingsPostActionLink(ctx, form) case "delete": - err := packages_service.RemovePackageVersion(ctx, ctx.Doer, ctx.Package.Descriptor.Version) - if err != nil { - log.Error("Error deleting package: %v", err) - ctx.Flash.Error(ctx.Tr("packages.settings.delete.error")) - } else { - ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) + packageSettingsPostActionDelete(ctx) + default: + ctx.NotFound(nil) + } +} + +func packageSettingsPostActionLink(ctx *context.Context, form *forms.PackageSettingForm) { + pd := ctx.Package.Descriptor + if form.RepoName == "" { // remove the link + if err := packages_model.SetRepositoryLink(ctx, pd.Package.ID, 0); err != nil { + ctx.JSONError(ctx.Tr("packages.settings.unlink.error")) + return } - redirectURL := ctx.Package.Owner.HomeLink() + "/-/packages" - // redirect to the package if there are still versions available - if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID, IsInternal: optional.Some(false)}); has { - redirectURL = ctx.Package.Descriptor.PackageWebLink() - } - - ctx.Redirect(redirectURL) + ctx.Flash.Success(ctx.Tr("packages.settings.unlink.success")) + ctx.JSONRedirect("") return } + + repo, err := repo_model.GetRepositoryByName(ctx, pd.Owner.ID, form.RepoName) + if err != nil { + if repo_model.IsErrRepoNotExist(err) { + ctx.JSONError(ctx.Tr("packages.settings.link.repo_not_found", form.RepoName)) + } else { + ctx.ServerError("GetRepositoryByOwnerAndName", err) + } + return + } + + if err := packages_model.SetRepositoryLink(ctx, pd.Package.ID, repo.ID); err != nil { + ctx.JSONError(ctx.Tr("packages.settings.link.error")) + return + } + + ctx.Flash.Success(ctx.Tr("packages.settings.link.success")) + ctx.JSONRedirect("") +} + +func packageSettingsPostActionDelete(ctx *context.Context) { + err := packages_service.RemovePackageVersion(ctx, ctx.Doer, ctx.Package.Descriptor.Version) + if err != nil { + log.Error("Error deleting package: %v", err) + ctx.Flash.Error(ctx.Tr("packages.settings.delete.error")) + } else { + ctx.Flash.Success(ctx.Tr("packages.settings.delete.success")) + } + + redirectURL := ctx.Package.Owner.HomeLink() + "/-/packages" + // redirect to the package if there are still versions available + if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID, IsInternal: optional.Some(false)}); has { + redirectURL = ctx.Package.Descriptor.PackageWebLink() + } + + ctx.Redirect(redirectURL) } // DownloadPackageFile serves the content of a package file diff --git a/services/actions/notifier_helper.go b/services/actions/notifier_helper.go index b8bc20cdbb..66916e9301 100644 --- a/services/actions/notifier_helper.go +++ b/services/actions/notifier_helper.go @@ -281,7 +281,7 @@ func skipWorkflows(ctx context.Context, input *notifyInput, commit *git.Commit) return true } } - // skip workflow runs events exceeding the maxiumum of 5 recursive events + // skip workflow runs events exceeding the maximum of 5 recursive events log.Debug("repo %s: skipped workflow_run because of recursive event of 5", input.Repo.RepoPath()) return true } diff --git a/services/agit/agit.go b/services/agit/agit.go index 9d2d122cfb..4ed867b358 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -15,6 +15,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" @@ -198,9 +199,9 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. } if !forcePush.Value() { - output, _, err := git.NewCommand("rev-list", "--max-count=1"). + output, _, err := gitcmd.NewCommand("rev-list", "--max-count=1"). AddDynamicArguments(oldCommitID, "^"+opts.NewCommitIDs[i]). - RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath(), Env: os.Environ()}) if err != nil { return nil, fmt.Errorf("failed to detect force push: %w", err) } else if len(output) > 0 { diff --git a/services/asymkey/sign.go b/services/asymkey/sign.go index 8fd2adc8b4..4fde342bea 100644 --- a/services/asymkey/sign.go +++ b/services/asymkey/sign.go @@ -17,6 +17,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" @@ -116,16 +117,16 @@ func SigningKey(ctx context.Context, repoPath string) (*git.SigningKey, *git.Sig if setting.Repository.Signing.SigningKey == "default" || setting.Repository.Signing.SigningKey == "" { // Can ignore the error here as it means that commit.gpgsign is not set - value, _, _ := git.NewCommand("config", "--get", "commit.gpgsign").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + value, _, _ := gitcmd.NewCommand("config", "--get", "commit.gpgsign").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) sign, valid := git.ParseBool(strings.TrimSpace(value)) if !sign || !valid { return nil, nil } - format, _, _ := git.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - signingKey, _, _ := git.NewCommand("config", "--get", "user.signingkey").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - signingName, _, _ := git.NewCommand("config", "--get", "user.name").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) - signingEmail, _, _ := git.NewCommand("config", "--get", "user.email").RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + format, _, _ := gitcmd.NewCommand("config", "--default", git.SigningKeyFormatOpenPGP, "--get", "gpg.format").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) + signingKey, _, _ := gitcmd.NewCommand("config", "--get", "user.signingkey").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) + signingName, _, _ := gitcmd.NewCommand("config", "--get", "user.name").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) + signingEmail, _, _ := gitcmd.NewCommand("config", "--get", "user.email").RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if strings.TrimSpace(signingKey) == "" { return nil, nil diff --git a/services/context/csrf.go b/services/context/csrf.go index 7b475a8fd8..f190465bdb 100644 --- a/services/context/csrf.go +++ b/services/context/csrf.go @@ -48,7 +48,7 @@ type csrfProtector struct { opt CsrfOptions // id must be unique per user. id string - // token is the valid one which wil be used by end user and passed via header, cookie, or hidden form value. + // token is the valid one which will be used by end user and passed via header, cookie, or hidden form value. token string } diff --git a/services/context/repo.go b/services/context/repo.go index afc6de9b16..04ddba70fe 100644 --- a/services/context/repo.go +++ b/services/context/repo.go @@ -14,6 +14,7 @@ import ( "path" "strings" + asymkey_model "code.gitea.io/gitea/models/asymkey" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" @@ -99,7 +100,7 @@ type CommitFormOptions struct { UserCanPush bool RequireSigned bool WillSign bool - SigningKey *git.SigningKey + SigningKeyFormDisplay string WontSignReason string CanCreatePullRequest bool CanCreateBasePullRequest bool @@ -139,7 +140,7 @@ func PrepareCommitFormOptions(ctx *Context, doer *user_model.User, targetRepo *r protectionRequireSigned = protectedBranch.RequireSignedCommits } - willSign, signKeyID, _, err := asymkey_service.SignCRUDAction(ctx, targetRepo.RepoPath(), doer, targetRepo.RepoPath(), refName.String()) + willSign, signKey, _, err := asymkey_service.SignCRUDAction(ctx, targetRepo.RepoPath(), doer, targetRepo.RepoPath(), refName.String()) wontSignReason := "" if asymkey_service.IsErrWontSign(err) { wontSignReason = string(err.(*asymkey_service.ErrWontSign).Reason) @@ -156,14 +157,14 @@ func PrepareCommitFormOptions(ctx *Context, doer *user_model.User, targetRepo *r canCreatePullRequest := targetRepo.UnitEnabled(ctx, unit_model.TypePullRequests) || canCreateBasePullRequest opts := &CommitFormOptions{ - TargetRepo: targetRepo, - WillSubmitToFork: submitToForkedRepo, - CanCommitToBranch: canCommitToBranch, - UserCanPush: canPushWithProtection, - RequireSigned: protectionRequireSigned, - WillSign: willSign, - SigningKey: signKeyID, - WontSignReason: wontSignReason, + TargetRepo: targetRepo, + WillSubmitToFork: submitToForkedRepo, + CanCommitToBranch: canCommitToBranch, + UserCanPush: canPushWithProtection, + RequireSigned: protectionRequireSigned, + WillSign: willSign, + SigningKeyFormDisplay: asymkey_model.GetDisplaySigningKey(signKey), + WontSignReason: wontSignReason, CanCreatePullRequest: canCreatePullRequest, CanCreateBasePullRequest: canCreateBasePullRequest, diff --git a/services/convert/issue.go b/services/convert/issue.go index ecb3b93af1..e26412bcca 100644 --- a/services/convert/issue.go +++ b/services/convert/issue.go @@ -59,6 +59,8 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss Created: issue.CreatedUnix.AsTime(), Updated: issue.UpdatedUnix.AsTime(), PinOrder: util.Iif(issue.PinOrder == -1, 0, issue.PinOrder), // -1 means loaded with no pin order + + TimeEstimate: issue.TimeEstimate, } if issue.Repo != nil { diff --git a/services/cron/tasks_basic.go b/services/cron/tasks_basic.go index 841981787d..48380b7b9a 100644 --- a/services/cron/tasks_basic.go +++ b/services/cron/tasks_basic.go @@ -11,7 +11,7 @@ import ( git_model "code.gitea.io/gitea/models/git" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/services/auth" "code.gitea.io/gitea/services/migrations" @@ -59,7 +59,7 @@ func registerRepoHealthCheck() { }, func(ctx context.Context, _ *user_model.User, config Config) error { rhcConfig := config.(*RepoHealthCheckConfig) // the git args are set by config, they can be safe to be trusted - return repo_service.GitFsckRepos(ctx, rhcConfig.Timeout, git.ToTrustedCmdArgs(rhcConfig.Args)) + return repo_service.GitFsckRepos(ctx, rhcConfig.Timeout, gitcmd.ToTrustedCmdArgs(rhcConfig.Args)) }) } diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index 3747111984..74fb12430d 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -10,7 +10,7 @@ import ( activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" issue_indexer "code.gitea.io/gitea/modules/indexer/issues" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/updatechecker" @@ -61,7 +61,7 @@ func registerGarbageCollectRepositories() { }, func(ctx context.Context, _ *user_model.User, config Config) error { rhcConfig := config.(*RepoHealthCheckConfig) // the git args are set by config, they can be safe to be trusted - return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, git.ToTrustedCmdArgs(rhcConfig.Args)) + return repo_service.GitGcRepos(ctx, rhcConfig.Timeout, gitcmd.ToTrustedCmdArgs(rhcConfig.Args)) }) } diff --git a/services/doctor/heads.go b/services/doctor/heads.go index bbfd40da5e..4354505806 100644 --- a/services/doctor/heads.go +++ b/services/doctor/heads.go @@ -8,6 +8,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -18,9 +19,9 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool) numReposUpdated := 0 err := iterateRepositories(ctx, func(repo *repo_model.Repository) error { numRepos++ - _, _, defaultBranchErr := git.NewCommand("rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + _, _, defaultBranchErr := gitcmd.NewCommand("rev-parse").AddDashesAndList(repo.DefaultBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) - head, _, headErr := git.NewCommand("symbolic-ref", "--short", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + head, _, headErr := gitcmd.NewCommand("symbolic-ref", "--short", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) // what we expect: default branch is valid, and HEAD points to it if headErr == nil && defaultBranchErr == nil && head == repo.DefaultBranch { @@ -46,7 +47,7 @@ func synchronizeRepoHeads(ctx context.Context, logger log.Logger, autofix bool) } // otherwise, let's try fixing HEAD - err := git.NewCommand("symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + err := gitcmd.NewCommand("symbolic-ref").AddDashesAndList("HEAD", git.BranchPrefix+repo.DefaultBranch).Run(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { logger.Warn("Failed to fix HEAD for %s/%s: %v", repo.OwnerName, repo.Name, err) return nil diff --git a/services/doctor/mergebase.go b/services/doctor/mergebase.go index cbd8aa59fd..a078d54dad 100644 --- a/services/doctor/mergebase.go +++ b/services/doctor/mergebase.go @@ -12,6 +12,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "xorm.io/builder" @@ -42,17 +43,17 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro if !pr.HasMerged { var err error - pr.MergeBase, _, err = git.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, pr.GetGitHeadRefName()).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err = gitcmd.NewCommand("merge-base").AddDashesAndList(pr.BaseBranch, pr.GetGitHeadRefName()).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { var err2 error - pr.MergeBase, _, err2 = git.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + pr.MergeBase, _, err2 = gitcmd.NewCommand("rev-parse").AddDynamicArguments(git.BranchPrefix+pr.BaseBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err2 != nil { logger.Warn("Unable to get merge base for PR ID %d, #%d onto %s in %s/%s. Error: %v & %v", pr.ID, pr.Index, pr.BaseBranch, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, err, err2) return nil } } } else { - parentsString, _, err := git.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + parentsString, _, err := gitcmd.NewCommand("rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { logger.Warn("Unable to get parents for merged PR ID %d, #%d onto %s in %s/%s. Error: %v", pr.ID, pr.Index, pr.BaseBranch, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, err) return nil @@ -64,8 +65,8 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro refs := append([]string{}, parents[1:]...) refs = append(refs, pr.GetGitHeadRefName()) - cmd := git.NewCommand("merge-base").AddDashesAndList(refs...) - pr.MergeBase, _, err = cmd.RunStdString(ctx, &git.RunOpts{Dir: repoPath}) + cmd := gitcmd.NewCommand("merge-base").AddDashesAndList(refs...) + pr.MergeBase, _, err = cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}) if err != nil { logger.Warn("Unable to get merge base for merged PR ID %d, #%d onto %s in %s/%s. Error: %v", pr.ID, pr.Index, pr.BaseBranch, pr.BaseRepo.OwnerName, pr.BaseRepo.Name, err) return nil diff --git a/services/forms/user_form.go b/services/forms/user_form.go index ddf2bd09b0..618294d434 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -416,8 +416,8 @@ func (f *WebauthnDeleteForm) Validate(req *http.Request, errs binding.Errors) bi // PackageSettingForm form for package settings type PackageSettingForm struct { - Action string - RepoID int64 `form:"repo_id"` + Action string + RepoName string `form:"repo_name"` } // Validate validates the fields diff --git a/services/forms/user_form_test.go b/services/forms/user_form_test.go index 09e9ec0f65..4246f955b3 100644 --- a/services/forms/user_form_test.go +++ b/services/forms/user_form_test.go @@ -6,10 +6,10 @@ package forms import ( "testing" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/test" - "github.com/gobwas/glob" "github.com/stretchr/testify/assert" ) diff --git a/services/gitdiff/git_diff_tree.go b/services/gitdiff/git_diff_tree.go index ed94bfbfe4..eeb354c1b6 100644 --- a/services/gitdiff/git_diff_tree.go +++ b/services/gitdiff/git_diff_tree.go @@ -13,6 +13,7 @@ import ( "strings" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -55,12 +56,12 @@ func runGitDiffTree(ctx context.Context, gitRepo *git.Repository, useMergeBase b return nil, err } - cmd := git.NewCommand("diff-tree", "--raw", "-r", "--find-renames", "--root") + cmd := gitcmd.NewCommand("diff-tree", "--raw", "-r", "--find-renames", "--root") if useMergeBase { cmd.AddArguments("--merge-base") } cmd.AddDynamicArguments(baseCommitID, headCommitID) - stdout, _, runErr := cmd.RunStdString(ctx, &git.RunOpts{Dir: gitRepo.Path}) + stdout, _, runErr := cmd.RunStdString(ctx, &gitcmd.RunOpts{Dir: gitRepo.Path}) if runErr != nil { log.Warn("git diff-tree: %v", runErr) return nil, runErr diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index 7c99e049d5..1bb7c05ba2 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -26,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/charset" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git/attribute" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/highlight" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" @@ -1090,7 +1091,7 @@ type DiffOptions struct { MaxLines int MaxLineCharacters int MaxFiles int - WhitespaceBehavior git.TrustedCmdArgs + WhitespaceBehavior gitcmd.TrustedCmdArgs DirectComparison bool } @@ -1131,7 +1132,7 @@ func getDiffBasic(ctx context.Context, gitRepo *git.Repository, opts *DiffOption return nil, nil, nil, err } - cmdDiff := git.NewCommand(). + cmdDiff := gitcmd.NewCommand(). AddArguments("diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"). AddArguments(opts.WhitespaceBehavior...) @@ -1158,7 +1159,7 @@ func getDiffBasic(ctx context.Context, gitRepo *git.Repository, opts *DiffOption go func() { stderr := &bytes.Buffer{} - if err := cmdDiff.Run(cmdCtx, &git.RunOpts{ + if err := cmdDiff.Run(cmdCtx, &gitcmd.RunOpts{ Timeout: time.Duration(setting.Git.Timeout.Default) * time.Second, Dir: repoPath, Stdout: writer, @@ -1395,8 +1396,8 @@ func CommentMustAsDiff(ctx context.Context, c *issues_model.Comment) *Diff { } // GetWhitespaceFlag returns git diff flag for treating whitespaces -func GetWhitespaceFlag(whitespaceBehavior string) git.TrustedCmdArgs { - whitespaceFlags := map[string]git.TrustedCmdArgs{ +func GetWhitespaceFlag(whitespaceBehavior string) gitcmd.TrustedCmdArgs { + whitespaceFlags := map[string]gitcmd.TrustedCmdArgs{ "ignore-all": {"-w"}, "ignore-change": {"-b"}, "ignore-eol": {"--ignore-space-at-eol"}, diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index 83815caeb5..7b64b6b5f8 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/setting" @@ -602,7 +603,7 @@ func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) { require.NoError(t, err) defer gitRepo.Close() - for _, behavior := range []git.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} { + for _, behavior := range []gitcmd.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} { diffs, err := GetDiffForAPI(t.Context(), gitRepo, &DiffOptions{ AfterCommitID: "d8e0bbb45f200e67d9a784ce55bd90821af45ebd", diff --git a/services/migrations/dump.go b/services/migrations/dump.go index 8edd567b08..385759800e 100644 --- a/services/migrations/dump.go +++ b/services/migrations/dump.go @@ -18,6 +18,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" base "code.gitea.io/gitea/modules/migration" "code.gitea.io/gitea/modules/repository" @@ -488,7 +489,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR if pr.Head.CloneURL == "" || pr.Head.Ref == "" { // Set head information if pr.Head.SHA is available if pr.Head.SHA != "" { - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("PR #%d in %s/%s unable to update-ref for pr HEAD: %v", pr.Number, g.repoOwner, g.repoName, err) } @@ -518,7 +519,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR if !ok { // Set head information if pr.Head.SHA is available if pr.Head.SHA != "" { - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("PR #%d in %s/%s unable to update-ref for pr HEAD: %v", pr.Number, g.repoOwner, g.repoName, err) } @@ -553,7 +554,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR fetchArg = git.BranchPrefix + fetchArg } - _, _, err = git.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("Fetch branch from %s failed: %v", pr.Head.CloneURL, err) // We need to continue here so that the Head.Ref is reset and we attempt to set the gitref for the PR @@ -577,7 +578,7 @@ func (g *RepositoryDumper) handlePullRequest(ctx context.Context, pr *base.PullR pr.Head.SHA = headSha } if pr.Head.SHA != "" { - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.gitPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.gitPath()}) if err != nil { log.Error("unable to set %s as the local head for PR #%d from %s in %s/%s. Error: %v", pr.Head.SHA, pr.Number, pr.Head.Ref, g.repoOwner, g.repoName, err) } diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 75eb06d01f..512468a832 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -20,6 +20,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/label" "code.gitea.io/gitea/modules/log" @@ -662,7 +663,7 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(ctx context.Context, pr *ba fetchArg = git.BranchPrefix + fetchArg } - _, _, err = git.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("fetch", "--no-tags").AddDashesAndList(remote, fetchArg).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { log.Error("Fetch branch from %s failed: %v", pr.Head.CloneURL, err) return head, nil @@ -681,7 +682,7 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(ctx context.Context, pr *ba pr.Head.SHA = headSha } - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { return "", err } @@ -698,13 +699,13 @@ func (g *GiteaLocalUploader) updateGitForPullRequest(ctx context.Context, pr *ba // The SHA is empty log.Warn("Empty reference, no pull head for PR #%d in %s/%s", pr.Number, g.repoOwner, g.repoName) } else { - _, _, err = git.NewCommand("rev-list", "--quiet", "-1").AddDynamicArguments(pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("rev-list", "--quiet", "-1").AddDynamicArguments(pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { // Git update-ref remove bad references with a relative path log.Warn("Deprecated local head %s for PR #%d in %s/%s, removing %s", pr.Head.SHA, pr.Number, g.repoOwner, g.repoName, pr.GetGitHeadRefName()) } else { // set head information - _, _, err = git.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &git.RunOpts{Dir: g.repo.RepoPath()}) + _, _, err = gitcmd.NewCommand("update-ref", "--no-deref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.Head.SHA).RunStdString(ctx, &gitcmd.RunOpts{Dir: g.repo.RepoPath()}) if err != nil { log.Error("unable to set %s as the local head for PR #%d from %s in %s/%s. Error: %v", pr.Head.SHA, pr.Number, pr.Head.Ref, g.repoOwner, g.repoName, err) } diff --git a/services/migrations/gitea_uploader_test.go b/services/migrations/gitea_uploader_test.go index 4856b66c6e..08efef5de6 100644 --- a/services/migrations/gitea_uploader_test.go +++ b/services/migrations/gitea_uploader_test.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -238,7 +239,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { baseRef := "master" // this is very different from the real situation. It should be a bare repository for all the Gitea managed repositories assert.NoError(t, git.InitRepository(t.Context(), fromRepo.RepoPath(), false, fromRepo.ObjectFormatName)) - err := git.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(t.Context(), &git.RunOpts{Dir: fromRepo.RepoPath()}) + err := gitcmd.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseRef).Run(t.Context(), &gitcmd.RunOpts{Dir: fromRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte("# Testing Repository\n\nOriginally created in: "+fromRepo.RepoPath()), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), fromRepo.RepoPath(), true)) @@ -262,7 +263,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { // fromRepo branch1 // headRef := "branch1" - _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(headRef).RunStdString(t.Context(), &git.RunOpts{Dir: fromRepo.RepoPath()}) + _, _, err = gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(headRef).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: fromRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(fromRepo.RepoPath(), "README.md"), []byte("SOMETHING"), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), fromRepo.RepoPath(), true)) @@ -286,7 +287,7 @@ func TestGiteaUploadUpdateGitForPullRequest(t *testing.T) { assert.NoError(t, git.Clone(t.Context(), fromRepo.RepoPath(), forkRepo.RepoPath(), git.CloneRepoOptions{ Branch: headRef, })) - _, _, err = git.NewCommand("checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(t.Context(), &git.RunOpts{Dir: forkRepo.RepoPath()}) + _, _, err = gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(forkHeadRef).RunStdString(t.Context(), &gitcmd.RunOpts{Dir: forkRepo.RepoPath()}) assert.NoError(t, err) assert.NoError(t, os.WriteFile(filepath.Join(forkRepo.RepoPath(), "README.md"), []byte("# branch2 "+forkRepo.RepoPath()), 0o644)) assert.NoError(t, git.AddChanges(t.Context(), forkRepo.RepoPath(), true)) diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index b9000f2703..6a87aa8a27 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -13,6 +13,7 @@ import ( system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" giturl "code.gitea.io/gitea/modules/git/url" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" @@ -255,7 +256,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo log.Trace("SyncMirrors [repo: %-v]: running git remote update...", m.Repo) // use fetch but not remote update because git fetch support --tags but remote update doesn't - cmd := git.NewCommand("fetch") + cmd := gitcmd.NewCommand("fetch") if m.EnablePrune { cmd.AddArguments("--prune") } @@ -271,7 +272,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo stdoutBuilder := strings.Builder{} stderrBuilder := strings.Builder{} - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath, Env: envs, @@ -296,7 +297,7 @@ func runSync(ctx context.Context, m *repo_model.Mirror) ([]*mirrorSyncResult, bo // Successful prune - reattempt mirror stderrBuilder.Reset() stdoutBuilder.Reset() - if err = cmd.Run(ctx, &git.RunOpts{ + if err = cmd.Run(ctx, &gitcmd.RunOpts{ Timeout: timeout, Dir: repoPath, Stdout: &stdoutBuilder, diff --git a/services/pull/check.go b/services/pull/check.go index 7fcec22f49..c2ee49b6bb 100644 --- a/services/pull/check.go +++ b/services/pull/check.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/graceful" @@ -280,9 +281,9 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com prHeadRef := pr.GetGitHeadRefName() // Check if the pull request is merged into BaseBranch - if _, _, err := git.NewCommand("merge-base", "--is-ancestor"). + if _, _, err := gitcmd.NewCommand("merge-base", "--is-ancestor"). AddDynamicArguments(prHeadRef, pr.BaseBranch). - RunStdString(ctx, &git.RunOpts{Dir: pr.BaseRepo.RepoPath()}); err != nil { + RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}); err != nil { if strings.Contains(err.Error(), "exit status 1") { // prHeadRef is not an ancestor of the base branch return nil, nil @@ -308,9 +309,9 @@ func getMergeCommit(ctx context.Context, pr *issues_model.PullRequest) (*git.Com objectFormat := git.ObjectFormatFromName(pr.BaseRepo.ObjectFormatName) // Get the commit from BaseBranch where the pull request got merged - mergeCommit, _, err := git.NewCommand("rev-list", "--ancestry-path", "--merges", "--reverse"). + mergeCommit, _, err := gitcmd.NewCommand("rev-list", "--ancestry-path", "--merges", "--reverse"). AddDynamicArguments(prHeadCommitID+".."+pr.BaseBranch). - RunStdString(ctx, &git.RunOpts{Dir: pr.BaseRepo.RepoPath()}) + RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}) if err != nil { return nil, fmt.Errorf("git rev-list --ancestry-path --merges --reverse: %w", err) } else if len(mergeCommit) < objectFormat.FullLength() { diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go index d15d318149..e7c14a5e7a 100644 --- a/services/pull/commit_status.go +++ b/services/pull/commit_status.go @@ -12,9 +12,9 @@ import ( issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/commitstatus" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" - "github.com/gobwas/glob" "github.com/pkg/errors" ) diff --git a/services/pull/merge.go b/services/pull/merge.go index a941c20435..4d6afb8d33 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -26,6 +26,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/httplib" "code.gitea.io/gitea/modules/log" @@ -400,7 +401,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use ) mergeCtx.env = append(mergeCtx.env, repo_module.EnvPushTrigger+"="+string(pushTrigger)) - pushCmd := git.NewCommand("push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch) + pushCmd := gitcmd.NewCommand("push", "origin").AddDynamicArguments(baseBranch + ":" + git.BranchPrefix + pr.BaseBranch) // Push back to upstream. // This cause an api call to "/api/internal/hook/post-receive/...", @@ -430,7 +431,7 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use } func commitAndSignNoAuthor(ctx *mergeContext, message string) error { - cmdCommit := git.NewCommand("commit").AddOptionFormat("--message=%s", message) + cmdCommit := gitcmd.NewCommand("commit").AddOptionFormat("--message=%s", message) if ctx.signKey == nil { cmdCommit.AddArguments("--no-gpg-sign") } else { @@ -499,7 +500,7 @@ func (err ErrMergeDivergingFastForwardOnly) Error() string { return fmt.Sprintf("Merge DivergingFastForwardOnly Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut) } -func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *git.Command) error { +func runMergeCommand(ctx *mergeContext, mergeStyle repo_model.MergeStyle, cmd *gitcmd.Command) error { if err := cmd.Run(ctx, ctx.RunOpts()); err != nil { // Merge will leave a MERGE_HEAD file in the .git folder if there is a conflict if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "MERGE_HEAD")); statErr == nil { diff --git a/services/pull/merge_ff_only.go b/services/pull/merge_ff_only.go index 6c3a68b95b..22a560e29c 100644 --- a/services/pull/merge_ff_only.go +++ b/services/pull/merge_ff_only.go @@ -5,13 +5,13 @@ package pull import ( repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) // doMergeStyleFastForwardOnly merges the tracking into the current HEAD - which is assumed to be staging branch (equal to the pr.BaseBranch) func doMergeStyleFastForwardOnly(ctx *mergeContext) error { - cmd := git.NewCommand("merge", "--ff-only").AddDynamicArguments(trackingBranch) + cmd := gitcmd.NewCommand("merge", "--ff-only").AddDynamicArguments(trackingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleFastForwardOnly, cmd); err != nil { log.Error("%-v Unable to merge tracking into base: %v", ctx.pr, err) return err diff --git a/services/pull/merge_merge.go b/services/pull/merge_merge.go index 118d21c7cd..bc94400f21 100644 --- a/services/pull/merge_merge.go +++ b/services/pull/merge_merge.go @@ -5,13 +5,13 @@ package pull import ( repo_model "code.gitea.io/gitea/models/repo" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) // doMergeStyleMerge merges the tracking branch into the current HEAD - which is assumed to be the staging branch (equal to the pr.BaseBranch) func doMergeStyleMerge(ctx *mergeContext, message string) error { - cmd := git.NewCommand("merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch) + cmd := gitcmd.NewCommand("merge", "--no-ff", "--no-commit").AddDynamicArguments(trackingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleMerge, cmd); err != nil { log.Error("%-v Unable to merge tracking into base: %v", ctx.pr, err) return err diff --git a/services/pull/merge_prepare.go b/services/pull/merge_prepare.go index 31a1e13734..d7152560d2 100644 --- a/services/pull/merge_prepare.go +++ b/services/pull/merge_prepare.go @@ -18,6 +18,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" asymkey_service "code.gitea.io/gitea/services/asymkey" ) @@ -31,10 +32,10 @@ type mergeContext struct { env []string } -func (ctx *mergeContext) RunOpts() *git.RunOpts { +func (ctx *mergeContext) RunOpts() *gitcmd.RunOpts { ctx.outbuf.Reset() ctx.errbuf.Reset() - return &git.RunOpts{ + return &gitcmd.RunOpts{ Env: ctx.env, Dir: ctx.tmpBasePath, Stdout: ctx.outbuf, @@ -73,7 +74,7 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque } if expectedHeadCommitID != "" { - trackingCommitID, _, err := git.NewCommand("show-ref", "--hash").AddDynamicArguments(git.BranchPrefix+trackingBranch).RunStdString(ctx, &git.RunOpts{Dir: mergeCtx.tmpBasePath}) + trackingCommitID, _, err := gitcmd.NewCommand("show-ref", "--hash").AddDynamicArguments(git.BranchPrefix+trackingBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: mergeCtx.tmpBasePath}) if err != nil { defer cancel() log.Error("failed to get sha of head branch in %-v: show-ref[%s] --hash refs/heads/tracking: %v", mergeCtx.pr, mergeCtx.tmpBasePath, err) @@ -151,7 +152,7 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error { } setConfig := func(key, value string) error { - if err := git.NewCommand("config", "--local").AddDynamicArguments(key, value). + if err := gitcmd.NewCommand("config", "--local").AddDynamicArguments(key, value). Run(ctx, ctx.RunOpts()); err != nil { log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String()) @@ -184,7 +185,7 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error { } // Read base branch index - if err := git.NewCommand("read-tree", "HEAD"). + if err := gitcmd.NewCommand("read-tree", "HEAD"). Run(ctx, ctx.RunOpts()); err != nil { log.Error("git read-tree HEAD: %v\n%s\n%s", err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("Unable to read base branch in to the index: %w\n%s\n%s", err, ctx.outbuf.String(), ctx.errbuf.String()) @@ -221,8 +222,8 @@ func getDiffTree(ctx context.Context, repoPath, baseBranch, headBranch string, o return 0, nil, nil } - err = git.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch). - Run(ctx, &git.RunOpts{ + err = gitcmd.NewCommand("diff-tree", "--no-commit-id", "--name-only", "-r", "-r", "-z", "--root").AddDynamicArguments(baseBranch, headBranch). + Run(ctx, &gitcmd.RunOpts{ Dir: repoPath, Stdout: diffOutWriter, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { @@ -272,7 +273,7 @@ func (err ErrRebaseConflicts) Error() string { // if there is a conflict it will return an ErrRebaseConflicts func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) error { // Checkout head branch - if err := git.NewCommand("checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch). + if err := gitcmd.NewCommand("checkout", "-b").AddDynamicArguments(stagingBranch, trackingBranch). Run(ctx, ctx.RunOpts()); err != nil { return fmt.Errorf("unable to git checkout tracking as staging in temp repo for %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) } @@ -280,7 +281,7 @@ func rebaseTrackingOnToBase(ctx *mergeContext, mergeStyle repo_model.MergeStyle) ctx.errbuf.Reset() // Rebase before merging - if err := git.NewCommand("rebase").AddDynamicArguments(baseBranch). + if err := gitcmd.NewCommand("rebase").AddDynamicArguments(baseBranch). Run(ctx, ctx.RunOpts()); err != nil { // Rebase will leave a REBASE_HEAD file in .git if there is a conflict if _, statErr := os.Stat(filepath.Join(ctx.tmpBasePath, ".git", "REBASE_HEAD")); statErr == nil { diff --git a/services/pull/merge_rebase.go b/services/pull/merge_rebase.go index dd7c8761f0..1d7395ebca 100644 --- a/services/pull/merge_rebase.go +++ b/services/pull/merge_rebase.go @@ -9,6 +9,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" ) @@ -16,7 +17,7 @@ import ( // getRebaseAmendMessage composes the message to amend commits in rebase merge of a pull request. func getRebaseAmendMessage(ctx *mergeContext, baseGitRepo *git.Repository) (message string, err error) { // Get existing commit message. - commitMessage, _, err := git.NewCommand("show", "--format=%B", "-s").RunStdString(ctx, &git.RunOpts{Dir: ctx.tmpBasePath}) + commitMessage, _, err := gitcmd.NewCommand("show", "--format=%B", "-s").RunStdString(ctx, &gitcmd.RunOpts{Dir: ctx.tmpBasePath}) if err != nil { return "", err } @@ -42,7 +43,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { return fmt.Errorf("Failed to get full commit id for HEAD: %w", err) } - cmd := git.NewCommand("merge", "--ff-only").AddDynamicArguments(stagingBranch) + cmd := gitcmd.NewCommand("merge", "--ff-only").AddDynamicArguments(stagingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleRebase, cmd); err != nil { log.Error("Unable to merge staging into base: %v", err) return err @@ -73,7 +74,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { } if newMessage != "" { - if err := git.NewCommand("commit", "--amend").AddOptionFormat("--message=%s", newMessage).Run(ctx, &git.RunOpts{Dir: ctx.tmpBasePath}); err != nil { + if err := gitcmd.NewCommand("commit", "--amend").AddOptionFormat("--message=%s", newMessage).Run(ctx, &gitcmd.RunOpts{Dir: ctx.tmpBasePath}); err != nil { log.Error("Unable to amend commit message: %v", err) return err } @@ -84,7 +85,7 @@ func doMergeRebaseFastForward(ctx *mergeContext) error { // Perform rebase merge with merge commit. func doMergeRebaseMergeCommit(ctx *mergeContext, message string) error { - cmd := git.NewCommand("merge").AddArguments("--no-ff", "--no-commit").AddDynamicArguments(stagingBranch) + cmd := gitcmd.NewCommand("merge").AddArguments("--no-ff", "--no-commit").AddDynamicArguments(stagingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleRebaseMerge, cmd); err != nil { log.Error("Unable to merge staging into base: %v", err) @@ -105,7 +106,7 @@ func doMergeStyleRebase(ctx *mergeContext, mergeStyle repo_model.MergeStyle, mes } // Checkout base branch again - if err := git.NewCommand("checkout").AddDynamicArguments(baseBranch). + if err := gitcmd.NewCommand("checkout").AddDynamicArguments(baseBranch). Run(ctx, ctx.RunOpts()); err != nil { log.Error("git checkout base prior to merge post staging rebase %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) return fmt.Errorf("git checkout base prior to merge post staging rebase %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String()) diff --git a/services/pull/merge_squash.go b/services/pull/merge_squash.go index 0049c0b117..99c4311e04 100644 --- a/services/pull/merge_squash.go +++ b/services/pull/merge_squash.go @@ -10,6 +10,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" ) @@ -57,7 +58,7 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error { return fmt.Errorf("getAuthorSignatureSquash: %w", err) } - cmdMerge := git.NewCommand("merge", "--squash").AddDynamicArguments(trackingBranch) + cmdMerge := gitcmd.NewCommand("merge", "--squash").AddDynamicArguments(trackingBranch) if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmdMerge); err != nil { log.Error("%-v Unable to merge --squash tracking into base: %v", ctx.pr, err) return err @@ -68,7 +69,7 @@ func doMergeStyleSquash(ctx *mergeContext, message string) error { message = AddCommitMessageTailer(message, "Co-authored-by", sig.String()) message = AddCommitMessageTailer(message, "Co-committed-by", sig.String()) // FIXME: this one should be removed, it is not really used or widely used } - cmdCommit := git.NewCommand("commit"). + cmdCommit := gitcmd.NewCommand("commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email). AddOptionFormat("--message=%s", message) if ctx.signKey == nil { diff --git a/services/pull/patch.go b/services/pull/patch.go index 9d9b8d0d07..674ae01253 100644 --- a/services/pull/patch.go +++ b/services/pull/patch.go @@ -18,14 +18,14 @@ import ( "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/process" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" - - "github.com/gobwas/glob" ) // DownloadDiffOrPatch will write the patch for the pr to the writer @@ -91,7 +91,7 @@ func testPullRequestTmpRepoBranchMergeable(ctx context.Context, prCtx *prTmpRepo defer gitRepo.Close() // 1. update merge base - pr.MergeBase, _, err = git.NewCommand("merge-base", "--", "base", "tracking").RunStdString(ctx, &git.RunOpts{Dir: prCtx.tmpBasePath}) + pr.MergeBase, _, err = gitcmd.NewCommand("merge-base", "--", "base", "tracking").RunStdString(ctx, &gitcmd.RunOpts{Dir: prCtx.tmpBasePath}) if err != nil { var err2 error pr.MergeBase, err2 = gitRepo.GetRefCommitID(git.BranchPrefix + "base") @@ -191,7 +191,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f } // Need to get the objects from the object db to attempt to merge - root, _, err := git.NewCommand("unpack-file").AddDynamicArguments(file.stage1.sha).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + root, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage1.sha).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return fmt.Errorf("unable to get root object: %s at path: %s for merging. Error: %w", file.stage1.sha, file.stage1.path, err) } @@ -200,7 +200,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f _ = util.Remove(filepath.Join(tmpBasePath, root)) }() - base, _, err := git.NewCommand("unpack-file").AddDynamicArguments(file.stage2.sha).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + base, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage2.sha).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return fmt.Errorf("unable to get base object: %s at path: %s for merging. Error: %w", file.stage2.sha, file.stage2.path, err) } @@ -208,7 +208,7 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f defer func() { _ = util.Remove(base) }() - head, _, err := git.NewCommand("unpack-file").AddDynamicArguments(file.stage3.sha).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + head, _, err := gitcmd.NewCommand("unpack-file").AddDynamicArguments(file.stage3.sha).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return fmt.Errorf("unable to get head object:%s at path: %s for merging. Error: %w", file.stage3.sha, file.stage3.path, err) } @@ -218,13 +218,13 @@ func attemptMerge(ctx context.Context, file *unmergedFile, tmpBasePath string, f }() // now git merge-file annoyingly takes a different order to the merge-tree ... - _, _, conflictErr := git.NewCommand("merge-file").AddDynamicArguments(base, root, head).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + _, _, conflictErr := gitcmd.NewCommand("merge-file").AddDynamicArguments(base, root, head).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if conflictErr != nil { return &errMergeConflict{file.stage2.path} } // base now contains the merged data - hash, _, err := git.NewCommand("hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + hash, _, err := gitcmd.NewCommand("hash-object", "-w", "--path").AddDynamicArguments(file.stage2.path, base).RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return err } @@ -249,7 +249,7 @@ func AttemptThreeWayMerge(ctx context.Context, gitPath string, gitRepo *git.Repo defer cancel() // First we use read-tree to do a simple three-way merge - if _, _, err := git.NewCommand("read-tree", "-m").AddDynamicArguments(base, ours, theirs).RunStdString(ctx, &git.RunOpts{Dir: gitPath}); err != nil { + if _, _, err := gitcmd.NewCommand("read-tree", "-m").AddDynamicArguments(base, ours, theirs).RunStdString(ctx, &gitcmd.RunOpts{Dir: gitPath}); err != nil { log.Error("Unable to run read-tree -m! Error: %v", err) return false, nil, fmt.Errorf("unable to run read-tree -m! Error: %w", err) } @@ -323,9 +323,9 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * // No conflicts detected so we need to check if the patch is empty... // a. Write the newly merged tree and check the new tree-hash var treeHash string - treeHash, _, err = git.NewCommand("write-tree").RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + treeHash, _, err = gitcmd.NewCommand("write-tree").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { - lsfiles, _, _ := git.NewCommand("ls-files", "-u").RunStdString(ctx, &git.RunOpts{Dir: tmpBasePath}) + lsfiles, _, _ := gitcmd.NewCommand("ls-files", "-u").RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) return false, fmt.Errorf("unable to write unconflicted tree: %w\n`git ls-files -u`:\n%s", err, lsfiles) } treeHash = strings.TrimSpace(treeHash) @@ -382,7 +382,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * log.Trace("PullRequest[%d].testPullRequestTmpRepoBranchMergeable (patchPath): %s", pr.ID, patchPath) // 4. Read the base branch in to the index of the temporary repository - _, _, err = git.NewCommand("read-tree", "base").RunStdString(gitRepo.Ctx, &git.RunOpts{Dir: tmpBasePath}) + _, _, err = gitcmd.NewCommand("read-tree", "base").RunStdString(gitRepo.Ctx, &gitcmd.RunOpts{Dir: tmpBasePath}) if err != nil { return false, fmt.Errorf("git read-tree %s: %w", pr.BaseBranch, err) } @@ -395,7 +395,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * prConfig := prUnit.PullRequestsConfig() // 6. Prepare the arguments to apply the patch against the index - cmdApply := git.NewCommand("apply", "--check", "--cached") + cmdApply := gitcmd.NewCommand("apply", "--check", "--cached") if prConfig.IgnoreWhitespaceConflicts { cmdApply.AddArguments("--ignore-whitespace") } @@ -426,7 +426,7 @@ func checkConflicts(ctx context.Context, pr *issues_model.PullRequest, gitRepo * // 8. Run the check command conflict = false - err = cmdApply.Run(gitRepo.Ctx, &git.RunOpts{ + err = cmdApply.Run(gitRepo.Ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stderr: stderrWriter, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { diff --git a/services/pull/patch_unmerged.go b/services/pull/patch_unmerged.go index 200d2233e9..9164035480 100644 --- a/services/pull/patch_unmerged.go +++ b/services/pull/patch_unmerged.go @@ -13,7 +13,7 @@ import ( "strconv" "strings" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" ) @@ -72,8 +72,8 @@ func readUnmergedLsFileLines(ctx context.Context, tmpBasePath string, outputChan }() stderr := &strings.Builder{} - err = git.NewCommand("ls-files", "-u", "-z"). - Run(ctx, &git.RunOpts{ + err = gitcmd.NewCommand("ls-files", "-u", "-z"). + Run(ctx, &gitcmd.RunOpts{ Dir: tmpBasePath, Stdout: lsFilesWriter, Stderr: stderr, @@ -116,7 +116,7 @@ func readUnmergedLsFileLines(ctx context.Context, tmpBasePath string, outputChan }, }) if err != nil { - outputChan <- &lsFileLine{err: fmt.Errorf("git ls-files -u -z: %w", git.ConcatenateError(err, stderr.String()))} + outputChan <- &lsFileLine{err: fmt.Errorf("git ls-files -u -z: %w", gitcmd.ConcatenateError(err, stderr.String()))} } } diff --git a/services/pull/pull.go b/services/pull/pull.go index 8144aee1b0..a256d04f2a 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -25,6 +25,7 @@ import ( "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/globallock" "code.gitea.io/gitea/modules/graceful" @@ -546,14 +547,14 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, return false, fmt.Errorf("GetMergeBase: %w", err) } - cmd := git.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(newCommitID, oldCommitID, base) + cmd := gitcmd.NewCommand("diff", "--name-only", "-z").AddDynamicArguments(newCommitID, oldCommitID, base) stdoutReader, stdoutWriter, err := os.Pipe() if err != nil { return false, fmt.Errorf("unable to open pipe for to run diff: %w", err) } stderr := new(bytes.Buffer) - if err := cmd.Run(ctx, &git.RunOpts{ + if err := cmd.Run(ctx, &gitcmd.RunOpts{ Dir: prCtx.tmpBasePath, Stdout: stdoutWriter, Stderr: stderr, @@ -568,7 +569,7 @@ func checkIfPRContentChanged(ctx context.Context, pr *issues_model.PullRequest, if err == util.ErrNotEmpty { return true, nil } - err = git.ConcatenateError(err, stderr.String()) + err = gitcmd.ConcatenateError(err, stderr.String()) log.Error("Unable to run diff on %s %s %s in tempRepo for PR[%d]%s/%s...%s/%s: Error: %v", newCommitID, oldCommitID, base, @@ -670,7 +671,7 @@ func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) { return err } - _, _, err = git.NewCommand("update-ref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.HeadCommitID).RunStdString(ctx, &git.RunOpts{Dir: pr.BaseRepo.RepoPath()}) + _, _, err = gitcmd.NewCommand("update-ref").AddDynamicArguments(pr.GetGitHeadRefName(), pr.HeadCommitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}) if err != nil { log.Error("Unable to update ref in base repository for PR[%d] Error: %v", pr.ID, err) } diff --git a/services/pull/temp_repo.go b/services/pull/temp_repo.go index 89f150fd92..8750b4288a 100644 --- a/services/pull/temp_repo.go +++ b/services/pull/temp_repo.go @@ -15,6 +15,7 @@ import ( issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -36,10 +37,10 @@ type prTmpRepoContext struct { errbuf *strings.Builder // any use should be preceded by a Reset and preferably after use } -func (ctx *prTmpRepoContext) RunOpts() *git.RunOpts { +func (ctx *prTmpRepoContext) RunOpts() *gitcmd.RunOpts { ctx.outbuf.Reset() ctx.errbuf.Reset() - return &git.RunOpts{ + return &gitcmd.RunOpts{ Dir: ctx.tmpBasePath, Stdout: ctx.outbuf, Stderr: ctx.errbuf, @@ -101,7 +102,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) remoteRepoName := "head_repo" baseBranch := "base" - fetchArgs := git.TrustedCmdArgs{"--no-tags"} + fetchArgs := gitcmd.TrustedCmdArgs{"--no-tags"} if git.DefaultFeatures().CheckVersionAtLeast("2.25.0") { // Writing the commit graph can be slow and is not needed here fetchArgs = append(fetchArgs, "--no-write-commit-graph") @@ -131,21 +132,21 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) return nil, nil, fmt.Errorf("Unable to add base repository to temporary repo [%s -> tmpBasePath]: %w", pr.BaseRepo.FullName(), err) } - if err := git.NewCommand("remote", "add", "-t").AddDynamicArguments(pr.BaseBranch).AddArguments("-m").AddDynamicArguments(pr.BaseBranch).AddDynamicArguments("origin", baseRepoPath). + if err := gitcmd.NewCommand("remote", "add", "-t").AddDynamicArguments(pr.BaseBranch).AddArguments("-m").AddDynamicArguments(pr.BaseBranch).AddDynamicArguments("origin", baseRepoPath). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to add base repository as origin [%s -> %s]: %v\n%s\n%s", pr, pr.BaseRepo.FullName(), tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() return nil, nil, fmt.Errorf("Unable to add base repository as origin [%s -> tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), err, prCtx.outbuf.String(), prCtx.errbuf.String()) } - if err := git.NewCommand("fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch). + if err := gitcmd.NewCommand("fetch", "origin").AddArguments(fetchArgs...).AddDashesAndList(pr.BaseBranch+":"+baseBranch, pr.BaseBranch+":original_"+baseBranch). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to fetch origin base branch [%s:%s -> base, original_base in %s]: %v:\n%s\n%s", pr, pr.BaseRepo.FullName(), pr.BaseBranch, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() return nil, nil, fmt.Errorf("Unable to fetch origin base branch [%s:%s -> base, original_base in tmpBasePath]: %w\n%s\n%s", pr.BaseRepo.FullName(), pr.BaseBranch, err, prCtx.outbuf.String(), prCtx.errbuf.String()) } - if err := git.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseBranch). + if err := gitcmd.NewCommand("symbolic-ref").AddDynamicArguments("HEAD", git.BranchPrefix+baseBranch). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to set HEAD as base branch in [%s]: %v\n%s\n%s", pr, tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() @@ -158,7 +159,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) return nil, nil, fmt.Errorf("Unable to add head base repository to temporary repo [%s -> tmpBasePath]: %w", pr.HeadRepo.FullName(), err) } - if err := git.NewCommand("remote", "add").AddDynamicArguments(remoteRepoName, headRepoPath). + if err := gitcmd.NewCommand("remote", "add").AddDynamicArguments(remoteRepoName, headRepoPath). Run(ctx, prCtx.RunOpts()); err != nil { log.Error("%-v Unable to add head repository as head_repo [%s -> %s]: %v\n%s\n%s", pr, pr.HeadRepo.FullName(), tmpBasePath, err, prCtx.outbuf.String(), prCtx.errbuf.String()) cancel() @@ -176,7 +177,7 @@ func createTemporaryRepoForPR(ctx context.Context, pr *issues_model.PullRequest) } else { headBranch = pr.GetGitHeadRefName() } - if err := git.NewCommand("fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch). + if err := gitcmd.NewCommand("fetch").AddArguments(fetchArgs...).AddDynamicArguments(remoteRepoName, headBranch+":"+trackingBranch). Run(ctx, prCtx.RunOpts()); err != nil { cancel() if !gitrepo.IsBranchExist(ctx, pr.HeadRepo, pr.HeadBranch) { diff --git a/services/pull/update_rebase.go b/services/pull/update_rebase.go index 9ff062f99c..3b5d3afba5 100644 --- a/services/pull/update_rebase.go +++ b/services/pull/update_rebase.go @@ -12,6 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -27,7 +28,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques defer cancel() // Determine the old merge-base before the rebase - we use this for LFS push later on - oldMergeBase, _, _ := git.NewCommand("merge-base").AddDashesAndList(baseBranch, trackingBranch).RunStdString(ctx, &git.RunOpts{Dir: mergeCtx.tmpBasePath}) + oldMergeBase, _, _ := gitcmd.NewCommand("merge-base").AddDashesAndList(baseBranch, trackingBranch).RunStdString(ctx, &gitcmd.RunOpts{Dir: mergeCtx.tmpBasePath}) oldMergeBase = strings.TrimSpace(oldMergeBase) // Rebase the tracking branch on to the base as the staging branch @@ -62,7 +63,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques headUser = pr.HeadRepo.Owner } - pushCmd := git.NewCommand("push", "-f", "head_repo"). + pushCmd := gitcmd.NewCommand("push", "-f", "head_repo"). AddDynamicArguments(stagingBranch + ":" + git.BranchPrefix + pr.HeadBranch) // Push back to the head repository. @@ -71,7 +72,7 @@ func updateHeadByRebaseOnToBase(ctx context.Context, pr *issues_model.PullReques mergeCtx.outbuf.Reset() mergeCtx.errbuf.Reset() - if err := pushCmd.Run(ctx, &git.RunOpts{ + if err := pushCmd.Run(ctx, &gitcmd.RunOpts{ Env: repo_module.FullPushingEnvironment( headUser, doer, diff --git a/services/release/release.go b/services/release/release.go index 1e2132bb60..3c5392c993 100644 --- a/services/release/release.go +++ b/services/release/release.go @@ -15,6 +15,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -370,8 +371,8 @@ func DeleteReleaseByID(ctx context.Context, repo *repo_model.Repository, rel *re } } - if stdout, _, err := git.NewCommand("tag", "-d").AddDashesAndList(rel.TagName). - RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}); err != nil && !strings.Contains(err.Error(), "not found") { + if stdout, _, err := gitcmd.NewCommand("tag", "-d").AddDashesAndList(rel.TagName). + RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}); err != nil && !strings.Contains(err.Error(), "not found") { log.Error("DeleteReleaseByID (git tag -d): %d in %v Failed:\nStdout: %s\nError: %v", rel.ID, repo, stdout, err) return fmt.Errorf("git tag -d: %w", err) } diff --git a/services/repository/adopt.go b/services/repository/adopt.go index a17111dfaf..8d8e59b053 100644 --- a/services/repository/adopt.go +++ b/services/repository/adopt.go @@ -17,6 +17,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/optional" @@ -24,8 +25,6 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" notify_service "code.gitea.io/gitea/services/notify" - - "github.com/gobwas/glob" ) func deleteFailedAdoptRepository(repoID int64) error { diff --git a/services/repository/check.go b/services/repository/check.go index 46eb4d7e7c..46394ba48e 100644 --- a/services/repository/check.go +++ b/services/repository/check.go @@ -13,7 +13,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -23,7 +23,7 @@ import ( ) // GitFsckRepos calls 'git fsck' to check repository health. -func GitFsckRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitFsckRepos(ctx context.Context, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Doing: GitFsck") if err := db.Iterate( @@ -47,7 +47,7 @@ func GitFsckRepos(ctx context.Context, timeout time.Duration, args git.TrustedCm } // GitFsckRepo calls 'git fsck' to check an individual repository's health. -func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Running health check on repository %-v", repo.FullName()) if err := gitrepo.Fsck(ctx, repo, timeout, args); err != nil { log.Warn("Failed to health check repository (%-v): %v", repo.FullName(), err) @@ -59,7 +59,7 @@ func GitFsckRepo(ctx context.Context, repo *repo_model.Repository, timeout time. } // GitGcRepos calls 'git gc' to remove unnecessary files and optimize the local repository -func GitGcRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitGcRepos(ctx context.Context, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Doing: GitGcRepos") if err := db.Iterate( @@ -84,12 +84,12 @@ func GitGcRepos(ctx context.Context, timeout time.Duration, args git.TrustedCmdA } // GitGcRepo calls 'git gc' to remove unnecessary files and optimize the local repository -func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args git.TrustedCmdArgs) error { +func GitGcRepo(ctx context.Context, repo *repo_model.Repository, timeout time.Duration, args gitcmd.TrustedCmdArgs) error { log.Trace("Running git gc on %-v", repo) - command := git.NewCommand("gc").AddArguments(args...) + command := gitcmd.NewCommand("gc").AddArguments(args...) var stdout string var err error - stdout, _, err = command.RunStdString(ctx, &git.RunOpts{Timeout: timeout, Dir: repo.RepoPath()}) + stdout, _, err = command.RunStdString(ctx, &gitcmd.RunOpts{Timeout: timeout, Dir: repo.RepoPath()}) if err != nil { log.Error("Repository garbage collection failed for %-v. Stdout: %s\nError: %v", repo, stdout, err) desc := fmt.Sprintf("Repository garbage collection failed for %s. Stdout: %s\nError: %v", repo.RepoPath(), stdout, err) diff --git a/services/repository/commitstatus/commitstatus.go b/services/repository/commitstatus/commitstatus.go index fa7a89882a..c0a8b8e824 100644 --- a/services/repository/commitstatus/commitstatus.go +++ b/services/repository/commitstatus/commitstatus.go @@ -120,7 +120,7 @@ func CreateCommitStatus(ctx context.Context, repo *repo_model.Repository, creato return nil } -// FindReposLastestCommitStatuses loading repository default branch latest combinded commit status with cache +// FindReposLastestCommitStatuses loading repository default branch latest combined commit status with cache func FindReposLastestCommitStatuses(ctx context.Context, repos []*repo_model.Repository) ([]*git_model.CommitStatus, error) { results := make([]*git_model.CommitStatus, len(repos)) allCached := true diff --git a/services/repository/contributors_graph.go b/services/repository/contributors_graph.go index a4ae505313..a7fb130cb5 100644 --- a/services/repository/contributors_graph.go +++ b/services/repository/contributors_graph.go @@ -19,6 +19,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -125,13 +126,13 @@ func getExtendedCommitStats(repo *git.Repository, revision string /*, limit int _ = stdoutWriter.Close() }() - gitCmd := git.NewCommand("log", "--shortstat", "--no-merges", "--pretty=format:---%n%aN%n%aE%n%as", "--reverse") + gitCmd := gitcmd.NewCommand("log", "--shortstat", "--no-merges", "--pretty=format:---%n%aN%n%aE%n%as", "--reverse") // AddOptionFormat("--max-count=%d", limit) gitCmd.AddDynamicArguments(baseCommit.ID.String()) var extendedCommitStats []*ExtendedCommitStats stderr := new(strings.Builder) - err = gitCmd.Run(repo.Ctx, &git.RunOpts{ + err = gitCmd.Run(repo.Ctx, &gitcmd.RunOpts{ Dir: repo.Path, Stdout: stdoutWriter, Stderr: stderr, diff --git a/services/repository/create.go b/services/repository/create.go index 9f0716c191..3006bfaeaf 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -22,6 +22,7 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" @@ -68,8 +69,8 @@ func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir ) // Clone to temporary path and do the init commit. - if stdout, _, err := git.NewCommand("clone").AddDynamicArguments(repo.RepoPath(), tmpDir). - RunStdString(ctx, &git.RunOpts{Dir: "", Env: env}); err != nil { + if stdout, _, err := gitcmd.NewCommand("clone").AddDynamicArguments(repo.RepoPath(), tmpDir). + RunStdString(ctx, &gitcmd.RunOpts{Dir: "", Env: env}); err != nil { log.Error("Failed to clone from %v into %s: stdout: %s\nError: %v", repo, tmpDir, stdout, err) return fmt.Errorf("git clone: %w", err) } @@ -313,7 +314,7 @@ func CreateRepositoryDirectly(ctx context.Context, doer, owner *user_model.User, licenses = append(licenses, opts.License) var stdout string - stdout, _, err = git.NewCommand("rev-parse", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}) + stdout, _, err = gitcmd.NewCommand("rev-parse", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}) if err != nil { log.Error("CreateRepository(git rev-parse HEAD) in %v: Stdout: %s\nError: %v", repo, stdout, err) return nil, fmt.Errorf("CreateRepository(git rev-parse HEAD): %w", err) @@ -474,8 +475,8 @@ func updateGitRepoAfterCreate(ctx context.Context, repo *repo_model.Repository) return fmt.Errorf("checkDaemonExportOK: %w", err) } - if stdout, _, err := git.NewCommand("update-server-info"). - RunStdString(ctx, &git.RunOpts{Dir: repo.RepoPath()}); err != nil { + if stdout, _, err := gitcmd.NewCommand("update-server-info"). + RunStdString(ctx, &gitcmd.RunOpts{Dir: repo.RepoPath()}); err != nil { log.Error("CreateRepository(git update-server-info) in %v: Stdout: %s\nError: %v", repo, stdout, err) return fmt.Errorf("CreateRepository(git update-server-info): %w", err) } diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index 11a8744b7f..093072dff2 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -12,6 +12,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" @@ -159,12 +160,12 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user stdout := &strings.Builder{} stderr := &strings.Builder{} - cmdApply := git.NewCommand("apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") + cmdApply := gitcmd.NewCommand("apply", "--index", "--recount", "--cached", "--ignore-whitespace", "--whitespace=fix", "--binary") if git.DefaultFeatures().CheckVersionAtLeast("2.32") { cmdApply.AddArguments("-3") } - if err := cmdApply.Run(ctx, &git.RunOpts{ + if err := cmdApply.Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdout: stdout, Stderr: stderr, diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index c2f61c8223..dcbe368357 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -17,6 +17,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -53,7 +54,7 @@ func (t *TemporaryUploadRepository) Close() { // Clone the base repository to our path and set branch as the HEAD func (t *TemporaryUploadRepository) Clone(ctx context.Context, branch string, bare bool) error { - cmd := git.NewCommand("clone", "-s", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath) + cmd := gitcmd.NewCommand("clone", "-s", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath) if bare { cmd.AddArguments("--bare") } @@ -97,7 +98,7 @@ func (t *TemporaryUploadRepository) Init(ctx context.Context, objectFormatName s // SetDefaultIndex sets the git index to our HEAD func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error { - if _, _, err := git.NewCommand("read-tree", "HEAD").RunStdString(ctx, &git.RunOpts{Dir: t.basePath}); err != nil { + if _, _, err := gitcmd.NewCommand("read-tree", "HEAD").RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}); err != nil { return fmt.Errorf("SetDefaultIndex: %w", err) } return nil @@ -105,7 +106,7 @@ func (t *TemporaryUploadRepository) SetDefaultIndex(ctx context.Context) error { // RefreshIndex looks at the current index and checks to see if merges or updates are needed by checking stat() information. func (t *TemporaryUploadRepository) RefreshIndex(ctx context.Context) error { - if _, _, err := git.NewCommand("update-index", "--refresh").RunStdString(ctx, &git.RunOpts{Dir: t.basePath}); err != nil { + if _, _, err := gitcmd.NewCommand("update-index", "--refresh").RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}); err != nil { return fmt.Errorf("RefreshIndex: %w", err) } return nil @@ -116,8 +117,8 @@ func (t *TemporaryUploadRepository) LsFiles(ctx context.Context, filenames ...st stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) - if err := git.NewCommand("ls-files", "-z").AddDashesAndList(filenames...). - Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("ls-files", "-z").AddDashesAndList(filenames...). + Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdout: stdOut, Stderr: stdErr, @@ -152,8 +153,8 @@ func (t *TemporaryUploadRepository) RemoveFilesFromIndex(ctx context.Context, fi } } - if err := git.NewCommand("update-index", "--remove", "-z", "--index-info"). - Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("update-index", "--remove", "-z", "--index-info"). + Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdin: stdIn, Stdout: stdOut, @@ -169,8 +170,8 @@ func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, cont stdOut := new(bytes.Buffer) stdErr := new(bytes.Buffer) - if err := git.NewCommand("hash-object", "-w", "--stdin"). - Run(ctx, &git.RunOpts{ + if err := gitcmd.NewCommand("hash-object", "-w", "--stdin"). + Run(ctx, &gitcmd.RunOpts{ Dir: t.basePath, Stdin: content, Stdout: stdOut, @@ -185,7 +186,7 @@ func (t *TemporaryUploadRepository) HashObjectAndWrite(ctx context.Context, cont // AddObjectToIndex adds the provided object hash to the index with the provided mode and path func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode, objectHash, objectPath string) error { - if _, _, err := git.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(ctx, &git.RunOpts{Dir: t.basePath}); err != nil { + if _, _, err := gitcmd.NewCommand("update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, objectHash, objectPath).RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}); err != nil { stderr := err.Error() if matched, _ := regexp.MatchString(".*Invalid path '.*", stderr); matched { return ErrFilePathInvalid{ @@ -201,7 +202,7 @@ func (t *TemporaryUploadRepository) AddObjectToIndex(ctx context.Context, mode, // WriteTree writes the current index as a tree to the object db and returns its hash func (t *TemporaryUploadRepository) WriteTree(ctx context.Context) (string, error) { - stdout, _, err := git.NewCommand("write-tree").RunStdString(ctx, &git.RunOpts{Dir: t.basePath}) + stdout, _, err := gitcmd.NewCommand("write-tree").RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}) if err != nil { log.Error("Unable to write tree in temporary repo: %s(%s): Error: %v", t.repo.FullName(), t.basePath, err) return "", fmt.Errorf("Unable to write-tree in temporary repo for: %s Error: %w", t.repo.FullName(), err) @@ -219,7 +220,7 @@ func (t *TemporaryUploadRepository) GetLastCommitByRef(ctx context.Context, ref if ref == "" { ref = "HEAD" } - stdout, _, err := git.NewCommand("rev-parse").AddDynamicArguments(ref).RunStdString(ctx, &git.RunOpts{Dir: t.basePath}) + stdout, _, err := gitcmd.NewCommand("rev-parse").AddDynamicArguments(ref).RunStdString(ctx, &gitcmd.RunOpts{Dir: t.basePath}) if err != nil { log.Error("Unable to get last ref for %s in temporary repo: %s(%s): Error: %v", ref, t.repo.FullName(), t.basePath, err) return "", fmt.Errorf("Unable to rev-parse %s in temporary repo for: %s Error: %w", ref, t.repo.FullName(), err) @@ -287,7 +288,7 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit _, _ = messageBytes.WriteString(opts.CommitMessage) _, _ = messageBytes.WriteString("\n") - cmdCommitTree := git.NewCommand("commit-tree").AddDynamicArguments(opts.TreeHash) + cmdCommitTree := gitcmd.NewCommand("commit-tree").AddDynamicArguments(opts.TreeHash) if opts.ParentCommitID != "" { cmdCommitTree.AddOptionValues("-p", opts.ParentCommitID) } @@ -337,7 +338,7 @@ func (t *TemporaryUploadRepository) CommitTree(ctx context.Context, opts *Commit stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) if err := cmdCommitTree. - Run(ctx, &git.RunOpts{ + Run(ctx, &gitcmd.RunOpts{ Env: env, Dir: t.basePath, Stdin: messageBytes, @@ -389,8 +390,8 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context) (*gitdiff.Dif }() stderr := new(bytes.Buffer) var diff *gitdiff.Diff - err = git.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD"). - Run(ctx, &git.RunOpts{ + err = gitcmd.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD"). + Run(ctx, &gitcmd.RunOpts{ Timeout: 30 * time.Second, Dir: t.basePath, Stdout: stdoutWriter, diff --git a/services/repository/fork.go b/services/repository/fork.go index 8bd3498b17..05909f0e0d 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" @@ -146,13 +147,13 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork } // 3 - Clone the repository - cloneCmd := git.NewCommand("clone", "--bare") + cloneCmd := gitcmd.NewCommand("clone", "--bare") if opts.SingleBranch != "" { cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(opts.SingleBranch) } var stdout []byte if stdout, _, err = cloneCmd.AddDynamicArguments(opts.BaseRepo.RepoPath(), repo.RepoPath()). - RunStdBytes(ctx, &git.RunOpts{Timeout: 10 * time.Minute}); err != nil { + RunStdBytes(ctx, &gitcmd.RunOpts{Timeout: 10 * time.Minute}); err != nil { log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err) return nil, fmt.Errorf("git clone: %w", err) } diff --git a/services/repository/generate.go b/services/repository/generate.go index 867b5d7855..c03d9b51a7 100644 --- a/services/repository/generate.go +++ b/services/repository/generate.go @@ -18,13 +18,14 @@ import ( git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" - "github.com/gobwas/glob" "github.com/huandu/xstrings" ) @@ -234,8 +235,8 @@ func generateRepoCommit(ctx context.Context, repo, templateRepo, generateRepo *r return err } - if stdout, _, err := git.NewCommand("remote", "add", "origin").AddDynamicArguments(repo.RepoPath()). - RunStdString(ctx, &git.RunOpts{Dir: tmpDir, Env: env}); err != nil { + if stdout, _, err := gitcmd.NewCommand("remote", "add", "origin").AddDynamicArguments(repo.RepoPath()). + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpDir, Env: env}); err != nil { log.Error("Unable to add %v as remote origin to temporary repo to %s: stdout %s\nError: %v", repo, tmpDir, stdout, err) return fmt.Errorf("git remote add: %w", err) } diff --git a/services/repository/gitgraph/graph.go b/services/repository/gitgraph/graph.go index d06d18c1b4..3bc97b7bbc 100644 --- a/services/repository/gitgraph/graph.go +++ b/services/repository/gitgraph/graph.go @@ -11,6 +11,7 @@ import ( "strings" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/setting" ) @@ -22,7 +23,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo page = 1 } - graphCmd := git.NewCommand("log", "--graph", "--date-order", "--decorate=full") + graphCmd := gitcmd.NewCommand("log", "--graph", "--date-order", "--decorate=full") if hidePRRefs { graphCmd.AddArguments("--exclude=" + git.PullPrefix + "*") @@ -53,7 +54,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo scanner := bufio.NewScanner(stdoutReader) - if err := graphCmd.Run(r.Ctx, &git.RunOpts{ + if err := graphCmd.Run(r.Ctx, &gitcmd.RunOpts{ Dir: r.Path, Stdout: stdoutWriter, Stderr: stderr, diff --git a/services/repository/gitgraph/graph_models.go b/services/repository/gitgraph/graph_models.go index 02b0268cd9..fc2eb85b87 100644 --- a/services/repository/gitgraph/graph_models.go +++ b/services/repository/gitgraph/graph_models.go @@ -182,7 +182,7 @@ func (flow *Flow) AddGlyph(row, column int, glyph byte) { }) } -// Glyph represents a co-ordinate and glyph +// Glyph represents a coordinate and glyph type Glyph struct { Row int Column int @@ -244,7 +244,7 @@ func newRefsFromRefNames(refNames []byte) []git.Reference { return refs } -// Commit represents a commit at co-ordinate X, Y with the data +// Commit represents a commit at coordinate X, Y with the data type Commit struct { Commit *git.Commit User *user_model.User diff --git a/services/repository/init.go b/services/repository/init.go index 1eeeb4aa4f..c905d1f6a3 100644 --- a/services/repository/init.go +++ b/services/repository/init.go @@ -11,7 +11,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/log" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -33,13 +33,13 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi committerName := sig.Name committerEmail := sig.Email - if stdout, _, err := git.NewCommand("add", "--all"). - RunStdString(ctx, &git.RunOpts{Dir: tmpPath}); err != nil { + if stdout, _, err := gitcmd.NewCommand("add", "--all"). + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpPath}); err != nil { log.Error("git add --all failed: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git add --all: %w", err) } - cmd := git.NewCommand("commit", "--message=Initial commit"). + cmd := gitcmd.NewCommand("commit", "--message=Initial commit"). AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email) sign, key, signer, _ := asymkey_service.SignInitialCommit(ctx, tmpPath, u) @@ -64,7 +64,7 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi ) if stdout, _, err := cmd. - RunStdString(ctx, &git.RunOpts{Dir: tmpPath, Env: env}); err != nil { + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpPath, Env: env}); err != nil { log.Error("Failed to commit: %v: Stdout: %s\nError: %v", cmd.LogString(), stdout, err) return fmt.Errorf("git commit: %w", err) } @@ -73,8 +73,8 @@ func initRepoCommit(ctx context.Context, tmpPath string, repo *repo_model.Reposi defaultBranch = setting.Repository.DefaultBranch } - if stdout, _, err := git.NewCommand("push", "origin").AddDynamicArguments("HEAD:"+defaultBranch). - RunStdString(ctx, &git.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil { + if stdout, _, err := gitcmd.NewCommand("push", "origin").AddDynamicArguments("HEAD:"+defaultBranch). + RunStdString(ctx, &gitcmd.RunOpts{Dir: tmpPath, Env: repo_module.InternalPushingEnvironment(u, repo)}); err != nil { log.Error("Failed to push back to HEAD: Stdout: %s\nError: %v", stdout, err) return fmt.Errorf("git push: %w", err) } diff --git a/services/repository/migrate.go b/services/repository/migrate.go index 66622f1601..db1f020b9f 100644 --- a/services/repository/migrate.go +++ b/services/repository/migrate.go @@ -16,6 +16,7 @@ import ( unit_model "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/lfs" "code.gitea.io/gitea/modules/log" @@ -225,9 +226,9 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User, // this is necessary for sync local tags from remote configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName()) - if stdout, _, err := git.NewCommand("config"). + if stdout, _, err := gitcmd.NewCommand("config"). AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`). - RunStdString(ctx, &git.RunOpts{Dir: repoPath}); err != nil { + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath}); err != nil { log.Error("MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*) in %v: Stdout: %s\nError: %v", repo, stdout, err) return repo, fmt.Errorf("error in MigrateRepositoryGitData(git config --add +refs/tags/*:refs/tags/*): %w", err) } diff --git a/services/user/email_test.go b/services/user/email_test.go index 78770633d2..76770a9230 100644 --- a/services/user/email_test.go +++ b/services/user/email_test.go @@ -9,9 +9,9 @@ import ( organization_model "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/setting" - "github.com/gobwas/glob" "github.com/stretchr/testify/assert" ) diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go index e8e6ed19c1..b6611a3576 100644 --- a/services/webhook/deliver.go +++ b/services/webhook/deliver.go @@ -21,6 +21,7 @@ import ( user_model "code.gitea.io/gitea/models/user" webhook_model "code.gitea.io/gitea/models/webhook" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/hostmatcher" "code.gitea.io/gitea/modules/log" @@ -30,8 +31,6 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" webhook_module "code.gitea.io/gitea/modules/webhook" - - "github.com/gobwas/glob" ) func newDefaultRequest(ctx context.Context, w *webhook_model.Webhook, t *webhook_model.HookTask) (req *http.Request, body []byte, err error) { diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go index 182078b39d..2b276207a1 100644 --- a/services/webhook/webhook.go +++ b/services/webhook/webhook.go @@ -15,6 +15,7 @@ import ( user_model "code.gitea.io/gitea/models/user" webhook_model "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/glob" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/optional" @@ -23,8 +24,6 @@ import ( api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" webhook_module "code.gitea.io/gitea/modules/webhook" - - "github.com/gobwas/glob" ) type Requester func(context.Context, *webhook_model.Webhook, *webhook_model.HookTask) (req *http.Request, body []byte, err error) diff --git a/templates/org/team/repositories.tmpl b/templates/org/team/repositories.tmpl index 4f4667ca8b..2f38071e89 100644 --- a/templates/org/team/repositories.tmpl +++ b/templates/org/team/repositories.tmpl @@ -12,7 +12,7 @@
{{.CsrfTokenHtml}} -