diff --git a/models/asymkey/gpg_key_add.go b/models/asymkey/gpg_key_add.go
index 1c7d2c1da2..3969edcc86 100644
--- a/models/asymkey/gpg_key_add.go
+++ b/models/asymkey/gpg_key_add.go
@@ -72,96 +72,90 @@ func AddGPGKey(ctx context.Context, ownerID int64, content, token, signature str
return nil, err
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return nil, err
- }
- defer committer.Close()
+ return db.WithTx2(ctx, func(ctx context.Context) ([]*GPGKey, error) {
+ keys := make([]*GPGKey, 0, len(ekeys))
- keys := make([]*GPGKey, 0, len(ekeys))
-
- verified := false
- // Handle provided signature
- if signature != "" {
- signer, err := openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token), strings.NewReader(signature), nil)
- if err != nil {
- signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\n"), strings.NewReader(signature), nil)
- }
- if err != nil {
- signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature), nil)
- }
- if err != nil {
- log.Debug("AddGPGKey CheckArmoredDetachedSignature failed: %v", err)
- return nil, ErrGPGInvalidTokenSignature{
- ID: ekeys[0].PrimaryKey.KeyIdString(),
- Wrapped: err,
+ verified := false
+ // Handle provided signature
+ if signature != "" {
+ signer, err := openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token), strings.NewReader(signature), nil)
+ if err != nil {
+ signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\n"), strings.NewReader(signature), nil)
}
+ if err != nil {
+ signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature), nil)
+ }
+ if err != nil {
+ log.Debug("AddGPGKey CheckArmoredDetachedSignature failed: %v", err)
+ return nil, ErrGPGInvalidTokenSignature{
+ ID: ekeys[0].PrimaryKey.KeyIdString(),
+ Wrapped: err,
+ }
+ }
+ ekeys = []*openpgp.Entity{signer}
+ verified = true
}
- ekeys = []*openpgp.Entity{signer}
- verified = true
- }
- if len(ekeys) > 1 {
- id2key := map[string]*openpgp.Entity{}
- newEKeys := make([]*openpgp.Entity, 0, len(ekeys))
- for _, ekey := range ekeys {
- id := ekey.PrimaryKey.KeyIdString()
- if original, has := id2key[id]; has {
- // Coalesce this with the other one
- for _, subkey := range ekey.Subkeys {
- if subkey.PublicKey == nil {
- continue
- }
- found := false
-
- for _, originalSubkey := range original.Subkeys {
- if originalSubkey.PublicKey == nil {
+ if len(ekeys) > 1 {
+ id2key := map[string]*openpgp.Entity{}
+ newEKeys := make([]*openpgp.Entity, 0, len(ekeys))
+ for _, ekey := range ekeys {
+ id := ekey.PrimaryKey.KeyIdString()
+ if original, has := id2key[id]; has {
+ // Coalesce this with the other one
+ for _, subkey := range ekey.Subkeys {
+ if subkey.PublicKey == nil {
continue
}
- if originalSubkey.PublicKey.KeyId == subkey.PublicKey.KeyId {
- found = true
- break
+ found := false
+
+ for _, originalSubkey := range original.Subkeys {
+ if originalSubkey.PublicKey == nil {
+ continue
+ }
+ if originalSubkey.PublicKey.KeyId == subkey.PublicKey.KeyId {
+ found = true
+ break
+ }
+ }
+ if !found {
+ original.Subkeys = append(original.Subkeys, subkey)
}
}
- if !found {
- original.Subkeys = append(original.Subkeys, subkey)
+ for name, identity := range ekey.Identities {
+ if _, has := original.Identities[name]; has {
+ continue
+ }
+ original.Identities[name] = identity
}
+ continue
}
- for name, identity := range ekey.Identities {
- if _, has := original.Identities[name]; has {
- continue
- }
- original.Identities[name] = identity
- }
- continue
+ id2key[id] = ekey
+ newEKeys = append(newEKeys, ekey)
}
- id2key[id] = ekey
- newEKeys = append(newEKeys, ekey)
- }
- ekeys = newEKeys
- }
-
- for _, ekey := range ekeys {
- // Key ID cannot be duplicated.
- has, err := db.GetEngine(ctx).Where("key_id=?", ekey.PrimaryKey.KeyIdString()).
- Get(new(GPGKey))
- if err != nil {
- return nil, err
- } else if has {
- return nil, ErrGPGKeyIDAlreadyUsed{ekey.PrimaryKey.KeyIdString()}
+ ekeys = newEKeys
}
- // Get DB session
+ for _, ekey := range ekeys {
+ // Key ID cannot be duplicated.
+ has, err := db.GetEngine(ctx).Where("key_id=?", ekey.PrimaryKey.KeyIdString()).
+ Get(new(GPGKey))
+ if err != nil {
+ return nil, err
+ } else if has {
+ return nil, ErrGPGKeyIDAlreadyUsed{ekey.PrimaryKey.KeyIdString()}
+ }
- key, err := parseGPGKey(ctx, ownerID, ekey, verified)
- if err != nil {
- return nil, err
- }
+ key, err := parseGPGKey(ctx, ownerID, ekey, verified)
+ if err != nil {
+ return nil, err
+ }
- if err = addGPGKey(ctx, key, content); err != nil {
- return nil, err
+ if err = addGPGKey(ctx, key, content); err != nil {
+ return nil, err
+ }
+ keys = append(keys, key)
}
- keys = append(keys, key)
- }
- return keys, committer.Commit()
+ return keys, nil
+ })
}
diff --git a/models/git/branch.go b/models/git/branch.go
index 6021e1101f..54351649cc 100644
--- a/models/git/branch.go
+++ b/models/git/branch.go
@@ -334,122 +334,111 @@ func FindRenamedBranch(ctx context.Context, repoID int64, from string) (branch *
// RenameBranch rename a branch
func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to string, gitAction func(ctx context.Context, isDefault bool) error) (err error) {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ sess := db.GetEngine(ctx)
- sess := db.GetEngine(ctx)
-
- // check whether from branch exist
- var branch Branch
- exist, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, from).Get(&branch)
- if err != nil {
- return err
- } else if !exist || branch.IsDeleted {
- return ErrBranchNotExist{
- RepoID: repo.ID,
- BranchName: from,
- }
- }
-
- // check whether to branch exist or is_deleted
- var dstBranch Branch
- exist, err = db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, to).Get(&dstBranch)
- if err != nil {
- return err
- }
- if exist {
- if !dstBranch.IsDeleted {
- return ErrBranchAlreadyExists{
- BranchName: to,
+ // check whether from branch exist
+ var branch Branch
+ exist, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, from).Get(&branch)
+ if err != nil {
+ return err
+ } else if !exist || branch.IsDeleted {
+ return ErrBranchNotExist{
+ RepoID: repo.ID,
+ BranchName: from,
}
}
- if _, err := db.GetEngine(ctx).ID(dstBranch.ID).NoAutoCondition().Delete(&dstBranch); err != nil {
- return err
- }
- }
-
- // 1. update branch in database
- if n, err := sess.Where("repo_id=? AND name=?", repo.ID, from).Update(&Branch{
- Name: to,
- }); err != nil {
- return err
- } else if n <= 0 {
- return ErrBranchNotExist{
- RepoID: repo.ID,
- BranchName: from,
- }
- }
-
- // 2. update default branch if needed
- isDefault := repo.DefaultBranch == from
- if isDefault {
- repo.DefaultBranch = to
- _, err = sess.ID(repo.ID).Cols("default_branch").Update(repo)
+ // check whether to branch exist or is_deleted
+ var dstBranch Branch
+ exist, err = db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, to).Get(&dstBranch)
if err != nil {
return err
}
- }
+ if exist {
+ if !dstBranch.IsDeleted {
+ return ErrBranchAlreadyExists{
+ BranchName: to,
+ }
+ }
- // 3. Update protected branch if needed
- protectedBranch, err := GetProtectedBranchRuleByName(ctx, repo.ID, from)
- if err != nil {
- return err
- }
+ if _, err := db.GetEngine(ctx).ID(dstBranch.ID).NoAutoCondition().Delete(&dstBranch); err != nil {
+ return err
+ }
+ }
- if protectedBranch != nil {
- // there is a protect rule for this branch
- protectedBranch.RuleName = to
- _, err = sess.ID(protectedBranch.ID).Cols("branch_name").Update(protectedBranch)
+ // 1. update branch in database
+ if n, err := sess.Where("repo_id=? AND name=?", repo.ID, from).Update(&Branch{
+ Name: to,
+ }); err != nil {
+ return err
+ } else if n <= 0 {
+ return ErrBranchNotExist{
+ RepoID: repo.ID,
+ BranchName: from,
+ }
+ }
+
+ // 2. update default branch if needed
+ isDefault := repo.DefaultBranch == from
+ if isDefault {
+ repo.DefaultBranch = to
+ _, err = sess.ID(repo.ID).Cols("default_branch").Update(repo)
+ if err != nil {
+ return err
+ }
+ }
+
+ // 3. Update protected branch if needed
+ protectedBranch, err := GetProtectedBranchRuleByName(ctx, repo.ID, from)
if err != nil {
return err
}
- } else {
- // some glob protect rules may match this branch
- protected, err := IsBranchProtected(ctx, repo.ID, from)
+
+ if protectedBranch != nil {
+ // there is a protect rule for this branch
+ protectedBranch.RuleName = to
+ if _, err = sess.ID(protectedBranch.ID).Cols("branch_name").Update(protectedBranch); err != nil {
+ return err
+ }
+ } else {
+ // some glob protect rules may match this branch
+ protected, err := IsBranchProtected(ctx, repo.ID, from)
+ if err != nil {
+ return err
+ }
+ if protected {
+ return ErrBranchIsProtected
+ }
+ }
+
+ // 4. Update all not merged pull request base branch name
+ _, err = sess.Table("pull_request").Where("base_repo_id=? AND base_branch=? AND has_merged=?",
+ repo.ID, from, false).
+ Update(map[string]any{"base_branch": to})
if err != nil {
return err
}
- if protected {
- return ErrBranchIsProtected
+
+ // 4.1 Update all not merged pull request head branch name
+ if _, err = sess.Table("pull_request").Where("head_repo_id=? AND head_branch=? AND has_merged=?",
+ repo.ID, from, false).
+ Update(map[string]any{"head_branch": to}); err != nil {
+ return err
}
- }
- // 4. Update all not merged pull request base branch name
- _, err = sess.Table("pull_request").Where("base_repo_id=? AND base_branch=? AND has_merged=?",
- repo.ID, from, false).
- Update(map[string]any{"base_branch": to})
- if err != nil {
- return err
- }
+ // 5. insert renamed branch record
+ if err = db.Insert(ctx, &RenamedBranch{
+ RepoID: repo.ID,
+ From: from,
+ To: to,
+ }); err != nil {
+ return err
+ }
- // 4.1 Update all not merged pull request head branch name
- if _, err = sess.Table("pull_request").Where("head_repo_id=? AND head_branch=? AND has_merged=?",
- repo.ID, from, false).
- Update(map[string]any{"head_branch": to}); err != nil {
- return err
- }
-
- // 5. insert renamed branch record
- renamedBranch := &RenamedBranch{
- RepoID: repo.ID,
- From: from,
- To: to,
- }
- err = db.Insert(ctx, renamedBranch)
- if err != nil {
- return err
- }
-
- // 6. do git action
- if err = gitAction(ctx, isDefault); err != nil {
- return err
- }
-
- return committer.Commit()
+ // 6. do git action
+ return gitAction(ctx, isDefault)
+ })
}
type FindRecentlyPushedNewBranchesOptions struct {
diff --git a/models/git/lfs.go b/models/git/lfs.go
index c471baf588..8bba060ff9 100644
--- a/models/git/lfs.go
+++ b/models/git/lfs.go
@@ -180,29 +180,25 @@ func RemoveLFSMetaObjectByOidFn(ctx context.Context, repoID int64, oid string, f
return 0, ErrLFSObjectNotExist
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return 0, err
- }
- defer committer.Close()
+ return db.WithTx2(ctx, func(ctx context.Context) (int64, error) {
+ m := &LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}, RepositoryID: repoID}
+ if _, err := db.DeleteByBean(ctx, m); err != nil {
+ return -1, err
+ }
- m := &LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}, RepositoryID: repoID}
- if _, err := db.DeleteByBean(ctx, m); err != nil {
- return -1, err
- }
-
- count, err := db.CountByBean(ctx, &LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}})
- if err != nil {
- return count, err
- }
-
- if fn != nil {
- if err := fn(count); err != nil {
+ count, err := db.CountByBean(ctx, &LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}})
+ if err != nil {
return count, err
}
- }
- return count, committer.Commit()
+ if fn != nil {
+ if err := fn(count); err != nil {
+ return count, err
+ }
+ }
+
+ return count, nil
+ })
}
// GetLFSMetaObjects returns all LFSMetaObjects associated with a repository
@@ -243,56 +239,46 @@ func ExistsLFSObject(ctx context.Context, oid string) (bool, error) {
// LFSAutoAssociate auto associates accessible LFSMetaObjects
func LFSAutoAssociate(ctx context.Context, metas []*LFSMetaObject, user *user_model.User, repoID int64) error {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ oids := make([]any, len(metas))
+ oidMap := make(map[string]*LFSMetaObject, len(metas))
+ for i, meta := range metas {
+ oids[i] = meta.Oid
+ oidMap[meta.Oid] = meta
+ }
- sess := db.GetEngine(ctx)
+ if !user.IsAdmin {
+ newMetas := make([]*LFSMetaObject, 0, len(metas))
+ cond := builder.In(
+ "`lfs_meta_object`.repository_id",
+ builder.Select("`repository`.id").From("repository").Where(repo_model.AccessibleRepositoryCondition(user, unit.TypeInvalid)),
+ )
+ if err := db.GetEngine(ctx).Cols("oid").Where(cond).In("oid", oids...).GroupBy("oid").Find(&newMetas); err != nil {
+ return err
+ }
+ if len(newMetas) != len(oidMap) {
+ return fmt.Errorf("unable collect all LFS objects from database, expected %d, actually %d", len(oidMap), len(newMetas))
+ }
+ for i := range newMetas {
+ newMetas[i].Size = oidMap[newMetas[i].Oid].Size
+ newMetas[i].RepositoryID = repoID
+ }
+ return db.Insert(ctx, newMetas)
+ }
- oids := make([]any, len(metas))
- oidMap := make(map[string]*LFSMetaObject, len(metas))
- for i, meta := range metas {
- oids[i] = meta.Oid
- oidMap[meta.Oid] = meta
- }
-
- if !user.IsAdmin {
- newMetas := make([]*LFSMetaObject, 0, len(metas))
- cond := builder.In(
- "`lfs_meta_object`.repository_id",
- builder.Select("`repository`.id").From("repository").Where(repo_model.AccessibleRepositoryCondition(user, unit.TypeInvalid)),
- )
- err = sess.Cols("oid").Where(cond).In("oid", oids...).GroupBy("oid").Find(&newMetas)
- if err != nil {
- return err
- }
- if len(newMetas) != len(oidMap) {
- return fmt.Errorf("unable collect all LFS objects from database, expected %d, actually %d", len(oidMap), len(newMetas))
- }
- for i := range newMetas {
- newMetas[i].Size = oidMap[newMetas[i].Oid].Size
- newMetas[i].RepositoryID = repoID
- }
- if err = db.Insert(ctx, newMetas); err != nil {
- return err
- }
- } else {
// admin can associate any LFS object to any repository, and we do not care about errors (eg: duplicated unique key),
// even if error occurs, it won't hurt users and won't make things worse
for i := range metas {
p := lfs.Pointer{Oid: metas[i].Oid, Size: metas[i].Size}
- _, err = sess.Insert(&LFSMetaObject{
+ if err := db.Insert(ctx, &LFSMetaObject{
Pointer: p,
RepositoryID: repoID,
- })
- if err != nil {
+ }); err != nil {
log.Warn("failed to insert LFS meta object %-v for repo_id: %d into database, err=%v", p, repoID, err)
}
}
- }
- return committer.Commit()
+ return nil
+ })
}
// CopyLFS copies LFS data from one repo to another
diff --git a/models/issues/assignees.go b/models/issues/assignees.go
index efd992cda2..54f995dd2e 100644
--- a/models/issues/assignees.go
+++ b/models/issues/assignees.go
@@ -91,18 +91,10 @@ func GetAssignedIssues(ctx context.Context, opts *AssignedIssuesOptions) ([]*Iss
// ToggleIssueAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
func ToggleIssueAssignee(ctx context.Context, issue *Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *Comment, err error) {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return false, nil, err
- }
- defer committer.Close()
-
- removed, comment, err = toggleIssueAssignee(ctx, issue, doer, assigneeID, false)
- if err != nil {
- return false, nil, err
- }
-
- if err := committer.Commit(); err != nil {
+ if err := db.WithTx(ctx, func(ctx context.Context) error {
+ removed, comment, err = toggleIssueAssignee(ctx, issue, doer, assigneeID, false)
+ return err
+ }); err != nil {
return false, nil, err
}
diff --git a/models/issues/comment.go b/models/issues/comment.go
index a366b7c6a9..3a4049700d 100644
--- a/models/issues/comment.go
+++ b/models/issues/comment.go
@@ -279,8 +279,8 @@ type Comment struct {
DependentIssue *Issue `xorm:"-"`
CommitID int64
- Line int64 // - previous line / + proposed line
- TreePath string
+ Line int64 // - previous line / + proposed line
+ TreePath string `xorm:"VARCHAR(4000)"` // SQLServer only supports up to 4000
Content string `xorm:"LONGTEXT"`
ContentVersion int `xorm:"NOT NULL DEFAULT 0"`
RenderedContent template.HTML `xorm:"-"`
diff --git a/models/issues/issue_update.go b/models/issues/issue_update.go
index 1c16817491..553e99aece 100644
--- a/models/issues/issue_update.go
+++ b/models/issues/issue_update.go
@@ -415,37 +415,28 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue
// NewIssue creates new issue with labels for repository.
// The title will be cut off at 255 characters if it's longer than 255 characters.
func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- idx, err := db.GetNextResourceIndex(ctx, "issue_index", repo.ID)
- if err != nil {
- return fmt.Errorf("generate issue index failed: %w", err)
- }
-
- issue.Index = idx
- issue.Title = util.EllipsisDisplayString(issue.Title, 255)
-
- if err = NewIssueWithIndex(ctx, issue.Poster, NewIssueOptions{
- Repo: repo,
- Issue: issue,
- LabelIDs: labelIDs,
- Attachments: uuids,
- }); err != nil {
- if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
- return err
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ idx, err := db.GetNextResourceIndex(ctx, "issue_index", repo.ID)
+ if err != nil {
+ return fmt.Errorf("generate issue index failed: %w", err)
}
- return fmt.Errorf("newIssue: %w", err)
- }
- if err = committer.Commit(); err != nil {
- return fmt.Errorf("Commit: %w", err)
- }
+ issue.Index = idx
+ issue.Title = util.EllipsisDisplayString(issue.Title, 255)
- return nil
+ if err = NewIssueWithIndex(ctx, issue.Poster, NewIssueOptions{
+ Repo: repo,
+ Issue: issue,
+ LabelIDs: labelIDs,
+ Attachments: uuids,
+ }); err != nil {
+ if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) || IsErrNewIssueInsert(err) {
+ return err
+ }
+ return fmt.Errorf("newIssue: %w", err)
+ }
+ return nil
+ })
}
// UpdateIssueMentions updates issue-user relations for mentioned users.
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 88967a8b87..1b1558f39d 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -393,6 +393,7 @@ func prepareMigrationTasks() []*migration {
// Gitea 1.24.0 ends at database version 321
newMigration(321, "Use LONGTEXT for some columns and fix review_state.updated_files column", v1_25.UseLongTextInSomeColumnsAndFixBugs),
+ newMigration(322, "Extend comment tree_path length limit", v1_25.ExtendCommentTreePathLength),
}
return preparedMigrations
}
diff --git a/models/migrations/v1_25/v322.go b/models/migrations/v1_25/v322.go
new file mode 100644
index 0000000000..32dae9945a
--- /dev/null
+++ b/models/migrations/v1_25/v322.go
@@ -0,0 +1,28 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package v1_25
+
+import (
+ "code.gitea.io/gitea/models/migrations/base"
+
+ "xorm.io/xorm"
+ "xorm.io/xorm/schemas"
+)
+
+func ExtendCommentTreePathLength(x *xorm.Engine) error {
+ dbType := x.Dialect().URI().DBType
+ if dbType == schemas.SQLITE { // For SQLITE, varchar or char will always be represented as TEXT
+ return nil
+ }
+
+ return base.ModifyColumn(x, "comment", &schemas.Column{
+ Name: "tree_path",
+ SQLType: schemas.SQLType{
+ Name: "VARCHAR",
+ },
+ Length: 4000,
+ Nullable: true, // To keep compatible as nullable
+ DefaultIsEmpty: true,
+ })
+}
diff --git a/models/user/email_address.go b/models/user/email_address.go
index cb423945f8..67aa1bdd82 100644
--- a/models/user/email_address.go
+++ b/models/user/email_address.go
@@ -442,58 +442,53 @@ func SearchEmails(ctx context.Context, opts *SearchEmailOptions) ([]*SearchEmail
// ActivateUserEmail will change the activated state of an email address,
// either primary or secondary (all in the email_address table)
func ActivateUserEmail(ctx context.Context, userID int64, email string, activate bool) (err error) {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- // Activate/deactivate a user's secondary email address
- // First check if there's another user active with the same address
- addr, exist, err := db.Get[EmailAddress](ctx, builder.Eq{"uid": userID, "lower_email": strings.ToLower(email)})
- if err != nil {
- return err
- } else if !exist {
- return fmt.Errorf("no such email: %d (%s)", userID, email)
- }
-
- if addr.IsActivated == activate {
- // Already in the desired state; no action
- return nil
- }
- if activate {
- if used, err := IsEmailActive(ctx, email, addr.ID); err != nil {
- return fmt.Errorf("unable to check isEmailActive() for %s: %w", email, err)
- } else if used {
- return ErrEmailAlreadyUsed{Email: email}
- }
- }
- if err = updateActivation(ctx, addr, activate); err != nil {
- return fmt.Errorf("unable to updateActivation() for %d:%s: %w", addr.ID, addr.Email, err)
- }
-
- // Activate/deactivate a user's primary email address and account
- if addr.IsPrimary {
- user, exist, err := db.Get[User](ctx, builder.Eq{"id": userID})
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ // Activate/deactivate a user's secondary email address
+ // First check if there's another user active with the same address
+ addr, exist, err := db.Get[EmailAddress](ctx, builder.Eq{"uid": userID, "lower_email": strings.ToLower(email)})
if err != nil {
return err
- } else if !exist || !strings.EqualFold(user.Email, email) {
- return fmt.Errorf("no user with ID: %d and Email: %s", userID, email)
+ } else if !exist {
+ return fmt.Errorf("no such email: %d (%s)", userID, email)
}
- // The user's activation state should be synchronized with the primary email
- if user.IsActive != activate {
- user.IsActive = activate
- if user.Rands, err = GetUserSalt(); err != nil {
- return fmt.Errorf("unable to generate salt: %w", err)
- }
- if err = UpdateUserCols(ctx, user, "is_active", "rands"); err != nil {
- return fmt.Errorf("unable to updateUserCols() for user ID: %d: %w", userID, err)
+ if addr.IsActivated == activate {
+ // Already in the desired state; no action
+ return nil
+ }
+ if activate {
+ if used, err := IsEmailActive(ctx, email, addr.ID); err != nil {
+ return fmt.Errorf("unable to check isEmailActive() for %s: %w", email, err)
+ } else if used {
+ return ErrEmailAlreadyUsed{Email: email}
}
}
- }
+ if err = updateActivation(ctx, addr, activate); err != nil {
+ return fmt.Errorf("unable to updateActivation() for %d:%s: %w", addr.ID, addr.Email, err)
+ }
- return committer.Commit()
+ // Activate/deactivate a user's primary email address and account
+ if addr.IsPrimary {
+ user, exist, err := db.Get[User](ctx, builder.Eq{"id": userID})
+ if err != nil {
+ return err
+ } else if !exist || !strings.EqualFold(user.Email, email) {
+ return fmt.Errorf("no user with ID: %d and Email: %s", userID, email)
+ }
+
+ // The user's activation state should be synchronized with the primary email
+ if user.IsActive != activate {
+ user.IsActive = activate
+ if user.Rands, err = GetUserSalt(); err != nil {
+ return fmt.Errorf("unable to generate salt: %w", err)
+ }
+ if err = UpdateUserCols(ctx, user, "is_active", "rands"); err != nil {
+ return fmt.Errorf("unable to updateUserCols() for user ID: %d: %w", userID, err)
+ }
+ }
+ }
+ return nil
+ })
}
// validateEmailBasic checks whether the email complies with the rules
diff --git a/models/user/user.go b/models/user/user.go
index ae500f3a1f..6143992a25 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -716,90 +716,82 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o
}
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- isExist, err := IsUserExist(ctx, 0, u.Name)
- if err != nil {
- return err
- } else if isExist {
- return ErrUserAlreadyExist{u.Name}
- }
-
- isExist, err = IsEmailUsed(ctx, u.Email)
- if err != nil {
- return err
- } else if isExist {
- return ErrEmailAlreadyUsed{
- Email: u.Email,
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ isExist, err := IsUserExist(ctx, 0, u.Name)
+ if err != nil {
+ return err
+ } else if isExist {
+ return ErrUserAlreadyExist{u.Name}
}
- }
- // prepare for database
+ isExist, err = IsEmailUsed(ctx, u.Email)
+ if err != nil {
+ return err
+ } else if isExist {
+ return ErrEmailAlreadyUsed{
+ Email: u.Email,
+ }
+ }
- u.LowerName = strings.ToLower(u.Name)
- u.AvatarEmail = u.Email
- if u.Rands, err = GetUserSalt(); err != nil {
- return err
- }
- if u.Passwd != "" {
- if err = u.SetPassword(u.Passwd); err != nil {
+ // prepare for database
+
+ u.LowerName = strings.ToLower(u.Name)
+ u.AvatarEmail = u.Email
+ if u.Rands, err = GetUserSalt(); err != nil {
return err
}
- } else {
- u.Salt = ""
- u.PasswdHashAlgo = ""
- }
+ if u.Passwd != "" {
+ if err = u.SetPassword(u.Passwd); err != nil {
+ return err
+ }
+ } else {
+ u.Salt = ""
+ u.PasswdHashAlgo = ""
+ }
- // save changes to database
+ // save changes to database
- if err = DeleteUserRedirect(ctx, u.Name); err != nil {
- return err
- }
-
- if u.CreatedUnix == 0 {
- // Caller expects auto-time for creation & update timestamps.
- err = db.Insert(ctx, u)
- } else {
- // Caller sets the timestamps themselves. They are responsible for ensuring
- // both `CreatedUnix` and `UpdatedUnix` are set appropriately.
- _, err = db.GetEngine(ctx).NoAutoTime().Insert(u)
- }
- if err != nil {
- return err
- }
-
- if setting.RecordUserSignupMetadata {
- // insert initial IP and UserAgent
- if err = SetUserSetting(ctx, u.ID, SignupIP, meta.InitialIP); err != nil {
+ if err = DeleteUserRedirect(ctx, u.Name); err != nil {
return err
}
- // trim user agent string to a reasonable length, if necessary
- userAgent := strings.TrimSpace(meta.InitialUserAgent)
- if len(userAgent) > 255 {
- userAgent = userAgent[:255]
+ if u.CreatedUnix == 0 {
+ // Caller expects auto-time for creation & update timestamps.
+ err = db.Insert(ctx, u)
+ } else {
+ // Caller sets the timestamps themselves. They are responsible for ensuring
+ // both `CreatedUnix` and `UpdatedUnix` are set appropriately.
+ _, err = db.GetEngine(ctx).NoAutoTime().Insert(u)
}
- if err = SetUserSetting(ctx, u.ID, SignupUserAgent, userAgent); err != nil {
+ if err != nil {
return err
}
- }
- // insert email address
- if err := db.Insert(ctx, &EmailAddress{
- UID: u.ID,
- Email: u.Email,
- LowerEmail: strings.ToLower(u.Email),
- IsActivated: u.IsActive,
- IsPrimary: true,
- }); err != nil {
- return err
- }
+ if setting.RecordUserSignupMetadata {
+ // insert initial IP and UserAgent
+ if err = SetUserSetting(ctx, u.ID, SignupIP, meta.InitialIP); err != nil {
+ return err
+ }
- return committer.Commit()
+ // trim user agent string to a reasonable length, if necessary
+ userAgent := strings.TrimSpace(meta.InitialUserAgent)
+ if len(userAgent) > 255 {
+ userAgent = userAgent[:255]
+ }
+ if err = SetUserSetting(ctx, u.ID, SignupUserAgent, userAgent); err != nil {
+ return err
+ }
+ }
+
+ // insert email address
+ return db.Insert(ctx, &EmailAddress{
+ UID: u.ID,
+ Email: u.Email,
+ LowerEmail: strings.ToLower(u.Email),
+ IsActivated: u.IsActive,
+ IsPrimary: true,
+ })
+ })
}
// ErrDeleteLastAdminUser represents a "DeleteLastAdminUser" kind of error.
diff --git a/options/fileicon/material-icon-rules.json b/options/fileicon/material-icon-rules.json
index 15bbf613db..622564fe2b 100644
--- a/options/fileicon/material-icon-rules.json
+++ b/options/fileicon/material-icon-rules.json
@@ -3367,6 +3367,22 @@
"..claude": "folder-claude",
"_.claude": "folder-claude",
"__.claude__": "folder-claude",
+ ".cursor": "folder-cursor",
+ "..cursor": "folder-cursor",
+ "_.cursor": "folder-cursor",
+ "__.cursor__": "folder-cursor",
+ "metro": "folder-metro",
+ ".metro": "folder-metro",
+ "_metro": "folder-metro",
+ "__metro__": "folder-metro",
+ "filter": "folder-filter",
+ ".filter": "folder-filter",
+ "_filter": "folder-filter",
+ "__filter__": "folder-filter",
+ "filters": "folder-filter",
+ ".filters": "folder-filter",
+ "_filters": "folder-filter",
+ "__filters__": "folder-filter",
"meta-inf": "folder-config",
".meta-inf": "folder-config",
"_meta-inf": "folder-config",
@@ -6763,7 +6779,23 @@
".claude": "folder-claude-open",
"..claude": "folder-claude-open",
"_.claude": "folder-claude-open",
- "__.claude__": "folder-claude-open"
+ "__.claude__": "folder-claude-open",
+ ".cursor": "folder-cursor-open",
+ "..cursor": "folder-cursor-open",
+ "_.cursor": "folder-cursor-open",
+ "__.cursor__": "folder-cursor-open",
+ "metro": "folder-metro-open",
+ ".metro": "folder-metro-open",
+ "_metro": "folder-metro-open",
+ "__metro__": "folder-metro-open",
+ "filter": "folder-filter-open",
+ ".filter": "folder-filter-open",
+ "_filter": "folder-filter-open",
+ "__filter__": "folder-filter-open",
+ "filters": "folder-filter-open",
+ ".filters": "folder-filter-open",
+ "_filters": "folder-filter-open",
+ "__filters__": "folder-filter-open"
},
"rootFolderNames": {},
"rootFolderNamesExpanded": {},
@@ -6800,6 +6832,7 @@
"sublime-project": "sublime",
"sublime-workspace": "sublime",
"slx": "simulink",
+ "qmd": "quarto",
"tw": "twine",
"twee": "twine",
"yml.dist": "yaml",
@@ -7366,6 +7399,7 @@
"mli": "ocaml",
"cmx": "ocaml",
"odin": "odin",
+ "onnx": "onnx",
"js.map": "javascript-map",
"mjs.map": "javascript-map",
"cjs.map": "javascript-map",
@@ -7468,6 +7502,7 @@
"tfvars": "terraform",
"tfstate": "terraform",
"tfbackend": "terraform",
+ "tofu": "opentofu",
"blade.php": "laravel",
"inky.php": "laravel",
"applescript": "applescript",
@@ -7761,12 +7796,24 @@
"geom": "shader",
"frag": "shader",
"comp": "shader",
+ "rgen": "shader",
+ "rint": "shader",
+ "rahit": "shader",
+ "rchit": "shader",
+ "rmiss": "shader",
+ "rcall": "shader",
"vert.glsl": "shader",
"tesc.glsl": "shader",
"tese.glsl": "shader",
"geom.glsl": "shader",
"frag.glsl": "shader",
"comp.glsl": "shader",
+ "rgen.glsl": "shader",
+ "rint.glsl": "shader",
+ "rahit.glsl": "shader",
+ "rchit.glsl": "shader",
+ "rmiss.glsl": "shader",
+ "rcall.glsl": "shader",
"vertex.glsl": "shader",
"geometry.glsl": "shader",
"fragment.glsl": "shader",
@@ -7790,6 +7837,8 @@
"comp.hlsl": "shader",
"tess.hlsl": "shader",
"wgsl": "shader",
+ "spv": "shader",
+ "slang": "shader",
"sy": "siyuan",
"ndst.yml": "ndst",
"ndst.yaml": "ndst",
@@ -7852,6 +7901,7 @@
"hurl": "hurl",
"cds": "cds",
"slint": "slint",
+ "verse": "verse",
"sw": "sway",
"zeabur": "zeabur",
"bench.ts": "bench-ts",
@@ -9004,6 +9054,7 @@
".eslintrc.base.json": "eslint",
".eslintignore": "eslint",
".eslintcache": "eslint",
+ "eslint-options.js": "eslint",
"code_of_conduct.md": "conduct",
"code_of_conduct.txt": "conduct",
"code_of_conduct": "conduct",
@@ -9025,6 +9076,7 @@
".mocharc.json": "mocha",
".mocharc.jsonc": "mocha",
"jenkinsfile": "jenkins",
+ "firebase.config.js": "firebase",
"firebase.json": "firebase",
".firebaserc": "firebase",
"firestore.rules": "firebase",
@@ -10032,6 +10084,18 @@
".oxlintrc.json": "oxlint",
"CLAUDE.md": "claude",
"CLAUDE.local.md": "claude",
+ ".cursorignore": "cursor",
+ ".cursorindexingignore": "cursor",
+ ".cursorrules": "cursor",
+ ".cursor": "cursor",
+ ".cursor.json": "cursor",
+ ".cursorrc": "cursor",
+ "metro.config.js": "metro",
+ "metro.config.json": "metro",
+ "src/bashly.yaml": "bashly",
+ "src/bashly.yml": "bashly",
+ "bashly-settings.yaml": "bashly-settings",
+ "bashly-settings.yml": "bashly-settings",
"xamlstyler.json": "xaml",
".rhistory": "r",
"cmakepresets.json": "cmake",
@@ -10113,6 +10177,7 @@
"haml": "haml",
"yang": "yang",
"terraform": "terraform",
+ "opentofu": "opentofu",
"applescript": "applescript",
"cake": "cake",
"cucumber": "cucumber",
@@ -10243,7 +10308,8 @@
"beancount": "beancount",
"ahk2": "ahk2",
"gnuplot": "gnuplot",
- "helm": "helm"
+ "helm": "helm",
+ "nginx": "nginx"
},
"light": {
"fileExtensions": {
@@ -10253,6 +10319,7 @@
"j2": "jinja_light",
"jinja-html": "jinja_light",
"toml": "toml_light",
+ "tofu": "opentofu_light",
"huff": "huff_light",
"cr": "crystal_light",
"ecr": "crystal_light",
@@ -10275,6 +10342,7 @@
"openapi.yml": "openapi_light",
"openapi.yaml": "openapi_light",
"tldr": "tldraw_light",
+ "verse": "verse_light",
"zeabur": "zeabur_light"
},
"fileNames": {
@@ -10437,7 +10505,15 @@
"zeabur.yml": "zeabur_light",
"zeabur.toml": "zeabur_light",
"copilot-instructions.md": "copilot_light",
- "hosts": "hosts_light"
+ "hosts": "hosts_light",
+ ".cursorignore": "cursor_light",
+ ".cursorindexingignore": "cursor_light",
+ ".cursorrules": "cursor_light",
+ ".cursor": "cursor_light",
+ ".cursor.json": "cursor_light",
+ ".cursorrc": "cursor_light",
+ "bashly-settings.yaml": "bashly-settings_light",
+ "bashly-settings.yml": "bashly-settings_light"
},
"languageIds": {
"toml": "toml_light",
@@ -10460,7 +10536,11 @@
"idea": "folder-intellij_light",
".idea": "folder-intellij_light",
"_idea": "folder-intellij_light",
- "__idea__": "folder-intellij_light"
+ "__idea__": "folder-intellij_light",
+ ".cursor": "folder-cursor_light",
+ "..cursor": "folder-cursor_light",
+ "_.cursor": "folder-cursor_light",
+ "__.cursor__": "folder-cursor_light"
},
"folderNamesExpanded": {
"jinja": "folder-jinja-open_light",
@@ -10478,7 +10558,11 @@
"idea": "folder-intellij-open_light",
".idea": "folder-intellij-open_light",
"_idea": "folder-intellij-open_light",
- "__idea__": "folder-intellij-open_light"
+ "__idea__": "folder-intellij-open_light",
+ ".cursor": "folder-cursor-open_light",
+ "..cursor": "folder-cursor-open_light",
+ "_.cursor": "folder-cursor-open_light",
+ "__.cursor__": "folder-cursor-open_light"
},
"rootFolderNames": {},
"rootFolderNamesExpanded": {}
diff --git a/options/fileicon/material-icon-svgs.json b/options/fileicon/material-icon-svgs.json
index 9d1e0ee075..9aa78359da 100644
--- a/options/fileicon/material-icon-svgs.json
+++ b/options/fileicon/material-icon-svgs.json
@@ -49,6 +49,10 @@
"azure": "",
"babel": "",
"ballerina": "",
+ "bashly-hook": "",
+ "bashly-settings.clone": "",
+ "bashly-settings_light.clone": "",
+ "bashly": "",
"bazel": "",
"bbx": "",
"beancount": "",
@@ -116,7 +120,7 @@
"commitlint": "",
"concourse": "",
"conduct": "",
- "console": "",
+ "console": "",
"container.clone": "",
"contentlayer": "",
"context": "",
@@ -134,6 +138,8 @@
"css": "",
"cucumber": "",
"cuda": "",
+ "cursor": "",
+ "cursor_light": "",
"cypress": "",
"d": "",
"dart": "",
@@ -287,6 +293,10 @@
"folder-coverage": "",
"folder-css-open": "",
"folder-css": "",
+ "folder-cursor-open": "",
+ "folder-cursor-open_light": "",
+ "folder-cursor": "",
+ "folder-cursor_light": "",
"folder-custom-open": "",
"folder-custom": "",
"folder-cypress-open": "",
@@ -339,6 +349,8 @@
"folder-fastlane": "",
"folder-favicon-open": "",
"folder-favicon": "",
+ "folder-filter-open": "",
+ "folder-filter": "",
"folder-firebase-open": "",
"folder-firebase": "",
"folder-firestore-open": "",
@@ -463,6 +475,8 @@
"folder-messages": "",
"folder-meta-open": "",
"folder-meta": "",
+ "folder-metro-open": "",
+ "folder-metro": "",
"folder-middleware-open": "",
"folder-middleware": "",
"folder-mjml-open": "",
@@ -830,6 +844,7 @@
"merlin": "",
"mermaid": "",
"meson": "",
+ "metro": "",
"minecraft-fabric": "",
"minecraft": "",
"mint": "",
@@ -881,10 +896,13 @@
"objective-cpp": "",
"ocaml": "",
"odin": "",
+ "onnx": "",
"opa": "",
"opam": "",
"openapi": "",
"openapi_light": "",
+ "opentofu": "",
+ "opentofu_light": "",
"otne": "",
"oxlint": "",
"packship": "",
@@ -935,6 +953,7 @@
"python": "",
"pytorch": "",
"qsharp": "",
+ "quarto": "",
"quasar": "",
"quokka": "",
"qwik": "",
@@ -1100,6 +1119,8 @@
"verdaccio": "",
"verified": "",
"verilog": "",
+ "verse": "",
+ "verse_light": "",
"vfl": "",
"video": "",
"vim": "",
diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini
index f75976bc4f..adf349e9d8 100644
--- a/options/locale/locale_fr-FR.ini
+++ b/options/locale/locale_fr-FR.ini
@@ -120,6 +120,7 @@ error404=La page que vous essayez d'atteindre n'existe pas ou <
error503=Le serveur n’a pas pu répondre à votre demande. Veuillez réessayer plus tard.
go_back=Retour
invalid_data=Données invalides : %v
+nothing_has_been_changed=Rien n’a été changé.
never=Jamais
unknown=Inconnu
@@ -550,6 +551,13 @@ repo.transfer.body=Pour l’accepter ou le rejeter, visitez %s ou ignorez-le.
repo.collaborator.added.subject=%s vous a ajouté à %s
repo.collaborator.added.text=Vous avez été ajouté en tant que collaborateur du dépôt :
+repo.actions.run.failed=L’exécution a échoué
+repo.actions.run.succeeded=L’exécution a réussi
+repo.actions.run.cancelled=L’exécution a été annulée
+repo.actions.jobs.all_succeeded=Tous les tâches ont réussi.
+repo.actions.jobs.all_failed=Toutes les tâches ont échoué.
+repo.actions.jobs.some_not_successful=Certaines tâches n’ont pas réussi.
+repo.actions.jobs.all_cancelled=Toutes les tâches ont bien été annulés.
team_invite.subject=%[1]s vous a invité à rejoindre l’organisation %[2]s
team_invite.text_1=%[1]s vous a invité à rejoindre l’équipe %[2]s dans l’organisation %[3]s.
@@ -2844,6 +2852,11 @@ settings.location=Localisation
settings.permission=Autorisations
settings.repoadminchangeteam=L'administrateur de dépôt peut ajouter et supprimer l'accès aux équipes
settings.visibility=Visibilité
+settings.change_visibility=Modifier la visibilité
+settings.change_visibility_notices_1=Si l’organisation est convertie en privé, les étoiles du dépôt seront supprimées et ne pourront pas être restaurées.
+settings.change_visibility_notices_2=Les non-membres ne pourront plus accéder aux dépôts de l’organisation si la visibilité devient privée.
+settings.change_visibility_success=La visibilité de l’organisation %s a été modifiée.
+settings.visibility_desc=Changez qui peut voir l’organisation et ses dépôts.
settings.visibility.public=Public
settings.visibility.limited=Limité (Visible uniquement aux utilisateurs authentifiés)
settings.visibility.limited_shortname=Limité
@@ -3420,6 +3433,7 @@ config.picture_service=Service d'Imagerie
config.disable_gravatar=Désactiver Gravatar
config.enable_federated_avatar=Activer les avatars unifiés
config.open_with_editor_app_help=Les éditeurs disponibles via « Ouvrir avec ». Si laissé vide, la valeur par défaut sera utilisée. Développez pour voir la valeur par défaut.
+config.git_guide_remote_name=Nom du dépôt distant pour les commandes git dans le guide
config.git_config=Configuration de Git
config.git_disable_diff_highlight=Désactiver la surbrillance syntaxique de Diff
diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini
index e345c336b4..4232562994 100644
--- a/options/locale/locale_pt-BR.ini
+++ b/options/locale/locale_pt-BR.ini
@@ -1010,9 +1010,9 @@ visibility.private_tooltip=VisÃvel apenas para membros das organizações à s q
new_repo_helper=Um repositório contém todos os arquivos do projeto, inclusive o histórico de revisões. Já está hospedando um em outro lugar? Migre o repositório.
owner=Proprietário
owner_helper=Algumas organizações podem não aparecer no menu devido a um limite de contagem dos repositórios.
-repo_name=Nome do repositório
+repo_name=Nome do Repositório
repo_name_helper=Bons nomes de repositórios usam palavras-chave curtas, memorizáveis e únicas. Um repositório chamado ".profile" ou ".profile-private" pode ser usado para adicionar um README.md para seu perfil de usuário/organização.
-repo_size=Tamanho do repositório
+repo_size=Tamanho do Repositório
template=Modelo
template_select=Selecione um modelo.
template_helper=Tornar repositório um modelo
@@ -1079,7 +1079,7 @@ mirror_lfs=Armazenamento de Arquivo Grande (LFS)
mirror_lfs_desc=Ativar espelhamento de dados LFS.
mirror_lfs_endpoint=Destino LFS
mirror_lfs_endpoint_desc=A sincronização tentará usar o URL de clonagem para determinar o servidor LFS. Você também pode especificar um destino personalizado se os dados do repositório LFS forem armazenados em outro lugar.
-mirror_last_synced=Última sincronização
+mirror_last_synced=Última Sincronização
mirror_password_placeholder=(inalterada)
mirror_password_blank_placeholder=(não definida)
mirror_password_help=Altere o nome de usuário para apagar uma senha armazenada.
@@ -1148,7 +1148,7 @@ migrate_options_lfs_endpoint.label=Destino LFS
migrate_options_lfs_endpoint.description=A migração tentará usar seu controle remoto Git para determinar o servidor LFS. Você também pode especificar um destino personalizado se os dados do repositório LFS forem armazenados em outro lugar.
migrate_options_lfs_endpoint.description.local=Um caminho de servidor local também é suportado.
migrate_options_lfs_endpoint.placeholder=Se for deixado em branco, o destino será derivado do URL de clone.
-migrate_items=Itens da migração
+migrate_items=Itens da Migração
migrate_items_wiki=Wiki
migrate_items_milestones=Marcos
migrate_items_labels=Etiquetas
@@ -1232,7 +1232,7 @@ find_tag=Pesquisar etiqueta
branches=Branches
tags=Tags
issues=Issues
-pulls=Pull requests
+pulls=Pull Requests
projects=Projetos
packages=Pacotes
actions=Ações
@@ -1396,7 +1396,7 @@ projects.description=Descrição (opcional)
projects.description_placeholder=Descrição
projects.create=Criar Projeto
projects.title=TÃtulo
-projects.new=Novo projeto
+projects.new=Novo Projeto
projects.new_subheader=Coordene, acompanhe e atualize seu trabalho em um só lugar, para que os projetos permaneçam transparentes e dentro do cronograma.
projects.create_success=Projeto "%s" criado.
projects.deletion=Apagar Projeto
@@ -1407,25 +1407,25 @@ projects.edit_subheader=Projetos organizam issues e acompanham o progresso.
projects.modify=Atualizar Projeto
projects.edit_success=Projeto "%s" atualizado.
projects.type.none=Nenhum
-projects.type.basic_kanban=Kanban básico
+projects.type.basic_kanban=Kanban Básico
projects.type.bug_triage=Triagem de Bugs
projects.template.desc=Modelo de projeto
projects.template.desc_helper=Selecione um modelo de projeto para começar
projects.column.edit=Editar coluna
projects.column.edit_title=Nome
projects.column.new_title=Nome
-projects.column.new_submit=Criar coluna
+projects.column.new_submit=Criar Coluna
projects.column.new=Nova Coluna
-projects.column.set_default=Atribuir como padrão
+projects.column.set_default=Atribuir como Padrão
projects.column.set_default_desc=Definir esta coluna como padrão para pull e issues sem categoria
-projects.column.delete=Excluir coluna
+projects.column.delete=Excluir Coluna
projects.column.color=Cor
projects.open=Abrir
projects.close=Fechar
projects.column.assigned_to=AtribuÃdo a
projects.card_type.desc=Pré-visualizações de Cards
projects.card_type.images_and_text=Imagens e Texto
-projects.card_type.text_only=Somente texto
+projects.card_type.text_only=Somente Texto
issues.desc=Organize relatórios de bugs, tarefas e marcos.
issues.filter_assignees=Filtrar Atribuição
@@ -1665,7 +1665,7 @@ issues.add_time_hours=Horas
issues.add_time_minutes=Minutos
issues.add_time_sum_to_small=Nenhum tempo foi inserido.
issues.time_spent_total=Tempo Total Gasto
-issues.time_spent_from_all_authors=`Tempo total gasto: %s`
+issues.time_spent_from_all_authors=`Tempo Total Gasto: %s`
issues.due_date=Data Limite
issues.invalid_due_date_format=Formato da data limite inválido, deve ser 'dd/mm/aaaa'.
@@ -1755,9 +1755,9 @@ compare.compare_base=base
compare.compare_head=comparar
pulls.desc=Habilitar pull requests e revisões de código.
-pulls.new=Novo pull request
+pulls.new=Novo Pull Request
pulls.view=Ver Pull Request
-pulls.compare_changes=Novo pull request
+pulls.compare_changes=Novo Pull Request
pulls.allow_edits_from_maintainers=Permitir edições de mantenedores
pulls.allow_edits_from_maintainers_desc=Usuários com acesso de gravação para o branch base também podem fazer push para este branch
pulls.allow_edits_from_maintainers_err=Falha na atualização
@@ -1787,7 +1787,7 @@ pulls.merged_title_desc=aplicou merge dos %[1]d commits de %[2]s em
pulls.change_target_branch_at=`mudou o branch de destino de %s para %s %s`
pulls.tab_conversation=Conversação
pulls.tab_commits=Commits
-pulls.tab_files=Arquivos alterados
+pulls.tab_files=Arquivos Alterados
pulls.reopen_to_merge=Por favor reabra este pull request para aplicar o merge.
pulls.cant_reopen_deleted_branch=Este pull request não pode ser reaberto porque o branch foi excluÃdo.
pulls.merged=Merge aplicado
@@ -1837,9 +1837,9 @@ pulls.merge_commit_id=A ID de merge commit
pulls.require_signed_wont_sign=O branch requer commits assinados, mas este merge não será assinado
pulls.invalid_merge_option=Você não pode usar esta opção de merge neste pull request.
-pulls.merge_conflict_summary=Mensagem de erro
+pulls.merge_conflict_summary=Mensagem de Erro
pulls.rebase_conflict_summary=Mensagem de Erro
-pulls.push_rejected_summary=Mensagem completa da rejeição
+pulls.push_rejected_summary=Mensagem Completa da Rejeição
pulls.open_unmerged_pull_exists=`Não é possÃvel executar uma operação de reabertura pois há um pull request pendente (#%d) com propriedades idênticas.`
pulls.status_checking=Algumas verificações estão pendentes
pulls.status_checks_success=Todas as verificações foram bem sucedidas
@@ -1855,7 +1855,7 @@ pulls.update_branch_rebase=Atualizar branch por rebase
pulls.update_branch_success=Atualização do branch foi bem-sucedida
pulls.update_not_allowed=Você não tem permissão para atualizar o branch
pulls.outdated_with_base_branch=Este branch está desatualizado com o branch base
-pulls.close=Fechar pull request
+pulls.close=Fechar Pull Request
pulls.closed_at=`fechou este pull request %[2]s`
pulls.reopened_at=`reabriu este pull request %[2]s`
pulls.cmd_instruction_checkout_title=Checkout
@@ -1885,7 +1885,7 @@ pull.deleted_branch=(excluÃdo):%s
pull.agit_documentation=Veja a documentação sobre AGit
-milestones.new=Novo marco
+milestones.new=Novo Marco
milestones.closed=Fechado %s
milestones.update_ago=Atualizado há %s
milestones.no_due_date=Sem data limite
@@ -1896,11 +1896,11 @@ milestones.completeness=%d%% ConcluÃdo
milestones.create=Criar Marco
milestones.title=TÃtulo
milestones.desc=Descrição
-milestones.due_date=Data limite (opcional)
+milestones.due_date=Data Limite (opcional)
milestones.clear=Limpar
milestones.invalid_due_date_format=Formato da data limite deve ser 'dd/mm/aaaa'.
milestones.create_success=O marco "%s" foi criado.
-milestones.edit=Editar marco
+milestones.edit=Editar Marco
milestones.edit_subheader=Marcos organizam as issues e acompanham o progresso.
milestones.cancel=Cancelar
milestones.modify=Atualizar Marco
@@ -2459,7 +2459,7 @@ releases.desc=Acompanhe as versões e downloads do projeto.
release.releases=Versões
release.detail=Detalhes da versão
release.tags=Tags
-release.new_release=Nova versão
+release.new_release=Nova Versão
release.draft=Rascunho
release.prerelease=Versão prévia
release.stable=Estável
@@ -2482,12 +2482,12 @@ release.message=Descreva esta versão
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
-release.save_draft=Salvar rascunho
-release.edit_release=Atualizar versão
+release.publish=Publicar Versão
+release.save_draft=Salvar Rascunho
+release.edit_release=Atualizar Versão
release.delete_release=Excluir Versão
release.delete_tag=Apagar Tag
-release.deletion=Excluir versão
+release.deletion=Excluir Versão
release.deletion_desc=A exclusão de uma versão apenas a remove do Gitea. Isso não afetará a tag do Git, o conteúdo do seu repositório ou seu histórico. Continuar?
release.deletion_success=A versão foi excluÃda.
release.deletion_tag_desc=A tag será excluÃda do repositório. Conteúdo do repositório e histórico permanecerão inalterados. Continuar?
diff --git a/package.json b/package.json
index 79aaa880a5..5fe8e70c3f 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
"@github/relative-time-element": "4.4.8",
"@github/text-expander-element": "2.9.2",
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
- "@primer/octicons": "19.17.0",
+ "@primer/octicons": "19.18.0",
"@resvg/resvg-wasm": "2.6.2",
"@silverwind/vue3-calendar-heatmap": "2.0.6",
"@techknowlogick/license-checker-webpack-plugin": "0.3.0",
@@ -31,14 +31,14 @@
"dropzone": "6.0.0-beta.2",
"easymde": "2.20.0",
"esbuild-loader": "4.3.0",
- "htmx.org": "2.0.6",
+ "htmx.org": "2.0.7",
"idiomorph": "0.7.3",
"jquery": "3.7.1",
"katex": "0.16.22",
"mermaid": "11.11.0",
"mini-css-extract-plugin": "2.9.4",
"minimatch": "10.0.3",
- "monaco-editor": "0.52.2",
+ "monaco-editor": "0.53.0",
"monaco-editor-webpack-plugin": "7.1.0",
"online-3d-viewer": "0.16.0",
"pdfobject": "2.3.1",
@@ -47,7 +47,7 @@
"postcss-loader": "8.2.0",
"postcss-nesting": "13.0.2",
"sortablejs": "1.15.6",
- "swagger-ui-dist": "5.28.1",
+ "swagger-ui-dist": "5.29.0",
"tailwindcss": "3.4.17",
"throttle-debounce": "5.0.2",
"tinycolor2": "1.6.0",
@@ -63,7 +63,7 @@
"vue-loader": "17.4.2",
"webpack": "5.101.3",
"webpack-cli": "6.0.1",
- "wrap-ansi": "9.0.0"
+ "wrap-ansi": "9.0.2"
},
"devDependencies": {
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
@@ -82,8 +82,8 @@
"@types/throttle-debounce": "5.0.2",
"@types/tinycolor2": "1.4.6",
"@types/toastify-js": "1.12.4",
- "@typescript-eslint/eslint-plugin": "8.42.0",
- "@typescript-eslint/parser": "8.42.0",
+ "@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",
@@ -102,7 +102,7 @@
"eslint-plugin-wc": "3.0.1",
"happy-dom": "18.0.1",
"markdownlint-cli": "0.45.0",
- "material-icon-theme": "5.26.0",
+ "material-icon-theme": "5.27.0",
"nolyfill": "1.0.44",
"postcss-html": "1.8.0",
"stylelint": "16.24.0",
@@ -112,7 +112,7 @@
"stylelint-value-no-unknown-custom-properties": "6.0.1",
"svgo": "4.0.0",
"type-fest": "4.41.0",
- "updates": "16.6.4",
+ "updates": "16.7.0",
"vite-string-plugin": "1.4.6",
"vitest": "3.2.4",
"vue-tsc": "3.0.6"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 149d8f179c..83a31ce8ad 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -51,8 +51,8 @@ importers:
specifier: 0.1.0-alpha-3
version: 0.1.0-alpha-3
'@primer/octicons':
- specifier: 19.17.0
- version: 19.17.0
+ specifier: 19.18.0
+ version: 19.18.0
'@resvg/resvg-wasm':
specifier: 2.6.2
version: 2.6.2
@@ -102,8 +102,8 @@ importers:
specifier: 4.3.0
version: 4.3.0(webpack@5.101.3)
htmx.org:
- specifier: 2.0.6
- version: 2.0.6
+ specifier: 2.0.7
+ version: 2.0.7
idiomorph:
specifier: 0.7.3
version: 0.7.3
@@ -123,11 +123,11 @@ importers:
specifier: 10.0.3
version: 10.0.3
monaco-editor:
- specifier: 0.52.2
- version: 0.52.2
+ specifier: 0.53.0
+ version: 0.53.0
monaco-editor-webpack-plugin:
specifier: 7.1.0
- version: 7.1.0(monaco-editor@0.52.2)(webpack@5.101.3)
+ version: 7.1.0(monaco-editor@0.53.0)(webpack@5.101.3)
online-3d-viewer:
specifier: 0.16.0
version: 0.16.0
@@ -150,8 +150,8 @@ importers:
specifier: 1.15.6
version: 1.15.6
swagger-ui-dist:
- specifier: 5.28.1
- version: 5.28.1
+ specifier: 5.29.0
+ version: 5.29.0
tailwindcss:
specifier: 3.4.17
version: 3.4.17
@@ -198,8 +198,8 @@ importers:
specifier: 6.0.1
version: 6.0.1(webpack@5.101.3)
wrap-ansi:
- specifier: 9.0.0
- version: 9.0.0
+ specifier: 9.0.2
+ version: 9.0.2
devDependencies:
'@eslint-community/eslint-plugin-eslint-comments':
specifier: 4.5.0
@@ -250,14 +250,14 @@ importers:
specifier: 1.12.4
version: 1.12.4
'@typescript-eslint/eslint-plugin':
- specifier: 8.42.0
- version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(typescript@5.9.2)
+ 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.42.0
- version: 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ specifier: 8.43.0
+ version: 8.43.0(eslint@8.57.0)(typescript@5.9.2)
'@vitejs/plugin-vue':
specifier: 6.0.1
- version: 6.0.1(vite@7.1.4(@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))
+ 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))
@@ -266,7 +266,7 @@ importers:
version: 8.57.0
eslint-import-resolver-typescript:
specifier: 4.4.4
- version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.42.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@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-plugin-array-func:
specifier: 4.0.0
version: 4.0.0(eslint@8.57.0)
@@ -275,7 +275,7 @@ importers:
version: 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-import-x:
specifier: 4.16.1
- version: 4.16.1(@typescript-eslint/utils@8.42.0(eslint@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0)
+ 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)
@@ -296,7 +296,7 @@ importers:
version: 56.0.1(eslint@8.57.0)
eslint-plugin-vue:
specifier: 10.4.0
- version: 10.4.0(@typescript-eslint/parser@8.42.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@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0))
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))
@@ -310,8 +310,8 @@ importers:
specifier: 0.45.0
version: 0.45.0
material-icon-theme:
- specifier: 5.26.0
- version: 5.26.0
+ specifier: 5.27.0
+ version: 5.27.0
nolyfill:
specifier: 1.0.44
version: 1.0.44
@@ -340,8 +340,8 @@ importers:
specifier: 4.41.0
version: 4.41.0
updates:
- specifier: 16.6.4
- version: 16.6.4
+ specifier: 16.7.0
+ version: 16.7.0
vite-string-plugin:
specifier: 1.4.6
version: 1.4.6
@@ -665,8 +665,8 @@ packages:
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
- '@eslint-community/eslint-utils@4.8.0':
- resolution: {integrity: sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==}
+ '@eslint-community/eslint-utils@4.9.0':
+ resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
@@ -876,8 +876,8 @@ packages:
'@popperjs/core@2.11.8':
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
- '@primer/octicons@19.17.0':
- resolution: {integrity: sha512-uM3ET0WC2aZMetxv7CRfIw3FexIo2fYtw2EgxqLFzLjn/rh+dIQWu781chLHh9d2mSNlxedauHLQmbYi0Dd/Mg==}
+ '@primer/octicons@19.18.0':
+ resolution: {integrity: sha512-4P8FS7slUp0vHE7zLtlfOQcgF99r0tdxpriT3ahp6iwwnf1hF3OlDWXEp5n6b6G5eIY1cNr1bCrjRL+DkRjFVw==}
'@resvg/resvg-wasm@2.6.2':
resolution: {integrity: sha512-FqALmHI8D4o6lk/LRWDnhw95z5eO+eAa6ORjVg09YRR7BkcM6oPHU9uyC0gtQG5vpFLvgpeU4+zEAz2H8APHNw==}
@@ -1334,6 +1334,9 @@ packages:
'@types/toastify-js@1.12.4':
resolution: {integrity: sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==}
+ '@types/trusted-types@1.0.6':
+ resolution: {integrity: sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==}
+
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
@@ -1355,63 +1358,63 @@ packages:
'@types/whatwg-mimetype@3.0.2':
resolution: {integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==}
- '@typescript-eslint/eslint-plugin@8.42.0':
- resolution: {integrity: sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ==}
+ '@typescript-eslint/eslint-plugin@8.43.0':
+ resolution: {integrity: sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.42.0
+ '@typescript-eslint/parser': ^8.43.0
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/parser@8.42.0':
- resolution: {integrity: sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==}
+ '@typescript-eslint/parser@8.43.0':
+ resolution: {integrity: sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==}
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-eslint/project-service@8.42.0':
- resolution: {integrity: sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==}
+ '@typescript-eslint/project-service@8.43.0':
+ resolution: {integrity: sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/scope-manager@8.42.0':
- resolution: {integrity: sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==}
+ '@typescript-eslint/scope-manager@8.43.0':
+ resolution: {integrity: sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/tsconfig-utils@8.42.0':
- resolution: {integrity: sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==}
+ '@typescript-eslint/tsconfig-utils@8.43.0':
+ resolution: {integrity: sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/type-utils@8.42.0':
- resolution: {integrity: sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ==}
+ '@typescript-eslint/type-utils@8.43.0':
+ resolution: {integrity: sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==}
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-eslint/types@8.42.0':
- resolution: {integrity: sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==}
+ '@typescript-eslint/types@8.43.0':
+ resolution: {integrity: sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.42.0':
- resolution: {integrity: sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==}
+ '@typescript-eslint/typescript-estree@8.43.0':
+ resolution: {integrity: sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.0.0'
- '@typescript-eslint/utils@8.42.0':
- resolution: {integrity: sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==}
+ '@typescript-eslint/utils@8.43.0':
+ resolution: {integrity: sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==}
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-eslint/visitor-keys@8.42.0':
- resolution: {integrity: sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==}
+ '@typescript-eslint/visitor-keys@8.43.0':
+ resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@ungap/structured-clone@1.3.0':
@@ -1750,16 +1753,16 @@ packages:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
- ansi-regex@6.2.0:
- resolution: {integrity: sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==}
+ ansi-regex@6.2.2:
+ resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
engines: {node: '>=12'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
- ansi-styles@6.2.1:
- resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
+ ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
engines: {node: '>=12'}
ansi_up@6.0.6:
@@ -2381,8 +2384,8 @@ packages:
easymde@2.20.0:
resolution: {integrity: sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ==}
- electron-to-chromium@1.5.214:
- resolution: {integrity: sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==}
+ electron-to-chromium@1.5.215:
+ resolution: {integrity: sha512-TIvGp57UpeNetj/wV/xpFNpWGb0b/ROw372lHPx5Aafx02gjTBtWnEEcaSX3W2dLM3OSdGGyHX/cHl01JQsLaQ==}
emoji-regex@10.5.0:
resolution: {integrity: sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==}
@@ -2829,8 +2832,8 @@ packages:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
- get-east-asian-width@1.3.1:
- resolution: {integrity: sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==}
+ get-east-asian-width@1.4.0:
+ resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
engines: {node: '>=18'}
get-set-props@0.1.0:
@@ -2935,8 +2938,8 @@ packages:
htmlparser2@8.0.2:
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
- htmx.org@2.0.6:
- resolution: {integrity: sha512-7ythjYneGSk3yCHgtCnQeaoF+D+o7U2LF37WU3O0JYv3gTZSicdEFiI/Ai/NJyC5ZpYJWMpUb11OC5Lr6AfAqA==}
+ htmx.org@2.0.7:
+ resolution: {integrity: sha512-YiJqF3U5KyO28VC5mPfehKJPF+n1Gni+cupK+D69TF0nm7wY6AXn3a4mPWIikfAXtl1u1F1+ZhSCS7KT8pVmqA==}
iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
@@ -3330,8 +3333,8 @@ packages:
magic-string@0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
- magic-string@0.30.18:
- resolution: {integrity: sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==}
+ magic-string@0.30.19:
+ resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
markdown-escape@2.0.0:
resolution: {integrity: sha512-Trz4v0+XWlwy68LJIyw3bLbsJiC8XAbRCKF9DbEtZjyndKOGVx6n+wNB0VfoRmY2LKboQLeniap3xrb6LGSJ8A==}
@@ -3359,8 +3362,8 @@ packages:
engines: {node: '>= 12'}
hasBin: true
- material-icon-theme@5.26.0:
- resolution: {integrity: sha512-Etrm3gMsgCRfpyqE11dDRqb3epoqxq94Pa1QEk20D7uIImneRhtsTFvhOcbKEQfMzup8IBUI1+oYrkfwIb6Xuw==}
+ material-icon-theme@5.27.0:
+ resolution: {integrity: sha512-zB3LtPY2n6z4Kp5fSc7OT8KwAZIJRvcOq6PZR4jmAkvmW1Ot+y6lNJmNqERK9rYAT42tZD1YmkhHaMcA2KEObA==}
engines: {vscode: ^1.55.0}
mathml-tag-names@2.1.3:
@@ -3513,8 +3516,8 @@ packages:
monaco-editor: '>= 0.31.0'
webpack: ^4.5.0 || 5.x
- monaco-editor@0.52.2:
- resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==}
+ monaco-editor@0.53.0:
+ resolution: {integrity: sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==}
moo@0.5.2:
resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==}
@@ -4172,8 +4175,8 @@ packages:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
- strip-ansi@7.1.0:
- resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ strip-ansi@7.1.2:
+ resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
engines: {node: '>=12'}
strip-bom@3.0.0:
@@ -4268,8 +4271,8 @@ packages:
svgson@5.3.1:
resolution: {integrity: sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA==}
- swagger-ui-dist@5.28.1:
- resolution: {integrity: sha512-IvPrtNi8MvjiuDgoSmPYgg27Lvu38fnLD1OSd8Y103xXsPAqezVNnNeHnVCZ/d+CMXJblflGaIyHxAYIF3O71w==}
+ swagger-ui-dist@5.29.0:
+ resolution: {integrity: sha512-gqs7Md3AxP4mbpXAq31o5QW+wGUZsUzVatg70yXpUR245dfIis5jAzufBd+UQM/w2xSfrhvA1eqsrgnl2PbezQ==}
sync-fetch@0.4.5:
resolution: {integrity: sha512-esiWJ7ixSKGpd9DJPBTC4ckChqdOjIwJfYhVHkcQ2Gnm41323p1TRmEI+esTQ9ppD+b5opps2OTEGTCGX5kF+g==}
@@ -4452,8 +4455,8 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
- updates@16.6.4:
- resolution: {integrity: sha512-HHJH9SBWJr/1+iSLuS1txaq4bz2q/ENK4KHRhcTgOgJEUeBnmLeF5/0nQya9vGnRGLnrXacuAk+pTAzKuOs9ng==}
+ updates@16.7.0:
+ resolution: {integrity: sha512-GOqKdZREAlOR90YBBY8FpkmJOPjjxntYcuAKZRWXK5Pvt2CAcPREk+KeqClG3yqqk+NGWkqAsIxa1ORzQB1iQA==}
engines: {node: '>=20'}
hasBin: true
@@ -4491,8 +4494,8 @@ packages:
vite-string-plugin@1.4.6:
resolution: {integrity: sha512-Csjtny8/uVIynzlaRRj4RpHrPAakNwlH9jw6kgQ8tQhc2f0zzA6bCbAgWD0y84EgB8aLNrz7pZFUqSt3LOtk+w==}
- vite@7.1.4:
- resolution: {integrity: sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==}
+ vite@7.1.5:
+ resolution: {integrity: sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
peerDependencies:
@@ -4705,8 +4708,8 @@ packages:
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
engines: {node: '>=12'}
- wrap-ansi@9.0.0:
- resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==}
+ wrap-ansi@9.0.2:
+ resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
engines: {node: '>=18'}
wrappy@1.0.2:
@@ -4983,7 +4986,7 @@ snapshots:
eslint: 8.57.0
ignore: 5.3.2
- '@eslint-community/eslint-utils@4.8.0(eslint@8.57.0)':
+ '@eslint-community/eslint-utils@4.9.0(eslint@8.57.0)':
dependencies:
eslint: 8.57.0
eslint-visitor-keys: 3.4.3
@@ -5056,7 +5059,7 @@ snapshots:
dependencies:
string-width: 5.1.2
string-width-cjs: string-width@4.2.3
- strip-ansi: 7.1.0
+ strip-ansi: 7.1.2
strip-ansi-cjs: strip-ansi@6.0.1
wrap-ansi: 8.1.0
wrap-ansi-cjs: wrap-ansi@7.0.0
@@ -5192,7 +5195,7 @@ snapshots:
'@popperjs/core@2.11.8': {}
- '@primer/octicons@19.17.0':
+ '@primer/octicons@19.18.0':
dependencies:
object-assign: 4.1.1
@@ -5797,6 +5800,8 @@ snapshots:
'@types/toastify-js@1.12.4': {}
+ '@types/trusted-types@1.0.6': {}
+
'@types/trusted-types@2.0.7':
optional: true
@@ -5825,14 +5830,14 @@ snapshots:
'@types/whatwg-mimetype@3.0.2': {}
- '@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.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@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(typescript@5.9.2)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
- '@typescript-eslint/scope-manager': 8.42.0
- '@typescript-eslint/type-utils': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
- '@typescript-eslint/utils': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
- '@typescript-eslint/visitor-keys': 8.42.0
+ '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(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/visitor-keys': 8.43.0
eslint: 8.57.0
graphemer: 1.4.0
ignore: 7.0.5
@@ -5842,41 +5847,41 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.42.0(eslint@8.57.0)(typescript@5.9.2)':
+ '@typescript-eslint/parser@8.43.0(eslint@8.57.0)(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/scope-manager': 8.42.0
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/visitor-keys': 8.42.0
+ '@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
typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.42.0(typescript@5.9.2)':
+ '@typescript-eslint/project-service@8.43.0(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/types': 8.42.0
+ '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.9.2)
+ '@typescript-eslint/types': 8.43.0
debug: 4.4.1
typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.42.0':
+ '@typescript-eslint/scope-manager@8.43.0':
dependencies:
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/visitor-keys': 8.42.0
+ '@typescript-eslint/types': 8.43.0
+ '@typescript-eslint/visitor-keys': 8.43.0
- '@typescript-eslint/tsconfig-utils@8.42.0(typescript@5.9.2)':
+ '@typescript-eslint/tsconfig-utils@8.43.0(typescript@5.9.2)':
dependencies:
typescript: 5.9.2
- '@typescript-eslint/type-utils@8.42.0(eslint@8.57.0)(typescript@5.9.2)':
+ '@typescript-eslint/type-utils@8.43.0(eslint@8.57.0)(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/utils': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ '@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)
debug: 4.4.1
eslint: 8.57.0
ts-api-utils: 2.1.0(typescript@5.9.2)
@@ -5884,14 +5889,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.42.0': {}
+ '@typescript-eslint/types@8.43.0': {}
- '@typescript-eslint/typescript-estree@8.42.0(typescript@5.9.2)':
+ '@typescript-eslint/typescript-estree@8.43.0(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/project-service': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/visitor-keys': 8.42.0
+ '@typescript-eslint/project-service': 8.43.0(typescript@5.9.2)
+ '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.9.2)
+ '@typescript-eslint/types': 8.43.0
+ '@typescript-eslint/visitor-keys': 8.43.0
debug: 4.4.1
fast-glob: 3.3.3
is-glob: 4.0.3
@@ -5902,20 +5907,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.42.0(eslint@8.57.0)(typescript@5.9.2)':
+ '@typescript-eslint/utils@8.43.0(eslint@8.57.0)(typescript@5.9.2)':
dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0)
- '@typescript-eslint/scope-manager': 8.42.0
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0)
+ '@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
typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.42.0':
+ '@typescript-eslint/visitor-keys@8.43.0':
dependencies:
- '@typescript-eslint/types': 8.42.0
+ '@typescript-eslint/types': 8.43.0
eslint-visitor-keys: 4.2.1
'@ungap/structured-clone@1.3.0': {}
@@ -5979,16 +5984,16 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.11.1':
optional: true
- '@vitejs/plugin-vue@6.0.1(vite@7.1.4(@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))':
+ '@vitejs/plugin-vue@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))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.29
- vite: 7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.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@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))':
dependencies:
- '@typescript-eslint/scope-manager': 8.42.0
- '@typescript-eslint/utils': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ '@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
optionalDependencies:
typescript: 5.9.2
@@ -6004,13 +6009,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))':
+ '@vitest/mocker@3.2.4(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))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
- magic-string: 0.30.18
+ magic-string: 0.30.19
optionalDependencies:
- vite: 7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.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)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -6025,7 +6030,7 @@ snapshots:
'@vitest/snapshot@3.2.4':
dependencies:
'@vitest/pretty-format': 3.2.4
- magic-string: 0.30.18
+ magic-string: 0.30.19
pathe: 2.0.3
'@vitest/spy@3.2.4':
@@ -6071,7 +6076,7 @@ snapshots:
'@vue/compiler-ssr': 3.5.21
'@vue/shared': 3.5.21
estree-walker: 2.0.2
- magic-string: 0.30.18
+ magic-string: 0.30.19
postcss: 8.5.6
source-map-js: 1.2.1
@@ -6270,13 +6275,13 @@ snapshots:
ansi-regex@5.0.1: {}
- ansi-regex@6.2.0: {}
+ ansi-regex@6.2.2: {}
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
- ansi-styles@6.2.1: {}
+ ansi-styles@6.2.3: {}
ansi_up@6.0.6: {}
@@ -6352,7 +6357,7 @@ snapshots:
browserslist@4.25.4:
dependencies:
caniuse-lite: 1.0.30001741
- electron-to-chromium: 1.5.214
+ electron-to-chromium: 1.5.215
node-releases: 2.0.20
update-browserslist-db: 1.1.3(browserslist@4.25.4)
@@ -6880,7 +6885,7 @@ snapshots:
codemirror-spell-checker: 1.1.2
marked: 4.3.0
- electron-to-chromium@1.5.214: {}
+ electron-to-chromium@1.5.215: {}
emoji-regex@10.5.0: {}
@@ -6974,7 +6979,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.42.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@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):
dependencies:
debug: 4.4.1
eslint: 8.57.0
@@ -6985,19 +6990,19 @@ snapshots:
tinyglobby: 0.2.15
unrs-resolver: 1.11.1
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.42.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.42.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@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)
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.42.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@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):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2)
eslint: 8.57.0
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.42.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@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)
transitivePeerDependencies:
- supports-color
@@ -7027,8 +7032,8 @@ snapshots:
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):
dependencies:
'@github/browserslist-config': 1.0.0
- '@typescript-eslint/eslint-plugin': 8.42.0(@typescript-eslint/parser@8.42.0(eslint@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(typescript@5.9.2)
- '@typescript-eslint/parser': 8.42.0(eslint@8.57.0)(typescript@5.9.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/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2)
aria-query: 5.3.2
eslint: 8.57.0
eslint-config-prettier: 10.1.8(eslint@8.57.0)
@@ -7036,7 +7041,7 @@ snapshots:
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.42.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@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-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)
@@ -7055,9 +7060,9 @@ snapshots:
dependencies:
eslint: 8.57.0
- eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.42.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@8.57.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0):
dependencies:
- '@typescript-eslint/types': 8.42.0
+ '@typescript-eslint/types': 8.43.0
comment-parser: 1.4.1
debug: 4.4.1
eslint: 8.57.0
@@ -7068,12 +7073,12 @@ snapshots:
stable-hash-x: 0.2.0
unrs-resolver: 1.11.1
optionalDependencies:
- '@typescript-eslint/utils': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.43.0(eslint@8.57.0)(typescript@5.9.2)
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.42.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@8.57.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@8.57.0):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: '@nolyfill/array-includes@1.0.44'
@@ -7084,7 +7089,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.42.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@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)
hasown: '@nolyfill/hasown@1.0.44'
is-core-module: '@nolyfill/is-core-module@1.0.39'
is-glob: 4.0.3
@@ -7096,7 +7101,7 @@ snapshots:
string.prototype.trimend: '@nolyfill/string.prototype.trimend@1.0.44'
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -7151,7 +7156,7 @@ snapshots:
eslint-plugin-regexp@2.10.0(eslint@8.57.0):
dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0)
'@eslint-community/regexpp': 4.12.1
comment-parser: 1.4.1
eslint: 8.57.0
@@ -7177,7 +7182,7 @@ snapshots:
eslint-plugin-unicorn@56.0.1(eslint@8.57.0):
dependencies:
'@babel/helper-validator-identifier': 7.27.1
- '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0)
ci-info: 4.3.0
clean-regexp: 1.0.0
core-js-compat: 3.45.1
@@ -7196,7 +7201,7 @@ snapshots:
eslint-plugin-vue-scoped-css@2.12.0(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0)):
dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0)
+ '@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)
lodash: 4.17.21
@@ -7209,9 +7214,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-plugin-vue@10.4.0(@typescript-eslint/parser@8.42.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@8.57.0)(typescript@5.9.2))(eslint@8.57.0)(vue-eslint-parser@10.2.0(eslint@8.57.0)):
dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0)
eslint: 8.57.0
natural-compare: 1.4.0
nth-check: 2.1.1
@@ -7220,7 +7225,7 @@ snapshots:
vue-eslint-parser: 10.2.0(eslint@8.57.0)
xml-name-validator: 4.0.0
optionalDependencies:
- '@typescript-eslint/parser': 8.42.0(eslint@8.57.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.43.0(eslint@8.57.0)(typescript@5.9.2)
eslint-plugin-wc@3.0.1(eslint@8.57.0):
dependencies:
@@ -7251,7 +7256,7 @@ snapshots:
eslint@8.57.0:
dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.9.0(eslint@8.57.0)
'@eslint-community/regexpp': 4.12.1
'@eslint/eslintrc': 2.1.4
'@eslint/js': 8.57.0
@@ -7443,7 +7448,7 @@ snapshots:
get-caller-file@2.0.5: {}
- get-east-asian-width@1.3.1: {}
+ get-east-asian-width@1.4.0: {}
get-set-props@0.1.0: {}
@@ -7555,7 +7560,7 @@ snapshots:
domutils: 3.2.2
entities: 4.5.0
- htmx.org@2.0.6: {}
+ htmx.org@2.0.7: {}
iconv-lite@0.6.3:
dependencies:
@@ -7882,7 +7887,7 @@ snapshots:
dependencies:
sourcemap-codec: 1.4.8
- magic-string@0.30.18:
+ magic-string@0.30.19:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -7930,7 +7935,7 @@ snapshots:
marked@4.3.0: {}
- material-icon-theme@5.26.0:
+ material-icon-theme@5.27.0:
dependencies:
chroma-js: 3.1.2
events: 3.3.0
@@ -8190,13 +8195,15 @@ snapshots:
pkg-types: 1.3.1
ufo: 1.6.1
- monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.52.2)(webpack@5.101.3):
+ monaco-editor-webpack-plugin@7.1.0(monaco-editor@0.53.0)(webpack@5.101.3):
dependencies:
loader-utils: 2.0.4
- monaco-editor: 0.52.2
+ monaco-editor: 0.53.0
webpack: 5.101.3(webpack-cli@6.0.1)
- monaco-editor@0.52.2: {}
+ monaco-editor@0.53.0:
+ dependencies:
+ '@types/trusted-types': 1.0.6
moo@0.5.2: {}
@@ -8808,21 +8815,21 @@ snapshots:
dependencies:
eastasianwidth: 0.2.0
emoji-regex: 9.2.2
- strip-ansi: 7.1.0
+ strip-ansi: 7.1.2
string-width@7.2.0:
dependencies:
emoji-regex: 10.5.0
- get-east-asian-width: 1.3.1
- strip-ansi: 7.1.0
+ get-east-asian-width: 1.4.0
+ strip-ansi: 7.1.2
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
- strip-ansi@7.1.0:
+ strip-ansi@7.1.2:
dependencies:
- ansi-regex: 6.2.0
+ ansi-regex: 6.2.2
strip-bom@3.0.0: {}
@@ -8959,7 +8966,7 @@ snapshots:
deep-rename-keys: 0.2.1
xml-reader: 2.4.3
- swagger-ui-dist@5.28.1:
+ swagger-ui-dist@5.29.0:
dependencies:
'@scarf/scarf': 1.4.0
@@ -9151,7 +9158,7 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
- updates@16.6.4: {}
+ updates@16.7.0: {}
uri-js@4.4.1:
dependencies:
@@ -9182,7 +9189,7 @@ snapshots:
debug: 4.4.1
es-module-lexer: 1.7.0
pathe: 2.0.3
- vite: 7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.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)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -9199,7 +9206,7 @@ snapshots:
vite-string-plugin@1.4.6: {}
- vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.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):
dependencies:
esbuild: 0.25.9
fdir: 6.5.0(picomatch@4.0.3)
@@ -9219,7 +9226,7 @@ snapshots:
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4(vite@7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1))
+ '@vitest/mocker': 3.2.4(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))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@@ -9228,7 +9235,7 @@ snapshots:
chai: 5.3.3
debug: 4.4.1
expect-type: 1.2.2
- magic-string: 0.30.18
+ magic-string: 0.30.19
pathe: 2.0.3
picomatch: 4.0.3
std-env: 3.9.0
@@ -9237,7 +9244,7 @@ snapshots:
tinyglobby: 0.2.15
tinypool: 1.1.1
tinyrainbow: 2.0.0
- vite: 7.1.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.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)
vite-node: 3.2.4(@types/node@24.3.1)(jiti@2.5.1)(stylus@0.57.0)(terser@5.44.0)(yaml@2.8.1)
why-is-node-running: 2.3.0
optionalDependencies:
@@ -9434,15 +9441,15 @@ snapshots:
wrap-ansi@8.1.0:
dependencies:
- ansi-styles: 6.2.1
+ ansi-styles: 6.2.3
string-width: 5.1.2
- strip-ansi: 7.1.0
+ strip-ansi: 7.1.2
- wrap-ansi@9.0.0:
+ wrap-ansi@9.0.2:
dependencies:
- ansi-styles: 6.2.1
+ ansi-styles: 6.2.3
string-width: 7.2.0
- strip-ansi: 7.1.0
+ strip-ansi: 7.1.2
wrappy@1.0.2: {}
diff --git a/public/assets/img/svg/octicon-checkbox-fill.svg b/public/assets/img/svg/octicon-checkbox-fill.svg
new file mode 100644
index 0000000000..6e9085f61c
--- /dev/null
+++ b/public/assets/img/svg/octicon-checkbox-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index 20f5d6262e..a7084bf0ae 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -524,7 +524,7 @@ func ParseCompareInfo(ctx *context.Context) *common.CompareInfo {
// Treat as pull request if both references are branches
if ctx.Data["PageIsComparePull"] == nil {
- ctx.Data["PageIsComparePull"] = headIsBranch && baseIsBranch
+ ctx.Data["PageIsComparePull"] = headIsBranch && baseIsBranch && permBase.CanReadIssuesOrPulls(true)
}
if ctx.Data["PageIsComparePull"] == true && !permBase.CanReadIssuesOrPulls(true) {
@@ -730,6 +730,7 @@ func CompareDiff(ctx *context.Context) {
return
}
+ ctx.Data["PageIsViewCode"] = true
ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes
ctx.Data["DirectComparison"] = ci.DirectComparison
ctx.Data["OtherCompareSeparator"] = ".."
diff --git a/services/issue/issue.go b/services/issue/issue.go
index b9ee66c1f2..620b76a9d1 100644
--- a/services/issue/issue.go
+++ b/services/issue/issue.go
@@ -246,74 +246,67 @@ func GetRefEndNamesAndURLs(issues []*issues_model.Issue, repoLink string) (map[i
// deleteIssue deletes the issue
func deleteIssue(ctx context.Context, issue *issues_model.Issue) ([]string, error) {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return nil, err
- }
- defer committer.Close()
-
- if _, err := db.GetEngine(ctx).ID(issue.ID).NoAutoCondition().Delete(issue); err != nil {
- return nil, err
- }
-
- // update the total issue numbers
- if err := repo_model.UpdateRepoIssueNumbers(ctx, issue.RepoID, issue.IsPull, false); err != nil {
- return nil, err
- }
- // if the issue is closed, update the closed issue numbers
- if issue.IsClosed {
- if err := repo_model.UpdateRepoIssueNumbers(ctx, issue.RepoID, issue.IsPull, true); err != nil {
+ return db.WithTx2(ctx, func(ctx context.Context) ([]string, error) {
+ if _, err := db.GetEngine(ctx).ID(issue.ID).NoAutoCondition().Delete(issue); err != nil {
return nil, err
}
- }
- if err := issues_model.UpdateMilestoneCounters(ctx, issue.MilestoneID); err != nil {
- return nil, fmt.Errorf("error updating counters for milestone id %d: %w",
- issue.MilestoneID, err)
- }
+ // update the total issue numbers
+ if err := repo_model.UpdateRepoIssueNumbers(ctx, issue.RepoID, issue.IsPull, false); err != nil {
+ return nil, err
+ }
+ // if the issue is closed, update the closed issue numbers
+ if issue.IsClosed {
+ if err := repo_model.UpdateRepoIssueNumbers(ctx, issue.RepoID, issue.IsPull, true); err != nil {
+ return nil, err
+ }
+ }
- if err := activities_model.DeleteIssueActions(ctx, issue.RepoID, issue.ID, issue.Index); err != nil {
- return nil, err
- }
+ if err := issues_model.UpdateMilestoneCounters(ctx, issue.MilestoneID); err != nil {
+ return nil, fmt.Errorf("error updating counters for milestone id %d: %w",
+ issue.MilestoneID, err)
+ }
- // find attachments related to this issue and remove them
- if err := issue.LoadAttachments(ctx); err != nil {
- return nil, err
- }
+ if err := activities_model.DeleteIssueActions(ctx, issue.RepoID, issue.ID, issue.Index); err != nil {
+ return nil, err
+ }
- var attachmentPaths []string
- for i := range issue.Attachments {
- attachmentPaths = append(attachmentPaths, issue.Attachments[i].RelativePath())
- }
+ // find attachments related to this issue and remove them
+ if err := issue.LoadAttachments(ctx); err != nil {
+ return nil, err
+ }
- // delete all database data still assigned to this issue
- if err := db.DeleteBeans(ctx,
- &issues_model.ContentHistory{IssueID: issue.ID},
- &issues_model.Comment{IssueID: issue.ID},
- &issues_model.IssueLabel{IssueID: issue.ID},
- &issues_model.IssueDependency{IssueID: issue.ID},
- &issues_model.IssueAssignees{IssueID: issue.ID},
- &issues_model.IssueUser{IssueID: issue.ID},
- &activities_model.Notification{IssueID: issue.ID},
- &issues_model.Reaction{IssueID: issue.ID},
- &issues_model.IssueWatch{IssueID: issue.ID},
- &issues_model.Stopwatch{IssueID: issue.ID},
- &issues_model.TrackedTime{IssueID: issue.ID},
- &project_model.ProjectIssue{IssueID: issue.ID},
- &repo_model.Attachment{IssueID: issue.ID},
- &issues_model.PullRequest{IssueID: issue.ID},
- &issues_model.Comment{RefIssueID: issue.ID},
- &issues_model.IssueDependency{DependencyID: issue.ID},
- &issues_model.Comment{DependentIssueID: issue.ID},
- &issues_model.IssuePin{IssueID: issue.ID},
- ); err != nil {
- return nil, err
- }
+ var attachmentPaths []string
+ for i := range issue.Attachments {
+ attachmentPaths = append(attachmentPaths, issue.Attachments[i].RelativePath())
+ }
- if err := committer.Commit(); err != nil {
- return nil, err
- }
- return attachmentPaths, nil
+ // delete all database data still assigned to this issue
+ if err := db.DeleteBeans(ctx,
+ &issues_model.ContentHistory{IssueID: issue.ID},
+ &issues_model.Comment{IssueID: issue.ID},
+ &issues_model.IssueLabel{IssueID: issue.ID},
+ &issues_model.IssueDependency{IssueID: issue.ID},
+ &issues_model.IssueAssignees{IssueID: issue.ID},
+ &issues_model.IssueUser{IssueID: issue.ID},
+ &activities_model.Notification{IssueID: issue.ID},
+ &issues_model.Reaction{IssueID: issue.ID},
+ &issues_model.IssueWatch{IssueID: issue.ID},
+ &issues_model.Stopwatch{IssueID: issue.ID},
+ &issues_model.TrackedTime{IssueID: issue.ID},
+ &project_model.ProjectIssue{IssueID: issue.ID},
+ &repo_model.Attachment{IssueID: issue.ID},
+ &issues_model.PullRequest{IssueID: issue.ID},
+ &issues_model.Comment{RefIssueID: issue.ID},
+ &issues_model.IssueDependency{DependencyID: issue.ID},
+ &issues_model.Comment{DependentIssueID: issue.ID},
+ &issues_model.IssuePin{IssueID: issue.ID},
+ ); err != nil {
+ return nil, err
+ }
+
+ return attachmentPaths, nil
+ })
}
// DeleteOrphanedIssues delete issues without a repo
diff --git a/services/org/org.go b/services/org/org.go
index 142a643f9f..8da77c691c 100644
--- a/services/org/org.go
+++ b/services/org/org.go
@@ -52,39 +52,34 @@ func deleteOrganization(ctx context.Context, org *org_model.Organization) error
// DeleteOrganization completely and permanently deletes everything of organization.
func DeleteOrganization(ctx context.Context, org *org_model.Organization, purge bool) error {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- if purge {
- err := repo_service.DeleteOwnerRepositoriesDirectly(ctx, org.AsUser())
- if err != nil {
- return err
+ if err := db.WithTx(ctx, func(ctx context.Context) error {
+ if purge {
+ err := repo_service.DeleteOwnerRepositoriesDirectly(ctx, org.AsUser())
+ if err != nil {
+ return err
+ }
}
- }
- // Check ownership of repository.
- count, err := repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{OwnerID: org.ID})
- if err != nil {
- return fmt.Errorf("GetRepositoryCount: %w", err)
- } else if count > 0 {
- return repo_model.ErrUserOwnRepos{UID: org.ID}
- }
+ // Check ownership of repository.
+ count, err := repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{OwnerID: org.ID})
+ if err != nil {
+ return fmt.Errorf("GetRepositoryCount: %w", err)
+ } else if count > 0 {
+ return repo_model.ErrUserOwnRepos{UID: org.ID}
+ }
- // Check ownership of packages.
- if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil {
- return fmt.Errorf("HasOwnerPackages: %w", err)
- } else if ownsPackages {
- return packages_model.ErrUserOwnPackages{UID: org.ID}
- }
+ // Check ownership of packages.
+ if ownsPackages, err := packages_model.HasOwnerPackages(ctx, org.ID); err != nil {
+ return fmt.Errorf("HasOwnerPackages: %w", err)
+ } else if ownsPackages {
+ return packages_model.ErrUserOwnPackages{UID: org.ID}
+ }
- if err := deleteOrganization(ctx, org); err != nil {
- return fmt.Errorf("DeleteOrganization: %w", err)
- }
-
- if err := committer.Commit(); err != nil {
+ if err := deleteOrganization(ctx, org); err != nil {
+ return fmt.Errorf("DeleteOrganization: %w", err)
+ }
+ return nil
+ }); err != nil {
return err
}
diff --git a/services/org/user.go b/services/org/user.go
index 26927253d2..6858271858 100644
--- a/services/org/user.go
+++ b/services/org/user.go
@@ -47,57 +47,52 @@ func RemoveOrgUser(ctx context.Context, org *organization.Organization, user *us
}
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ if _, err := db.DeleteByID[organization.OrgUser](ctx, ou.ID); err != nil {
+ return err
+ } else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members=num_members-1 WHERE id=?", org.ID); err != nil {
+ return err
+ }
- if _, err := db.DeleteByID[organization.OrgUser](ctx, ou.ID); err != nil {
- return err
- } else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members=num_members-1 WHERE id=?", org.ID); err != nil {
- return err
- }
+ // Delete all repository accesses and unwatch them.
+ env, err := repo_model.AccessibleReposEnv(ctx, org, user.ID)
+ if err != nil {
+ return fmt.Errorf("AccessibleReposEnv: %w", err)
+ }
+ repoIDs, err := env.RepoIDs(ctx)
+ if err != nil {
+ return fmt.Errorf("GetUserRepositories [%d]: %w", user.ID, err)
+ }
- // Delete all repository accesses and unwatch them.
- env, err := repo_model.AccessibleReposEnv(ctx, org, user.ID)
- if err != nil {
- return fmt.Errorf("AccessibleReposEnv: %w", err)
- }
- repoIDs, err := env.RepoIDs(ctx)
- if err != nil {
- return fmt.Errorf("GetUserRepositories [%d]: %w", user.ID, err)
- }
+ for _, repoID := range repoIDs {
+ repo, err := repo_model.GetRepositoryByID(ctx, repoID)
+ if err != nil {
+ return err
+ }
+ if err = repo_model.WatchRepo(ctx, user, repo, false); err != nil {
+ return err
+ }
+ }
- for _, repoID := range repoIDs {
- repo, err := repo_model.GetRepositoryByID(ctx, repoID)
+ if len(repoIDs) > 0 {
+ if _, err = db.GetEngine(ctx).
+ Where("user_id = ?", user.ID).
+ In("repo_id", repoIDs).
+ Delete(new(access_model.Access)); err != nil {
+ return err
+ }
+ }
+
+ // Delete member in their teams.
+ teams, err := organization.GetUserOrgTeams(ctx, org.ID, user.ID)
if err != nil {
return err
}
- if err = repo_model.WatchRepo(ctx, user, repo, false); err != nil {
- return err
+ for _, t := range teams {
+ if err = removeTeamMember(ctx, t, user); err != nil {
+ return err
+ }
}
- }
-
- if len(repoIDs) > 0 {
- if _, err = db.GetEngine(ctx).
- Where("user_id = ?", user.ID).
- In("repo_id", repoIDs).
- Delete(new(access_model.Access)); err != nil {
- return err
- }
- }
-
- // Delete member in their teams.
- teams, err := organization.GetUserOrgTeams(ctx, org.ID, user.ID)
- if err != nil {
- return err
- }
- for _, t := range teams {
- if err = removeTeamMember(ctx, t, user); err != nil {
- return err
- }
- }
-
- return committer.Commit()
+ return nil
+ })
}
diff --git a/services/release/release.go b/services/release/release.go
index 0b8a74252a..1e2132bb60 100644
--- a/services/release/release.go
+++ b/services/release/release.go
@@ -267,74 +267,69 @@ func UpdateRelease(ctx context.Context, doer *user_model.User, gitRepo *git.Repo
}
rel.LowerTagName = strings.ToLower(rel.TagName)
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
oldRelease, err := repo_model.GetReleaseByID(ctx, rel.ID)
if err != nil {
return err
}
isConvertedFromTag := oldRelease.IsTag && !rel.IsTag
- if err = repo_model.UpdateRelease(ctx, rel); err != nil {
- return err
- }
-
- if err = repo_model.AddReleaseAttachments(ctx, rel.ID, addAttachmentUUIDs); err != nil {
- return fmt.Errorf("AddReleaseAttachments: %w", err)
- }
-
- deletedUUIDs := make(container.Set[string])
- if len(delAttachmentUUIDs) > 0 {
- // Check attachments
- attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, delAttachmentUUIDs)
- if err != nil {
- return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %w", delAttachmentUUIDs, err)
+ if err := db.WithTx(ctx, func(ctx context.Context) error {
+ if err = repo_model.UpdateRelease(ctx, rel); err != nil {
+ return err
}
- for _, attach := range attachments {
- if attach.ReleaseID != rel.ID {
- return util.NewPermissionDeniedErrorf("delete attachment of release permission denied")
+
+ if err = repo_model.AddReleaseAttachments(ctx, rel.ID, addAttachmentUUIDs); err != nil {
+ return fmt.Errorf("AddReleaseAttachments: %w", err)
+ }
+
+ deletedUUIDs := make(container.Set[string])
+ if len(delAttachmentUUIDs) > 0 {
+ // Check attachments
+ attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, delAttachmentUUIDs)
+ if err != nil {
+ return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %w", delAttachmentUUIDs, err)
+ }
+ for _, attach := range attachments {
+ if attach.ReleaseID != rel.ID {
+ return util.NewPermissionDeniedErrorf("delete attachment of release permission denied")
+ }
+ deletedUUIDs.Add(attach.UUID)
}
- deletedUUIDs.Add(attach.UUID)
- }
- if _, err := repo_model.DeleteAttachments(ctx, attachments, true); err != nil {
- return fmt.Errorf("DeleteAttachments [uuids: %v]: %w", delAttachmentUUIDs, err)
- }
- }
-
- if len(editAttachments) > 0 {
- updateAttachmentsList := make([]string, 0, len(editAttachments))
- for k := range editAttachments {
- updateAttachmentsList = append(updateAttachmentsList, k)
- }
- // Check attachments
- attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, updateAttachmentsList)
- if err != nil {
- return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %w", updateAttachmentsList, err)
- }
- for _, attach := range attachments {
- if attach.ReleaseID != rel.ID {
- return util.NewPermissionDeniedErrorf("update attachment of release permission denied")
+ if _, err := repo_model.DeleteAttachments(ctx, attachments, true); err != nil {
+ return fmt.Errorf("DeleteAttachments [uuids: %v]: %w", delAttachmentUUIDs, err)
}
}
- for uuid, newName := range editAttachments {
- if !deletedUUIDs.Contains(uuid) {
- if err = repo_model.UpdateAttachmentByUUID(ctx, &repo_model.Attachment{
- UUID: uuid,
- Name: newName,
- }, "name"); err != nil {
- return err
+ if len(editAttachments) > 0 {
+ updateAttachmentsList := make([]string, 0, len(editAttachments))
+ for k := range editAttachments {
+ updateAttachmentsList = append(updateAttachmentsList, k)
+ }
+ // Check attachments
+ attachments, err := repo_model.GetAttachmentsByUUIDs(ctx, updateAttachmentsList)
+ if err != nil {
+ return fmt.Errorf("GetAttachmentsByUUIDs [uuids: %v]: %w", updateAttachmentsList, err)
+ }
+ for _, attach := range attachments {
+ if attach.ReleaseID != rel.ID {
+ return util.NewPermissionDeniedErrorf("update attachment of release permission denied")
+ }
+ }
+
+ for uuid, newName := range editAttachments {
+ if !deletedUUIDs.Contains(uuid) {
+ if err = repo_model.UpdateAttachmentByUUID(ctx, &repo_model.Attachment{
+ UUID: uuid,
+ Name: newName,
+ }, "name"); err != nil {
+ return err
+ }
}
}
}
- }
-
- if err := committer.Commit(); err != nil {
+ return nil
+ }); err != nil {
return err
}
diff --git a/services/repository/migrate.go b/services/repository/migrate.go
index 664f0cf097..66622f1601 100644
--- a/services/repository/migrate.go
+++ b/services/repository/migrate.go
@@ -173,92 +173,88 @@ func MigrateRepositoryGitData(ctx context.Context, u *user_model.User,
}
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return nil, err
- }
- defer committer.Close()
-
- if opts.Mirror {
- remoteAddress, err := util.SanitizeURL(opts.CloneAddr)
- if err != nil {
- return repo, err
- }
- mirrorModel := repo_model.Mirror{
- RepoID: repo.ID,
- Interval: setting.Mirror.DefaultInterval,
- EnablePrune: true,
- NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
- LFS: opts.LFS,
- RemoteAddress: remoteAddress,
- }
- if opts.LFS {
- mirrorModel.LFSEndpoint = opts.LFSEndpoint
- }
-
- if opts.MirrorInterval != "" {
- parsedInterval, err := time.ParseDuration(opts.MirrorInterval)
+ return db.WithTx2(ctx, func(ctx context.Context) (*repo_model.Repository, error) {
+ if opts.Mirror {
+ remoteAddress, err := util.SanitizeURL(opts.CloneAddr)
if err != nil {
- log.Error("Failed to set Interval: %v", err)
return repo, err
}
- if parsedInterval == 0 {
- mirrorModel.Interval = 0
- mirrorModel.NextUpdateUnix = 0
- } else if parsedInterval < setting.Mirror.MinInterval {
- err := fmt.Errorf("interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval)
- log.Error("Interval: %s is too frequent", opts.MirrorInterval)
- return repo, err
- } else {
- mirrorModel.Interval = parsedInterval
- mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval)
+ mirrorModel := repo_model.Mirror{
+ RepoID: repo.ID,
+ Interval: setting.Mirror.DefaultInterval,
+ EnablePrune: true,
+ NextUpdateUnix: timeutil.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
+ LFS: opts.LFS,
+ RemoteAddress: remoteAddress,
+ }
+ if opts.LFS {
+ mirrorModel.LFSEndpoint = opts.LFSEndpoint
+ }
+
+ if opts.MirrorInterval != "" {
+ parsedInterval, err := time.ParseDuration(opts.MirrorInterval)
+ if err != nil {
+ log.Error("Failed to set Interval: %v", err)
+ return repo, err
+ }
+ if parsedInterval == 0 {
+ mirrorModel.Interval = 0
+ mirrorModel.NextUpdateUnix = 0
+ } else if parsedInterval < setting.Mirror.MinInterval {
+ err := fmt.Errorf("interval %s is set below Minimum Interval of %s", parsedInterval, setting.Mirror.MinInterval)
+ log.Error("Interval: %s is too frequent", opts.MirrorInterval)
+ return repo, err
+ } else {
+ mirrorModel.Interval = parsedInterval
+ mirrorModel.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(parsedInterval)
+ }
+ }
+
+ if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil {
+ return repo, fmt.Errorf("InsertOne: %w", err)
+ }
+
+ repo.IsMirror = true
+ if err = repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "num_watches", "is_empty", "default_branch", "default_wiki_branch", "is_mirror"); err != nil {
+ return nil, err
+ }
+
+ if err = repo_module.UpdateRepoSize(ctx, repo); err != nil {
+ log.Error("Failed to update size for repository: %v", err)
+ }
+
+ // this is necessary for sync local tags from remote
+ configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName())
+ if stdout, _, err := git.NewCommand("config").
+ AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`).
+ RunStdString(ctx, &git.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)
+ }
+ } else {
+ if err = repo_module.UpdateRepoSize(ctx, repo); err != nil {
+ log.Error("Failed to update size for repository: %v", err)
+ }
+ if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil {
+ return nil, err
}
}
- if err = repo_model.InsertMirror(ctx, &mirrorModel); err != nil {
- return repo, fmt.Errorf("InsertOne: %w", err)
+ var enableRepoUnits []repo_model.RepoUnit
+ if opts.Releases && !unit_model.TypeReleases.UnitGlobalDisabled() {
+ enableRepoUnits = append(enableRepoUnits, repo_model.RepoUnit{RepoID: repo.ID, Type: unit_model.TypeReleases})
}
-
- repo.IsMirror = true
- if err = repo_model.UpdateRepositoryColsNoAutoTime(ctx, repo, "num_watches", "is_empty", "default_branch", "default_wiki_branch", "is_mirror"); err != nil {
- return nil, err
+ if opts.Wiki && !unit_model.TypeWiki.UnitGlobalDisabled() {
+ enableRepoUnits = append(enableRepoUnits, repo_model.RepoUnit{RepoID: repo.ID, Type: unit_model.TypeWiki})
}
-
- if err = repo_module.UpdateRepoSize(ctx, repo); err != nil {
- log.Error("Failed to update size for repository: %v", err)
+ if len(enableRepoUnits) > 0 {
+ err = UpdateRepositoryUnits(ctx, repo, enableRepoUnits, nil)
+ if err != nil {
+ return nil, err
+ }
}
-
- // this is necessary for sync local tags from remote
- configName := fmt.Sprintf("remote.%s.fetch", mirrorModel.GetRemoteName())
- if stdout, _, err := git.NewCommand("config").
- AddOptionValues("--add", configName, `+refs/tags/*:refs/tags/*`).
- RunStdString(ctx, &git.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)
- }
- } else {
- if err = repo_module.UpdateRepoSize(ctx, repo); err != nil {
- log.Error("Failed to update size for repository: %v", err)
- }
- if repo, err = CleanUpMigrateInfo(ctx, repo); err != nil {
- return nil, err
- }
- }
-
- var enableRepoUnits []repo_model.RepoUnit
- if opts.Releases && !unit_model.TypeReleases.UnitGlobalDisabled() {
- enableRepoUnits = append(enableRepoUnits, repo_model.RepoUnit{RepoID: repo.ID, Type: unit_model.TypeReleases})
- }
- if opts.Wiki && !unit_model.TypeWiki.UnitGlobalDisabled() {
- enableRepoUnits = append(enableRepoUnits, repo_model.RepoUnit{RepoID: repo.ID, Type: unit_model.TypeWiki})
- }
- if len(enableRepoUnits) > 0 {
- err = UpdateRepositoryUnits(ctx, repo, enableRepoUnits, nil)
- if err != nil {
- return nil, err
- }
- }
- return repo, committer.Commit()
+ return repo, nil
+ })
}
// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors.
diff --git a/services/user/user.go b/services/user/user.go
index c7252430de..d8abf199c3 100644
--- a/services/user/user.go
+++ b/services/user/user.go
@@ -210,65 +210,59 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
}
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
+ if err := db.WithTx(ctx, func(ctx context.Context) error {
+ // Note: A user owns any repository or belongs to any organization
+ // cannot perform delete operation. This causes a race with the purge above
+ // however consistency requires that we ensure that this is the case
+
+ // Check ownership of repository.
+ count, err := repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{OwnerID: u.ID})
+ if err != nil {
+ return fmt.Errorf("GetRepositoryCount: %w", err)
+ } else if count > 0 {
+ return repo_model.ErrUserOwnRepos{UID: u.ID}
+ }
+
+ // Check membership of organization.
+ count, err = organization.GetOrganizationCount(ctx, u)
+ if err != nil {
+ return fmt.Errorf("GetOrganizationCount: %w", err)
+ } else if count > 0 {
+ return organization.ErrUserHasOrgs{UID: u.ID}
+ }
+
+ // Check ownership of packages.
+ if ownsPackages, err := packages_model.HasOwnerPackages(ctx, u.ID); err != nil {
+ return fmt.Errorf("HasOwnerPackages: %w", err)
+ } else if ownsPackages {
+ return packages_model.ErrUserOwnPackages{UID: u.ID}
+ }
+
+ if err := deleteUser(ctx, u, purge); err != nil {
+ return fmt.Errorf("DeleteUser: %w", err)
+ }
+ return nil
+ }); err != nil {
return err
}
- defer committer.Close()
- // Note: A user owns any repository or belongs to any organization
- // cannot perform delete operation. This causes a race with the purge above
- // however consistency requires that we ensure that this is the case
-
- // Check ownership of repository.
- count, err := repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{OwnerID: u.ID})
- if err != nil {
- return fmt.Errorf("GetRepositoryCount: %w", err)
- } else if count > 0 {
- return repo_model.ErrUserOwnRepos{UID: u.ID}
- }
-
- // Check membership of organization.
- count, err = organization.GetOrganizationCount(ctx, u)
- if err != nil {
- return fmt.Errorf("GetOrganizationCount: %w", err)
- } else if count > 0 {
- return organization.ErrUserHasOrgs{UID: u.ID}
- }
-
- // Check ownership of packages.
- if ownsPackages, err := packages_model.HasOwnerPackages(ctx, u.ID); err != nil {
- return fmt.Errorf("HasOwnerPackages: %w", err)
- } else if ownsPackages {
- return packages_model.ErrUserOwnPackages{UID: u.ID}
- }
-
- if err := deleteUser(ctx, u, purge); err != nil {
- return fmt.Errorf("DeleteUser: %w", err)
- }
-
- if err := committer.Commit(); err != nil {
+ if err := asymkey_service.RewriteAllPublicKeys(ctx); err != nil {
return err
}
- _ = committer.Close()
-
- if err = asymkey_service.RewriteAllPublicKeys(ctx); err != nil {
- return err
- }
- if err = asymkey_service.RewriteAllPrincipalKeys(ctx); err != nil {
+ if err := asymkey_service.RewriteAllPrincipalKeys(ctx); err != nil {
return err
}
// Note: There are something just cannot be roll back, so just keep error logs of those operations.
path := user_model.UserPath(u.Name)
- if err = util.RemoveAll(path); err != nil {
+ if err := util.RemoveAll(path); err != nil {
err = fmt.Errorf("failed to RemoveAll %s: %w", path, err)
_ = system_model.CreateNotice(ctx, system_model.NoticeTask, fmt.Sprintf("delete user '%s': %v", u.Name, err))
}
if u.Avatar != "" {
avatarPath := u.CustomAvatarRelativePath()
- if err = storage.Avatars.Delete(avatarPath); err != nil {
+ if err := storage.Avatars.Delete(avatarPath); err != nil {
err = fmt.Errorf("failed to remove %s: %w", avatarPath, err)
_ = system_model.CreateNotice(ctx, system_model.NoticeTask, fmt.Sprintf("delete user '%s': %v", u.Name, err))
}
diff --git a/uv.lock b/uv.lock
index 6a6374d3fa..db2fa1212d 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1,5 +1,5 @@
version = 1
-revision = 2
+revision = 3
requires-python = ">=3.10"
[[package]]
@@ -118,11 +118,11 @@ wheels = [
[[package]]
name = "json5"
-version = "0.12.0"
+version = "0.12.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/12/be/c6c745ec4c4539b25a278b70e29793f10382947df0d9efba2fa09120895d/json5-0.12.0.tar.gz", hash = "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a", size = 51907, upload-time = "2025-04-03T16:33:13.201Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/12/ae/929aee9619e9eba9015207a9d2c1c54db18311da7eb4dcf6d41ad6f0eb67/json5-0.12.1.tar.gz", hash = "sha256:b2743e77b3242f8d03c143dd975a6ec7c52e2f2afe76ed934e53503dd4ad4990", size = 52191, upload-time = "2025-08-12T19:47:42.583Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/41/9f/3500910d5a98549e3098807493851eeef2b89cdd3032227558a104dfe926/json5-0.12.0-py3-none-any.whl", hash = "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db", size = 36079, upload-time = "2025-04-03T16:33:11.927Z" },
+ { url = "https://files.pythonhosted.org/packages/85/e2/05328bd2621be49a6fed9e3030b1e51a2d04537d3f816d211b9cc53c5262/json5-0.12.1-py3-none-any.whl", hash = "sha256:d9c9b3bc34a5f54d43c35e11ef7cb87d8bdd098c6ace87117a7b7e83e705c1d5", size = 36119, upload-time = "2025-08-12T19:47:41.131Z" },
]
[[package]]
@@ -180,81 +180,81 @@ wheels = [
[[package]]
name = "regex"
-version = "2025.7.34"
+version = "2025.9.1"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/0b/de/e13fa6dc61d78b30ba47481f99933a3b49a57779d625c392d8036770a60d/regex-2025.7.34.tar.gz", hash = "sha256:9ead9765217afd04a86822dfcd4ed2747dfe426e887da413b15ff0ac2457e21a", size = 400714, upload-time = "2025-07-31T00:21:16.262Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/b2/5a/4c63457fbcaf19d138d72b2e9b39405954f98c0349b31c601bfcb151582c/regex-2025.9.1.tar.gz", hash = "sha256:88ac07b38d20b54d79e704e38aa3bd2c0f8027432164226bdee201a1c0c9c9ff", size = 400852, upload-time = "2025-09-01T22:10:10.479Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/50/d2/0a44a9d92370e5e105f16669acf801b215107efea9dea4317fe96e9aad67/regex-2025.7.34-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d856164d25e2b3b07b779bfed813eb4b6b6ce73c2fd818d46f47c1eb5cd79bd6", size = 484591, upload-time = "2025-07-31T00:18:46.675Z" },
- { url = "https://files.pythonhosted.org/packages/2e/b1/00c4f83aa902f1048495de9f2f33638ce970ce1cf9447b477d272a0e22bb/regex-2025.7.34-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d15a9da5fad793e35fb7be74eec450d968e05d2e294f3e0e77ab03fa7234a83", size = 289293, upload-time = "2025-07-31T00:18:53.069Z" },
- { url = "https://files.pythonhosted.org/packages/f3/b0/5bc5c8ddc418e8be5530b43ae1f7c9303f43aeff5f40185c4287cf6732f2/regex-2025.7.34-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:95b4639c77d414efa93c8de14ce3f7965a94d007e068a94f9d4997bb9bd9c81f", size = 285932, upload-time = "2025-07-31T00:18:54.673Z" },
- { url = "https://files.pythonhosted.org/packages/46/c7/a1a28d050b23665a5e1eeb4d7f13b83ea86f0bc018da7b8f89f86ff7f094/regex-2025.7.34-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d7de1ceed5a5f84f342ba4a9f4ae589524adf9744b2ee61b5da884b5b659834", size = 780361, upload-time = "2025-07-31T00:18:56.13Z" },
- { url = "https://files.pythonhosted.org/packages/cb/0d/82e7afe7b2c9fe3d488a6ab6145d1d97e55f822dfb9b4569aba2497e3d09/regex-2025.7.34-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02e5860a250cd350c4933cf376c3bc9cb28948e2c96a8bc042aee7b985cfa26f", size = 849176, upload-time = "2025-07-31T00:18:57.483Z" },
- { url = "https://files.pythonhosted.org/packages/bf/16/3036e16903d8194f1490af457a7e33b06d9e9edd9576b1fe6c7ac660e9ed/regex-2025.7.34-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0a5966220b9a1a88691282b7e4350e9599cf65780ca60d914a798cb791aa1177", size = 897222, upload-time = "2025-07-31T00:18:58.721Z" },
- { url = "https://files.pythonhosted.org/packages/5a/c2/010e089ae00d31418e7d2c6601760eea1957cde12be719730c7133b8c165/regex-2025.7.34-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48fb045bbd4aab2418dc1ba2088a5e32de4bfe64e1457b948bb328a8dc2f1c2e", size = 789831, upload-time = "2025-07-31T00:19:00.436Z" },
- { url = "https://files.pythonhosted.org/packages/dd/86/b312b7bf5c46d21dbd9a3fdc4a80fde56ea93c9c0b89cf401879635e094d/regex-2025.7.34-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:20ff8433fa45e131f7316594efe24d4679c5449c0ca69d91c2f9d21846fdf064", size = 780665, upload-time = "2025-07-31T00:19:01.828Z" },
- { url = "https://files.pythonhosted.org/packages/40/e5/674b82bfff112c820b09e3c86a423d4a568143ede7f8440fdcbce259e895/regex-2025.7.34-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c436fd1e95c04c19039668cfb548450a37c13f051e8659f40aed426e36b3765f", size = 773511, upload-time = "2025-07-31T00:19:03.654Z" },
- { url = "https://files.pythonhosted.org/packages/2d/18/39e7c578eb6cf1454db2b64e4733d7e4f179714867a75d84492ec44fa9b2/regex-2025.7.34-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:0b85241d3cfb9f8a13cefdfbd58a2843f208f2ed2c88181bf84e22e0c7fc066d", size = 843990, upload-time = "2025-07-31T00:19:05.61Z" },
- { url = "https://files.pythonhosted.org/packages/b6/d9/522a6715aefe2f463dc60c68924abeeb8ab6893f01adf5720359d94ede8c/regex-2025.7.34-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:075641c94126b064c65ab86e7e71fc3d63e7ff1bea1fb794f0773c97cdad3a03", size = 834676, upload-time = "2025-07-31T00:19:07.023Z" },
- { url = "https://files.pythonhosted.org/packages/59/53/c4d5284cb40543566542e24f1badc9f72af68d01db21e89e36e02292eee0/regex-2025.7.34-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:70645cad3407d103d1dbcb4841839d2946f7d36cf38acbd40120fee1682151e5", size = 778420, upload-time = "2025-07-31T00:19:08.511Z" },
- { url = "https://files.pythonhosted.org/packages/ea/4a/b779a7707d4a44a7e6ee9d0d98e40b2a4de74d622966080e9c95e25e2d24/regex-2025.7.34-cp310-cp310-win32.whl", hash = "sha256:3b836eb4a95526b263c2a3359308600bd95ce7848ebd3c29af0c37c4f9627cd3", size = 263999, upload-time = "2025-07-31T00:19:10.072Z" },
- { url = "https://files.pythonhosted.org/packages/ef/6e/33c7583f5427aa039c28bff7f4103c2de5b6aa5b9edc330c61ec576b1960/regex-2025.7.34-cp310-cp310-win_amd64.whl", hash = "sha256:cbfaa401d77334613cf434f723c7e8ba585df162be76474bccc53ae4e5520b3a", size = 276023, upload-time = "2025-07-31T00:19:11.34Z" },
- { url = "https://files.pythonhosted.org/packages/9f/fc/00b32e0ac14213d76d806d952826402b49fd06d42bfabacdf5d5d016bc47/regex-2025.7.34-cp310-cp310-win_arm64.whl", hash = "sha256:bca11d3c38a47c621769433c47f364b44e8043e0de8e482c5968b20ab90a3986", size = 268357, upload-time = "2025-07-31T00:19:12.729Z" },
- { url = "https://files.pythonhosted.org/packages/0d/85/f497b91577169472f7c1dc262a5ecc65e39e146fc3a52c571e5daaae4b7d/regex-2025.7.34-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:da304313761b8500b8e175eb2040c4394a875837d5635f6256d6fa0377ad32c8", size = 484594, upload-time = "2025-07-31T00:19:13.927Z" },
- { url = "https://files.pythonhosted.org/packages/1c/c5/ad2a5c11ce9e6257fcbfd6cd965d07502f6054aaa19d50a3d7fd991ec5d1/regex-2025.7.34-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:35e43ebf5b18cd751ea81455b19acfdec402e82fe0dc6143edfae4c5c4b3909a", size = 289294, upload-time = "2025-07-31T00:19:15.395Z" },
- { url = "https://files.pythonhosted.org/packages/8e/01/83ffd9641fcf5e018f9b51aa922c3e538ac9439424fda3df540b643ecf4f/regex-2025.7.34-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96bbae4c616726f4661fe7bcad5952e10d25d3c51ddc388189d8864fbc1b3c68", size = 285933, upload-time = "2025-07-31T00:19:16.704Z" },
- { url = "https://files.pythonhosted.org/packages/77/20/5edab2e5766f0259bc1da7381b07ce6eb4401b17b2254d02f492cd8a81a8/regex-2025.7.34-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9feab78a1ffa4f2b1e27b1bcdaad36f48c2fed4870264ce32f52a393db093c78", size = 792335, upload-time = "2025-07-31T00:19:18.561Z" },
- { url = "https://files.pythonhosted.org/packages/30/bd/744d3ed8777dce8487b2606b94925e207e7c5931d5870f47f5b643a4580a/regex-2025.7.34-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f14b36e6d4d07f1a5060f28ef3b3561c5d95eb0651741474ce4c0a4c56ba8719", size = 858605, upload-time = "2025-07-31T00:19:20.204Z" },
- { url = "https://files.pythonhosted.org/packages/99/3d/93754176289718d7578c31d151047e7b8acc7a8c20e7706716f23c49e45e/regex-2025.7.34-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85c3a958ef8b3d5079c763477e1f09e89d13ad22198a37e9d7b26b4b17438b33", size = 905780, upload-time = "2025-07-31T00:19:21.876Z" },
- { url = "https://files.pythonhosted.org/packages/ee/2e/c689f274a92deffa03999a430505ff2aeace408fd681a90eafa92fdd6930/regex-2025.7.34-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37555e4ae0b93358fa7c2d240a4291d4a4227cc7c607d8f85596cdb08ec0a083", size = 798868, upload-time = "2025-07-31T00:19:23.222Z" },
- { url = "https://files.pythonhosted.org/packages/0d/9e/39673688805d139b33b4a24851a71b9978d61915c4d72b5ffda324d0668a/regex-2025.7.34-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ee38926f31f1aa61b0232a3a11b83461f7807661c062df9eb88769d86e6195c3", size = 781784, upload-time = "2025-07-31T00:19:24.59Z" },
- { url = "https://files.pythonhosted.org/packages/18/bd/4c1cab12cfabe14beaa076523056b8ab0c882a8feaf0a6f48b0a75dab9ed/regex-2025.7.34-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a664291c31cae9c4a30589bd8bc2ebb56ef880c9c6264cb7643633831e606a4d", size = 852837, upload-time = "2025-07-31T00:19:25.911Z" },
- { url = "https://files.pythonhosted.org/packages/cb/21/663d983cbb3bba537fc213a579abbd0f263fb28271c514123f3c547ab917/regex-2025.7.34-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f3e5c1e0925e77ec46ddc736b756a6da50d4df4ee3f69536ffb2373460e2dafd", size = 844240, upload-time = "2025-07-31T00:19:27.688Z" },
- { url = "https://files.pythonhosted.org/packages/8e/2d/9beeeb913bc5d32faa913cf8c47e968da936af61ec20af5d269d0f84a100/regex-2025.7.34-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d428fc7731dcbb4e2ffe43aeb8f90775ad155e7db4347a639768bc6cd2df881a", size = 787139, upload-time = "2025-07-31T00:19:29.475Z" },
- { url = "https://files.pythonhosted.org/packages/eb/f5/9b9384415fdc533551be2ba805dd8c4621873e5df69c958f403bfd3b2b6e/regex-2025.7.34-cp311-cp311-win32.whl", hash = "sha256:e154a7ee7fa18333ad90b20e16ef84daaeac61877c8ef942ec8dfa50dc38b7a1", size = 264019, upload-time = "2025-07-31T00:19:31.129Z" },
- { url = "https://files.pythonhosted.org/packages/18/9d/e069ed94debcf4cc9626d652a48040b079ce34c7e4fb174f16874958d485/regex-2025.7.34-cp311-cp311-win_amd64.whl", hash = "sha256:24257953d5c1d6d3c129ab03414c07fc1a47833c9165d49b954190b2b7f21a1a", size = 276047, upload-time = "2025-07-31T00:19:32.497Z" },
- { url = "https://files.pythonhosted.org/packages/fd/cf/3bafbe9d1fd1db77355e7fbbbf0d0cfb34501a8b8e334deca14f94c7b315/regex-2025.7.34-cp311-cp311-win_arm64.whl", hash = "sha256:3157aa512b9e606586900888cd469a444f9b898ecb7f8931996cb715f77477f0", size = 268362, upload-time = "2025-07-31T00:19:34.094Z" },
- { url = "https://files.pythonhosted.org/packages/ff/f0/31d62596c75a33f979317658e8d261574785c6cd8672c06741ce2e2e2070/regex-2025.7.34-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:7f7211a746aced993bef487de69307a38c5ddd79257d7be83f7b202cb59ddb50", size = 485492, upload-time = "2025-07-31T00:19:35.57Z" },
- { url = "https://files.pythonhosted.org/packages/d8/16/b818d223f1c9758c3434be89aa1a01aae798e0e0df36c1f143d1963dd1ee/regex-2025.7.34-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fb31080f2bd0681484b275461b202b5ad182f52c9ec606052020fe13eb13a72f", size = 290000, upload-time = "2025-07-31T00:19:37.175Z" },
- { url = "https://files.pythonhosted.org/packages/cd/70/69506d53397b4bd6954061bae75677ad34deb7f6ca3ba199660d6f728ff5/regex-2025.7.34-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0200a5150c4cf61e407038f4b4d5cdad13e86345dac29ff9dab3d75d905cf130", size = 286072, upload-time = "2025-07-31T00:19:38.612Z" },
- { url = "https://files.pythonhosted.org/packages/b0/73/536a216d5f66084fb577bb0543b5cb7de3272eb70a157f0c3a542f1c2551/regex-2025.7.34-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:739a74970e736df0773788377969c9fea3876c2fc13d0563f98e5503e5185f46", size = 797341, upload-time = "2025-07-31T00:19:40.119Z" },
- { url = "https://files.pythonhosted.org/packages/26/af/733f8168449e56e8f404bb807ea7189f59507cbea1b67a7bbcd92f8bf844/regex-2025.7.34-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4fef81b2f7ea6a2029161ed6dea9ae13834c28eb5a95b8771828194a026621e4", size = 862556, upload-time = "2025-07-31T00:19:41.556Z" },
- { url = "https://files.pythonhosted.org/packages/19/dd/59c464d58c06c4f7d87de4ab1f590e430821345a40c5d345d449a636d15f/regex-2025.7.34-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ea74cf81fe61a7e9d77989050d0089a927ab758c29dac4e8e1b6c06fccf3ebf0", size = 910762, upload-time = "2025-07-31T00:19:43Z" },
- { url = "https://files.pythonhosted.org/packages/37/a8/b05ccf33ceca0815a1e253693b2c86544932ebcc0049c16b0fbdf18b688b/regex-2025.7.34-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e4636a7f3b65a5f340ed9ddf53585c42e3ff37101d383ed321bfe5660481744b", size = 801892, upload-time = "2025-07-31T00:19:44.645Z" },
- { url = "https://files.pythonhosted.org/packages/5f/9a/b993cb2e634cc22810afd1652dba0cae156c40d4864285ff486c73cd1996/regex-2025.7.34-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cef962d7834437fe8d3da6f9bfc6f93f20f218266dcefec0560ed7765f5fe01", size = 786551, upload-time = "2025-07-31T00:19:46.127Z" },
- { url = "https://files.pythonhosted.org/packages/2d/79/7849d67910a0de4e26834b5bb816e028e35473f3d7ae563552ea04f58ca2/regex-2025.7.34-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:cbe1698e5b80298dbce8df4d8d1182279fbdaf1044e864cbc9d53c20e4a2be77", size = 856457, upload-time = "2025-07-31T00:19:47.562Z" },
- { url = "https://files.pythonhosted.org/packages/91/c6/de516bc082524b27e45cb4f54e28bd800c01efb26d15646a65b87b13a91e/regex-2025.7.34-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:32b9f9bcf0f605eb094b08e8da72e44badabb63dde6b83bd530580b488d1c6da", size = 848902, upload-time = "2025-07-31T00:19:49.312Z" },
- { url = "https://files.pythonhosted.org/packages/7d/22/519ff8ba15f732db099b126f039586bd372da6cd4efb810d5d66a5daeda1/regex-2025.7.34-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:524c868ba527eab4e8744a9287809579f54ae8c62fbf07d62aacd89f6026b282", size = 788038, upload-time = "2025-07-31T00:19:50.794Z" },
- { url = "https://files.pythonhosted.org/packages/3f/7d/aabb467d8f57d8149895d133c88eb809a1a6a0fe262c1d508eb9dfabb6f9/regex-2025.7.34-cp312-cp312-win32.whl", hash = "sha256:d600e58ee6d036081c89696d2bdd55d507498a7180df2e19945c6642fac59588", size = 264417, upload-time = "2025-07-31T00:19:52.292Z" },
- { url = "https://files.pythonhosted.org/packages/3b/39/bd922b55a4fc5ad5c13753274e5b536f5b06ec8eb9747675668491c7ab7a/regex-2025.7.34-cp312-cp312-win_amd64.whl", hash = "sha256:9a9ab52a466a9b4b91564437b36417b76033e8778e5af8f36be835d8cb370d62", size = 275387, upload-time = "2025-07-31T00:19:53.593Z" },
- { url = "https://files.pythonhosted.org/packages/f7/3c/c61d2fdcecb754a40475a3d1ef9a000911d3e3fc75c096acf44b0dfb786a/regex-2025.7.34-cp312-cp312-win_arm64.whl", hash = "sha256:c83aec91af9c6fbf7c743274fd952272403ad9a9db05fe9bfc9df8d12b45f176", size = 268482, upload-time = "2025-07-31T00:19:55.183Z" },
- { url = "https://files.pythonhosted.org/packages/15/16/b709b2119975035169a25aa8e4940ca177b1a2e25e14f8d996d09130368e/regex-2025.7.34-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c3c9740a77aeef3f5e3aaab92403946a8d34437db930a0280e7e81ddcada61f5", size = 485334, upload-time = "2025-07-31T00:19:56.58Z" },
- { url = "https://files.pythonhosted.org/packages/94/a6/c09136046be0595f0331bc58a0e5f89c2d324cf734e0b0ec53cf4b12a636/regex-2025.7.34-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:69ed3bc611540f2ea70a4080f853741ec698be556b1df404599f8724690edbcd", size = 289942, upload-time = "2025-07-31T00:19:57.943Z" },
- { url = "https://files.pythonhosted.org/packages/36/91/08fc0fd0f40bdfb0e0df4134ee37cfb16e66a1044ac56d36911fd01c69d2/regex-2025.7.34-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d03c6f9dcd562c56527c42b8530aad93193e0b3254a588be1f2ed378cdfdea1b", size = 285991, upload-time = "2025-07-31T00:19:59.837Z" },
- { url = "https://files.pythonhosted.org/packages/be/2f/99dc8f6f756606f0c214d14c7b6c17270b6bbe26d5c1f05cde9dbb1c551f/regex-2025.7.34-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6164b1d99dee1dfad33f301f174d8139d4368a9fb50bf0a3603b2eaf579963ad", size = 797415, upload-time = "2025-07-31T00:20:01.668Z" },
- { url = "https://files.pythonhosted.org/packages/62/cf/2fcdca1110495458ba4e95c52ce73b361cf1cafd8a53b5c31542cde9a15b/regex-2025.7.34-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1e4f4f62599b8142362f164ce776f19d79bdd21273e86920a7b604a4275b4f59", size = 862487, upload-time = "2025-07-31T00:20:03.142Z" },
- { url = "https://files.pythonhosted.org/packages/90/38/899105dd27fed394e3fae45607c1983e138273ec167e47882fc401f112b9/regex-2025.7.34-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:72a26dcc6a59c057b292f39d41465d8233a10fd69121fa24f8f43ec6294e5415", size = 910717, upload-time = "2025-07-31T00:20:04.727Z" },
- { url = "https://files.pythonhosted.org/packages/ee/f6/4716198dbd0bcc9c45625ac4c81a435d1c4d8ad662e8576dac06bab35b17/regex-2025.7.34-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5273fddf7a3e602695c92716c420c377599ed3c853ea669c1fe26218867002f", size = 801943, upload-time = "2025-07-31T00:20:07.1Z" },
- { url = "https://files.pythonhosted.org/packages/40/5d/cff8896d27e4e3dd11dd72ac78797c7987eb50fe4debc2c0f2f1682eb06d/regex-2025.7.34-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c1844be23cd40135b3a5a4dd298e1e0c0cb36757364dd6cdc6025770363e06c1", size = 786664, upload-time = "2025-07-31T00:20:08.818Z" },
- { url = "https://files.pythonhosted.org/packages/10/29/758bf83cf7b4c34f07ac3423ea03cee3eb3176941641e4ccc05620f6c0b8/regex-2025.7.34-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dde35e2afbbe2272f8abee3b9fe6772d9b5a07d82607b5788e8508974059925c", size = 856457, upload-time = "2025-07-31T00:20:10.328Z" },
- { url = "https://files.pythonhosted.org/packages/d7/30/c19d212b619963c5b460bfed0ea69a092c6a43cba52a973d46c27b3e2975/regex-2025.7.34-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:f3f6e8e7af516a7549412ce57613e859c3be27d55341a894aacaa11703a4c31a", size = 849008, upload-time = "2025-07-31T00:20:11.823Z" },
- { url = "https://files.pythonhosted.org/packages/9e/b8/3c35da3b12c87e3cc00010ef6c3a4ae787cff0bc381aa3d251def219969a/regex-2025.7.34-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:469142fb94a869beb25b5f18ea87646d21def10fbacb0bcb749224f3509476f0", size = 788101, upload-time = "2025-07-31T00:20:13.729Z" },
- { url = "https://files.pythonhosted.org/packages/47/80/2f46677c0b3c2b723b2c358d19f9346e714113865da0f5f736ca1a883bde/regex-2025.7.34-cp313-cp313-win32.whl", hash = "sha256:da7507d083ee33ccea1310447410c27ca11fb9ef18c95899ca57ff60a7e4d8f1", size = 264401, upload-time = "2025-07-31T00:20:15.233Z" },
- { url = "https://files.pythonhosted.org/packages/be/fa/917d64dd074682606a003cba33585c28138c77d848ef72fc77cbb1183849/regex-2025.7.34-cp313-cp313-win_amd64.whl", hash = "sha256:9d644de5520441e5f7e2db63aec2748948cc39ed4d7a87fd5db578ea4043d997", size = 275368, upload-time = "2025-07-31T00:20:16.711Z" },
- { url = "https://files.pythonhosted.org/packages/65/cd/f94383666704170a2154a5df7b16be28f0c27a266bffcd843e58bc84120f/regex-2025.7.34-cp313-cp313-win_arm64.whl", hash = "sha256:7bf1c5503a9f2cbd2f52d7e260acb3131b07b6273c470abb78568174fe6bde3f", size = 268482, upload-time = "2025-07-31T00:20:18.189Z" },
- { url = "https://files.pythonhosted.org/packages/ac/23/6376f3a23cf2f3c00514b1cdd8c990afb4dfbac3cb4a68b633c6b7e2e307/regex-2025.7.34-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:8283afe7042d8270cecf27cca558873168e771183d4d593e3c5fe5f12402212a", size = 485385, upload-time = "2025-07-31T00:20:19.692Z" },
- { url = "https://files.pythonhosted.org/packages/73/5b/6d4d3a0b4d312adbfd6d5694c8dddcf1396708976dd87e4d00af439d962b/regex-2025.7.34-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6c053f9647e3421dd2f5dff8172eb7b4eec129df9d1d2f7133a4386319b47435", size = 289788, upload-time = "2025-07-31T00:20:21.941Z" },
- { url = "https://files.pythonhosted.org/packages/92/71/5862ac9913746e5054d01cb9fb8125b3d0802c0706ef547cae1e7f4428fa/regex-2025.7.34-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a16dd56bbcb7d10e62861c3cd000290ddff28ea142ffb5eb3470f183628011ac", size = 286136, upload-time = "2025-07-31T00:20:26.146Z" },
- { url = "https://files.pythonhosted.org/packages/27/df/5b505dc447eb71278eba10d5ec940769ca89c1af70f0468bfbcb98035dc2/regex-2025.7.34-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69c593ff5a24c0d5c1112b0df9b09eae42b33c014bdca7022d6523b210b69f72", size = 797753, upload-time = "2025-07-31T00:20:27.919Z" },
- { url = "https://files.pythonhosted.org/packages/86/38/3e3dc953d13998fa047e9a2414b556201dbd7147034fbac129392363253b/regex-2025.7.34-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:98d0ce170fcde1a03b5df19c5650db22ab58af375aaa6ff07978a85c9f250f0e", size = 863263, upload-time = "2025-07-31T00:20:29.803Z" },
- { url = "https://files.pythonhosted.org/packages/68/e5/3ff66b29dde12f5b874dda2d9dec7245c2051f2528d8c2a797901497f140/regex-2025.7.34-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d72765a4bff8c43711d5b0f5b452991a9947853dfa471972169b3cc0ba1d0751", size = 910103, upload-time = "2025-07-31T00:20:31.313Z" },
- { url = "https://files.pythonhosted.org/packages/9e/fe/14176f2182125977fba3711adea73f472a11f3f9288c1317c59cd16ad5e6/regex-2025.7.34-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4494f8fd95a77eb434039ad8460e64d57baa0434f1395b7da44015bef650d0e4", size = 801709, upload-time = "2025-07-31T00:20:33.323Z" },
- { url = "https://files.pythonhosted.org/packages/5a/0d/80d4e66ed24f1ba876a9e8e31b709f9fd22d5c266bf5f3ab3c1afe683d7d/regex-2025.7.34-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4f42b522259c66e918a0121a12429b2abcf696c6f967fa37bdc7b72e61469f98", size = 786726, upload-time = "2025-07-31T00:20:35.252Z" },
- { url = "https://files.pythonhosted.org/packages/12/75/c3ebb30e04a56c046f5c85179dc173818551037daae2c0c940c7b19152cb/regex-2025.7.34-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:aaef1f056d96a0a5d53ad47d019d5b4c66fe4be2da87016e0d43b7242599ffc7", size = 857306, upload-time = "2025-07-31T00:20:37.12Z" },
- { url = "https://files.pythonhosted.org/packages/b1/b2/a4dc5d8b14f90924f27f0ac4c4c4f5e195b723be98adecc884f6716614b6/regex-2025.7.34-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:656433e5b7dccc9bc0da6312da8eb897b81f5e560321ec413500e5367fcd5d47", size = 848494, upload-time = "2025-07-31T00:20:38.818Z" },
- { url = "https://files.pythonhosted.org/packages/0d/21/9ac6e07a4c5e8646a90b56b61f7e9dac11ae0747c857f91d3d2bc7c241d9/regex-2025.7.34-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e91eb2c62c39705e17b4d42d4b86c4e86c884c0d15d9c5a47d0835f8387add8e", size = 787850, upload-time = "2025-07-31T00:20:40.478Z" },
- { url = "https://files.pythonhosted.org/packages/be/6c/d51204e28e7bc54f9a03bb799b04730d7e54ff2718862b8d4e09e7110a6a/regex-2025.7.34-cp314-cp314-win32.whl", hash = "sha256:f978ddfb6216028c8f1d6b0f7ef779949498b64117fc35a939022f67f810bdcb", size = 269730, upload-time = "2025-07-31T00:20:42.253Z" },
- { url = "https://files.pythonhosted.org/packages/74/52/a7e92d02fa1fdef59d113098cb9f02c5d03289a0e9f9e5d4d6acccd10677/regex-2025.7.34-cp314-cp314-win_amd64.whl", hash = "sha256:4b7dc33b9b48fb37ead12ffc7bdb846ac72f99a80373c4da48f64b373a7abeae", size = 278640, upload-time = "2025-07-31T00:20:44.42Z" },
- { url = "https://files.pythonhosted.org/packages/d1/78/a815529b559b1771080faa90c3ab401730661f99d495ab0071649f139ebd/regex-2025.7.34-cp314-cp314-win_arm64.whl", hash = "sha256:4b8c4d39f451e64809912c82392933d80fe2e4a87eeef8859fcc5380d0173c64", size = 271757, upload-time = "2025-07-31T00:20:46.355Z" },
+ { url = "https://files.pythonhosted.org/packages/46/c1/ed9ef923156105a78aa004f9390e5dd87eadc29f5ca8840f172cadb638de/regex-2025.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5aa2a6a73bf218515484b36a0d20c6ad9dc63f6339ff6224147b0e2c095ee55", size = 484813, upload-time = "2025-09-01T22:07:45.528Z" },
+ { url = "https://files.pythonhosted.org/packages/05/de/97957618a774c67f892609eee2fafe3e30703fbbba66de5e6b79d7196dbc/regex-2025.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c2ff5c01d5e47ad5fc9d31bcd61e78c2fa0068ed00cab86b7320214446da766", size = 288981, upload-time = "2025-09-01T22:07:48.464Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/b0/441afadd0a6ffccbd58a9663e5bdd182daa237893e5f8ceec6ff9df4418a/regex-2025.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d49dc84e796b666181de8a9973284cad6616335f01b52bf099643253094920fc", size = 286608, upload-time = "2025-09-01T22:07:50.484Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/cf/d89aecaf17e999ab11a3ef73fc9ab8b64f4e156f121250ef84340b35338d/regex-2025.9.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9914fe1040874f83c15fcea86d94ea54091b0666eab330aaab69e30d106aabe", size = 780459, upload-time = "2025-09-01T22:07:52.34Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/05/05884594a9975a29597917bbdd6837f7b97e8ac23faf22d628aa781e58f7/regex-2025.9.1-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e71bceb3947362ec5eabd2ca0870bb78eae4edfc60c6c21495133c01b6cd2df4", size = 849276, upload-time = "2025-09-01T22:07:54.591Z" },
+ { url = "https://files.pythonhosted.org/packages/8c/8d/2b3067506838d02096bf107beb129b2ce328cdf776d6474b7f542c0a7bfd/regex-2025.9.1-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:67a74456f410fe5e869239ee7a5423510fe5121549af133809d9591a8075893f", size = 897320, upload-time = "2025-09-01T22:07:56.129Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/b3/0f9f7766e980b900df0ba9901b52871a2e4203698fb35cdebd219240d5f7/regex-2025.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5c3b96ed0223b32dbdc53a83149b6de7ca3acd5acd9c8e64b42a166228abe29c", size = 789931, upload-time = "2025-09-01T22:07:57.834Z" },
+ { url = "https://files.pythonhosted.org/packages/47/9f/7b2f29c8f8b698eb44be5fc68e8b9c8d32e99635eac5defc98de114e9f35/regex-2025.9.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:113d5aa950f428faf46fd77d452df62ebb4cc6531cb619f6cc30a369d326bfbd", size = 780764, upload-time = "2025-09-01T22:07:59.413Z" },
+ { url = "https://files.pythonhosted.org/packages/ac/ac/56176caa86155c14462531eb0a4ddc450d17ba8875001122b3b7c0cb01bf/regex-2025.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fcdeb38de4f7f3d69d798f4f371189061446792a84e7c92b50054c87aae9c07c", size = 773610, upload-time = "2025-09-01T22:08:01.042Z" },
+ { url = "https://files.pythonhosted.org/packages/39/e8/9d6b9bd43998268a9de2f35602077519cacc9cb149f7381758cf8f502ba7/regex-2025.9.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4bcdff370509164b67a6c8ec23c9fb40797b72a014766fdc159bb809bd74f7d8", size = 844090, upload-time = "2025-09-01T22:08:02.94Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/92/d89743b089005cae4cb81cc2fe177e180b7452e60f29de53af34349640f8/regex-2025.9.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:7383efdf6e8e8c61d85e00cfb2e2e18da1a621b8bfb4b0f1c2747db57b942b8f", size = 834775, upload-time = "2025-09-01T22:08:04.781Z" },
+ { url = "https://files.pythonhosted.org/packages/01/8f/86a3e0aaa89295d2a3445bb238e56369963ef6b02a5b4aa3362f4e687413/regex-2025.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1ec2bd3bdf0f73f7e9f48dca550ba7d973692d5e5e9a90ac42cc5f16c4432d8b", size = 778521, upload-time = "2025-09-01T22:08:06.596Z" },
+ { url = "https://files.pythonhosted.org/packages/3e/df/72072acb370ee8577c255717f8a58264f1d0de40aa3c9e6ebd5271cac633/regex-2025.9.1-cp310-cp310-win32.whl", hash = "sha256:9627e887116c4e9c0986d5c3b4f52bcfe3df09850b704f62ec3cbf177a0ae374", size = 264105, upload-time = "2025-09-01T22:08:08.708Z" },
+ { url = "https://files.pythonhosted.org/packages/97/73/fb82faaf0375aeaa1bb675008246c79b6779fa5688585a35327610ea0e2e/regex-2025.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:94533e32dc0065eca43912ee6649c90ea0681d59f56d43c45b5bcda9a740b3dd", size = 276131, upload-time = "2025-09-01T22:08:10.156Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/3a/77d7718a2493e54725494f44da1a1e55704743dc4b8fabe5b0596f7b8014/regex-2025.9.1-cp310-cp310-win_arm64.whl", hash = "sha256:a874a61bb580d48642ffd338570ee24ab13fa023779190513fcacad104a6e251", size = 268462, upload-time = "2025-09-01T22:08:11.651Z" },
+ { url = "https://files.pythonhosted.org/packages/06/4d/f741543c0c59f96c6625bc6c11fea1da2e378b7d293ffff6f318edc0ce14/regex-2025.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e5bcf112b09bfd3646e4db6bf2e598534a17d502b0c01ea6550ba4eca780c5e6", size = 484811, upload-time = "2025-09-01T22:08:12.834Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/bd/27e73e92635b6fbd51afc26a414a3133243c662949cd1cda677fe7bb09bd/regex-2025.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:67a0295a3c31d675a9ee0238d20238ff10a9a2fdb7a1323c798fc7029578b15c", size = 288977, upload-time = "2025-09-01T22:08:14.499Z" },
+ { url = "https://files.pythonhosted.org/packages/eb/7d/7dc0c6efc8bc93cd6e9b947581f5fde8a5dbaa0af7c4ec818c5729fdc807/regex-2025.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea8267fbadc7d4bd7c1301a50e85c2ff0de293ff9452a1a9f8d82c6cafe38179", size = 286606, upload-time = "2025-09-01T22:08:15.881Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/01/9b5c6dd394f97c8f2c12f6e8f96879c9ac27292a718903faf2e27a0c09f6/regex-2025.9.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6aeff21de7214d15e928fb5ce757f9495214367ba62875100d4c18d293750cc1", size = 792436, upload-time = "2025-09-01T22:08:17.38Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/24/b7430cfc6ee34bbb3db6ff933beb5e7692e5cc81e8f6f4da63d353566fb0/regex-2025.9.1-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d89f1bbbbbc0885e1c230f7770d5e98f4f00b0ee85688c871d10df8b184a6323", size = 858705, upload-time = "2025-09-01T22:08:19.037Z" },
+ { url = "https://files.pythonhosted.org/packages/d6/98/155f914b4ea6ae012663188545c4f5216c11926d09b817127639d618b003/regex-2025.9.1-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca3affe8ddea498ba9d294ab05f5f2d3b5ad5d515bc0d4a9016dd592a03afe52", size = 905881, upload-time = "2025-09-01T22:08:20.377Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/a7/a470e7bc8259c40429afb6d6a517b40c03f2f3e455c44a01abc483a1c512/regex-2025.9.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:91892a7a9f0a980e4c2c85dd19bc14de2b219a3a8867c4b5664b9f972dcc0c78", size = 798968, upload-time = "2025-09-01T22:08:22.081Z" },
+ { url = "https://files.pythonhosted.org/packages/1d/fa/33f6fec4d41449fea5f62fdf5e46d668a1c046730a7f4ed9f478331a8e3a/regex-2025.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e1cb40406f4ae862710615f9f636c1e030fd6e6abe0e0f65f6a695a2721440c6", size = 781884, upload-time = "2025-09-01T22:08:23.832Z" },
+ { url = "https://files.pythonhosted.org/packages/42/de/2b45f36ab20da14eedddf5009d370625bc5942d9953fa7e5037a32d66843/regex-2025.9.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:94f6cff6f7e2149c7e6499a6ecd4695379eeda8ccbccb9726e8149f2fe382e92", size = 852935, upload-time = "2025-09-01T22:08:25.536Z" },
+ { url = "https://files.pythonhosted.org/packages/1e/f9/878f4fc92c87e125e27aed0f8ee0d1eced9b541f404b048f66f79914475a/regex-2025.9.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6c0226fb322b82709e78c49cc33484206647f8a39954d7e9de1567f5399becd0", size = 844340, upload-time = "2025-09-01T22:08:27.141Z" },
+ { url = "https://files.pythonhosted.org/packages/90/c2/5b6f2bce6ece5f8427c718c085eca0de4bbb4db59f54db77aa6557aef3e9/regex-2025.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a12f59c7c380b4fcf7516e9cbb126f95b7a9518902bcf4a852423ff1dcd03e6a", size = 787238, upload-time = "2025-09-01T22:08:28.75Z" },
+ { url = "https://files.pythonhosted.org/packages/47/66/1ef1081c831c5b611f6f55f6302166cfa1bc9574017410ba5595353f846a/regex-2025.9.1-cp311-cp311-win32.whl", hash = "sha256:49865e78d147a7a4f143064488da5d549be6bfc3f2579e5044cac61f5c92edd4", size = 264118, upload-time = "2025-09-01T22:08:30.388Z" },
+ { url = "https://files.pythonhosted.org/packages/ad/e0/8adc550d7169df1d6b9be8ff6019cda5291054a0107760c2f30788b6195f/regex-2025.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:d34b901f6f2f02ef60f4ad3855d3a02378c65b094efc4b80388a3aeb700a5de7", size = 276151, upload-time = "2025-09-01T22:08:32.073Z" },
+ { url = "https://files.pythonhosted.org/packages/cb/bd/46fef29341396d955066e55384fb93b0be7d64693842bf4a9a398db6e555/regex-2025.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:47d7c2dab7e0b95b95fd580087b6ae196039d62306a592fa4e162e49004b6299", size = 268460, upload-time = "2025-09-01T22:08:33.281Z" },
+ { url = "https://files.pythonhosted.org/packages/39/ef/a0372febc5a1d44c1be75f35d7e5aff40c659ecde864d7fa10e138f75e74/regex-2025.9.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:84a25164bd8dcfa9f11c53f561ae9766e506e580b70279d05a7946510bdd6f6a", size = 486317, upload-time = "2025-09-01T22:08:34.529Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/25/d64543fb7eb41a1024786d518cc57faf1ce64aa6e9ddba097675a0c2f1d2/regex-2025.9.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:645e88a73861c64c1af558dd12294fb4e67b5c1eae0096a60d7d8a2143a611c7", size = 289698, upload-time = "2025-09-01T22:08:36.162Z" },
+ { url = "https://files.pythonhosted.org/packages/d8/dc/fbf31fc60be317bd9f6f87daa40a8a9669b3b392aa8fe4313df0a39d0722/regex-2025.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10a450cba5cd5409526ee1d4449f42aad38dd83ac6948cbd6d7f71ca7018f7db", size = 287242, upload-time = "2025-09-01T22:08:37.794Z" },
+ { url = "https://files.pythonhosted.org/packages/0f/74/f933a607a538f785da5021acf5323961b4620972e2c2f1f39b6af4b71db7/regex-2025.9.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e9dc5991592933a4192c166eeb67b29d9234f9c86344481173d1bc52f73a7104", size = 797441, upload-time = "2025-09-01T22:08:39.108Z" },
+ { url = "https://files.pythonhosted.org/packages/89/d0/71fc49b4f20e31e97f199348b8c4d6e613e7b6a54a90eb1b090c2b8496d7/regex-2025.9.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a32291add816961aab472f4fad344c92871a2ee33c6c219b6598e98c1f0108f2", size = 862654, upload-time = "2025-09-01T22:08:40.586Z" },
+ { url = "https://files.pythonhosted.org/packages/59/05/984edce1411a5685ba9abbe10d42cdd9450aab4a022271f9585539788150/regex-2025.9.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:588c161a68a383478e27442a678e3b197b13c5ba51dbba40c1ccb8c4c7bee9e9", size = 910862, upload-time = "2025-09-01T22:08:42.416Z" },
+ { url = "https://files.pythonhosted.org/packages/b2/02/5c891bb5fe0691cc1bad336e3a94b9097fbcf9707ec8ddc1dce9f0397289/regex-2025.9.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:47829ffaf652f30d579534da9085fe30c171fa2a6744a93d52ef7195dc38218b", size = 801991, upload-time = "2025-09-01T22:08:44.072Z" },
+ { url = "https://files.pythonhosted.org/packages/f1/ae/fd10d6ad179910f7a1b3e0a7fde1ef8bb65e738e8ac4fd6ecff3f52252e4/regex-2025.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e978e5a35b293ea43f140c92a3269b6ab13fe0a2bf8a881f7ac740f5a6ade85", size = 786651, upload-time = "2025-09-01T22:08:46.079Z" },
+ { url = "https://files.pythonhosted.org/packages/30/cf/9d686b07bbc5bf94c879cc168db92542d6bc9fb67088d03479fef09ba9d3/regex-2025.9.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4cf09903e72411f4bf3ac1eddd624ecfd423f14b2e4bf1c8b547b72f248b7bf7", size = 856556, upload-time = "2025-09-01T22:08:48.376Z" },
+ { url = "https://files.pythonhosted.org/packages/91/9d/302f8a29bb8a49528abbab2d357a793e2a59b645c54deae0050f8474785b/regex-2025.9.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d016b0f77be63e49613c9e26aaf4a242f196cd3d7a4f15898f5f0ab55c9b24d2", size = 849001, upload-time = "2025-09-01T22:08:50.067Z" },
+ { url = "https://files.pythonhosted.org/packages/93/fa/b4c6dbdedc85ef4caec54c817cd5f4418dbfa2453214119f2538082bf666/regex-2025.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:656563e620de6908cd1c9d4f7b9e0777e3341ca7db9d4383bcaa44709c90281e", size = 788138, upload-time = "2025-09-01T22:08:51.933Z" },
+ { url = "https://files.pythonhosted.org/packages/4a/1b/91ee17a3cbf87f81e8c110399279d0e57f33405468f6e70809100f2ff7d8/regex-2025.9.1-cp312-cp312-win32.whl", hash = "sha256:df33f4ef07b68f7ab637b1dbd70accbf42ef0021c201660656601e8a9835de45", size = 264524, upload-time = "2025-09-01T22:08:53.75Z" },
+ { url = "https://files.pythonhosted.org/packages/92/28/6ba31cce05b0f1ec6b787921903f83bd0acf8efde55219435572af83c350/regex-2025.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:5aba22dfbc60cda7c0853516104724dc904caa2db55f2c3e6e984eb858d3edf3", size = 275489, upload-time = "2025-09-01T22:08:55.037Z" },
+ { url = "https://files.pythonhosted.org/packages/bd/ed/ea49f324db00196e9ef7fe00dd13c6164d5173dd0f1bbe495e61bb1fb09d/regex-2025.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:ec1efb4c25e1849c2685fa95da44bfde1b28c62d356f9c8d861d4dad89ed56e9", size = 268589, upload-time = "2025-09-01T22:08:56.369Z" },
+ { url = "https://files.pythonhosted.org/packages/98/25/b2959ce90c6138c5142fe5264ee1f9b71a0c502ca4c7959302a749407c79/regex-2025.9.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bc6834727d1b98d710a63e6c823edf6ffbf5792eba35d3fa119531349d4142ef", size = 485932, upload-time = "2025-09-01T22:08:57.913Z" },
+ { url = "https://files.pythonhosted.org/packages/49/2e/6507a2a85f3f2be6643438b7bd976e67ad73223692d6988eb1ff444106d3/regex-2025.9.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c3dc05b6d579875719bccc5f3037b4dc80433d64e94681a0061845bd8863c025", size = 289568, upload-time = "2025-09-01T22:08:59.258Z" },
+ { url = "https://files.pythonhosted.org/packages/c7/d8/de4a4b57215d99868f1640e062a7907e185ec7476b4b689e2345487c1ff4/regex-2025.9.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:22213527df4c985ec4a729b055a8306272d41d2f45908d7bacb79be0fa7a75ad", size = 286984, upload-time = "2025-09-01T22:09:00.835Z" },
+ { url = "https://files.pythonhosted.org/packages/03/15/e8cb403403a57ed316e80661db0e54d7aa2efcd85cb6156f33cc18746922/regex-2025.9.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8e3f6e3c5a5a1adc3f7ea1b5aec89abfc2f4fbfba55dafb4343cd1d084f715b2", size = 797514, upload-time = "2025-09-01T22:09:02.538Z" },
+ { url = "https://files.pythonhosted.org/packages/e4/26/2446f2b9585fed61faaa7e2bbce3aca7dd8df6554c32addee4c4caecf24a/regex-2025.9.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bcb89c02a0d6c2bec9b0bb2d8c78782699afe8434493bfa6b4021cc51503f249", size = 862586, upload-time = "2025-09-01T22:09:04.322Z" },
+ { url = "https://files.pythonhosted.org/packages/fd/b8/82ffbe9c0992c31bbe6ae1c4b4e21269a5df2559102b90543c9b56724c3c/regex-2025.9.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b0e2f95413eb0c651cd1516a670036315b91b71767af83bc8525350d4375ccba", size = 910815, upload-time = "2025-09-01T22:09:05.978Z" },
+ { url = "https://files.pythonhosted.org/packages/2f/d8/7303ea38911759c1ee30cc5bc623ee85d3196b733c51fd6703c34290a8d9/regex-2025.9.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a41dc039e1c97d3c2ed3e26523f748e58c4de3ea7a31f95e1cf9ff973fff5a", size = 802042, upload-time = "2025-09-01T22:09:07.865Z" },
+ { url = "https://files.pythonhosted.org/packages/fc/0e/6ad51a55ed4b5af512bb3299a05d33309bda1c1d1e1808fa869a0bed31bc/regex-2025.9.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f0b4258b161094f66857a26ee938d3fe7b8a5063861e44571215c44fbf0e5df", size = 786764, upload-time = "2025-09-01T22:09:09.362Z" },
+ { url = "https://files.pythonhosted.org/packages/8d/d5/394e3ffae6baa5a9217bbd14d96e0e5da47bb069d0dbb8278e2681a2b938/regex-2025.9.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bf70e18ac390e6977ea7e56f921768002cb0fa359c4199606c7219854ae332e0", size = 856557, upload-time = "2025-09-01T22:09:11.129Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/80/b288d3910c41194ad081b9fb4b371b76b0bbfdce93e7709fc98df27b37dc/regex-2025.9.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b84036511e1d2bb0a4ff1aec26951caa2dea8772b223c9e8a19ed8885b32dbac", size = 849108, upload-time = "2025-09-01T22:09:12.877Z" },
+ { url = "https://files.pythonhosted.org/packages/d1/cd/5ec76bf626d0d5abdc277b7a1734696f5f3d14fbb4a3e2540665bc305d85/regex-2025.9.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c2e05dcdfe224047f2a59e70408274c325d019aad96227ab959403ba7d58d2d7", size = 788201, upload-time = "2025-09-01T22:09:14.561Z" },
+ { url = "https://files.pythonhosted.org/packages/b5/36/674672f3fdead107565a2499f3007788b878188acec6d42bc141c5366c2c/regex-2025.9.1-cp313-cp313-win32.whl", hash = "sha256:3b9a62107a7441b81ca98261808fed30ae36ba06c8b7ee435308806bd53c1ed8", size = 264508, upload-time = "2025-09-01T22:09:16.193Z" },
+ { url = "https://files.pythonhosted.org/packages/83/ad/931134539515eb64ce36c24457a98b83c1b2e2d45adf3254b94df3735a76/regex-2025.9.1-cp313-cp313-win_amd64.whl", hash = "sha256:b38afecc10c177eb34cfae68d669d5161880849ba70c05cbfbe409f08cc939d7", size = 275469, upload-time = "2025-09-01T22:09:17.462Z" },
+ { url = "https://files.pythonhosted.org/packages/24/8c/96d34e61c0e4e9248836bf86d69cb224fd222f270fa9045b24e218b65604/regex-2025.9.1-cp313-cp313-win_arm64.whl", hash = "sha256:ec329890ad5e7ed9fc292858554d28d58d56bf62cf964faf0aa57964b21155a0", size = 268586, upload-time = "2025-09-01T22:09:18.948Z" },
+ { url = "https://files.pythonhosted.org/packages/21/b1/453cbea5323b049181ec6344a803777914074b9726c9c5dc76749966d12d/regex-2025.9.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:72fb7a016467d364546f22b5ae86c45680a4e0de6b2a6f67441d22172ff641f1", size = 486111, upload-time = "2025-09-01T22:09:20.734Z" },
+ { url = "https://files.pythonhosted.org/packages/f6/0e/92577f197bd2f7652c5e2857f399936c1876978474ecc5b068c6d8a79c86/regex-2025.9.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c9527fa74eba53f98ad86be2ba003b3ebe97e94b6eb2b916b31b5f055622ef03", size = 289520, upload-time = "2025-09-01T22:09:22.249Z" },
+ { url = "https://files.pythonhosted.org/packages/af/c6/b472398116cca7ea5a6c4d5ccd0fc543f7fd2492cb0c48d2852a11972f73/regex-2025.9.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c905d925d194c83a63f92422af7544ec188301451b292c8b487f0543726107ca", size = 287215, upload-time = "2025-09-01T22:09:23.657Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/11/f12ecb0cf9ca792a32bb92f758589a84149017467a544f2f6bfb45c0356d/regex-2025.9.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74df7c74a63adcad314426b1f4ea6054a5ab25d05b0244f0c07ff9ce640fa597", size = 797855, upload-time = "2025-09-01T22:09:25.197Z" },
+ { url = "https://files.pythonhosted.org/packages/46/88/bbb848f719a540fb5997e71310f16f0b33a92c5d4b4d72d4311487fff2a3/regex-2025.9.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4f6e935e98ea48c7a2e8be44494de337b57a204470e7f9c9c42f912c414cd6f5", size = 863363, upload-time = "2025-09-01T22:09:26.705Z" },
+ { url = "https://files.pythonhosted.org/packages/54/a9/2321eb3e2838f575a78d48e03c1e83ea61bd08b74b7ebbdeca8abc50fc25/regex-2025.9.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4a62d033cd9ebefc7c5e466731a508dfabee827d80b13f455de68a50d3c2543d", size = 910202, upload-time = "2025-09-01T22:09:28.906Z" },
+ { url = "https://files.pythonhosted.org/packages/33/07/d1d70835d7d11b7e126181f316f7213c4572ecf5c5c97bdbb969fb1f38a2/regex-2025.9.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef971ebf2b93bdc88d8337238be4dfb851cc97ed6808eb04870ef67589415171", size = 801808, upload-time = "2025-09-01T22:09:30.733Z" },
+ { url = "https://files.pythonhosted.org/packages/13/d1/29e4d1bed514ef2bf3a4ead3cb8bb88ca8af94130239a4e68aa765c35b1c/regex-2025.9.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d936a1db208bdca0eca1f2bb2c1ba1d8370b226785c1e6db76e32a228ffd0ad5", size = 786824, upload-time = "2025-09-01T22:09:32.61Z" },
+ { url = "https://files.pythonhosted.org/packages/33/27/20d8ccb1bee460faaa851e6e7cc4cfe852a42b70caa1dca22721ba19f02f/regex-2025.9.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:7e786d9e4469698fc63815b8de08a89165a0aa851720eb99f5e0ea9d51dd2b6a", size = 857406, upload-time = "2025-09-01T22:09:34.117Z" },
+ { url = "https://files.pythonhosted.org/packages/74/fe/60c6132262dc36430d51e0c46c49927d113d3a38c1aba6a26c7744c84cf3/regex-2025.9.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:6b81d7dbc5466ad2c57ce3a0ddb717858fe1a29535c8866f8514d785fdb9fc5b", size = 848593, upload-time = "2025-09-01T22:09:35.598Z" },
+ { url = "https://files.pythonhosted.org/packages/cc/ae/2d4ff915622fabbef1af28387bf71e7f2f4944a348b8460d061e85e29bf0/regex-2025.9.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cd4890e184a6feb0ef195338a6ce68906a8903a0f2eb7e0ab727dbc0a3156273", size = 787951, upload-time = "2025-09-01T22:09:37.139Z" },
+ { url = "https://files.pythonhosted.org/packages/85/37/dc127703a9e715a284cc2f7dbdd8a9776fd813c85c126eddbcbdd1ca5fec/regex-2025.9.1-cp314-cp314-win32.whl", hash = "sha256:34679a86230e46164c9e0396b56cab13c0505972343880b9e705083cc5b8ec86", size = 269833, upload-time = "2025-09-01T22:09:39.245Z" },
+ { url = "https://files.pythonhosted.org/packages/83/bf/4bed4d3d0570e16771defd5f8f15f7ea2311edcbe91077436d6908956c4a/regex-2025.9.1-cp314-cp314-win_amd64.whl", hash = "sha256:a1196e530a6bfa5f4bde029ac5b0295a6ecfaaffbfffede4bbaf4061d9455b70", size = 278742, upload-time = "2025-09-01T22:09:40.651Z" },
+ { url = "https://files.pythonhosted.org/packages/cf/3e/7d7ac6fd085023312421e0d69dfabdfb28e116e513fadbe9afe710c01893/regex-2025.9.1-cp314-cp314-win_arm64.whl", hash = "sha256:f46d525934871ea772930e997d577d48c6983e50f206ff7b66d4ac5f8941e993", size = 271860, upload-time = "2025-09-01T22:09:42.413Z" },
]
[[package]]
@@ -319,11 +319,11 @@ wheels = [
[[package]]
name = "typing-extensions"
-version = "4.14.1"
+version = "4.15.0"
source = { registry = "https://pypi.org/simple" }
-sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" },
+ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
]
[[package]]
diff --git a/web_src/css/user.css b/web_src/css/user.css
index d42e8688fb..a9b283b504 100644
--- a/web_src/css/user.css
+++ b/web_src/css/user.css
@@ -120,6 +120,7 @@
flex-wrap: wrap;
gap: 0.5em;
padding: 0.5em 1em;
+ overflow-wrap: anywhere;
}
.notifications-item:hover {