Skip to content

Commit

Permalink
Merge remote-tracking branch 'giteaofficial/main'
Browse files Browse the repository at this point in the history
* giteaofficial/main:
  Fix slow patch checking with commits that add or remove many files (go-gitea#31548)
  Add typescript guideline and typescript-specific eslint plugins and fix issues (go-gitea#31521)
  • Loading branch information
zjjhot committed Jul 5, 2024
2 parents b021c13 + b88e5fc commit e9ea4a5
Show file tree
Hide file tree
Showing 13 changed files with 274 additions and 167 deletions.
133 changes: 127 additions & 6 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ parserOptions:
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/extensions: [".js", ".ts"]
Expand All @@ -24,7 +25,9 @@ settings:
plugins:
- "@eslint-community/eslint-plugin-eslint-comments"
- "@stylistic/eslint-plugin-js"
- "@typescript-eslint/eslint-plugin"
- eslint-plugin-array-func
- eslint-plugin-deprecation
- eslint-plugin-github
- eslint-plugin-i
- eslint-plugin-no-jquery
Expand Down Expand Up @@ -209,6 +212,123 @@ rules:
"@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/ban-types": [2, {extendDefaults: true, types: {Function: false}}]
"@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-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-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": [2]
"@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": [0]
"@typescript-eslint/no-restricted-imports": [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-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-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": [0]
"@typescript-eslint/no-useless-constructor": [0]
"@typescript-eslint/no-useless-empty-export": [0]
"@typescript-eslint/no-var-requires": [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": [2]
"@typescript-eslint/unified-signatures": [2]
accessor-pairs: [2]
array-callback-return: [2, {checkForEach: true}]
array-func/avoid-reverse: [2]
Expand All @@ -230,6 +350,7 @@ rules:
default-case-last: [2]
default-case: [0]
default-param-last: [0]
deprecation/deprecation: [2]
dot-notation: [0]
eqeqeq: [2]
for-direction: [2]
Expand Down Expand Up @@ -321,7 +442,7 @@ rules:
multiline-comment-style: [2, separate-lines]
new-cap: [0]
no-alert: [0]
no-array-constructor: [2]
no-array-constructor: [0] # handled by @typescript-eslint/no-array-constructor
no-async-promise-executor: [0]
no-await-in-loop: [0]
no-bitwise: [0]
Expand Down Expand Up @@ -365,7 +486,7 @@ rules:
no-global-assign: [2]
no-implicit-coercion: [2]
no-implicit-globals: [0]
no-implied-eval: [2]
no-implied-eval: [0] # handled by @typescript-eslint/no-implied-eval
no-import-assign: [2]
no-inline-comments: [0]
no-inner-declarations: [2]
Expand Down Expand Up @@ -471,7 +592,7 @@ rules:
no-lone-blocks: [2]
no-lonely-if: [0]
no-loop-func: [0]
no-loss-of-precision: [2]
no-loss-of-precision: [0] # handled by @typescript-eslint/no-loss-of-precision
no-magic-numbers: [0]
no-misleading-character-class: [2]
no-multi-assign: [0]
Expand All @@ -493,7 +614,7 @@ rules:
no-promise-executor-return: [0]
no-proto: [2]
no-prototype-builtins: [2]
no-redeclare: [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, location, 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, self, status, statusbar, stop, toolbar, top, __dirname, __filename]
Expand Down Expand Up @@ -526,7 +647,7 @@ rules:
no-unused-expressions: [2]
no-unused-labels: [2]
no-unused-private-class-members: [2]
no-unused-vars: [2, {args: all, argsIgnorePattern: ^_, varsIgnorePattern: ^_, caughtErrorsIgnorePattern: ^_, destructuredArrayIgnorePattern: ^_, ignoreRestSiblings: false}]
no-unused-vars: [0] # handled by @typescript-eslint/no-unused-vars
no-use-before-define: [2, {functions: false, classes: true, variables: true, allowNamedExports: true}]
no-use-extend-native/no-use-extend-native: [2]
no-useless-backreference: [2]
Expand Down Expand Up @@ -641,7 +762,7 @@ rules:
regexp/unicode-escape: [0]
regexp/use-ignore-case: [0]
require-atomic-updates: [0]
require-await: [0]
require-await: [0] # handled by @typescript-eslint/require-await
require-unicode-regexp: [0]
require-yield: [2]
sonarjs/cognitive-complexity: [0]
Expand Down
16 changes: 16 additions & 0 deletions docs/content/contributing/guidelines-frontend.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ We use htmx for simple interactions. You can see an example for simple interacti
Although mixing different frameworks is discouraged,
it should also work if the mixing is necessary and the code is well-designed and maintainable.

### Typescript

Gitea is in the process of migrating to type-safe Typescript. Here are some specific guidelines regarding Typescript in the codebase:

#### Use type aliases instead of interfaces

Prefer to use type aliases because they can represent any type and are generally more flexible to use than interfaces.

#### Use separate type imports

We use `verbatimModuleSyntax` so type and non-type imports from the same file must be split into two `import type` statements. This enables the typescript compiler to completely eliminate the type import statements during compilation.

#### Use `@ts-expect-error` instead of `@ts-ignore`

Both annotations should be avoided, but if you have to use them, use `@ts-expect-error` because it will not leave ineffective statements after the issue is fixed.

### `async` Functions

Only mark a function as `async` if and only if there are `await` calls
Expand Down
35 changes: 27 additions & 8 deletions modules/git/repo_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,8 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
buffer := new(bytes.Buffer)
for _, file := range filenames {
if file != "" {
buffer.WriteString("0 ")
buffer.WriteString(objectFormat.EmptyObjectID().String())
buffer.WriteByte('\t')
buffer.WriteString(file)
buffer.WriteByte('\000')
// using format: mode SP type SP sha1 TAB path
buffer.WriteString("0 blob " + objectFormat.EmptyObjectID().String() + "\t" + file + "\000")
}
}
return cmd.Run(&RunOpts{
Expand All @@ -119,11 +116,33 @@ func (repo *Repository) RemoveFilesFromIndex(filenames ...string) error {
})
}

type IndexObjectInfo struct {
Mode string
Object ObjectID
Filename string
}

// AddObjectsToIndex adds the provided object hashes to the index at the provided filenames
func (repo *Repository) AddObjectsToIndex(objects ...IndexObjectInfo) error {
cmd := NewCommand(repo.Ctx, "update-index", "--add", "--replace", "-z", "--index-info")
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
buffer := new(bytes.Buffer)
for _, object := range objects {
// using format: mode SP type SP sha1 TAB path
buffer.WriteString(object.Mode + " blob " + object.Object.String() + "\t" + object.Filename + "\000")
}
return cmd.Run(&RunOpts{
Dir: repo.Path,
Stdin: bytes.NewReader(buffer.Bytes()),
Stdout: stdout,
Stderr: stderr,
})
}

// AddObjectToIndex adds the provided object hash to the index at the provided filename
func (repo *Repository) AddObjectToIndex(mode string, object ObjectID, filename string) error {
cmd := NewCommand(repo.Ctx, "update-index", "--add", "--replace", "--cacheinfo").AddDynamicArguments(mode, object.String(), filename)
_, _, err := cmd.RunStdString(&RunOpts{Dir: repo.Path})
return err
return repo.AddObjectsToIndex(IndexObjectInfo{Mode: mode, Object: object, Filename: filename})
}

// WriteTree writes the current index as a tree to the object db and returns its hash
Expand Down
Loading

0 comments on commit e9ea4a5

Please sign in to comment.