From 821d8e3aef90e47aff58a12b47835cb4153815bb Mon Sep 17 00:00:00 2001 From: Yohann Delafollye Date: Wed, 26 Feb 2020 18:42:14 -0500 Subject: [PATCH 001/550] Improve users management through the CLI (#6001) - add user subcommand - add list, create, delete, change-password microcommands - delete create-user and change-password subcommands --- cmd/admin.go | 89 +++++++++++++++++++++++++++++++++++++++++++++++--- models/user.go | 6 ++++ 2 files changed, 90 insertions(+), 5 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index bc469cdae3a4c..ead262834ba49 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -29,16 +29,38 @@ var ( Name: "admin", Usage: "Command line interface to perform common administrative operations", Subcommands: []cli.Command{ - subcmdCreateUser, - subcmdChangePassword, + subcmdUser, subcmdRepoSyncReleases, subcmdRegenerate, subcmdAuth, }, } - subcmdCreateUser = cli.Command{ - Name: "create-user", + subcmdUser = cli.Command{ + Name: "user", + Usage: "Modify users", + Subcommands: []cli.Command{ + microcmdUserCreate, + microcmdUserList, + microcmdUserChangePassword, + microcmdUserDelete, + }, + } + + microcmdUserList = cli.Command{ + Name: "list", + Usage: "List users", + Action: runListUsers, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "admin", + Usage: "List only admin users", + }, + }, + } + + microcmdUserCreate = cli.Command{ + Name: "create", Usage: "Create a new user in database", Action: runCreateUser, Flags: []cli.Flag{ @@ -82,7 +104,7 @@ var ( }, } - subcmdChangePassword = cli.Command{ + microcmdUserChangePassword = cli.Command{ Name: "change-password", Usage: "Change a user's password", Action: runChangePassword, @@ -100,6 +122,13 @@ var ( }, } + microcmdUserDelete = cli.Command{ + Name: "delete", + Usage: "Delete specific user", + Flags: []cli.Flag{idFlag}, + Action: runDeleteUser, + } + subcmdRepoSyncReleases = cli.Command{ Name: "repo-sync-releases", Usage: "Synchronize repository releases with tags", @@ -343,6 +372,56 @@ func runCreateUser(c *cli.Context) error { return nil } +func runListUsers(c *cli.Context) error { + if err := initDB(); err != nil { + return err + } + + users, err := models.ListUsers() + + if err != nil { + return err + } + + w := tabwriter.NewWriter(os.Stdout, 5, 0, 1, ' ', 0) + + if c.IsSet("admin") { + fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\n") + for _, u := range users { + if u.IsAdmin { + fmt.Fprintf(w, "%d\t%s\t%s\t%t\n", u.ID, u.Name, u.Email, u.IsActive) + } + } + } else { + fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\tIsAdmin\n") + for _, u := range users { + fmt.Fprintf(w, "%d\t%s\t%s\t%t\t%t\n", u.ID, u.Name, u.Email, u.IsAdmin, u.IsActive) + } + + } + + w.Flush() + return nil + +} + +func runDeleteUser(c *cli.Context) error { + if !c.IsSet("id") { + return fmt.Errorf("--id flag is missing") + } + + if err := initDB(); err != nil { + return err + } + + user, err := models.GetUserByID(c.Int64("id")) + if err != nil { + return err + } + + return models.DeleteUser(user) +} + func runRepoSyncReleases(c *cli.Context) error { if err := initDB(); err != nil { return err diff --git a/models/user.go b/models/user.go index 30ede2373ef57..292bfff644c85 100644 --- a/models/user.go +++ b/models/user.go @@ -236,6 +236,12 @@ func (u *User) GetEmail() string { return u.Email } +// ListUsers returns a slice of all users found in DB. +func ListUsers() ([]*User, error) { + users := make([]*User, 0) + return users, x.Find(&users) +} + // APIFormat converts a User to api.User func (u *User) APIFormat() *api.User { if u == nil { From d452842e2923227ef894b2111318326f0de62355 Mon Sep 17 00:00:00 2001 From: Yohann Delafollye Date: Thu, 27 Feb 2020 09:44:15 -0500 Subject: [PATCH 002/550] Apply suggestions from code review --- cmd/admin.go | 2 +- models/user.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/admin.go b/cmd/admin.go index ead262834ba49..c229cf7b58886 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -377,7 +377,7 @@ func runListUsers(c *cli.Context) error { return err } - users, err := models.ListUsers() + users, err := models.GetAllUsers() if err != nil { return err diff --git a/models/user.go b/models/user.go index 292bfff644c85..5284971c67fa5 100644 --- a/models/user.go +++ b/models/user.go @@ -236,10 +236,10 @@ func (u *User) GetEmail() string { return u.Email } -// ListUsers returns a slice of all users found in DB. -func ListUsers() ([]*User, error) { +// GetAllUsers returns a slice of all users found in DB. +func GetAllUsers() ([]*User, error) { users := make([]*User, 0) - return users, x.Find(&users) + return users, x.OrderBy("id").Find(&users) } // APIFormat converts a User to api.User From ff82e82697911f146f1a67e2d0681a529c11a3c7 Mon Sep 17 00:00:00 2001 From: Yohann Delafollye Date: Thu, 27 Feb 2020 09:44:25 -0500 Subject: [PATCH 003/550] Update the documentation --- docs/content/doc/usage/command-line.en-us.md | 50 ++++++++++++-------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index 60c2e26a7b7cd..e1118913bcbb3 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -55,28 +55,40 @@ Starts the server: Admin operations: - Commands: - - `create-user` - - Options: - - `--name value`: Username. Required. As of gitea 1.9.0, use the `--username` flag instead. - - `--username value`: Username. Required. New in gitea 1.9.0. - - `--password value`: Password. Required. - - `--email value`: Email. Required. - - `--admin`: If provided, this makes the user an admin. Optional. - - `--access-token`: If provided, an access token will be created for the user. Optional. (default: false). - - `--must-change-password`: If provided, the created user will be required to choose a newer password after + - `user`: + - `list`: + - Options: + - `--admin`: List only admin users. Optional. + - Description: lists all users that exist + - Examples: + - `gitea admin user list` + - `delete`: + - Options: + - `--id`: ID of user to be deleted. Required. + - Examples: + - `gitea admin user delete --id 1` + - `create`: + - Options: + - `--name value`: Username. Required. As of gitea 1.9.0, use the `--username` flag instead. + - `--username value`: Username. Required. New in gitea 1.9.0. + - `--password value`: Password. Required. + - `--email value`: Email. Required. + - `--admin`: If provided, this makes the user an admin. Optional. + - `--access-token`: If provided, an access token will be created for the user. Optional. (default: false). + - `--must-change-password`: If provided, the created user will be required to choose a newer password after the initial login. Optional. (default: true). - - ``--random-password``: If provided, a randomly generated password will be used as the password of + - ``--random-password``: If provided, a randomly generated password will be used as the password of the created user. The value of `--password` will be discarded. Optional. - - `--random-password-length`: If provided, it will be used to configure the length of the randomly + - `--random-password-length`: If provided, it will be used to configure the length of the randomly generated password. Optional. (default: 12) - - Examples: - - `gitea admin create-user --username myname --password asecurepassword --email me@example.com` - - `change-password` - - Options: - - `--username value`, `-u value`: Username. Required. - - `--password value`, `-p value`: New password. Required. - - Examples: - - `gitea admin change-password --username myname --password asecurepassword` + - Examples: + - `gitea admin create-user --username myname --password asecurepassword --email me@example.com` + - `change-password`: + - Options: + - `--username value`, `-u value`: Username. Required. + - `--password value`, `-p value`: New password. Required. + - Examples: + - `gitea admin change-password --username myname --password asecurepassword` - `regenerate` - Options: - `hooks`: Regenerate git-hooks for all repositories From 0039e7d22b4740ddf27be94b7a98fb4abb540289 Mon Sep 17 00:00:00 2001 From: ydelafollye Date: Tue, 31 Mar 2020 16:14:59 -0400 Subject: [PATCH 004/550] fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: 赵智超 <1012112796@qq.com> --- cmd/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/admin.go b/cmd/admin.go index c229cf7b58886..19d8e74fa05f4 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -395,7 +395,7 @@ func runListUsers(c *cli.Context) error { } else { fmt.Fprintf(w, "ID\tUsername\tEmail\tIsActive\tIsAdmin\n") for _, u := range users { - fmt.Fprintf(w, "%d\t%s\t%s\t%t\t%t\n", u.ID, u.Name, u.Email, u.IsAdmin, u.IsActive) + fmt.Fprintf(w, "%d\t%s\t%s\t%t\t%t\n", u.ID, u.Name, u.Email, u.IsActive, u.IsAdmin) } } From 97d6fc66862c99c3ab6590b01cdc629ec2db9f3d Mon Sep 17 00:00:00 2001 From: ydelafollye Date: Tue, 9 Jun 2020 14:33:43 -0400 Subject: [PATCH 005/550] Update models/user.go Co-authored-by: Lanre Adelowo --- models/user.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/models/user.go b/models/user.go index eb946231d92cb..df753af8ebe43 100644 --- a/models/user.go +++ b/models/user.go @@ -236,12 +236,18 @@ func (u *User) GetEmail() string { return u.Email } + +type AllUsersOpts struct { + AdminsOnly bool +} + // GetAllUsers returns a slice of all users found in DB. -func GetAllUsers() ([]*User, error) { +func GetAllUsers(opts AllUsersOpts) ([]*User, error) { users := make([]*User, 0) - return users, x.OrderBy("id").Find(&users) + return users, x.OrderBy("id").Where("is_admin = ?", opts.AdminsOnly).Find(&users) } + // APIFormat converts a User to api.User func (u *User) APIFormat() *api.User { if u == nil { From b72116a979b806526efb0b291ab2eee363a50c25 Mon Sep 17 00:00:00 2001 From: zeripath Date: Mon, 6 Apr 2020 14:33:15 +0100 Subject: [PATCH 006/550] Change default charset for MySQL on install to utf8mb4 (#10989) Signed-off-by: Andrew Thornton Co-authored-by: Lunny Xiao --- templates/install.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/install.tmpl b/templates/install.tmpl index 5251382cc4ab5..6dc5e58e4f272 100644 --- a/templates/install.tmpl +++ b/templates/install.tmpl @@ -73,12 +73,12 @@
From a742aae0812120a637bf12399cbd47313e47c767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com> Date: Mon, 6 Apr 2020 22:23:15 +0800 Subject: [PATCH 007/550] Users should not be able to prohibit their own login (#10970) * ui: limit managers prohibit themself to login Because I think it's crazy and not reasonale , that if a user can prohibit themself to login. so suggest limit this choice on ui Signed-off-by: a1012112796 <1012112796@qq.com> * skip self Prohibit Login in post event handle * fix comment Co-authored-by: zeripath Co-authored-by: John Olheiser Co-authored-by: Lunny Xiao --- routers/admin/users.go | 8 +++++++- templates/admin/user/edit.tmpl | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/routers/admin/users.go b/routers/admin/users.go index 10ae622c323c6..a28db2b445312 100644 --- a/routers/admin/users.go +++ b/routers/admin/users.go @@ -243,7 +243,13 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) { u.AllowGitHook = form.AllowGitHook u.AllowImportLocal = form.AllowImportLocal u.AllowCreateOrganization = form.AllowCreateOrganization - u.ProhibitLogin = form.ProhibitLogin + + // skip self Prohibit Login + if ctx.User.ID == u.ID { + u.ProhibitLogin = false + } else { + u.ProhibitLogin = form.ProhibitLogin + } if err := models.UpdateUser(u); err != nil { if models.IsErrEmailAlreadyUsed(err) { diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index da75cb5065c6a..feeaacbba23db 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -74,7 +74,7 @@
- +
From 75ab5819cf518bfd9d30ada21ab77980e1d69256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com> Date: Tue, 7 Apr 2020 00:33:34 +0800 Subject: [PATCH 008/550] add request review from specific reviewers feature in pull request (#10756) * add request review feature in pull request add a way to notify specific reviewers to review like github , by add or delet a special type review . The acton is is similar to Assign , so many code reuse the function and items of Assignee, but the meaning and result is different. The Permission style is is similar to github, that only writer can add a review request from Reviewers, but the poster can recall and remove a review request after a reviwer has revied even if he don't have Write Premission. only manager , the poster and reviewer of a request review can remove it. The reviewers can be requested to review contain all readers for private repo , for public, contain all writers and watchers. The offical Review Request will block merge if Reject can block it. an other change: add ui otify for Assignees. Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-authored-by: Lauris BH Signed-off-by: a1012112796 <1012112796@qq.com> * new change * add placeholder string * do some changes follow #10238 to add review requests num on lists also change icon for review requests to eye Co-authored-by: Lauris BH --- models/branches.go | 3 +- models/issue_comment.go | 2 + models/notification.go | 77 +++++---- models/notification_test.go | 2 +- models/repo.go | 58 +++++++ models/review.go | 154 +++++++++++++++++- models/review_test.go | 3 +- modules/notification/base/notifier.go | 1 + modules/notification/base/null.go | 4 + modules/notification/mail/mail.go | 7 + modules/notification/notification.go | 7 + modules/notification/ui/ui.go | 35 +++- options/locale/locale_en-US.ini | 12 ++ routers/repo/issue.go | 152 ++++++++++++++++- routers/routes/routes.go | 1 + routers/user/home.go | 2 + services/issue/assignee.go | 20 +++ templates/repo/issue/list.tmpl | 21 ++- templates/repo/issue/milestone_issues.tmpl | 21 ++- .../repo/issue/view_content/comments.tmpl | 22 ++- templates/repo/issue/view_content/pull.tmpl | 22 ++- .../repo/issue/view_content/sidebar.tmpl | 91 +++++++++++ templates/user/dashboard/issues.tmpl | 21 ++- web_src/js/index.js | 43 ++++- 24 files changed, 714 insertions(+), 67 deletions(-) diff --git a/models/branches.go b/models/branches.go index d488fc9fcc199..44cfb4140380a 100644 --- a/models/branches.go +++ b/models/branches.go @@ -177,12 +177,13 @@ func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) } // MergeBlockedByRejectedReview returns true if merge is blocked by rejected reviews +// An official ReviewRequest should also block Merge like Reject func (protectBranch *ProtectedBranch) MergeBlockedByRejectedReview(pr *PullRequest) bool { if !protectBranch.BlockOnRejectedReviews { return false } rejectExist, err := x.Where("issue_id = ?", pr.IssueID). - And("type = ?", ReviewTypeReject). + And("type in ( ?, ?)", ReviewTypeReject, ReviewTypeRequest). And("official = ?", true). Exist(new(Review)) if err != nil { diff --git a/models/issue_comment.go b/models/issue_comment.go index 303cf3f9c1361..f522604afcaf5 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -86,6 +86,8 @@ const ( CommentTypeChangeTargetBranch // Delete time manual for time tracking CommentTypeDeleteTimeManual + // add or remove Request from one + CommentTypeReviewRequest ) // CommentTag defines comment tag type diff --git a/models/notification.go b/models/notification.go index 0cee8616cadf5..8d74ac129f01e 100644 --- a/models/notification.go +++ b/models/notification.go @@ -118,64 +118,73 @@ func GetNotifications(opts FindNotificationOptions) (NotificationList, error) { // CreateOrUpdateIssueNotifications creates an issue notification // for each watcher, or updates it if already exists -func CreateOrUpdateIssueNotifications(issueID, commentID int64, notificationAuthorID int64) error { +// receiverID > 0 just send to reciver, else send to all watcher +func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error { sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { return err } - if err := createOrUpdateIssueNotifications(sess, issueID, commentID, notificationAuthorID); err != nil { + if err := createOrUpdateIssueNotifications(sess, issueID, commentID, notificationAuthorID, receiverID); err != nil { return err } return sess.Commit() } -func createOrUpdateIssueNotifications(e Engine, issueID, commentID int64, notificationAuthorID int64) error { +func createOrUpdateIssueNotifications(e Engine, issueID, commentID, notificationAuthorID, receiverID int64) error { // init - toNotify := make(map[int64]struct{}, 32) + var toNotify map[int64]struct{} notifications, err := getNotificationsByIssueID(e, issueID) + if err != nil { return err } + issue, err := getIssueByID(e, issueID) if err != nil { return err } - issueWatches, err := getIssueWatchersIDs(e, issueID, true) - if err != nil { - return err - } - for _, id := range issueWatches { - toNotify[id] = struct{}{} - } + if receiverID > 0 { + toNotify = make(map[int64]struct{}, 1) + toNotify[receiverID] = struct{}{} + } else { + toNotify = make(map[int64]struct{}, 32) + issueWatches, err := getIssueWatchersIDs(e, issueID, true) + if err != nil { + return err + } + for _, id := range issueWatches { + toNotify[id] = struct{}{} + } - repoWatches, err := getRepoWatchersIDs(e, issue.RepoID) - if err != nil { - return err - } - for _, id := range repoWatches { - toNotify[id] = struct{}{} - } - issueParticipants, err := issue.getParticipantIDsByIssue(e) - if err != nil { - return err - } - for _, id := range issueParticipants { - toNotify[id] = struct{}{} - } + repoWatches, err := getRepoWatchersIDs(e, issue.RepoID) + if err != nil { + return err + } + for _, id := range repoWatches { + toNotify[id] = struct{}{} + } + issueParticipants, err := issue.getParticipantIDsByIssue(e) + if err != nil { + return err + } + for _, id := range issueParticipants { + toNotify[id] = struct{}{} + } - // dont notify user who cause notification - delete(toNotify, notificationAuthorID) - // explicit unwatch on issue - issueUnWatches, err := getIssueWatchersIDs(e, issueID, false) - if err != nil { - return err - } - for _, id := range issueUnWatches { - delete(toNotify, id) + // dont notify user who cause notification + delete(toNotify, notificationAuthorID) + // explicit unwatch on issue + issueUnWatches, err := getIssueWatchersIDs(e, issueID, false) + if err != nil { + return err + } + for _, id := range issueUnWatches { + delete(toNotify, id) + } } err = issue.loadRepo(e) diff --git a/models/notification_test.go b/models/notification_test.go index 6485f8dc7a08d..07b9f97de5af4 100644 --- a/models/notification_test.go +++ b/models/notification_test.go @@ -14,7 +14,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue) - assert.NoError(t, CreateOrUpdateIssueNotifications(issue.ID, 0, 2)) + assert.NoError(t, CreateOrUpdateIssueNotifications(issue.ID, 0, 2, 0)) // User 9 is inactive, thus notifications for user 1 and 4 are created notf := AssertExistsAndLoadBean(t, &Notification{UserID: 1, IssueID: issue.ID}).(*Notification) diff --git a/models/repo.go b/models/repo.go index 74b5a021f46dd..8f0736ef820e6 100644 --- a/models/repo.go +++ b/models/repo.go @@ -622,6 +622,64 @@ func (repo *Repository) GetAssignees() (_ []*User, err error) { return repo.getAssignees(x) } +func (repo *Repository) getReviewersPrivate(e Engine, doerID, posterID int64) (users []*User, err error) { + users = make([]*User, 0, 20) + + if err = e. + SQL("SELECT * FROM `user` WHERE id in (SELECT user_id FROM `access` WHERE repo_id = ? AND mode >= ? AND user_id NOT IN ( ?, ?)) ORDER BY name", + repo.ID, AccessModeRead, + doerID, posterID). + Find(&users); err != nil { + return nil, err + } + + return users, nil +} + +func (repo *Repository) getReviewersPublic(e Engine, doerID, posterID int64) (_ []*User, err error) { + + users := make([]*User, 0) + + const SQLCmd = "SELECT * FROM `user` WHERE id IN ( " + + "SELECT user_id FROM `access` WHERE repo_id = ? AND mode >= ? AND user_id NOT IN ( ?, ?) " + + "UNION " + + "SELECT user_id FROM `watch` WHERE repo_id = ? AND user_id NOT IN ( ?, ?) AND mode IN (?, ?) " + + ") ORDER BY name" + + if err = e. + SQL(SQLCmd, + repo.ID, AccessModeRead, doerID, posterID, + repo.ID, doerID, posterID, RepoWatchModeNormal, RepoWatchModeAuto). + Find(&users); err != nil { + return nil, err + } + + return users, nil +} + +func (repo *Repository) getReviewers(e Engine, doerID, posterID int64) (users []*User, err error) { + if err = repo.getOwner(e); err != nil { + return nil, err + } + + if repo.IsPrivate || + (repo.Owner.IsOrganization() && repo.Owner.Visibility == api.VisibleTypePrivate) { + users, err = repo.getReviewersPrivate(x, doerID, posterID) + } else { + users, err = repo.getReviewersPublic(x, doerID, posterID) + } + return +} + +// GetReviewers get all users can be requested to review +// for private rpo , that return all users that have read access or higher to the repository. +// but for public rpo, that return all users that have write access or higher to the repository, +// and all repo watchers. +// TODO: may be we should hava a busy choice for users to block review request to them. +func (repo *Repository) GetReviewers(doerID, posterID int64) (_ []*User, err error) { + return repo.getReviewers(x, doerID, posterID) +} + // GetMilestoneByID returns the milestone belongs to repository by given ID. func (repo *Repository) GetMilestoneByID(milestoneID int64) (*Milestone, error) { return GetMilestoneByRepoID(repo.ID, milestoneID) diff --git a/models/review.go b/models/review.go index 993b5577bd897..3f7223154e627 100644 --- a/models/review.go +++ b/models/review.go @@ -27,6 +27,8 @@ const ( ReviewTypeComment // ReviewTypeReject gives feedback blocking merge ReviewTypeReject + // ReviewTypeRequest request review from others + ReviewTypeRequest ) // Icon returns the corresponding icon for the review type @@ -38,6 +40,8 @@ func (rt ReviewType) Icon() string { return "request-changes" case ReviewTypeComment: return "comment" + case ReviewTypeRequest: + return "primitive-dot" default: return "comment" } @@ -369,15 +373,15 @@ func GetReviewersByIssueID(issueID int64) (reviews []*Review, err error) { } // Get latest review of each reviwer, sorted in order they were made - if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND type in (?, ?) GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC", - issueID, ReviewTypeApprove, ReviewTypeReject). + if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND type in (?, ?, ?) GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC", + issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). Find(&reviewsUnfiltered); err != nil { return nil, err } // Load reviewer and skip if user is deleted for _, review := range reviewsUnfiltered { - if err := review.loadReviewer(sess); err != nil { + if err = review.loadReviewer(sess); err != nil { if !IsErrUserNotExist(err) { return nil, err } @@ -389,6 +393,19 @@ func GetReviewersByIssueID(issueID int64) (reviews []*Review, err error) { return reviews, nil } +// GetReviewerByIssueIDAndUserID get the latest review of reviewer for a pull request +func GetReviewerByIssueIDAndUserID(issueID, userID int64) (review *Review, err error) { + review = new(Review) + + if _, err := x.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_id = ? AND type in (?, ?, ?))", + issueID, userID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). + Get(review); err != nil { + return nil, err + } + + return +} + // MarkReviewsAsStale marks existing reviews as stale func MarkReviewsAsStale(issueID int64) (err error) { _, err = x.Exec("UPDATE `review` SET stale=? WHERE issue_id=?", true, issueID) @@ -442,3 +459,134 @@ func InsertReviews(reviews []*Review) error { return sess.Commit() } + +// AddRewiewRequest add a review request from one reviewer +func AddRewiewRequest(issue *Issue, reviewer *User, doer *User) (comment *Comment, err error) { + review, err := GetReviewerByIssueIDAndUserID(issue.ID, reviewer.ID) + if err != nil { + return + } + + // skip it when reviewer hase been request to review + if review != nil && review.Type == ReviewTypeRequest { + return nil, nil + } + + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return nil, err + } + + var official bool + official, err = isOfficialReviewer(sess, issue, reviewer) + + if err != nil { + return nil, err + } + + if !official { + official, err = isOfficialReviewer(sess, issue, doer) + + if err != nil { + return nil, err + } + } + + if official { + if _, err := sess.Exec("UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_id=?", false, issue.ID, reviewer.ID); err != nil { + return nil, err + } + } + + _, err = createReview(sess, CreateReviewOptions{ + Type: ReviewTypeRequest, + Issue: issue, + Reviewer: reviewer, + Official: official, + Stale: false, + }) + + if err != nil { + return + } + + comment, err = createComment(sess, &CreateCommentOptions{ + Type: CommentTypeReviewRequest, + Doer: doer, + Repo: issue.Repo, + Issue: issue, + RemovedAssignee: false, // Use RemovedAssignee as !isRequest + AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID + }) + + if err != nil { + return nil, err + } + + return comment, sess.Commit() +} + +//RemoveRewiewRequest remove a review request from one reviewer +func RemoveRewiewRequest(issue *Issue, reviewer *User, doer *User) (comment *Comment, err error) { + review, err := GetReviewerByIssueIDAndUserID(issue.ID, reviewer.ID) + if err != nil { + return + } + + if review.Type != ReviewTypeRequest { + return nil, nil + } + + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return nil, err + } + + _, err = sess.Delete(review) + if err != nil { + return nil, err + } + + var official bool + official, err = isOfficialReviewer(sess, issue, reviewer) + if err != nil { + return + } + + if official { + // recalculate which is the latest official review from that user + var review *Review + + review, err = GetReviewerByIssueIDAndUserID(issue.ID, reviewer.ID) + if err != nil { + return nil, err + } + + if review != nil { + if _, err := sess.Exec("UPDATE `review` SET official=? WHERE id=?", true, review.ID); err != nil { + return nil, err + } + } + } + + if err != nil { + return nil, err + } + + comment, err = CreateComment(&CreateCommentOptions{ + Type: CommentTypeReviewRequest, + Doer: doer, + Repo: issue.Repo, + Issue: issue, + RemovedAssignee: true, // Use RemovedAssignee as !isRequest + AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID + }) + + if err != nil { + return nil, err + } + + return comment, sess.Commit() +} diff --git a/models/review_test.go b/models/review_test.go index dd7ae662adde0..45ddb3181d2b9 100644 --- a/models/review_test.go +++ b/models/review_test.go @@ -52,7 +52,8 @@ func TestReviewType_Icon(t *testing.T) { assert.Equal(t, "request-changes", ReviewTypeReject.Icon()) assert.Equal(t, "comment", ReviewTypeComment.Icon()) assert.Equal(t, "comment", ReviewTypeUnknown.Icon()) - assert.Equal(t, "comment", ReviewType(4).Icon()) + assert.Equal(t, "primitive-dot", ReviewTypeRequest.Icon()) + assert.Equal(t, "comment", ReviewType(6).Icon()) } func TestFindReviews(t *testing.T) { diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index 1c607ded3b250..43b68b603c03f 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -24,6 +24,7 @@ type Notifier interface { NotifyIssueChangeStatus(*models.User, *models.Issue, *models.Comment, bool) NotifyIssueChangeMilestone(doer *models.User, issue *models.Issue, oldMilestoneID int64) NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, assignee *models.User, removed bool, comment *models.Comment) + NotifyPullRewiewRequest(doer *models.User, issue *models.Issue, reviewer *models.User, isRequest bool, comment *models.Comment) NotifyIssueChangeContent(doer *models.User, issue *models.Issue, oldContent string) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index f6c423b4694c4..4b5efd80bb545 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -86,6 +86,10 @@ func (*NullNotifier) NotifyIssueChangeContent(doer *models.User, issue *models.I func (*NullNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, assignee *models.User, removed bool, comment *models.Comment) { } +// NotifyPullRewiewRequest places a place holder function +func (*NullNotifier) NotifyPullRewiewRequest(doer *models.User, issue *models.Issue, reviewer *models.User, isRequest bool, comment *models.Comment) { +} + // NotifyIssueClearLabels places a place holder function func (*NullNotifier) NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { } diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index ec7d9d617e572..b5c2db383153c 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -100,6 +100,13 @@ func (m *mailNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *model } } +func (m *mailNotifier) NotifyPullRewiewRequest(doer *models.User, issue *models.Issue, reviewer *models.User, isRequest bool, comment *models.Comment) { + if isRequest && doer.ID != reviewer.ID && reviewer.EmailNotifications() == models.EmailNotificationsEnabled { + ct := fmt.Sprintf("Requested to review #%d.", issue.Index) + mailer.SendIssueAssignedMail(issue, doer, ct, comment, []string{reviewer.Email}) + } +} + func (m *mailNotifier) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User) { if err := pr.LoadIssue(); err != nil { log.Error("pr.LoadIssue: %v", err) diff --git a/modules/notification/notification.go b/modules/notification/notification.go index 8c5d7d60358e2..95117c1f3e558 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -150,6 +150,13 @@ func NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, assignee } } +// NotifyPullRewiewRequest notifies Request Review change +func NotifyPullRewiewRequest(doer *models.User, issue *models.Issue, reviewer *models.User, isRequest bool, comment *models.Comment) { + for _, notifier := range notifiers { + notifier.NotifyPullRewiewRequest(doer, issue, reviewer, isRequest, comment) + } +} + // NotifyIssueClearLabels notifies clear labels to notifiers func NotifyIssueClearLabels(doer *models.User, issue *models.Issue) { for _, notifier := range notifiers { diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index 525753425a4ab..6ce14a90cc394 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -22,6 +22,7 @@ type ( IssueID int64 CommentID int64 NotificationAuthorID int64 + ReceiverID int64 // 0 -- ALL Watcher } ) @@ -39,7 +40,7 @@ func NewNotifier() base.Notifier { func (ns *notificationService) handle(data ...queue.Data) { for _, datum := range data { opts := datum.(issueNotificationOpts) - if err := models.CreateOrUpdateIssueNotifications(opts.IssueID, opts.CommentID, opts.NotificationAuthorID); err != nil { + if err := models.CreateOrUpdateIssueNotifications(opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { log.Error("Was unable to create issue notification: %v", err) } } @@ -103,3 +104,35 @@ func (ns *notificationService) NotifyPullRequestReview(pr *models.PullRequest, r } _ = ns.issueQueue.Push(opts) } + +func (ns *notificationService) NotifyIssueChangeAssignee(doer *models.User, issue *models.Issue, assignee *models.User, removed bool, comment *models.Comment) { + if !removed { + var opts = issueNotificationOpts{ + IssueID: issue.ID, + NotificationAuthorID: doer.ID, + ReceiverID: assignee.ID, + } + + if comment != nil { + opts.CommentID = comment.ID + } + + _ = ns.issueQueue.Push(opts) + } +} + +func (ns *notificationService) NotifyPullRewiewRequest(doer *models.User, issue *models.Issue, reviewer *models.User, isRequest bool, comment *models.Comment) { + if isRequest { + var opts = issueNotificationOpts{ + IssueID: issue.ID, + NotificationAuthorID: doer.ID, + ReceiverID: reviewer.ID, + } + + if comment != nil { + opts.CommentID = comment.ID + } + + _ = ns.issueQueue.Push(opts) + } +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index cb34e695ec960..dfdae8f82b691 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -827,6 +827,7 @@ issues.desc = Organize bug reports, tasks and milestones. issues.filter_assignees = Filter Assignee issues.filter_milestones = Filter Milestone issues.filter_labels = Filter Label +issues.filter_reviewers = Filter Reviewer issues.new = New Issue issues.new.title_empty = Title cannot be empty issues.new.labels = Labels @@ -844,6 +845,8 @@ issues.new.assignees = Assignees issues.new.add_assignees_title = Assign users issues.new.clear_assignees = Clear assignees issues.new.no_assignees = No Assignees +issues.new.no_reviewers = No reviewers +issues.new.add_reviewer_title = Request review issues.no_ref = No Branch/Tag Specified issues.create = Create Issue issues.new_label = New Label @@ -937,6 +940,9 @@ issues.ref_from = `from %[1]s` issues.poster = Poster issues.collaborator = Collaborator issues.owner = Owner +issues.re_request_review=Re-request review +issues.remove_request_review=Remove review request +issues.remove_request_review_block=Can't remove review request issues.sign_in_require_desc = Sign in to join this conversation. issues.edit = Edit issues.cancel = Cancel @@ -1048,6 +1054,10 @@ issues.review.approve = "approved these changes %s" issues.review.comment = "reviewed %s" issues.review.content.empty = You need to leave a comment indicating the requested change(s). issues.review.reject = "requested changes %s" +issues.review.wait = "was requested for review %s" +issues.review.add_review_request = "requested review from %s %s" +issues.review.remove_review_request = "removed review request for %s %s" +issues.review.remove_review_request_self = "refused to review %s" issues.review.pending = Pending issues.review.review = Review issues.review.reviewers = Reviewers @@ -1096,6 +1106,8 @@ pulls.approve_count_1 = "%d approval" pulls.approve_count_n = "%d approvals" pulls.reject_count_1 = "%d change request" pulls.reject_count_n = "%d change requests" +pulls.waiting_count_1 = "%d waiting review" +pulls.waiting_count_n = "%d waiting reviews" pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled. pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually. diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 0697d11a6623c..0a059bf789627 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -289,6 +289,8 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB reviewTyp := models.ReviewTypeApprove if typ == "reject" { reviewTyp = models.ReviewTypeReject + } else if typ == "waiting" { + reviewTyp = models.ReviewTypeRequest } for _, count := range counts { if count.Type == reviewTyp { @@ -377,6 +379,16 @@ func RetrieveRepoMilestonesAndAssignees(ctx *context.Context, repo *models.Repos } } +// RetrieveRepoReviewers find all reviewers of a repository +func RetrieveRepoReviewers(ctx *context.Context, repo *models.Repository, issuePosterID int64) { + var err error + ctx.Data["Reviewers"], err = repo.GetReviewers(ctx.User.ID, issuePosterID) + if err != nil { + ctx.ServerError("GetReviewers", err) + return + } +} + // RetrieveRepoMetas find all the meta information of a repository func RetrieveRepoMetas(ctx *context.Context, repo *models.Repository, isPull bool) []*models.Label { if !ctx.Repo.CanWriteIssuesOrPulls(isPull) { @@ -815,6 +827,28 @@ func ViewIssue(ctx *context.Context) { } } + if issue.IsPull { + canChooseReviewer := ctx.Repo.CanWrite(models.UnitTypePullRequests) + if !canChooseReviewer && ctx.User != nil && ctx.IsSigned { + canChooseReviewer, err = models.IsOfficialReviewer(issue, ctx.User) + if err != nil { + ctx.ServerError("IsOfficialReviewer", err) + return + } + } + + if canChooseReviewer { + RetrieveRepoReviewers(ctx, repo, issue.PosterID) + ctx.Data["CanChooseReviewer"] = true + } else { + ctx.Data["CanChooseReviewer"] = false + } + + if ctx.Written() { + return + } + } + if ctx.IsSigned { // Update issue-user. if err = issue.ReadBy(ctx.User.ID); err != nil { @@ -926,7 +960,7 @@ func ViewIssue(ctx *context.Context) { if comment.MilestoneID > 0 && comment.Milestone == nil { comment.Milestone = ghostMilestone } - } else if comment.Type == models.CommentTypeAssignees { + } else if comment.Type == models.CommentTypeAssignees || comment.Type == models.CommentTypeReviewRequest { if err = comment.LoadAssigneeUser(); err != nil { ctx.ServerError("LoadAssigneeUser", err) return @@ -1273,6 +1307,122 @@ func UpdateIssueAssignee(ctx *context.Context) { }) } +func isLegalReviewRequest(reviewer, doer *models.User, isAdd bool, issue *models.Issue) error { + if reviewer.IsOrganization() { + return fmt.Errorf("Organization can't be added as reviewer [user_id: %d, repo_id: %d]", reviewer.ID, issue.PullRequest.BaseRepo.ID) + } + if doer.IsOrganization() { + return fmt.Errorf("Organization can't be doer to add reviewer [user_id: %d, repo_id: %d]", doer.ID, issue.PullRequest.BaseRepo.ID) + } + + permReviewer, err := models.GetUserRepoPermission(issue.Repo, reviewer) + if err != nil { + return err + } + + permDoer, err := models.GetUserRepoPermission(issue.Repo, doer) + if err != nil { + return err + } + + lastreview, err := models.GetReviewerByIssueIDAndUserID(issue.ID, reviewer.ID) + if err != nil { + return err + } + + var pemResult bool + if isAdd { + pemResult = permReviewer.CanAccessAny(models.AccessModeRead, models.UnitTypePullRequests) + if !pemResult { + return fmt.Errorf("Reviewer can't read [user_id: %d, repo_name: %s]", reviewer.ID, issue.Repo.Name) + } + + if doer.ID == issue.PosterID && lastreview != nil && lastreview.Type != models.ReviewTypeRequest { + return nil + } + + pemResult = permDoer.CanAccessAny(models.AccessModeWrite, models.UnitTypePullRequests) + if !pemResult { + pemResult, err = models.IsOfficialReviewer(issue, doer) + if err != nil { + return err + } + if !pemResult { + return fmt.Errorf("Doer can't choose reviewer [user_id: %d, repo_name: %s, issue_id: %d]", doer.ID, issue.Repo.Name, issue.ID) + } + } + + if doer.ID == reviewer.ID { + return fmt.Errorf("doer can't be reviewer [user_id: %d, repo_name: %s]", doer.ID, issue.Repo.Name) + } + + if reviewer.ID == issue.PosterID { + return fmt.Errorf("poster of pr can't be reviewer [user_id: %d, repo_name: %s]", reviewer.ID, issue.Repo.Name) + } + } else { + if lastreview.Type == models.ReviewTypeRequest && lastreview.ReviewerID == doer.ID { + return nil + } + + pemResult = permDoer.IsAdmin() + if !pemResult { + return fmt.Errorf("Doer is not admin [user_id: %d, repo_name: %s]", doer.ID, issue.Repo.Name) + } + } + + return nil +} + +// updatePullReviewRequest change pull's request reviewers +func updatePullReviewRequest(ctx *context.Context) { + issues := getActionIssues(ctx) + if ctx.Written() { + return + } + + reviewID := ctx.QueryInt64("id") + event := ctx.Query("is_add") + + if event != "add" && event != "remove" { + ctx.ServerError("updatePullReviewRequest", fmt.Errorf("is_add should not be \"%s\"", event)) + return + } + + for _, issue := range issues { + if issue.IsPull { + + reviewer, err := models.GetUserByID(reviewID) + if err != nil { + ctx.ServerError("GetUserByID", err) + return + } + + err = isLegalReviewRequest(reviewer, ctx.User, event == "add", issue) + if err != nil { + ctx.ServerError("isLegalRequestReview", err) + return + } + + err = issue_service.ReviewRequest(issue, ctx.User, reviewer, event == "add") + if err != nil { + ctx.ServerError("ReviewRequest", err) + return + } + } else { + ctx.ServerError("updatePullReviewRequest", fmt.Errorf("%d in %d is not Pull Request", issue.ID, issue.Repo.ID)) + } + } + + ctx.JSON(200, map[string]interface{}{ + "ok": true, + }) +} + +// UpdatePullReviewRequest add or remove review request +func UpdatePullReviewRequest(ctx *context.Context) { + updatePullReviewRequest(ctx) +} + // UpdateIssueStatus change issue's status func UpdateIssueStatus(ctx *context.Context) { issues := getActionIssues(ctx) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 4409830dfe2e8..5f477a847ef92 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -738,6 +738,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/labels", reqRepoIssuesOrPullsWriter, repo.UpdateIssueLabel) m.Post("/milestone", reqRepoIssuesOrPullsWriter, repo.UpdateIssueMilestone) m.Post("/assignee", reqRepoIssuesOrPullsWriter, repo.UpdateIssueAssignee) + m.Post("/request_review", reqRepoIssuesOrPullsReader, repo.UpdatePullReviewRequest) m.Post("/status", reqRepoIssuesOrPullsWriter, repo.UpdateIssueStatus) }, context.RepoMustNotBeArchived()) m.Group("/comments/:id", func() { diff --git a/routers/user/home.go b/routers/user/home.go index 71a65d6d9fb7a..3807025ea52fe 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -632,6 +632,8 @@ func Issues(ctx *context.Context) { reviewTyp := models.ReviewTypeApprove if typ == "reject" { reviewTyp = models.ReviewTypeReject + } else if typ == "waiting" { + reviewTyp = models.ReviewTypeRequest } for _, count := range counts { if count.Type == reviewTyp { diff --git a/services/issue/assignee.go b/services/issue/assignee.go index 281f824da768e..9711de4c60342 100644 --- a/services/issue/assignee.go +++ b/services/issue/assignee.go @@ -51,3 +51,23 @@ func ToggleAssignee(issue *models.Issue, doer *models.User, assigneeID int64) (r return } + +// ReviewRequest add or remove a review for this PR, and make comment for it. +func ReviewRequest(issue *models.Issue, doer *models.User, reviewer *models.User, isAdd bool) (err error) { + var comment *models.Comment + if isAdd { + comment, err = models.AddRewiewRequest(issue, reviewer, doer) + } else { + comment, err = models.RemoveRewiewRequest(issue, reviewer, doer) + } + + if err != nil { + return + } + + if comment != nil { + notification.NotifyPullRewiewRequest(doer, issue, reviewer, isAdd, comment) + } + + return nil +} diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 05018bacdd051..4fe0aaa00df0a 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -271,14 +271,25 @@ {{if .IsPull}} {{$approveOfficial := call $approvalCounts .ID "approve"}} {{$rejectOfficial := call $approvalCounts .ID "reject"}} - {{if or (gt $approveOfficial 0) (gt $rejectOfficial 0)}} + {{$waitingOfficial := call $approvalCounts .ID "waiting"}} + {{if gt $approveOfficial 0}} {{svg "octicon-check" 16}} {{$.i18n.Tr (TrN $.i18n.Lang $approveOfficial "repo.pulls.approve_count_1" "repo.pulls.approve_count_n") $approveOfficial}} - {{if or (gt $rejectOfficial 0)}} - {{svg "octicon-x" 16}} - {{$.i18n.Tr (TrN $.i18n.Lang $rejectOfficial "repo.pulls.reject_count_1" "repo.pulls.reject_count_n") $rejectOfficial}} - {{end}} + {{end}} + + {{if gt $rejectOfficial 0}} + {{svg "octicon-request-changes" 16}} + {{$.i18n.Tr (TrN $.i18n.Lang $rejectOfficial "repo.pulls.reject_count_1" "repo.pulls.reject_count_n") $rejectOfficial}} + + {{end}} + + {{if gt $waitingOfficial 0}} + {{svg "octicon-eye" 16}} + {{$.i18n.Tr (TrN $.i18n.Lang $waitingOfficial "repo.pulls.waiting_count_1" "repo.pulls.waiting_count_n") $waitingOfficial}} + + {{end}} + {{if and (not .PullRequest.HasMerged) (gt (len .PullRequest.ConflictedFiles) 0)}} {{svg "octicon-mirror" 16}} {{$.i18n.Tr (TrN $.i18n.Lang (len .PullRequest.ConflictedFiles) "repo.pulls.num_conflicting_files_1" "repo.pulls.num_conflicting_files_n") (len .PullRequest.ConflictedFiles)}} {{end}} diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl index d144a97f14f81..5307c05733b85 100644 --- a/templates/repo/issue/milestone_issues.tmpl +++ b/templates/repo/issue/milestone_issues.tmpl @@ -241,14 +241,25 @@ {{if .IsPull}} {{$approveOfficial := call $approvalCounts .ID "approve"}} {{$rejectOfficial := call $approvalCounts .ID "reject"}} - {{if or (gt $approveOfficial 0) (gt $rejectOfficial 0)}} + {{$waitingOfficial := call $approvalCounts .ID "waiting"}} + {{if gt $approveOfficial 0}} {{svg "octicon-check" 16}} {{$.i18n.Tr (TrN $.i18n.Lang $approveOfficial "repo.pulls.approve_count_1" "repo.pulls.approve_count_n") $approveOfficial}} - {{if or (gt $rejectOfficial 0)}} - {{svg "octicon-x" 16}} - {{$.i18n.Tr (TrN $.i18n.Lang $rejectOfficial "repo.pulls.reject_count_1" "repo.pulls.reject_count_n") $rejectOfficial}} - {{end}} + {{end}} + + {{if gt $rejectOfficial 0}} + {{svg "octicon-request-changes" 16}} + {{$.i18n.Tr (TrN $.i18n.Lang $rejectOfficial "repo.pulls.reject_count_1" "repo.pulls.reject_count_n") $rejectOfficial}} + + {{end}} + + {{if gt $waitingOfficial 0}} + {{svg "octicon-eye" 16}} + {{$.i18n.Tr (TrN $.i18n.Lang $waitingOfficial "repo.pulls.waiting_count_1" "repo.pulls.waiting_count_n") $waitingOfficial}} + + {{end}} + {{if and (not .PullRequest.HasMerged) (gt (len .PullRequest.ConflictedFiles) 0)}} {{svg "octicon-mirror" 16}} {{$.i18n.Tr (TrN $.i18n.Lang (len .PullRequest.ConflictedFiles) "repo.pulls.num_conflicting_files_1" "repo.pulls.num_conflicting_files_n") (len .PullRequest.ConflictedFiles)}} {{end}} diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index bb8188def95c6..022e96a02e24b 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -7,7 +7,7 @@ 13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL, 16 = ADDED_DEADLINE, 17 = MODIFIED_DEADLINE, 18 = REMOVED_DEADLINE, 19 = ADD_DEPENDENCY, 20 = REMOVE_DEPENDENCY, 21 = CODE, 22 = REVIEW, 23 = ISSUE_LOCKED, 24 = ISSUE_UNLOCKED, 25 = TARGET_BRANCH_CHANGED, - 26 = DELETE_TIME_MANUAL --> + 26 = DELETE_TIME_MANUAL, 27 = REVIEW_REQUEST --> {{if eq .Type 0}}
{{if .OriginalAuthor }} @@ -468,5 +468,25 @@ {{.Content}}
+ {{else if eq .Type 27}} +
+ {{svg "octicon-eye" 16}} + + + + + {{.Poster.GetDisplayName}} + {{if .RemovedAssignee}} + {{if eq .PosterID .AssigneeID}} + {{$.i18n.Tr "repo.issues.review.remove_review_request_self" $createdStr | Safe}} + {{else}} + {{$.i18n.Tr "repo.issues.review.remove_review_request" (.Assignee.GetDisplayName|Escape) $createdStr | Safe}} + {{end}} + {{else}} + {{$.i18n.Tr "repo.issues.review.add_review_request" (.Assignee.GetDisplayName|Escape) $createdStr | Safe}} + {{end}} + +
+ {{end}} {{end}} diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index c7cf737b34917..09c7cd1d9f465 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -10,7 +10,25 @@ + {{- else if eq .Type 4}}yellow + {{else}}grey{{end}}"> + + {{$canChoose := false}} + {{if eq .Type 4}} + {{if or (eq .ReviewerID $.SignedUserID) $.Permission.IsAdmin}} + {{$canChoose = true}} + {{end}} + {{else}} + {{if and (or $.IsIssuePoster $.CanChooseReviewer) (not (eq $.SignedUserID .ReviewerID))}} + {{$canChoose = true}} + {{end}} + {{end}} + + {{if $canChoose }} + + {{svg "octicon-sync" 16}} + + {{end}} {{svg (printf "octicon-%s" .Type.Icon) 16}} {{if .Stale}} @@ -28,6 +46,8 @@ {{$.i18n.Tr "repo.issues.review.comment" $createdStr | Safe}} {{else if eq .Type 3}} {{$.i18n.Tr "repo.issues.review.reject" $createdStr | Safe}} + {{else if eq .Type 4}} + {{$.i18n.Tr "repo.issues.review.wait" $createdStr | Safe}} {{else}} {{$.i18n.Tr "repo.issues.review.comment" $createdStr | Safe}} {{end}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 2aed8f31580bd..941141b55f4e3 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -2,6 +2,97 @@
{{template "repo/issue/branch_selector_field" .}} + {{if .Issue.IsPull }} + + + + +
+ {{.i18n.Tr "repo.issues.new.no_reviewers"}} +
+ {{range .PullReviewers}} +
+  {{.Reviewer.GetDisplayName}} + + + {{$canChoose := false}} + {{if eq .Type 4}} + {{if or (eq .ReviewerID $.SignedUserID) $.Permission.IsAdmin}} + {{$canChoose = true}} + {{end}} + {{else}} + {{if and (or $.IsIssuePoster $.CanChooseReviewer) (not (eq $.SignedUserID .ReviewerID))}} + {{$canChoose = true}} + {{end}} + {{end}} + + {{if $canChoose}} + + {{svg "octicon-sync" 16}} + + {{end}} + {{svg (printf "octicon-%s" .Type.Icon) 16}} + +
+ {{end}} +
+
+ + {{end}} + +
+
-
+
From feefb8a5893920ab30c200632c51e11d55d67cd3 Mon Sep 17 00:00:00 2001 From: Dan Molik Date: Thu, 9 Apr 2020 20:37:31 -0400 Subject: [PATCH 029/550] Add Get/Update for api/v1/user/applications/oauth2 (#11008) Add api methods for getting and updating user oauth2 applications. Signed-off-by: Dan Molik Co-authored-by: techknowlogick --- integrations/api_oauth2_apps_test.go | 69 +++++++++++++++++++++- routers/api/v1/api.go | 5 +- routers/api/v1/user/app.go | 86 ++++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 58 +++++++++++++++++++ 4 files changed, 214 insertions(+), 4 deletions(-) diff --git a/integrations/api_oauth2_apps_test.go b/integrations/api_oauth2_apps_test.go index fe79582308c13..998043a6fb069 100644 --- a/integrations/api_oauth2_apps_test.go +++ b/integrations/api_oauth2_apps_test.go @@ -19,6 +19,8 @@ func TestOAuth2Application(t *testing.T) { defer prepareTestEnv(t)() testAPICreateOAuth2Application(t) testAPIListOAuth2Applications(t) + testAPIGetOAuth2Application(t) + testAPIUpdateOAuth2Application(t) testAPIDeleteOAuth2Application(t) } @@ -83,9 +85,6 @@ func testAPIDeleteOAuth2Application(t *testing.T) { oldApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ UID: user.ID, Name: "test-app-1", - RedirectURIs: []string{ - "http://www.google.com", - }, }).(*models.OAuth2Application) urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", oldApp.ID, token) @@ -94,3 +93,67 @@ func testAPIDeleteOAuth2Application(t *testing.T) { models.AssertNotExistsBean(t, &models.OAuth2Application{UID: oldApp.UID, Name: oldApp.Name}) } + +func testAPIGetOAuth2Application(t *testing.T) { + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + session := loginUser(t, user.Name) + token := getTokenForLoggedInUser(t, session) + + existApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ + UID: user.ID, + Name: "test-app-1", + RedirectURIs: []string{ + "http://www.google.com", + }, + }).(*models.OAuth2Application) + + urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d?token=%s", existApp.ID, token) + req := NewRequest(t, "GET", urlStr) + resp := session.MakeRequest(t, req, http.StatusOK) + + var app api.OAuth2Application + DecodeJSON(t, resp, &app) + expectedApp := app + + assert.EqualValues(t, existApp.Name, expectedApp.Name) + assert.EqualValues(t, existApp.ClientID, expectedApp.ClientID) + assert.Len(t, expectedApp.ClientID, 36) + assert.Empty(t, expectedApp.ClientSecret) + assert.EqualValues(t, len(expectedApp.RedirectURIs), 1) + assert.EqualValues(t, existApp.RedirectURIs[0], expectedApp.RedirectURIs[0]) + models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name}) +} + +func testAPIUpdateOAuth2Application(t *testing.T) { + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + + existApp := models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ + UID: user.ID, + Name: "test-app-1", + RedirectURIs: []string{ + "http://www.google.com", + }, + }).(*models.OAuth2Application) + + appBody := api.CreateOAuth2ApplicationOptions{ + Name: "test-app-1", + RedirectURIs: []string{ + "http://www.google.com/", + "http://www.github.com/", + }, + } + + urlStr := fmt.Sprintf("/api/v1/user/applications/oauth2/%d", existApp.ID) + req := NewRequestWithJSON(t, "PATCH", urlStr, &appBody) + req = AddBasicAuthHeader(req, user.Name) + resp := MakeRequest(t, req, http.StatusOK) + + var app api.OAuth2Application + DecodeJSON(t, resp, &app) + expectedApp := app + + assert.EqualValues(t, len(expectedApp.RedirectURIs), 2) + assert.EqualValues(t, expectedApp.RedirectURIs[0], appBody.RedirectURIs[0]) + assert.EqualValues(t, expectedApp.RedirectURIs[1], appBody.RedirectURIs[1]) + models.AssertExistsAndLoadBean(t, &models.OAuth2Application{ID: expectedApp.ID, Name: expectedApp.Name}) +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 150c073c91857..bce3bf2452832 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -580,7 +580,10 @@ func RegisterRoutes(m *macaron.Macaron) { m.Combo("/oauth2"). Get(user.ListOauth2Applications). Post(bind(api.CreateOAuth2ApplicationOptions{}), user.CreateOauth2Application) - m.Delete("/oauth2/:id", user.DeleteOauth2Application) + m.Combo("/oauth2/:id"). + Delete(user.DeleteOauth2Application). + Patch(bind(api.CreateOAuth2ApplicationOptions{}), user.UpdateOauth2Application). + Get(user.GetOauth2Application) }, reqToken()) m.Group("/gpg_keys", func() { diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index 7e0e620fea736..9ec506bcf2494 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -231,3 +231,89 @@ func DeleteOauth2Application(ctx *context.APIContext) { ctx.Status(http.StatusNoContent) } + +// GetOauth2Application get OAuth2 Application +func GetOauth2Application(ctx *context.APIContext) { + // swagger:operation GET /user/applications/oauth2/{id} user userGetOAuth2Application + // --- + // summary: get an OAuth2 Application + // produces: + // - application/json + // parameters: + // - name: id + // in: path + // description: Application ID to be found + // type: integer + // format: int64 + // required: true + // responses: + // "200": + // "$ref": "#/responses/OAuth2Application" + appID := ctx.ParamsInt64(":id") + app, err := models.GetOAuth2ApplicationByID(appID) + if err != nil { + if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) { + ctx.NotFound() + } else { + ctx.Error(http.StatusInternalServerError, "GetOauth2ApplicationByID", err) + } + return + } + + app.ClientSecret = "" + + ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app)) +} + +// UpdateOauth2Application update OAuth2 Application +func UpdateOauth2Application(ctx *context.APIContext, data api.CreateOAuth2ApplicationOptions) { + // swagger:operation PATCH /user/applications/oauth2/{id} user userUpdateOAuth2Application + // --- + // summary: update an OAuth2 Application, this includes regenerating the client secret + // produces: + // - application/json + // parameters: + // - name: id + // in: path + // description: application to be updated + // type: integer + // format: int64 + // required: true + // - name: body + // in: body + // required: true + // schema: + // "$ref": "#/definitions/CreateOAuth2ApplicationOptions" + // responses: + // "200": + // "$ref": "#/responses/OAuth2Application" + appID := ctx.ParamsInt64(":id") + + err := models.UpdateOAuth2Application(models.UpdateOAuth2ApplicationOptions{ + Name: data.Name, + UserID: ctx.User.ID, + ID: appID, + RedirectURIs: data.RedirectURIs, + }) + if err != nil { + ctx.Error(http.StatusBadRequest, "", "error updating oauth2 application") + return + } + app, err := models.GetOAuth2ApplicationByID(appID) + if err != nil { + if models.IsErrOauthClientIDInvalid(err) || models.IsErrOAuthApplicationNotFound(err) { + ctx.NotFound() + } else { + ctx.Error(http.StatusInternalServerError, "UpdateOauth2ApplicationByID", err) + } + return + } + secret, err := app.GenerateClientSecret() + if err != nil { + ctx.Error(http.StatusBadRequest, "", "error updating application secret") + return + } + app.ClientSecret = secret + + ctx.JSON(http.StatusOK, convert.ToOAuth2Application(app)) +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 55094e391dabc..8591381ef4a7b 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -8360,6 +8360,31 @@ } }, "/user/applications/oauth2/{id}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "get an OAuth2 Application", + "operationId": "userGetOAuth2Application", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "Application ID to be found", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/OAuth2Application" + } + } + }, "delete": { "produces": [ "application/json" @@ -8384,6 +8409,39 @@ "$ref": "#/responses/empty" } } + }, + "patch": { + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "update an OAuth2 Application, this includes regenerating the client secret", + "operationId": "userUpdateOAuth2Application", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "application to be updated", + "name": "id", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/CreateOAuth2ApplicationOptions" + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/OAuth2Application" + } + } } }, "/user/emails": { From c1c74e4648b715ef3505dc11bee526a98ed6d306 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Fri, 10 Apr 2020 12:40:36 +0200 Subject: [PATCH 030/550] Load pr Issue Poster on API too (#11033) --- services/pull/merge.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/pull/merge.go b/services/pull/merge.go index b412e71896db9..2d4d9722e8395 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -337,6 +337,10 @@ func rawMerge(pr *models.PullRequest, doer *models.User, mergeStyle models.Merge return "", err } + if err = pr.Issue.LoadPoster(); err != nil { + log.Error("LoadPoster: %v", err) + return "", fmt.Errorf("LoadPoster: %v", err) + } sig := pr.Issue.Poster.NewGitSig() if signArg == "" { if err := git.NewCommand("commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", message).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, &outbuf, &errbuf); err != nil { From 6c2916d6d7b3f043ae044cb0878947469aafcc1c Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Fri, 10 Apr 2020 10:43:04 +0000 Subject: [PATCH 031/550] [skip ci] Updated translations via Crowdin --- options/locale/locale_zh-CN.ini | 53 +++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index ff63d540c6100..2a2ffe2380975 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -215,6 +215,7 @@ user_no_results=未找到匹配的用户。 org_no_results=未找到匹配的组织。 code_no_results=未找到与搜索字词匹配的源代码。 code_search_results=“%s” 的搜索结果是 +code_last_indexed_at=最后索引于 %s [auth] create_new_account=注册帐号 @@ -377,6 +378,7 @@ user_bio=简历 form.name_reserved='%s' 用户名被保留。 form.name_pattern_not_allowed=用户名中不允许使用 "%s"。 +form.name_chars_not_allowed=用户名 '%s' 包含无效字符。 [settings] profile=个人信息 @@ -437,7 +439,11 @@ manage_openid=管理 OpenID 地址 email_desc=您的主要邮箱地址将被用于通知提醒和其它操作。 theme_desc=这将是您在整个网站上的默认主题。 primary=主要 +activated=已激活 +requires_activation=需要激活 primary_email=设为主要邮件地址 +activate_email=发送激活邮件 +activations_pending=等待激活 delete_email=移除 email_deletion=移除电子邮件地址 email_deletion_desc=电子邮箱地址和相关信息将会被删除。使用此电子邮箱地址发送的Git提交将会保留,继续? @@ -718,6 +724,8 @@ tags=标签列表 issues=工单 pulls=合并请求 labels=标签 +org_labels_desc=组织级别的标签,可以被本组织下的 所有仓库 使用 +org_labels_desc_manage=管理 milestones=里程碑 commits=提交 @@ -731,6 +739,7 @@ file_too_large=文件过大,无法显示。 video_not_supported_in_browser=您的浏览器不支持使用 HTML5 'video' 标签。 audio_not_supported_in_browser=您的浏览器不支持使用 HTML5 'video' 标签。 stored_lfs=存储到Git LFS +symbolic_link=符号链接 commit_graph=提交图 blame=Blame normal_view=普通视图 @@ -782,6 +791,8 @@ editor.commit_empty_file_header=提交一个空文件 editor.commit_empty_file_text=您要提交的文件是空的,继续吗? editor.no_changes_to_show=没有可以显示的变更。 editor.fail_to_update_file=更新/创建文件 '%s' 时发生错误:%v +editor.push_rejected_no_message=此更改被服务器拒绝并且没有反馈消息。请检查 githooks。 +editor.push_rejected=此更改被服务器拒绝,消息如下:
%s
请检查 githooks。 editor.add_subdir=添加目录 editor.unable_to_upload_files=上传文件至 '%s' 时发生错误:%v editor.upload_file_is_locked=文件%s被 %s 锁定。 @@ -804,25 +815,37 @@ commits.date=提交日期 commits.older=更旧的提交 commits.newer=更新的提交 commits.signed_by=签署人: +commits.signed_by_untrusted_user=由未授信的用户签名 +commits.signed_by_untrusted_user_unmatched=由与提交者不匹配的未授信的用户签名 commits.gpg_key_id=GPG 密钥 ID ext_issues=外部工单 ext_issues.desc=链接到外部工单跟踪系统。 issues.desc=组织 bug 报告、任务和里程碑。 +issues.filter_assignees=筛选指派人 +issues.filter_milestones=筛选里程碑 +issues.filter_labels=筛选标签 +issues.filter_reviewers=筛选审核者 issues.new=创建工单 issues.new.title_empty=标题不能为空 issues.new.labels=标签 +issues.new.add_labels_title=添加标签 issues.new.no_label=未选择标签 issues.new.clear_labels=清除选中标签 +issues.new.no_items=无可选项 issues.new.milestone=里程碑 +issues.new.add_milestone_title=设置里程碑 issues.new.no_milestone=未选择里程碑 issues.new.clear_milestone=取消选中里程碑 issues.new.open_milestone=开启中的里程碑 issues.new.closed_milestone=已关闭的里程碑 issues.new.assignees=指派成员 +issues.new.add_assignees_title=指派用户 issues.new.clear_assignees=取消指派成员 issues.new.no_assignees=未指派成员 +issues.new.no_reviewers=无审核者 +issues.new.add_reviewer_title=请求审核 issues.no_ref=分支/标记未指定 issues.create=创建工单 issues.new_label=创建标签 @@ -883,7 +906,9 @@ issues.action_assignee_no_select=未指派 issues.opened_by=由 %[3]s 于 %[1]s创建 pulls.merged_by=由 %[3]s 于 %[1]s 合并 pulls.merged_by_fake=由 %[2]s 于 %[1]s 合并 +issues.closed_by=按 %[3]s 关闭%[1]s issues.opened_by_fake=由 %[2]s 于 %[1]s创建 +issues.closed_by_fake=通过 %[2]s 关闭 %[1]s issues.previous=上一页 issues.next=下一页 issues.open_title=开启中 @@ -914,7 +939,10 @@ issues.ref_from=`来自 %[1]s` issues.poster=发布者 issues.collaborator=协作者 issues.owner=所有者 -issues.sign_in_require_desc=登陆 并参与到对话中。 +issues.re_request_review=再次请求审核 +issues.remove_request_review=移除审核请求 +issues.remove_request_review_block=无法移除审核请求 +issues.sign_in_require_desc=登录 并参与到对话中。 issues.edit=编辑 issues.cancel=取消 issues.save=保存 @@ -931,6 +959,8 @@ issues.label_deletion_desc=删除标签会将其从所有问题中删除。继 issues.label_deletion_success=该标签已被删除。 issues.label.filter_sort.alphabetically=按字母顺序排序 issues.label.filter_sort.reverse_alphabetically=按字母逆序排序 +issues.label.filter_sort.by_size=最小尺寸 +issues.label.filter_sort.reverse_by_size=最大尺寸 issues.num_participants=%d 名参与者 issues.attachment.open_tab=`在新的标签页中查看 '%s'` issues.attachment.download=`点击下载 '%s'` @@ -1023,6 +1053,10 @@ issues.review.approve=已于 %s 批准这些更改 issues.review.comment=评审于 %s issues.review.content.empty=您需要留下一个注释,表明需要的更改。 issues.review.reject=请求变更 %s +issues.review.wait=已请求 %s 审核 +issues.review.add_review_request=请求 %s 评审 %s +issues.review.remove_review_request=取消对 %s 的评审请求 %s +issues.review.remove_review_request_self=拒绝审核 %s issues.review.pending=待定 issues.review.review=评审 issues.review.reviewers=评审人 @@ -1067,6 +1101,12 @@ pulls.cannot_auto_merge_desc=该合并请求存在冲突,无法进行自动合 pulls.cannot_auto_merge_helper=手动合并解决此冲突 pulls.num_conflicting_files_1=%d 个冲突文件 pulls.num_conflicting_files_n=%d 个冲突文件 +pulls.approve_count_1=%d 项批准 +pulls.approve_count_n=%d 批准的 +pulls.reject_count_1=%d 变更请求 +pulls.reject_count_n=%d 变更请求 +pulls.waiting_count_1=%d 个正在等待审核 +pulls.waiting_count_n=%d 个正在等待审核 pulls.no_merge_desc=由于未启用合并选项,此合并请求无法被合并。 pulls.no_merge_helper=在仓库设置中启用合并选项或者手工合并请求。 @@ -1083,6 +1123,8 @@ pulls.merge_conflict=合并失败:合并时发生冲突:%[1]s
[2]
提 pulls.rebase_conflict=合并失败:Rebase合并时发生冲突:%[1]s
%[2]s
%[3]s
提示:尝试不同的合并策略 pulls.unrelated_histories=合并失败:两个分支没有共同历史。提示:尝试不同的策略 pulls.merge_out_of_date=合并失败:在生成合并时,主分支已更新。提示:再试一次。 +pulls.push_rejected=合并失败:这个推送被拒绝并收到以下消息:
%s
检查这个仓库的 githooks +pulls.push_rejected_no_message=合并失败:这个推送被拒绝但没有远程消息。
检查这个仓库的 githooks pulls.open_unmerged_pull_exists=`您不能执行重新打开操作, 因为已经存在相同的合并请求 (#%d)。` pulls.status_checking=一些检测仍在等待运行 pulls.status_checks_success=所有检测均成功 @@ -1359,17 +1401,23 @@ settings.event_desc=触发条件: settings.event_push_only=推送事件 settings.event_send_everything=所有事件 settings.event_choose=自定义事件... +settings.event_header_repository=仓库事件 settings.event_create=创建 settings.event_create_desc=创建分支或标签 settings.event_delete=刪除 +settings.event_delete_desc=分支或标签已删除。 settings.event_fork=派生 +settings.event_fork_desc=仓库被派生。 settings.event_release=版本发布 settings.event_release_desc=发布、更新或删除版本时。 settings.event_push=推送 settings.event_push_desc=Git 仓库推送 settings.event_repository=仓库 settings.event_repository_desc=创建或删除仓库 +settings.event_header_issue=工单事件 settings.event_issues=工单 +settings.event_issues_desc=工单已打开、已关闭、已重新打开或已编辑。 +settings.event_issue_assign=工单已指派 settings.event_issue_comment=工单评论 settings.event_issue_comment_desc=工单评论被创建、编辑或删除 settings.event_pull_request=合并请求 @@ -1881,7 +1929,7 @@ auths.oauth2_profileURL=Profile URL auths.oauth2_emailURL=电子邮件 URL auths.enable_auto_register=允许用户自动注册 auths.sspi_auto_create_users=自动创建用户 -auths.sspi_auto_create_users_helper=允许 SSPI 认证在用户第一次登陆时自动创建新账号 +auths.sspi_auto_create_users_helper=允许 SSPI 认证在用户第一次登录时自动创建新账号 auths.sspi_auto_activate_users=自动激活用户 auths.sspi_auto_activate_users_helper=允许 SSPI 认证自动激活新用户 auths.sspi_strip_domain_names=从用户名中删除域名部分 @@ -1904,6 +1952,7 @@ auths.tip.openid_connect=使用 OpenID 连接发现 URL (/.well-known/op auths.tip.twitter=访问 https://dev.twitter.com/apps,创建应用并确保启用了"允许此应用程序用于登录 Twitter"的选项。 auths.tip.discord=在 https://discordapp.com/developers/applications/me 上注册新应用程序 auths.tip.gitea=注册一个新的 OAuth2 应用程序。可以访问 https://docs.gitea.io/en-us/oauth 2-product/ 查看帮助 。 +auths.tip.yandex=在 https://oauth.yandex.com/client/new 上创建一个新的应用程序。在“ Yandex.Passport API”这部分中选择以下权限:“访问电子邮件地址(Access to email address)”,“访问用户头像(Access to user avatar)”和“访问用户名,名字和姓氏,性别(Access to username, first name and surname, genderAccess to username, first name and surname, gender)” auths.edit=修改认证源 auths.activated=该认证源已经启用 auths.new_success=已添加身份验证 '%s'。 From b86e3dac955ff927725a2c8ffe46e8c5a599145c Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Fri, 10 Apr 2020 13:26:37 +0200 Subject: [PATCH 032/550] remove package code.gitea.io/gitea/modules/git import out of models (#11025) --- models/pull.go | 200 ------------------- routers/repo/issue.go | 2 +- routers/repo/pull.go | 1 + routers/user/home.go | 3 +- services/pull/pull.go | 202 +++++++++++++++++++- templates/repo/issue/view_content/pull.tmpl | 3 +- 6 files changed, 206 insertions(+), 205 deletions(-) diff --git a/models/pull.go b/models/pull.go index 48d2340544377..02b5e98c49319 100644 --- a/models/pull.go +++ b/models/pull.go @@ -10,7 +10,6 @@ import ( "io" "strings" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" @@ -215,143 +214,6 @@ func (pr *PullRequest) GetDefaultMergeMessage() string { return fmt.Sprintf("Merge pull request '%s' (#%d) from %s:%s into %s", pr.Issue.Title, pr.Issue.Index, pr.HeadRepo.FullName(), pr.HeadBranch, pr.BaseBranch) } -// GetCommitMessages returns the commit messages between head and merge base (if there is one) -func (pr *PullRequest) GetCommitMessages() string { - if err := pr.LoadIssue(); err != nil { - log.Error("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err) - return "" - } - - if err := pr.Issue.LoadPoster(); err != nil { - log.Error("Cannot load poster %d for pr id %d, index %d Error: %v", pr.Issue.PosterID, pr.ID, pr.Index, err) - return "" - } - - if pr.HeadRepo == nil { - var err error - pr.HeadRepo, err = GetRepositoryByID(pr.HeadRepoID) - if err != nil { - log.Error("GetRepositoryById[%d]: %v", pr.HeadRepoID, err) - return "" - } - } - - gitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) - if err != nil { - log.Error("Unable to open head repository: Error: %v", err) - return "" - } - defer gitRepo.Close() - - headCommit, err := gitRepo.GetBranchCommit(pr.HeadBranch) - if err != nil { - log.Error("Unable to get head commit: %s Error: %v", pr.HeadBranch, err) - return "" - } - - mergeBase, err := gitRepo.GetCommit(pr.MergeBase) - if err != nil { - log.Error("Unable to get merge base commit: %s Error: %v", pr.MergeBase, err) - return "" - } - - limit := setting.Repository.PullRequest.DefaultMergeMessageCommitsLimit - - list, err := gitRepo.CommitsBetweenLimit(headCommit, mergeBase, limit, 0) - if err != nil { - log.Error("Unable to get commits between: %s %s Error: %v", pr.HeadBranch, pr.MergeBase, err) - return "" - } - - maxSize := setting.Repository.PullRequest.DefaultMergeMessageSize - - posterSig := pr.Issue.Poster.NewGitSig().String() - - authorsMap := map[string]bool{} - authors := make([]string, 0, list.Len()) - stringBuilder := strings.Builder{} - element := list.Front() - for element != nil { - commit := element.Value.(*git.Commit) - - if maxSize < 0 || stringBuilder.Len() < maxSize { - toWrite := []byte(commit.CommitMessage) - if len(toWrite) > maxSize-stringBuilder.Len() && maxSize > -1 { - toWrite = append(toWrite[:maxSize-stringBuilder.Len()], "..."...) - } - if _, err := stringBuilder.Write(toWrite); err != nil { - log.Error("Unable to write commit message Error: %v", err) - return "" - } - - if _, err := stringBuilder.WriteRune('\n'); err != nil { - log.Error("Unable to write commit message Error: %v", err) - return "" - } - } - - authorString := commit.Author.String() - if !authorsMap[authorString] && authorString != posterSig { - authors = append(authors, authorString) - authorsMap[authorString] = true - } - element = element.Next() - } - - // Consider collecting the remaining authors - if limit >= 0 && setting.Repository.PullRequest.DefaultMergeMessageAllAuthors { - skip := limit - limit = 30 - for { - list, err := gitRepo.CommitsBetweenLimit(headCommit, mergeBase, limit, skip) - if err != nil { - log.Error("Unable to get commits between: %s %s Error: %v", pr.HeadBranch, pr.MergeBase, err) - return "" - - } - if list.Len() == 0 { - break - } - element := list.Front() - for element != nil { - commit := element.Value.(*git.Commit) - - authorString := commit.Author.String() - if !authorsMap[authorString] && authorString != posterSig { - authors = append(authors, authorString) - authorsMap[authorString] = true - } - element = element.Next() - } - - } - } - - if len(authors) > 0 { - if _, err := stringBuilder.WriteRune('\n'); err != nil { - log.Error("Unable to write to string builder Error: %v", err) - return "" - } - } - - for _, author := range authors { - if _, err := stringBuilder.Write([]byte("Co-authored-by: ")); err != nil { - log.Error("Unable to write to string builder Error: %v", err) - return "" - } - if _, err := stringBuilder.Write([]byte(author)); err != nil { - log.Error("Unable to write to string builder Error: %v", err) - return "" - } - if _, err := stringBuilder.WriteRune('\n'); err != nil { - log.Error("Unable to write to string builder Error: %v", err) - return "" - } - } - - return stringBuilder.String() -} - // ReviewCount represents a count of Reviews type ReviewCount struct { IssueID int64 @@ -465,39 +327,6 @@ func (pr *PullRequest) CanAutoMerge() bool { return pr.Status == PullRequestStatusMergeable } -// GetLastCommitStatus returns the last commit status for this pull request. -func (pr *PullRequest) GetLastCommitStatus() (status *CommitStatus, err error) { - if err = pr.LoadHeadRepo(); err != nil { - return nil, err - } - - if pr.HeadRepo == nil { - return nil, ErrPullRequestHeadRepoMissing{pr.ID, pr.HeadRepoID} - } - - headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) - if err != nil { - return nil, err - } - defer headGitRepo.Close() - - lastCommitID, err := headGitRepo.GetBranchCommitID(pr.HeadBranch) - if err != nil { - return nil, err - } - - err = pr.LoadBaseRepo() - if err != nil { - return nil, err - } - - statusList, err := GetLatestCommitStatus(pr.BaseRepo, lastCommitID, 0) - if err != nil { - return nil, err - } - return CalcCommitStatus(statusList), nil -} - // MergeStyle represents the approach to merge commits into base branch. type MergeStyle string @@ -786,35 +615,6 @@ func (pr *PullRequest) GetWorkInProgressPrefix() string { return "" } -// IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head -func (pr *PullRequest) IsHeadEqualWithBranch(branchName string) (bool, error) { - var err error - if err = pr.LoadBaseRepo(); err != nil { - return false, err - } - baseGitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath()) - if err != nil { - return false, err - } - baseCommit, err := baseGitRepo.GetBranchCommit(branchName) - if err != nil { - return false, err - } - - if err = pr.LoadHeadRepo(); err != nil { - return false, err - } - headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) - if err != nil { - return false, err - } - headCommit, err := headGitRepo.GetBranchCommit(pr.HeadBranch) - if err != nil { - return false, err - } - return baseCommit.HasPreviousCommit(headCommit.ID) -} - // IsSameRepo returns true if base repo and head repo is the same func (pr *PullRequest) IsSameRepo() bool { return pr.BaseRepoID == pr.HeadRepoID diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 0a059bf789627..3655de7ed44ff 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -240,7 +240,7 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB return } - commitStatus[issues[i].PullRequest.ID], _ = issues[i].PullRequest.GetLastCommitStatus() + commitStatus[issues[i].PullRequest.ID], _ = pull_service.GetLastCommitStatus(issues[i].PullRequest) } } diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 55b8bbb42f521..ef000208f4411 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -433,6 +433,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare return nil } ctx.Data["Divergence"] = divergence + ctx.Data["GetCommitMessages"] = pull_service.GetCommitMessages(pull) } sha, err := baseGitRepo.GetRefCommitID(pull.GetGitRefName()) diff --git a/routers/user/home.go b/routers/user/home.go index 3807025ea52fe..816968562fd60 100644 --- a/routers/user/home.go +++ b/routers/user/home.go @@ -22,6 +22,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + pull_service "code.gitea.io/gitea/services/pull" "github.com/keybase/go-crypto/openpgp" "github.com/keybase/go-crypto/openpgp/armor" @@ -553,7 +554,7 @@ func Issues(ctx *context.Context) { issue.Repo = showReposMap[issue.RepoID] if isPullList { - commitStatus[issue.PullRequest.ID], _ = issue.PullRequest.GetLastCommitStatus() + commitStatus[issue.PullRequest.ID], _ = pull_service.GetLastCommitStatus(issue.PullRequest) } } diff --git a/services/pull/pull.go b/services/pull/pull.go index ce5c4ff22ffc2..2797294980eb1 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -19,6 +19,7 @@ import ( "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/notification" + "code.gitea.io/gitea/modules/setting" issue_service "code.gitea.io/gitea/services/issue" "github.com/unknwon/com" @@ -79,7 +80,7 @@ func ChangeTargetBranch(pr *models.PullRequest, doer *models.User, targetBranch } // Check if branches are equal - branchesEqual, err := pr.IsHeadEqualWithBranch(targetBranch) + branchesEqual, err := IsHeadEqualWithBranch(pr, targetBranch) if err != nil { return err } @@ -454,3 +455,202 @@ func CloseRepoBranchesPulls(doer *models.User, repo *models.Repository) error { } return nil } + +// GetCommitMessages returns the commit messages between head and merge base (if there is one) +func GetCommitMessages(pr *models.PullRequest) string { + if err := pr.LoadIssue(); err != nil { + log.Error("Cannot load issue %d for PR id %d: Error: %v", pr.IssueID, pr.ID, err) + return "" + } + + if err := pr.Issue.LoadPoster(); err != nil { + log.Error("Cannot load poster %d for pr id %d, index %d Error: %v", pr.Issue.PosterID, pr.ID, pr.Index, err) + return "" + } + + if pr.HeadRepo == nil { + var err error + pr.HeadRepo, err = models.GetRepositoryByID(pr.HeadRepoID) + if err != nil { + log.Error("GetRepositoryById[%d]: %v", pr.HeadRepoID, err) + return "" + } + } + + gitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) + if err != nil { + log.Error("Unable to open head repository: Error: %v", err) + return "" + } + defer gitRepo.Close() + + headCommit, err := gitRepo.GetBranchCommit(pr.HeadBranch) + if err != nil { + log.Error("Unable to get head commit: %s Error: %v", pr.HeadBranch, err) + return "" + } + + mergeBase, err := gitRepo.GetCommit(pr.MergeBase) + if err != nil { + log.Error("Unable to get merge base commit: %s Error: %v", pr.MergeBase, err) + return "" + } + + limit := setting.Repository.PullRequest.DefaultMergeMessageCommitsLimit + + list, err := gitRepo.CommitsBetweenLimit(headCommit, mergeBase, limit, 0) + if err != nil { + log.Error("Unable to get commits between: %s %s Error: %v", pr.HeadBranch, pr.MergeBase, err) + return "" + } + + maxSize := setting.Repository.PullRequest.DefaultMergeMessageSize + + posterSig := pr.Issue.Poster.NewGitSig().String() + + authorsMap := map[string]bool{} + authors := make([]string, 0, list.Len()) + stringBuilder := strings.Builder{} + element := list.Front() + for element != nil { + commit := element.Value.(*git.Commit) + + if maxSize < 0 || stringBuilder.Len() < maxSize { + toWrite := []byte(commit.CommitMessage) + if len(toWrite) > maxSize-stringBuilder.Len() && maxSize > -1 { + toWrite = append(toWrite[:maxSize-stringBuilder.Len()], "..."...) + } + if _, err := stringBuilder.Write(toWrite); err != nil { + log.Error("Unable to write commit message Error: %v", err) + return "" + } + + if _, err := stringBuilder.WriteRune('\n'); err != nil { + log.Error("Unable to write commit message Error: %v", err) + return "" + } + } + + authorString := commit.Author.String() + if !authorsMap[authorString] && authorString != posterSig { + authors = append(authors, authorString) + authorsMap[authorString] = true + } + element = element.Next() + } + + // Consider collecting the remaining authors + if limit >= 0 && setting.Repository.PullRequest.DefaultMergeMessageAllAuthors { + skip := limit + limit = 30 + for { + list, err := gitRepo.CommitsBetweenLimit(headCommit, mergeBase, limit, skip) + if err != nil { + log.Error("Unable to get commits between: %s %s Error: %v", pr.HeadBranch, pr.MergeBase, err) + return "" + + } + if list.Len() == 0 { + break + } + element := list.Front() + for element != nil { + commit := element.Value.(*git.Commit) + + authorString := commit.Author.String() + if !authorsMap[authorString] && authorString != posterSig { + authors = append(authors, authorString) + authorsMap[authorString] = true + } + element = element.Next() + } + + } + } + + if len(authors) > 0 { + if _, err := stringBuilder.WriteRune('\n'); err != nil { + log.Error("Unable to write to string builder Error: %v", err) + return "" + } + } + + for _, author := range authors { + if _, err := stringBuilder.Write([]byte("Co-authored-by: ")); err != nil { + log.Error("Unable to write to string builder Error: %v", err) + return "" + } + if _, err := stringBuilder.Write([]byte(author)); err != nil { + log.Error("Unable to write to string builder Error: %v", err) + return "" + } + if _, err := stringBuilder.WriteRune('\n'); err != nil { + log.Error("Unable to write to string builder Error: %v", err) + return "" + } + } + + return stringBuilder.String() +} + +// GetLastCommitStatus returns the last commit status for this pull request. +func GetLastCommitStatus(pr *models.PullRequest) (status *models.CommitStatus, err error) { + if err = pr.LoadHeadRepo(); err != nil { + return nil, err + } + + if pr.HeadRepo == nil { + return nil, models.ErrPullRequestHeadRepoMissing{ID: pr.ID, HeadRepoID: pr.HeadRepoID} + } + + headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) + if err != nil { + return nil, err + } + defer headGitRepo.Close() + + lastCommitID, err := headGitRepo.GetBranchCommitID(pr.HeadBranch) + if err != nil { + return nil, err + } + + err = pr.LoadBaseRepo() + if err != nil { + return nil, err + } + + statusList, err := models.GetLatestCommitStatus(pr.BaseRepo, lastCommitID, 0) + if err != nil { + return nil, err + } + return models.CalcCommitStatus(statusList), nil +} + +// IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head +func IsHeadEqualWithBranch(pr *models.PullRequest, branchName string) (bool, error) { + var err error + if err = pr.LoadBaseRepo(); err != nil { + return false, err + } + baseGitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath()) + if err != nil { + return false, err + } + baseCommit, err := baseGitRepo.GetBranchCommit(branchName) + if err != nil { + return false, err + } + + if err = pr.LoadHeadRepo(); err != nil { + return false, err + } + headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) + if err != nil { + return false, err + } + headCommit, err := headGitRepo.GetBranchCommit(pr.HeadBranch) + if err != nil { + return false, err + } + return baseCommit.HasPreviousCommit(headCommit.ID) +} diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index 09c7cd1d9f465..baad7f864df52 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -234,7 +234,6 @@
{{end}} {{if $prUnit.PullRequestsConfig.AllowSquash}} - {{$commitMessages := .Issue.PullRequest.GetCommitMessages}}
- +
- - {{end}} - {{$filename}} -
- {{$diff := (CommentMustAsDiff (index $comms 0))}} - {{if $diff}} - {{$file := (index $diff.Files 0)}} -
-
-
- - - {{template "repo/diff/section_unified" dict "file" $file "root" $}} - -
+ {{if .Review.CodeComments}} +
+ {{ range $filename, $lines := .Review.CodeComments}} + {{range $line, $comms := $lines}} +
+
+ {{$invalid := (index $comms 0).Invalidated}} + {{if $invalid}} + + + {{end}} + {{$filename}} +
+ {{$diff := (CommentMustAsDiff (index $comms 0))}} + {{if $diff}} + {{$file := (index $diff.Files 0)}} +
+
+
+ + + {{template "repo/diff/section_unified" dict "file" $file "root" $}} + +
+
-
- {{end}} -
-
- {{range $comms}} - {{ $createdSubStr:= TimeSinceUnix .CreatedUnix $.Lang }} -
- - - -
-
- {{.Poster.GetDisplayName}} - -
-
- {{if .RenderedContent}} - {{.RenderedContent|Str2html}} - {{else}} - {{$.i18n.Tr "repo.issues.no_content"}} - {{end}} + {{end}} +
+
+ {{range $comms}} + {{ $createdSubStr:= TimeSinceUnix .CreatedUnix $.Lang }} +
+ + + +
+
+ {{.Poster.GetDisplayName}} + +
+
+ {{if .RenderedContent}} + {{.RenderedContent|Str2html}} + {{else}} + {{$.i18n.Tr "repo.issues.no_content"}} + {{end}} +
+
{{.Content}}
-
{{.Content}}
-
- {{end}} + {{end}} +
+ {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $comms 0).ReviewID "root" $ "comment" (index $comms 0)}}
- {{template "repo/diff/comment_form_datahandler" dict "hidden" true "reply" (index $comms 0).ReviewID "root" $ "comment" (index $comms 0)}}
-
+ {{end}} {{end}} +
{{end}}
{{else if eq .Type 23}} -
- {{svg "octicon-lock" 16}} +
+ {{svg "octicon-lock" 16}} @@ -436,8 +458,8 @@ {{ end }}
{{else if eq .Type 24}} -
- {{svg "octicon-key" 16}} +
+ {{svg "octicon-key" 16}} @@ -447,8 +469,8 @@
{{else if eq .Type 25}} -
- {{svg "octicon-primitive-dot" 16}} +
+ {{svg "octicon-git-branch" 16}} @@ -457,8 +479,8 @@
{{else if eq .Type 26}} -
- {{svg "octicon-primitive-dot" 16}} +
+ {{svg "octicon-clock" 16}} @@ -469,8 +491,8 @@
{{else if eq .Type 27}} -
- {{svg "octicon-eye" 16}} +
+ {{svg "octicon-eye" 16}} diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index baad7f864df52..e580d9558656a 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -58,8 +58,8 @@
{{end}} -
- + .content { + margin-left: -16px; + } + + &.event > .text { + line-height: 30px; + } + } + + .comment { + .tag { color: #767676; margin-top: 3px; @@ -778,8 +851,6 @@ } .content { - margin-left: 4em; - > .header { #avatar-arrow; font-weight: normal; @@ -787,7 +858,6 @@ position: relative; color: #767676; background-color: #f7f7f7; - border-bottom: 1px solid #eeeeee; border-top-left-radius: 3px; border-top-right-radius: 3px; @@ -796,6 +866,29 @@ padding-top: 10px; padding-bottom: 10px; } + + &.arrow-top::before, + &.arrow-top::after { + transform: rotate(90deg); + } + + &.arrow-top::before { + top: -9px; + left: 6px; + } + + &.arrow-top::after { + top: -8px; + left: 7px; + } + + .actions a { + color: rgba(0, 0, 0, .4); + + &:hover { + color: rgba(0, 0, 0, .8); + } + } } > .merge-section { @@ -892,9 +985,7 @@ } .event { - position: relative; - margin: 15px 0 15px 79px; - padding-left: 25px; + padding-left: 15px; & > .svg:not(.issue-symbol) { text-shadow: -2px 0 #fff, 0 2px #fff, 2px 0 #fff, 0 -2px #fff; @@ -935,46 +1026,6 @@ } } - .svg { - width: 30px; - float: left; - text-align: center; - - &.octicon-circle-slash { - margin-top: 5px; - margin-left: -35.5px; - height: 20px; - color: #bd2c00; - } - - &.octicon-primitive-dot { - margin-top: -1px; - margin-left: -35.5px; - margin-right: -1px; - height: 30px; - color: #6cc644; - } - - &.octicon-bookmark { - margin-top: 2px; - margin-left: -35.5px; - margin-right: -1px; - height: 25px; - } - - &.octicon-eye { - margin-top: 3px; - margin-left: -35.5px; - margin-right: 0; - height: 22px; - } - - &.octicon-x { - margin-left: -35.5px; - height: 25px; - } - } - .detail { font-size: .9rem; margin-top: 5px; @@ -986,11 +1037,11 @@ } } } - } - } - .ui.segment.metas { - margin-top: -3px; + .segments { + box-shadow: none; + } + } } .ui.participants { @@ -2169,8 +2220,8 @@ .select-reaction { float: left; - padding: .5em; - padding-left: 1em; + padding: .4em; + line-height: 21px; &:not(.active) a { display: none; diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/less/themes/theme-arc-green.less index ffc6872cb3f9a..d56b7b8eebd34 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/less/themes/theme-arc-green.less @@ -672,13 +672,13 @@ a.ui.basic.green.label:hover { color: #dbdbdb !important; } -.ui.comments .comment .actions a { - color: #9e9e9e; +.ui .comment .actions a { + color: #9e9e9e !important; } -.ui.comments .comment .actions a.active, -.ui.comments .comment .actions a:hover { - color: #fff; +.ui .comment .actions a.active, +.ui .comment .actions a:hover { + color: #fff !important; } .repository.view.issue .comment-list .comment .content .header:after { @@ -698,10 +698,16 @@ a.ui.basic.green.label:hover { } .repository.view.issue .comment-list:not(.prevent-before-timeline):before, -.repository.view.issue .comment-list .timeline-line:before { +.repository.view.issue .comment-list .timeline:before { background-color: #3b4954; } +.repository.view.issue .comment-list .timeline-item .badge { + background-color: #383c4a; + border-color: #3b4954; + color: #9e9e9e; +} + .repository .comment.form .content .form:after { border-right-color: #313c47; } From 1a6ba1b977f19081399ee42d202aa407b975c2d8 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 11 Apr 2020 01:49:39 +0200 Subject: [PATCH 034/550] [Api] Check Notify (always return json) (#10059) * BEAKING: check return status based on struct not httpStatus * update Tests * CI.restart() --- integrations/api_notification_test.go | 10 +++++++++- routers/api/v1/notify/notifications.go | 13 ++----------- templates/swagger/v1_json.tmpl | 3 --- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/integrations/api_notification_test.go b/integrations/api_notification_test.go index baab00f6d29bb..3296604a081fc 100644 --- a/integrations/api_notification_test.go +++ b/integrations/api_notification_test.go @@ -81,9 +81,15 @@ func TestAPINotification(t *testing.T) { assert.EqualValues(t, thread5.Issue.APIURL(), apiN.Subject.URL) assert.EqualValues(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL) + new := struct { + New int64 `json:"new"` + }{} + // -- check notifications -- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/new?token=%s", token)) resp = session.MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &new) + assert.True(t, new.New > 0) // -- mark notifications as read -- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications?token=%s", token)) @@ -110,5 +116,7 @@ func TestAPINotification(t *testing.T) { // -- check notifications -- req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/notifications/new?token=%s", token)) - resp = session.MakeRequest(t, req, http.StatusNoContent) + resp = session.MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &new) + assert.True(t, new.New == 0) } diff --git a/routers/api/v1/notify/notifications.go b/routers/api/v1/notify/notifications.go index 847fe3313e0d5..71dd7d949267f 100644 --- a/routers/api/v1/notify/notifications.go +++ b/routers/api/v1/notify/notifications.go @@ -19,15 +19,6 @@ func NewAvailable(ctx *context.APIContext) { // summary: Check if unread notifications exist // responses: // "200": - // "$ref": "#/responses/NotificationCount" - // "204": - // description: No unread notification - - count := models.CountUnread(ctx.User) - - if count > 0 { - ctx.JSON(http.StatusOK, api.NotificationCount{New: count}) - } else { - ctx.Status(http.StatusNoContent) - } + // "$ref": "#/responses/NotificationCount" + ctx.JSON(http.StatusOK, api.NotificationCount{New: models.CountUnread(ctx.User)}) } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 8591381ef4a7b..8b10a759901d3 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -530,9 +530,6 @@ "responses": { "200": { "$ref": "#/responses/NotificationCount" - }, - "204": { - "description": "No unread notification" } } } From fab984b914e5dcceaf5cca34430f0bbb6bf5a617 Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Sat, 11 Apr 2020 10:13:31 +0700 Subject: [PATCH 035/550] [Docs] Cross Build Gitea from Source (#10999) * Add cross-build docs Note that C cross compiler is required for building Gitea with `TAGS`. * Apply suggestion from @mrsdizzie Co-Authored-By: mrsdizzie * Apply suggestion from @guillep2k Co-Authored-By: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-authored-by: Lunny Xiao Co-authored-by: mrsdizzie Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> Co-authored-by: John Olheiser --- .../doc/installation/from-source.en-us.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/content/doc/installation/from-source.en-us.md b/docs/content/doc/installation/from-source.en-us.md index 2089a5df39148..d70e000352b86 100644 --- a/docs/content/doc/installation/from-source.en-us.md +++ b/docs/content/doc/installation/from-source.en-us.md @@ -157,3 +157,23 @@ Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable a with the appropriate `TAGS` as above. Running `gitea help` will allow you to review what the computed settings will be for your `gitea`. + +## Cross Build + +The `go` compiler toolchain supports cross-compiling to different architecture targets that are supported by the toolchain. See [`GOOS` and `GOARCH` environment variable](https://golang.org/doc/install/source#environment) for the list of supported targets. Cross compilation is helpful if you want to build Gitea for less-powerful systems (such as Raspberry Pi). + +To cross build Gitea with build tags (`TAGS`), you also need a C cross compiler which targets the same architecture as selected by the `GOOS` and `GOARCH` variables. For example, to cross build for Linux ARM64 (`GOOS=linux` and `GOARCH=arm64`), you need the `aarch64-unknown-linux-gnu-gcc` cross compiler. This is required because Gitea build tags uses `cgo`'s foreign-function interface (FFI). + +Cross-build Gitea for Linux ARM64, without any tags: + +``` +GOOS=linux GOARCH=arm64 make build +``` + +Cross-build Gitea for Linux ARM64, with recommended build tags: + +``` +CC=aarch64-unknown-linux-gnu-gcc GOOS=linux GOARCH=arm64 TAGS="bindata sqlite sqlite_unlock_notify" make build +``` + +Replace `CC`, `GOOS`, and `GOARCH` as appropriate for your architecture target. From 04dce08b8eedacde6d5e2a98f312df65413fb223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com> Date: Sat, 11 Apr 2020 12:44:50 +0800 Subject: [PATCH 036/550] Fix CreateComment for SQLite and JS click event on Request Review (#11040) * fix some bug about Request review * fix ``CreateComment`` wrong using ,it will not work when use Sqlite * fix wrong js click event code , it will send wrong data when it has many choices Signed-off-by: a1012112796 <1012112796@qq.com> * Apply suggestions from code review Co-Authored-By: Lauris BH * add getReviewerByIssueIDAndUserID fix wrong conditions check in initIssueComments after #10972 * call CI again Co-authored-by: Lauris BH Co-authored-by: techknowlogick Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- models/review.go | 10 +++++++--- web_src/js/index.js | 18 +++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/models/review.go b/models/review.go index 3f7223154e627..d6bb77925eb57 100644 --- a/models/review.go +++ b/models/review.go @@ -395,9 +395,13 @@ func GetReviewersByIssueID(issueID int64) (reviews []*Review, err error) { // GetReviewerByIssueIDAndUserID get the latest review of reviewer for a pull request func GetReviewerByIssueIDAndUserID(issueID, userID int64) (review *Review, err error) { + return getReviewerByIssueIDAndUserID(x, issueID, userID) +} + +func getReviewerByIssueIDAndUserID(e Engine, issueID, userID int64) (review *Review, err error) { review = new(Review) - if _, err := x.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_id = ? AND type in (?, ?, ?))", + if _, err := e.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_id = ? AND type in (?, ?, ?))", issueID, userID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). Get(review); err != nil { return nil, err @@ -559,7 +563,7 @@ func RemoveRewiewRequest(issue *Issue, reviewer *User, doer *User) (comment *Com // recalculate which is the latest official review from that user var review *Review - review, err = GetReviewerByIssueIDAndUserID(issue.ID, reviewer.ID) + review, err = getReviewerByIssueIDAndUserID(sess, issue.ID, reviewer.ID) if err != nil { return nil, err } @@ -575,7 +579,7 @@ func RemoveRewiewRequest(issue *Issue, reviewer *User, doer *User) (comment *Com return nil, err } - comment, err = CreateComment(&CreateCommentOptions{ + comment, err = createComment(sess, &CreateCommentOptions{ Type: CommentTypeReviewRequest, Doer: doer, Repo: issue.Repo, diff --git a/web_src/js/index.js b/web_src/js/index.js index c56abdde887d1..6476b2cfbf962 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -661,17 +661,21 @@ function initInstall() { } function initIssueComments() { - if ($('.repository.view.issue .comments').length === 0) return; + if ($('.repository.view.issue .timeline').length === 0) return; + + $('.re-request-review').on('click', function (event) { + const url = $(this).data('update-url'); + const issueId = $(this).data('issue-id'); + const id = $(this).data('id'); + const isChecked = $(this).data('is-checked'); - $('.re-request-review').click((event) => { - const $this = $('.re-request-review'); event.preventDefault(); updateIssuesMeta( - $this.data('update-url'), + url, '', - $this.data('issue-id'), - $this.data('id'), - $this.data('is-checked') + issueId, + id, + isChecked ).then(reload); }); From 016e043c267e505f7bd588e7d5b3c2200a4ea778 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sat, 11 Apr 2020 17:59:29 +0200 Subject: [PATCH 037/550] Tweak app.ini.sample (#11042) Few misc tweaks to the sample config --- custom/conf/app.ini.sample | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index f83f06bc6050e..86224ab8c6920 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -1,4 +1,3 @@ - ; This file lists the default values used by Gitea ; Copy required sections to your own app.ini (default is custom/conf/app.ini) ; and modify as needed. @@ -221,6 +220,7 @@ ROOT_URL = %(PROTOCOL)s://%(DOMAIN)s:%(HTTP_PORT)s/ STATIC_URL_PREFIX = ; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket. HTTP_ADDR = 0.0.0.0 +; The port to listen on. Leave empty when using a unix socket. HTTP_PORT = 3000 ; If REDIRECT_OTHER_PORT is true, and PROTOCOL is set to https an http server ; will be started on PORT_TO_REDIRECT and it will redirect plain, non-secure http requests to the main @@ -335,7 +335,7 @@ RSA = 2048 DSA = 1024 [database] -; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice +; Database to use. Either "mysql", "postgres", "mssql" or "sqlite3". DB_TYPE = mysql HOST = 127.0.0.1:3306 NAME = gitea @@ -713,7 +713,7 @@ ENABLE_FEDERATED_AVATAR = false ENABLED = true ; Path for attachments. Defaults to `data/attachments` PATH = data/attachments -; One or more allowed types, e.g. image/jpeg|image/png +; One or more allowed types, e.g. "image/jpeg|image/png". Use "*/*" for all types. ALLOWED_TYPES = image/jpeg|image/png|application/zip|application/gzip ; Max size of each file. Defaults to 4MB MAX_SIZE = 4 From c4f2d4ae3f2665d6a7ac2c8059e7ff3b591a63b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com> Date: Sun, 12 Apr 2020 04:31:17 +0800 Subject: [PATCH 038/550] fix 404 and 500 image size in small size screen (#11043) do it by define Semantic UI image class Signed-off-by: a1012112796 <1012112796@qq.com> Co-authored-by: techknowlogick --- templates/status/404.tmpl | 2 +- templates/status/500.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/status/404.tmpl b/templates/status/404.tmpl index 6992803113070..bb5ac1d5c66bf 100644 --- a/templates/status/404.tmpl +++ b/templates/status/404.tmpl @@ -1,7 +1,7 @@ {{template "base/head" .}} {{if .IsRepo}}
{{template "repo/header" .}}
{{end}}
-

404

+

404


{{.i18n.Tr "error404" | Safe}} diff --git a/templates/status/500.tmpl b/templates/status/500.tmpl index 191e5929d8799..1dc7061d450d6 100644 --- a/templates/status/500.tmpl +++ b/templates/status/500.tmpl @@ -1,6 +1,6 @@ {{template "base/head" .}}

-

500

+

500


{{if .ErrorMsg}}

An error has occurred :

From 9184fc62128adecb96a2889127d33bd5885be9c6 Mon Sep 17 00:00:00 2001 From: silverwind Date: Sun, 12 Apr 2020 05:50:59 +0200 Subject: [PATCH 039/550] add 'make watch-frontend' and expand docs (#10931) * add 'make watch-frontend' and expand docs * add bindata note * add .PHONY Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- Makefile | 5 +++++ .../doc/advanced/hacking-on-gitea.en-us.md | 22 +++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index bb328b4f10a7c..f6d24be085893 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,7 @@ help: @echo " - lint lint everything" @echo " - lint-frontend lint frontend files" @echo " - lint-backend lint backend files" + @echo " - watch-frontend watch frontend files and continuously rebuild" @echo " - webpack build webpack files" @echo " - fomantic build fomantic files" @echo " - generate run \"go generate\"" @@ -275,6 +276,10 @@ lint-frontend: node_modules npx eslint web_src/js webpack.config.js npx stylelint web_src/less +.PHONY: watch-frontend +watch-frontend: node_modules + NODE_ENV=development npx webpack --hide-modules --display-entrypoints=false --watch + .PHONY: test test: $(GO) test $(GOTESTFLAGS) -mod=vendor -tags='sqlite sqlite_unlock_notify' $(GO_PACKAGES) diff --git a/docs/content/doc/advanced/hacking-on-gitea.en-us.md b/docs/content/doc/advanced/hacking-on-gitea.en-us.md index 902bf8473f0fc..31574d0a1849f 100644 --- a/docs/content/doc/advanced/hacking-on-gitea.en-us.md +++ b/docs/content/doc/advanced/hacking-on-gitea.en-us.md @@ -128,10 +128,28 @@ make revive vet misspell-check ### Working on JS and CSS -Edit files in `web_src` and run the linter and build the files in `public`: +For simple changes, edit files in `web_src`, run the build and start the server to test: ```bash -make webpack +make build && ./gitea +``` + +For more involved changes use the `watch-frontend` task to continuously rebuild files when their sources change. The `bindata` tag must be absent to ensure the file system will be used for files in `public`. First, build and run the backend: + +```bash +make backend && ./gitea +``` + +With the backend running, open another terminal and run: + +```bash +make watch-frontend +``` + +Before committing, make sure the linters pass: + +```bash +make lint-frontend ``` Note: When working on frontend code, it is advisable to set `USE_SERVICE_WORKER` to `false` in `app.ini` which will prevent undesirable caching of frontend assets. From bc44b7b1922ed29a9c7c413f28a5337cf27629a2 Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 13 Apr 2020 15:02:31 +0200 Subject: [PATCH 040/550] Move syntax highlighting to web worker (#11017) This should eliminate page freezes when loading big files/diff. `highlightBlock` is needed to preserve existing nodes when highlighting and for that, highlight.js needs access to the DOM API so I added a DOM implementation to make it work, which adds around 300kB to the output file size of the lazy-loaded `highlight.js`. Co-authored-by: Lauris BH --- .eslintrc | 7 +++++++ package-lock.json | 25 +++++++++++++++++++++++++ package.json | 4 +++- web_src/js/features/highlight.js | 23 +++++++++++++++-------- web_src/js/features/highlight.worker.js | 12 ++++++++++++ web_src/js/index.js | 15 +++++++-------- webpack.config.js | 14 ++++++++++++++ 7 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 web_src/js/features/highlight.worker.js diff --git a/.eslintrc b/.eslintrc index 76e6f8c48dfa3..8fd53d54a183b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -24,6 +24,13 @@ globals: SimpleMDE: false u2fApi: false +overrides: + - files: ["web_src/**/*.worker.js"] + env: + worker: true + rules: + no-restricted-globals: [0] + rules: arrow-body-style: [0] arrow-parens: [2, always] diff --git a/package-lock.json b/package-lock.json index 6f1f73245df11..f0f7d080173fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3659,6 +3659,11 @@ "domelementtype": "1" } }, + "domino": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.4.tgz", + "integrity": "sha512-l70mlQ7IjPKC8kT7GljQXJZmt5OqFL+RE91ik5y5WWQtsd9wP8R7gpFnNu96fK5MqAAZRXfLLsnzKtkty5fWGQ==" + }, "dompurify": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.8.tgz", @@ -15008,6 +15013,26 @@ "errno": "~0.1.7" } }, + "worker-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", + "requires": { + "loader-utils": "^1.0.0", + "schema-utils": "^0.4.0" + }, + "dependencies": { + "schema-utils": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, "wrap-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", diff --git a/package.json b/package.json index abb04356a2d6e..88360b6b6ffeb 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "core-js": "3.6.4", "css-loader": "3.4.2", "cssnano": "4.1.10", + "domino": "2.1.4", "dropzone": "5.7.0", "fast-glob": "3.2.2", "fomantic-ui": "2.8.4", @@ -44,7 +45,8 @@ "vue-template-compiler": "2.6.11", "webpack": "4.42.0", "webpack-cli": "3.3.11", - "webpack-fix-style-only-entries": "0.4.0" + "webpack-fix-style-only-entries": "0.4.0", + "worker-loader": "2.0.0" }, "devDependencies": { "eslint": "6.8.0", diff --git a/web_src/js/features/highlight.js b/web_src/js/features/highlight.js index dcd8a8d21e5ca..d3f6ba71b8034 100644 --- a/web_src/js/features/highlight.js +++ b/web_src/js/features/highlight.js @@ -1,12 +1,19 @@ -export default async function initHighlight() { - if (!window.config || !window.config.HighlightJS) return; +export default async function highlight(elementOrNodeList) { + if (!window.config || !window.config.HighlightJS || !elementOrNodeList) return; + const nodes = 'length' in elementOrNodeList ? elementOrNodeList : [elementOrNodeList]; + if (!nodes.length) return; - const hljs = await import(/* webpackChunkName: "highlight" */'highlight.js'); + const {default: Worker} = await import(/* webpackChunkName: "highlight" */'./highlight.worker.js'); + const worker = new Worker(); - const nodes = [].slice.call(document.querySelectorAll('pre code') || []); - for (let i = 0; i < nodes.length; i++) { - hljs.highlightBlock(nodes[i]); - } + worker.addEventListener('message', ({data}) => { + const {index, html} = data; + nodes[index].outerHTML = html; + }); - return hljs; + for (let index = 0; index < nodes.length; index++) { + const node = nodes[index]; + if (!node) continue; + worker.postMessage({index, html: node.outerHTML}); + } } diff --git a/web_src/js/features/highlight.worker.js b/web_src/js/features/highlight.worker.js new file mode 100644 index 0000000000000..7d6cc4e4381d8 --- /dev/null +++ b/web_src/js/features/highlight.worker.js @@ -0,0 +1,12 @@ +import {highlightBlock} from 'highlight.js'; +import {createWindow} from 'domino'; + +self.onmessage = function ({data}) { + const window = createWindow(); + self.document = window.document; + + const {index, html} = data; + document.body.innerHTML = html; + highlightBlock(document.body.firstChild); + self.postMessage({index, html: document.body.innerHTML}); +}; diff --git a/web_src/js/index.js b/web_src/js/index.js index 6476b2cfbf962..63a5134bbd5bf 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -11,12 +11,12 @@ import './vendor/semanticdropdown.js'; import {svg} from './utils.js'; import initContextPopups from './features/contextpopup.js'; -import initHighlight from './features/highlight.js'; import initGitGraph from './features/gitgraph.js'; import initClipboard from './features/clipboard.js'; import initUserHeatmap from './features/userheatmap.js'; import initDateTimePicker from './features/datetimepicker.js'; import createDropzone from './features/dropzone.js'; +import highlight from './features/highlight.js'; import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; @@ -29,7 +29,6 @@ let previewFileModes; let simpleMDEditor; const commentMDEditors = {}; let codeMirrorEditor; -let hljs; // Silence fomantic's error logging when tabs are used without a target content element $.fn.tab.settings.silent = true; @@ -49,7 +48,7 @@ function initCommentPreviewTab($form) { $previewPanel.html(data); emojify.run($previewPanel[0]); $('pre code', $previewPanel[0]).each(function () { - hljs.highlightBlock(this); + highlight(this); }); }); }); @@ -75,7 +74,7 @@ function initEditPreviewTab($form) { $previewPanel.html(data); emojify.run($previewPanel[0]); $('pre code', $previewPanel[0]).each(function () { - hljs.highlightBlock(this); + highlight(this); }); }); }); @@ -1011,7 +1010,7 @@ async function initRepository() { $renderContent.html(data.content); emojify.run($renderContent[0]); $('pre code', $renderContent[0]).each(function () { - hljs.highlightBlock(this); + highlight(this); }); } const $content = $segment.parent(); @@ -1337,7 +1336,7 @@ function initWikiForm() { preview.innerHTML = `
${data}
`; emojify.run($('.editor-preview')[0]); $(preview).find('pre code').each((_, e) => { - hljs.highlightBlock(e); + highlight(e); }); }); }; @@ -2633,8 +2632,8 @@ $(document).ready(async () => { }); // parallel init of lazy-loaded features - [hljs] = await Promise.all([ - initHighlight(), + await Promise.all([ + highlight(document.querySelectorAll('pre code')), initGitGraph(), initClipboard(), initUserHeatmap(), diff --git a/webpack.config.js b/webpack.config.js index 57a41a11a7704..77680cb3797e8 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -51,6 +51,7 @@ module.exports = { sourceMap: true, extractComments: false, terserOptions: { + keep_fnames: /^(HTML|SVG)/, // https://github.com/fgnass/domino/issues/144 output: { comments: false, }, @@ -89,6 +90,19 @@ module.exports = { test: require.resolve('jquery-datetimepicker'), use: 'imports-loader?define=>false,exports=>false', }, + { + test: /\.worker\.js$/, + use: [ + { + loader: 'worker-loader', + options: { + name: '[name].js', + inline: true, + fallback: false, + }, + }, + ], + }, { test: /\.js$/, exclude: /node_modules/, From 6baa02766e1a31186f875d7e13fd0c78424d8d24 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 13 Apr 2020 13:03:35 +0000 Subject: [PATCH 041/550] [skip ci] Updated translations via Crowdin --- options/locale/locale_ja-JP.ini | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 65333293a828f..d67d06f4f3032 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -459,6 +459,7 @@ add_email=メールアドレスを追加 add_openid=OpenID URIを追加する add_email_confirmation_sent='%s' に確認メールを送信しました。 %s以内に受信トレイを確認し、メールアドレス確認を行ってください。 add_email_success=新しいメールアドレスを追加しました。 +email_preference_set_success=メール設定を保存しました。 add_openid_success=新しいOpenIDアドレスを追加しました。 keep_email_private=メールアドレスを隠す keep_email_private_popup=あなたのメールアドレスは他のユーザーから隠されます。 @@ -826,6 +827,7 @@ issues.desc=バグ報告、タスク、マイルストーンの作成。 issues.filter_assignees=候補者の絞り込み issues.filter_milestones=マイルストーンの絞り込み issues.filter_labels=ラベルの絞り込み +issues.filter_reviewers=レビューアの絞り込み issues.new=新しい課題 issues.new.title_empty=タイトルは空にできません issues.new.labels=ラベル @@ -843,7 +845,9 @@ issues.new.assignees=担当者 issues.new.add_assignees_title=担当者の割り当て issues.new.clear_assignees=担当者をクリア issues.new.no_assignees=担当者なし -issues.no_ref=ブランチ/タグが指定されていません +issues.new.no_reviewers=レビューアなし +issues.new.add_reviewer_title=レビュー依頼 +issues.no_ref=ブランチ/タグ指定なし issues.create=課題を作成 issues.new_label=新しいラベル issues.new_label_placeholder=ラベル名 @@ -936,6 +940,9 @@ issues.ref_from=` %[1]s にて` issues.poster=投稿者 issues.collaborator=共同作業者 issues.owner=オーナー +issues.re_request_review=レビューを再依頼 +issues.remove_request_review=レビュー依頼を取り消し +issues.remove_request_review_block=レビュー依頼の取り消しはできません issues.sign_in_require_desc=
サインインしてこの会話に参加。 issues.edit=編集 issues.cancel=キャンセル @@ -1045,8 +1052,13 @@ issues.review.self.approval=自分のプルリクエストを承認すること issues.review.self.rejection=自分のプルリクエストに対して修正を要求することはできません。 issues.review.approve=が変更を承認 %s issues.review.comment=がレビュー %s +issues.review.left_comment=がコメント issues.review.content.empty=修正を指示するコメントを残す必要があります。 issues.review.reject=が変更を要請 %s +issues.review.wait=にレビュー依頼 %s +issues.review.add_review_request=が %s にレビューを依頼 %s +issues.review.remove_review_request=が %s へのレビュー依頼を取り消し %s +issues.review.remove_review_request_self=がレビューを拒否 %s issues.review.pending=保留 issues.review.review=レビュー issues.review.reviewers=レビューア @@ -1095,6 +1107,8 @@ pulls.approve_count_1=承認 %d pulls.approve_count_n=承認 %d pulls.reject_count_1=変更要請 %d pulls.reject_count_n=変更要請 %d +pulls.waiting_count_1=レビュー待ち %d +pulls.waiting_count_n=レビュー待ち %d pulls.no_merge_desc=リポジトリのマージオプションがすべて無効になっているため、このプルリクエストをマージすることはできせん。 pulls.no_merge_helper=リポジトリ設定でマージを有効にするか、手動でマージしてください。 From ab84e824aa590fe996db1494b8f78091e3c13ca9 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 13 Apr 2020 21:02:48 +0200 Subject: [PATCH 042/550] Reject duplicate AccessToken names (#10994) * make sure duplicate token names cannot be used * add check to api routes too * add @lunny s suggestion * fix & don't forget User.ID * AccessTokenByNameExists() return error too * unique token for each test * fix lint Signed-off-by: 6543 <6543@obermui.de> Co-authored-by: Lanre Adelowo --- integrations/integration_test.go | 6 ++++- models/token.go | 5 ++++ models/token_test.go | 36 ++++++++++++++++++++++++++++ options/locale/locale_en-US.ini | 1 + routers/api/v1/user/app.go | 12 ++++++++++ routers/user/setting/applications.go | 12 ++++++++++ 6 files changed, 71 insertions(+), 1 deletion(-) diff --git a/integrations/integration_test.go b/integrations/integration_test.go index 138d751859d5a..c6a4169751b5c 100644 --- a/integrations/integration_test.go +++ b/integrations/integration_test.go @@ -330,14 +330,18 @@ func loginUserWithPassword(t testing.TB, userName, password string) *TestSession return session } +//token has to be unique this counter take care of +var tokenCounter int64 + func getTokenForLoggedInUser(t testing.TB, session *TestSession) string { t.Helper() + tokenCounter++ req := NewRequest(t, "GET", "/user/settings/applications") resp := session.MakeRequest(t, req, http.StatusOK) doc := NewHTMLParser(t, resp.Body) req = NewRequestWithValues(t, "POST", "/user/settings/applications", map[string]string{ "_csrf": doc.GetCSRF(), - "name": "api-testing-token", + "name": fmt.Sprintf("api-testing-token-%d", tokenCounter), }) resp = session.MakeRequest(t, req, http.StatusFound) req = NewRequest(t, "GET", "/user/settings/applications") diff --git a/models/token.go b/models/token.go index 7ad9d41676efc..71a9f0975fc5b 100644 --- a/models/token.go +++ b/models/token.go @@ -77,6 +77,11 @@ func GetAccessTokenBySHA(token string) (*AccessToken, error) { return nil, ErrAccessTokenNotExist{token} } +// AccessTokenByNameExists checks if a token name has been used already by a user. +func AccessTokenByNameExists(token *AccessToken) (bool, error) { + return x.Table("access_token").Where("name = ?", token.Name).And("uid = ?", token.UID).Exist() +} + // ListAccessTokens returns a list of access tokens belongs to given user. func ListAccessTokens(uid int64, listOptions ListOptions) ([]*AccessToken, error) { sess := x. diff --git a/models/token_test.go b/models/token_test.go index 45f50a1b82663..572a5de609d67 100644 --- a/models/token_test.go +++ b/models/token_test.go @@ -27,6 +27,42 @@ func TestNewAccessToken(t *testing.T) { assert.Error(t, NewAccessToken(invalidToken)) } +func TestAccessTokenByNameExists(t *testing.T) { + + name := "Token Gitea" + + assert.NoError(t, PrepareTestDatabase()) + token := &AccessToken{ + UID: 3, + Name: name, + } + + // Check to make sure it doesn't exists already + exist, err := AccessTokenByNameExists(token) + assert.NoError(t, err) + assert.False(t, exist) + + // Save it to the database + assert.NoError(t, NewAccessToken(token)) + AssertExistsAndLoadBean(t, token) + + // This token must be found by name in the DB now + exist, err = AccessTokenByNameExists(token) + assert.NoError(t, err) + assert.True(t, exist) + + user4Token := &AccessToken{ + UID: 4, + Name: name, + } + + // Name matches but different user ID, this shouldn't exists in the + // database + exist, err = AccessTokenByNameExists(user4Token) + assert.NoError(t, err) + assert.False(t, exist) +} + func TestGetAccessTokenBySHA(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) token, err := GetAccessTokenBySHA("d2c6c1ba3890b309189a8e618c72a162e4efbf36") diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index a565a754af1c7..9a1a458f662c4 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -517,6 +517,7 @@ new_token_desc = Applications using a token have full access to your account. token_name = Token Name generate_token = Generate Token generate_token_success = Your new token has been generated. Copy it now as it will not be shown again. +generate_token_name_duplicate = %s has been used as an application name already. Please use a new one. delete_token = Delete access_token_deletion = Delete Access Token access_token_deletion_desc = Deleting a token will revoke access to your account for applications using it. Continue? diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go index 9ec506bcf2494..f29572ef62124 100644 --- a/routers/api/v1/user/app.go +++ b/routers/api/v1/user/app.go @@ -6,6 +6,7 @@ package user import ( + "errors" "net/http" "code.gitea.io/gitea/models" @@ -89,6 +90,17 @@ func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption UID: ctx.User.ID, Name: form.Name, } + + exist, err := models.AccessTokenByNameExists(t) + if err != nil { + ctx.InternalServerError(err) + return + } + if exist { + ctx.Error(http.StatusBadRequest, "AccessTokenByNameExists", errors.New("access token name has been used already")) + return + } + if err := models.NewAccessToken(t); err != nil { ctx.Error(http.StatusInternalServerError, "NewAccessToken", err) return diff --git a/routers/user/setting/applications.go b/routers/user/setting/applications.go index e7bf6122697a9..febb5b0c19b34 100644 --- a/routers/user/setting/applications.go +++ b/routers/user/setting/applications.go @@ -43,6 +43,18 @@ func ApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) { UID: ctx.User.ID, Name: form.Name, } + + exist, err := models.AccessTokenByNameExists(t) + if err != nil { + ctx.ServerError("AccessTokenByNameExists", err) + return + } + if exist { + ctx.Flash.Error(ctx.Tr("settings.generate_token_name_duplicate", t.Name)) + ctx.Redirect(setting.AppSubURL + "/user/settings/applications") + return + } + if err := models.NewAccessToken(t); err != nil { ctx.ServerError("NewAccessToken", err) return From be102e537390113e6071d7316a34713056399dfa Mon Sep 17 00:00:00 2001 From: silverwind Date: Mon, 13 Apr 2020 22:00:32 +0200 Subject: [PATCH 043/550] Fix language label vertical alignment (#11061) Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- templates/explore/code.tmpl | 2 +- templates/repo/search.tmpl | 2 +- web_src/less/_base.less | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/templates/explore/code.tmpl b/templates/explore/code.tmpl index 418d669fe985a..43b44af4bfddc 100644 --- a/templates/explore/code.tmpl +++ b/templates/explore/code.tmpl @@ -18,7 +18,7 @@
{{range $term := .SearchResultLanguages}} - + {{$term.Language}}
{{$term.Count}}
diff --git a/templates/repo/search.tmpl b/templates/repo/search.tmpl index 5aa2f8983e0d1..984b3fe9e5523 100644 --- a/templates/repo/search.tmpl +++ b/templates/repo/search.tmpl @@ -18,7 +18,7 @@
{{range $term := .SearchResultLanguages}} - + {{$term.Language}}
{{$term.Count}}
diff --git a/web_src/less/_base.less b/web_src/less/_base.less index ba3bbff369ad5..1c5626be0b25d 100644 --- a/web_src/less/_base.less +++ b/web_src/less/_base.less @@ -1228,3 +1228,12 @@ i.icon.centerlock { overflow-x: hidden; text-overflow: ellipsis; } + +.language-label { + display: inline-flex !important; + align-items: center !important; +} + +.language-label .color-icon { + position: static !important; +} From 78f3a15426957a7679e60b68f2f957e5825cb3b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com> Date: Tue, 14 Apr 2020 09:06:23 +0800 Subject: [PATCH 044/550] ui: Add MergePull comment type instead of close for merge PR (#11058) Signed-off-by: a1012112796 <1012112796@qq.com> Co-authored-by: Lauris BH --- models/issue.go | 6 ++++-- models/issue_comment.go | 2 ++ models/pull.go | 2 +- options/locale/locale_en-US.ini | 1 + templates/repo/issue/view_content/comments.tmpl | 14 +++++++++++++- 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/models/issue.go b/models/issue.go index ba211e9670dc5..17ec0a6888d39 100644 --- a/models/issue.go +++ b/models/issue.go @@ -554,7 +554,7 @@ func updateIssueCols(e Engine, issue *Issue, cols ...string) error { return nil } -func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (*Comment, error) { +func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed, isMergePull bool) (*Comment, error) { // Reload the issue currentIssue, err := getIssueByID(e, issue.ID) if err != nil { @@ -620,6 +620,8 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (*C cmtType := CommentTypeClose if !issue.IsClosed { cmtType = CommentTypeReopen + } else if isMergePull { + cmtType = CommentTypeMergePull } return createComment(e, &CreateCommentOptions{ @@ -645,7 +647,7 @@ func (issue *Issue) ChangeStatus(doer *User, isClosed bool) (*Comment, error) { return nil, err } - comment, err := issue.changeStatus(sess, doer, isClosed) + comment, err := issue.changeStatus(sess, doer, isClosed, false) if err != nil { return nil, err } diff --git a/models/issue_comment.go b/models/issue_comment.go index f522604afcaf5..2e59a2cb3f156 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -88,6 +88,8 @@ const ( CommentTypeDeleteTimeManual // add or remove Request from one CommentTypeReviewRequest + // merge pull request + CommentTypeMergePull ) // CommentTag defines comment tag type diff --git a/models/pull.go b/models/pull.go index 02b5e98c49319..055f9bbc6e5e7 100644 --- a/models/pull.go +++ b/models/pull.go @@ -390,7 +390,7 @@ func (pr *PullRequest) SetMerged() (bool, error) { return false, err } - if _, err := pr.Issue.changeStatus(sess, pr.Merger, true); err != nil { + if _, err := pr.Issue.changeStatus(sess, pr.Merger, true, true); err != nil { return false, fmt.Errorf("Issue.changeStatus: %v", err) } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 9a1a458f662c4..8b43115c07a3b 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -925,6 +925,7 @@ issues.context.edit = Edit issues.context.delete = Delete issues.no_content = There is no content yet. issues.close_issue = Close +issues.pull_merged_at = `merged commit
%[2]s into %[3]s %[4]s` issues.close_comment_issue = Comment and Close issues.reopen_issue = Reopen issues.reopen_comment_issue = Comment and Reopen diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index dc7d2db3c6113..da1483ec37008 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -7,7 +7,7 @@ 13 = STOP_TRACKING, 14 = ADD_TIME_MANUAL, 16 = ADDED_DEADLINE, 17 = MODIFIED_DEADLINE, 18 = REMOVED_DEADLINE, 19 = ADD_DEPENDENCY, 20 = REMOVE_DEPENDENCY, 21 = CODE, 22 = REVIEW, 23 = ISSUE_LOCKED, 24 = ISSUE_UNLOCKED, 25 = TARGET_BRANCH_CHANGED, - 26 = DELETE_TIME_MANUAL, 27 = REVIEW_REQUEST --> + 26 = DELETE_TIME_MANUAL, 27 = REVIEW_REQUEST, 28 = MERGE_PULL_REQUEST --> {{if eq .Type 0}}
{{if .OriginalAuthor }} @@ -84,6 +84,18 @@ {{.Poster.GetDisplayName}} {{$.i18n.Tr "repo.issues.closed_at" .EventTag $createdStr | Safe}}
+ {{else if eq .Type 28}} +
+ {{svg "octicon-git-merge" 16}} + + + + + {{.Poster.GetDisplayName}} + {{$link := printf "%s/commit/%s" $.Repository.HTMLURL $.Issue.PullRequest.MergedCommitID}} + {{$.i18n.Tr "repo.issues.pull_merged_at" $link (ShortSha $.Issue.PullRequest.MergedCommitID) $.BaseTarget $createdStr | Str2html}} + +
{{else if eq .Type 3 5 6}} {{ $refFrom:= "" }} {{if ne .RefRepoID .Issue.RepoID}} From d203290cba5c35d9fd5a8f94f349c029a9c3f8b2 Mon Sep 17 00:00:00 2001 From: maxm123 Date: Tue, 14 Apr 2020 04:55:20 +0200 Subject: [PATCH 045/550] Add charset handling to backup/restore doc (#11062) Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- docs/content/doc/usage/backup-and-restore.en-us.md | 2 +- docs/content/doc/usage/backup-and-restore.zh-cn.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/doc/usage/backup-and-restore.en-us.md b/docs/content/doc/usage/backup-and-restore.en-us.md index a3887bc64a632..cefdf5d3da48d 100644 --- a/docs/content/doc/usage/backup-and-restore.en-us.md +++ b/docs/content/doc/usage/backup-and-restore.en-us.md @@ -75,7 +75,7 @@ mv custom/conf/app.ini /etc/gitea/conf/app.ini # or mv app.ini /etc/gitea/conf/a unzip gitea-repo.zip mv gitea-repo/* /var/lib/gitea/repositories/ chown -R gitea:gitea /etc/gitea/conf/app.ini /var/lib/gitea/repositories/ -mysql -u$USER -p$PASS $DATABASE Date: Tue, 14 Apr 2020 19:37:10 +0800 Subject: [PATCH 046/550] ui: Change icon on title for merged PR to git-merge (#11064) Signed-off-by: a1012112796 <1012112796@qq.com> --- templates/repo/issue/view_title.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl index 4a6eefa4c4222..db048a119caa8 100644 --- a/templates/repo/issue/view_title.tmpl +++ b/templates/repo/issue/view_title.tmpl @@ -17,7 +17,7 @@ {{end}}
{{if .HasMerged}} -
{{svg "octicon-git-pull-request" 16}} {{.i18n.Tr "repo.pulls.merged"}}
+
{{svg "octicon-git-merge" 16}} {{.i18n.Tr "repo.pulls.merged"}}
{{else if .Issue.IsClosed}}
{{svg "octicon-issue-closed" 16}} {{.i18n.Tr "repo.issues.closed_title"}}
{{else if .Issue.IsPull}} From 241136632c8a940654b47a0603a0e1ff6d613745 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Tue, 14 Apr 2020 11:38:33 +0000 Subject: [PATCH 047/550] [skip ci] Updated translations via Crowdin --- options/locale/locale_es-ES.ini | 20 ++++++ options/locale/locale_pt-PT.ini | 110 ++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 6 deletions(-) diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 8e31d773d1ffa..1b153cff6a21e 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -821,19 +821,28 @@ ext_issues=Incidencias externas ext_issues.desc=Enlace a un gestor de incidencias externo. issues.desc=Organizar los informes de fallos, tareas e hitos. +issues.filter_milestones=Filtrar hito +issues.filter_labels=Filtrar etiqueta +issues.filter_reviewers=Filtrar revisor issues.new=Nueva incidencia issues.new.title_empty=El título no puede estar vacío issues.new.labels=Etiquetas +issues.new.add_labels_title=Aplicar etiquetas issues.new.no_label=Sin etiquetas issues.new.clear_labels=Limpiar etiquetas +issues.new.no_items=No hay elementos issues.new.milestone=Milestone +issues.new.add_milestone_title=Fijar hito issues.new.no_milestone=Sin Milestone issues.new.clear_milestone=Limpiar Milestone issues.new.open_milestone=Milestones abiertas issues.new.closed_milestone=Milestones cerradas issues.new.assignees=Asignados +issues.new.add_assignees_title=Asignar usuarios issues.new.clear_assignees=Limpiar asignados issues.new.no_assignees=No asignados +issues.new.no_reviewers=No hay revisores +issues.new.add_reviewer_title=Solicitar revisión issues.no_ref=Ninguna Rama/Etiqueta especificada issues.create=Crear incidencia issues.new_label=Nueva Etiqueta @@ -894,7 +903,9 @@ issues.action_assignee_no_select=Sin asignado issues.opened_by=abierta %[1]s por %[3]s pulls.merged_by=fusionado %[1]s por %[3]s pulls.merged_by_fake=fusionado %[1]s por %[2]s +issues.closed_by=por %[3]s cerrado %[1]s issues.opened_by_fake=abierta %[1]s por %[2]s +issues.closed_by_fake=por %[2]s cerrado %[1]s issues.previous=Página Anterior issues.next=Página Siguiente issues.open_title=Abierta @@ -925,6 +936,9 @@ issues.ref_from=`de %[1]s` issues.poster=Autor issues.collaborator=Colaborador issues.owner=Propietario +issues.re_request_review=Solicitar revisión de nuevo +issues.remove_request_review=Eliminar solicitud de revisión +issues.remove_request_review_block=No se puede eliminar la solicitud de revisión issues.sign_in_require_desc=Inicie sesión para unirse a esta conversación. issues.edit=Editar issues.cancel=Cancelar @@ -942,6 +956,8 @@ issues.label_deletion_desc=Eliminar una etiqueta la elimina de todos las inciden issues.label_deletion_success=La etiqueta ha sido eliminada. issues.label.filter_sort.alphabetically=Alfabéticamente issues.label.filter_sort.reverse_alphabetically=Invertir alfabéticamente +issues.label.filter_sort.by_size=Tamaño más pequeño +issues.label.filter_sort.reverse_by_size=Tamaño más grande issues.num_participants=%d participantes issues.attachment.open_tab='Haga clic para ver "%s" en una pestaña nueva' issues.attachment.download=`Haga clic para descargar "%s"` @@ -1034,6 +1050,10 @@ issues.review.approve=aprobado estos cambios %s issues.review.comment=revisado %s issues.review.content.empty=Es necesario dejar un comentario indicando los cambios solicitados. issues.review.reject=cambios solicitados %s +issues.review.wait=se solicitó para revisión %s +issues.review.add_review_request=solicitud de revisión de %s %s +issues.review.remove_review_request=solicitud de revisión eliminada para %s %s +issues.review.remove_review_request_self=rechazó revisar %s issues.review.pending=Pendiente issues.review.review=Revisar issues.review.reviewers=Revisores diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 78626337e3333..5ade2fe821f90 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -387,10 +387,60 @@ password=Senha security=Segurança avatar=Avatar ssh_gpg_keys=Chaves SSH / GPG - - - - +social=Contas sociais +applications=Aplicações +orgs=Gerir organizações +repos=Repositórios +delete=Eliminar a conta +twofa=Autenticação em dois passos +account_link=Contas vinculadas +organization=Organizações +uid=Uid +u2f=Chaves de segurança + +public_profile=Perfil público +profile_desc=O seu endereço de email será usado para notificações e outras operações. +password_username_disabled=Utilizadores não-locais não podem mudar os seus nomes de utilizador. Entre em contacto com o administrador do sítio saber para mais detalhes. +full_name=Nome completo +website=Sítio web +location=Localização +update_theme=Substituir tema +update_profile=Modificar perfil +update_profile_success=O seu perfil foi modificado. +change_username=Seu nome de utilizador foi alterado. +change_username_prompt=Nota: alterações do nome de utilizador também alteram o URL de sua conta. +continue=Continuar +cancel=Cancelar +language=Idioma +ui=Tema + +lookup_avatar_by_mail=Procurar avatar com base no endereço de email +federated_avatar_lookup=Pesquisa de avatar federada +enable_custom_avatar=Usar avatar personalizado +choose_new_avatar=Escolher um novo avatar +update_avatar=Substituir avatar +delete_current_avatar=Eliminar o avatar corrente +uploaded_avatar_not_a_image=O ficheiro enviado não é uma imagem. +uploaded_avatar_is_too_big=O ficheiro enviado excedeu o tamanho máximo. +update_avatar_success=O seu avatar foi substituído. + +change_password=Substituir a senha +old_password=Senha corrente +new_password=Nova senha +retype_new_password=Volte a introduzir a nova senha +password_incorrect=A senha corrente está errada. +change_password_success=A sua senha foi substituída. Inicie a sessão com a nova senha a partir de agora. +password_change_disabled=Os utilizadores não-locais não podem alterar a sua senha através da interface web do Gitea. + +emails=Endereços de email +manage_emails=Gerir endereços de email +manage_themes=Escolher o tema padrão +manage_openid=Gerir endereços OpenID +email_desc=O seu endereço de email principal será usado para notificações e outras operações. +theme_desc=Este será o seu tema padrão em todo o sítio. +primary=Principal +activated=Operante +requires_activation=Tem que ser habilitado primary_email=Tornar no principal activate_email=Enviar pedido de verificação activations_pending=Verificações pendentes @@ -555,6 +605,7 @@ repo_name_helper=Um bom nome de repositório utiliza palavras curtas, memorávei repo_size=Tamanho do repositório template=Modelo +template.avatar=Avatar template.issue_labels=Etiquetas das questões template.one_item=Tem que escolher pelo menos um item do modelo template.invalid=Tem que escolher um repositório modelo @@ -714,8 +765,55 @@ commits.message=Mensagem commits.date=Data commits.older=Mais antigos commits.newer=Mais recentes - - +commits.signed_by=Assinados por +commits.signed_by_untrusted_user=Assinado por um utilizador não fiável +commits.signed_by_untrusted_user_unmatched=Assinado por um utilizador não fiável que não corresponde a quem comete +commits.gpg_key_id=ID da chave GPG + +ext_issues=Questões ext. +ext_issues.desc=Ligação para um rastreador de questões externo. + +issues.desc=Organize relatórios de erros, tarefas e etapas. +issues.filter_assignees=Filtrar responsável +issues.filter_milestones=Filtrar etapa +issues.filter_labels=Filtrar etiqueta +issues.filter_reviewers=Filtrar avaliador +issues.new=Nova questão +issues.new.title_empty=O título não pode estar vazio +issues.new.labels=Etiquetas +issues.new.add_labels_title=Aplicar etiquetas +issues.new.no_label=Sem etiquetas +issues.new.clear_labels=Limpar etiquetas +issues.new.no_items=Sem itens +issues.new.milestone=Etapa +issues.new.add_milestone_title=Definir etapa +issues.new.no_milestone=Sem etapa +issues.new.clear_milestone=Limpar etapa +issues.new.open_milestone=Etapas abertas +issues.new.closed_milestone=Etapas fechadas +issues.new.assignees=Responsáveis +issues.new.add_assignees_title=Definir responsáveis +issues.new.clear_assignees=Limpar responsáveis +issues.new.no_assignees=Sem responsáveis +issues.new.no_reviewers=Sem avaliadores +issues.new.add_reviewer_title=Solicitar avaliação +issues.no_ref=Sem ramo ou etiqueta especificados +issues.create=Criar questão +issues.new_label=Nova etiqueta +issues.new_label_placeholder=Nome da etiqueta +issues.new_label_desc_placeholder=Descrição +issues.create_label=Criar etiqueta +issues.label_templates.title=Carregar um conjunto predefinido de etiquetas +issues.label_templates.info=Ainda não existem etiquetas. Crie uma etiqueta com 'Nova etiqueta' ou use um conjunto de etiquetas predefinido: +issues.label_templates.helper=Escolha um conjunto de etiquetas +issues.label_templates.use=Usar conjunto de etiquetas +issues.label_templates.fail_to_load_file=Falha ao carregar o ficheiro modelo de etiquetas '%s': %v +issues.add_label_at=adicionou a etiqueta
%s
%s +issues.remove_label_at=removeu a etiqueta
%s
%s +issues.add_milestone_at=`adicionou esta questão à etapa %s %s` +issues.change_milestone_at=`modificou a etapa de %s para %s %s` +issues.remove_milestone_at=`removeu esta questão da etapa %s %s` +issues.deleted_milestone=`(eliminada)` issues.remove_self_assignment=`removeu a auto-atribuição %s` issues.change_title_at=`mudou o título de %s para %s %s` issues.delete_branch_at=`eliminou o ramo %s %s` From 7c9bf3e8d100cbc65ff0526e4c70fe7a57d03895 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 14 Apr 2020 15:53:34 +0200 Subject: [PATCH 048/550] Cache PullRequest Divergence (#10914) * Cache PullRequest Divergence * only re-calc divergence if AddTestPullRequestTask() is exec * migrate already open pulls * finalize * take care of closed¬-merged+deleted-branch pull requests * fix nil pointer exeption Signed-off-by: 6543 <6543@obermui.de> * try this * no error its a warn * init gitea-repositories-meta * dont use gitDivergence type * CI.restart() * CI.restart() * CI.restart() * CI.restart() * check IsUserAllowedToUpdate independend from CommitsBehind --- integrations/migration-test/migration_test.go | 7 ++ models/migrations/migrations.go | 2 + models/migrations/v136.go | 69 +++++++++++++++++++ models/pull.go | 17 +++++ routers/repo/pull.go | 12 +--- services/pull/pull.go | 25 +++++++ templates/repo/issue/view_content/pull.tmpl | 2 +- 7 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 models/migrations/v136.go diff --git a/integrations/migration-test/migration_test.go b/integrations/migration-test/migration_test.go index a4d01efef3c18..4ee045db38348 100644 --- a/integrations/migration-test/migration_test.go +++ b/integrations/migration-test/migration_test.go @@ -12,6 +12,7 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "regexp" "sort" "strings" @@ -25,6 +26,7 @@ import ( "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" + "github.com/unknwon/com" "xorm.io/xorm" ) @@ -54,6 +56,11 @@ func initMigrationTest(t *testing.T) func() { } setting.NewContext() + + assert.True(t, len(setting.RepoRootPath) != 0) + assert.NoError(t, os.RemoveAll(setting.RepoRootPath)) + assert.NoError(t, com.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"), setting.RepoRootPath)) + setting.CheckLFSVersion() setting.InitDBConfig() setting.NewLogServices(true) diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index cad7f05f15989..e1d46236a9bdf 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -204,6 +204,8 @@ var migrations = []Migration{ NewMigration("Refix merge base for merged pull requests", refixMergeBase), // v135 -> 136 NewMigration("Add OrgID column to Labels table", addOrgIDLabelColumn), + // v136 -> 137 + NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", addCommitDivergenceToPulls), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v136.go b/models/migrations/v136.go new file mode 100644 index 0000000000000..115861f344cce --- /dev/null +++ b/models/migrations/v136.go @@ -0,0 +1,69 @@ +// Copyright 2020 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package migrations + +import ( + "fmt" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + pull_service "code.gitea.io/gitea/services/pull" + + "xorm.io/xorm" +) + +func addCommitDivergenceToPulls(x *xorm.Engine) error { + + if err := x.Sync2(new(models.PullRequest)); err != nil { + return fmt.Errorf("Sync2: %v", err) + } + + var last int + batchSize := setting.Database.IterateBufferSize + sess := x.NewSession() + defer sess.Close() + for { + if err := sess.Begin(); err != nil { + return err + } + var results = make([]*models.PullRequest, 0, batchSize) + err := sess.Where("has_merged = ?", false).OrderBy("id").Limit(batchSize, last).Find(&results) + if err != nil { + return err + } + if len(results) == 0 { + break + } + last += len(results) + + for _, pr := range results { + divergence, err := pull_service.GetDiverging(pr) + if err != nil { + if err = pr.LoadIssue(); err != nil { + return fmt.Errorf("pr.LoadIssue()[%d]: %v", pr.ID, err) + } + if !pr.Issue.IsClosed { + return fmt.Errorf("GetDiverging: %v", err) + } + log.Warn("Could not recalculate Divergence for pull: %d", pr.ID) + pr.CommitsAhead = 0 + pr.CommitsBehind = 0 + } + if divergence != nil { + pr.CommitsAhead = divergence.Ahead + pr.CommitsBehind = divergence.Behind + } + if _, err = sess.ID(pr.ID).Cols("commits_ahead", "commits_behind").Update(pr); err != nil { + return fmt.Errorf("Update Cols: %v", err) + } + } + + if err := sess.Commit(); err != nil { + return err + } + } + return nil +} diff --git a/models/pull.go b/models/pull.go index 055f9bbc6e5e7..9f1f485266a59 100644 --- a/models/pull.go +++ b/models/pull.go @@ -42,6 +42,8 @@ type PullRequest struct { Type PullRequestType Status PullRequestStatus ConflictedFiles []string `xorm:"TEXT JSON"` + CommitsAhead int + CommitsBehind int IssueID int64 `xorm:"INDEX"` Issue *Issue `xorm:"-"` @@ -615,6 +617,21 @@ func (pr *PullRequest) GetWorkInProgressPrefix() string { return "" } +// UpdateCommitDivergence update Divergence of a pull request +func (pr *PullRequest) UpdateCommitDivergence(ahead, behind int) error { + return pr.updateCommitDivergence(x, ahead, behind) +} + +func (pr *PullRequest) updateCommitDivergence(e Engine, ahead, behind int) error { + if pr.ID == 0 { + return fmt.Errorf("pull ID is 0") + } + pr.CommitsAhead = ahead + pr.CommitsBehind = behind + _, err := e.ID(pr.ID).Cols("commits_ahead", "commits_behind").Update(pr) + return err +} + // IsSameRepo returns true if base repo and head repo is the same func (pr *PullRequest) IsSameRepo() bool { return pr.BaseRepoID == pr.HeadRepoID diff --git a/routers/repo/pull.go b/routers/repo/pull.go index ef000208f4411..00195fd02a1e3 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -399,8 +399,6 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare var headBranchSha string // HeadRepo may be missing if pull.HeadRepo != nil { - var err error - headGitRepo, err := git.OpenRepository(pull.HeadRepo.RepoPath()) if err != nil { ctx.ServerError("OpenRepository", err) @@ -420,19 +418,11 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare } if headBranchExist { - allowUpdate, err := pull_service.IsUserAllowedToUpdate(pull, ctx.User) + ctx.Data["UpdateAllowed"], err = pull_service.IsUserAllowedToUpdate(pull, ctx.User) if err != nil { ctx.ServerError("IsUserAllowedToUpdate", err) return nil } - ctx.Data["UpdateAllowed"] = allowUpdate - - divergence, err := pull_service.GetDiverging(pull) - if err != nil { - ctx.ServerError("GetDiverging", err) - return nil - } - ctx.Data["Divergence"] = divergence ctx.Data["GetCommitMessages"] = pull_service.GetCommitMessages(pull) } diff --git a/services/pull/pull.go b/services/pull/pull.go index 2797294980eb1..fb4af06372844 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -31,6 +31,13 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6 return err } + divergence, err := GetDiverging(pr) + if err != nil { + return err + } + pr.CommitsAhead = divergence.Ahead + pr.CommitsBehind = divergence.Behind + if err := models.NewPullRequest(repo, pull, labelIDs, uuids, pr); err != nil { return err } @@ -212,6 +219,15 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy if err := models.MarkReviewsAsNotStale(pr.IssueID, newCommitID); err != nil { log.Error("MarkReviewsAsNotStale: %v", err) } + divergence, err := GetDiverging(pr) + if err != nil { + log.Error("GetDiverging: %v", err) + } else { + err = pr.UpdateCommitDivergence(divergence.Ahead, divergence.Behind) + if err != nil { + log.Error("UpdateCommitDivergence: %v", err) + } + } } pr.Issue.PullRequest = pr @@ -229,6 +245,15 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy return } for _, pr := range prs { + divergence, err := GetDiverging(pr) + if err != nil { + log.Error("GetDiverging: %v", err) + } else { + err = pr.UpdateCommitDivergence(divergence.Ahead, divergence.Behind) + if err != nil { + log.Error("UpdateCommitDivergence: %v", err) + } + } AddToTaskQueue(pr) } }) diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index e580d9558656a..03ac1b6cd704d 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -305,7 +305,7 @@
{{end}} {{end}} - {{if and .Divergence (gt .Divergence.Behind 0)}} + {{if gt .Issue.PullRequest.CommitsBehind 0}}
From c487985b7c345831044a37ece15b4dffceb55cd3 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 14 Apr 2020 18:29:31 +0200 Subject: [PATCH 049/550] fix (#11066) --- services/pull/merge.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/pull/merge.go b/services/pull/merge.go index 2d4d9722e8395..a20a2140143da 100644 --- a/services/pull/merge.go +++ b/services/pull/merge.go @@ -535,6 +535,9 @@ func IsSignedIfRequired(pr *models.PullRequest, doer *models.User) (bool, error) // IsUserAllowedToMerge check if user is allowed to merge PR with given permissions and branch protections func IsUserAllowedToMerge(pr *models.PullRequest, p models.Permission, user *models.User) (bool, error) { + if user == nil { + return false, nil + } err := pr.LoadProtectedBranch() if err != nil { From cb8cc110a715b329a9dfd547c5776506c68a67ef Mon Sep 17 00:00:00 2001 From: zeripath Date: Tue, 14 Apr 2020 19:32:03 +0100 Subject: [PATCH 050/550] Remove check on username if AccessToken authentication (#11015) Signed-off-by: Andrew Thornton --- modules/auth/sso/basic.go | 20 +++++--------------- routers/repo/http.go | 25 +++++-------------------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/modules/auth/sso/basic.go b/modules/auth/sso/basic.go index 7f1841df71198..b5885d38db1e0 100644 --- a/modules/auth/sso/basic.go +++ b/modules/auth/sso/basic.go @@ -85,22 +85,12 @@ func (b *Basic) VerifyAuthData(ctx *macaron.Context, sess session.Store) *models } token, err := models.GetAccessTokenBySHA(authToken) if err == nil { - if isUsernameToken { - u, err = models.GetUserByID(token.UID) - if err != nil { - log.Error("GetUserByID: %v", err) - return nil - } - } else { - u, err = models.GetUserByName(uname) - if err != nil { - log.Error("GetUserByID: %v", err) - return nil - } - if u.ID != token.UID { - return nil - } + u, err = models.GetUserByID(token.UID) + if err != nil { + log.Error("GetUserByID: %v", err) + return nil } + token.UpdatedUnix = timeutil.TimeStampNow() if err = models.UpdateAccessToken(token); err != nil { log.Error("UpdateAccessToken: %v", err) diff --git a/routers/repo/http.go b/routers/repo/http.go index e0beba888ea5b..725659bcf00c5 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -188,27 +188,12 @@ func HTTP(ctx *context.Context) { // Assume password is a token. token, err := models.GetAccessTokenBySHA(authToken) if err == nil { - if isUsernameToken { - authUser, err = models.GetUserByID(token.UID) - if err != nil { - ctx.ServerError("GetUserByID", err) - return - } - } else { - authUser, err = models.GetUserByName(authUsername) - if err != nil { - if models.IsErrUserNotExist(err) { - ctx.HandleText(http.StatusUnauthorized, fmt.Sprintf("invalid credentials from %s", ctx.RemoteAddr())) - } else { - ctx.ServerError("GetUserByName", err) - } - return - } - if authUser.ID != token.UID { - ctx.HandleText(http.StatusUnauthorized, fmt.Sprintf("invalid credentials from %s", ctx.RemoteAddr())) - return - } + authUser, err = models.GetUserByID(token.UID) + if err != nil { + ctx.ServerError("GetUserByID", err) + return } + token.UpdatedUnix = timeutil.TimeStampNow() if err = models.UpdateAccessToken(token); err != nil { ctx.ServerError("UpdateAccessToken", err) From 358486dbe4ff3a6df68f09e91830993da89ddb56 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Tue, 14 Apr 2020 18:33:15 +0000 Subject: [PATCH 051/550] [skip ci] Updated translations via Crowdin --- options/locale/locale_pt-PT.ini | 102 +++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 5ade2fe821f90..65db5494210f1 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -459,6 +459,7 @@ add_email=Adicionar endereço de email add_openid=Adicionar URI OpenID add_email_confirmation_sent=Um email de confirmação foi enviado para '%s'. Verifique sua caixa de entrada dentro de %s para confirmar o seu endereço de email. add_email_success=O novo endereço de email foi adicionado. +email_preference_set_success=As preferências relativas ao email foram definidas com sucesso. add_openid_success=O novo endereço OpenID foi adicionado. keep_email_private=Ocultar endereço de email keep_email_private_popup=Seu endereço de email será escondido dos outros utilizadores. @@ -604,7 +605,56 @@ repo_name=Nome do repositório repo_name_helper=Um bom nome de repositório utiliza palavras curtas, memoráveis e únicas. repo_size=Tamanho do repositório template=Modelo - +template_select=Escolha um modelo. +template_helper=Fazer do repositório um modelo +template_description=Repositórios modelo permitem que os utilizadores gerem novos repositórios com a mesma estrutura de pastas, ficheiros e configurações opcionais. +visibility=Visibilidade +visibility_description=Somente o proprietário ou os membros da organização, se tiverem direitos, poderão vê-lo. +visibility_helper=Tornar o repositório privado +visibility_helper_forced=O administrador obriga a que os repositórios novos sejam privados. +visibility_fork_helper=(alterar este parâmetro irá alterar também todas as derivações) +clone_helper=Precisa de ajuda para clonar? Visite a Ajuda. +fork_repo=Derivar repositório +fork_from=Derivar de +fork_visibility_helper=A visibilidade de um repositório derivado não pode ser alterada. +use_template=Usar este modelo +generate_repo=Gerar repositório +generate_from=Gerar a partir de +repo_desc=Descrição +repo_lang=Idioma +repo_gitignore_helper=Escolher modelos .gitignore. +issue_labels=Etiquetas para as questões +issue_labels_helper=Escolha um conjunto de etiquetas para as questões. +license=Licença +license_helper=Escolha um ficheiro de licença. +readme=README +readme_helper=Escolha um modelo de ficheiro README. +auto_init=Inicializar repositório (adiciona `.gitignore`, `LICENSE` e `README.md`) +create_repo=Criar repositório +default_branch=Ramo padrão +mirror_prune=Podar +mirror_prune_desc=Remover referências obsoletas de seguimento remoto +mirror_interval=Intervalo de espelhamento (as unidade de tempo válidas são 'h', 'm' e 's'). O valor zero desabilita a sincronização automática. +mirror_interval_invalid=O intervalo do espelhamento não é válido. +mirror_address=Clonar a partir do URL +mirror_address_desc=Coloque, na secção de Autorização de Clonagem, as credenciais que, eventualmente, sejam necessárias. +mirror_address_url_invalid=O URL fornecido é inválido. Tem que codificar adequadamente todos os componentes do URL. +mirror_address_protocol_invalid=O URL fornecido é inválido. Só se pode espelhar a partir de endereços http(s):// ou git://. +mirror_last_synced=Última sincronização +watchers=Vigilantes +stargazers=Fãs +forks=Derivações +pick_reaction=Escolha sua resposta +reactions_more=e mais %d +unit_disabled=O administrador desabilitou esta secção do repositório. +language_other=Outros + +template.items=Itens do modelo +template.git_content=Conteúdo Git (ramo padrão) +template.git_hooks=Automatismos do Git +template.git_hooks_tooltip=Neste momento não pode modificar ou remover automatismos do git depois de adicionados. Escolha esta opção somente se confiar no repositório modelo. +template.webhooks=Automatismos web +template.topics=Tópicos template.avatar=Avatar template.issue_labels=Etiquetas das questões template.one_item=Tem que escolher pelo menos um item do modelo @@ -864,6 +914,9 @@ issues.closed_title=Fechadas issues.num_comments=%d comentários issues.commented_at=`comentado %s` issues.delete_comment_confirm=Tem a certeza que quer eliminar este comentário? +issues.attachment.download=`Clique para descarregar "%s"` +issues.subscribe=Subscrever +issues.unsubscribe=Anular subscrição issues.lock=Bloquear diálogo issues.unlock=Desbloquear diálogo issues.lock.unknown_reason=Não é possível bloquear uma questão com um motivo desconhecido. @@ -885,6 +938,53 @@ issues.unlock.title=Desbloquear diálogo sobre esta questão. issues.comment_on_locked=Não pode comentar numa questão bloqueada. issues.tracker=Gestor de tempo issues.start_tracking_short=Iniciar +issues.start_tracking=Iniciar contagem de tempo +issues.start_tracking_history=`começou a trabalhar %s` +issues.tracker_auto_close=O temporizador será parado automaticamente quando esta questão for fechada +issues.tracking_already_started=`Já tinha iniciado a contagem de tempo para esta questão!` +issues.stop_tracking=Parar +issues.stop_tracking_history=`parou de trabalhar %s` +issues.add_time=Adicionar tempo manualmente +issues.add_time_short=Adicionar tempo +issues.add_time_cancel=Cancelar +issues.add_time_history=`adicionou o tempo gasto %s` +issues.del_time_history=`apagou o tempo gasto %s` +issues.add_time_hours=Horas +issues.add_time_minutes=Minutos +issues.add_time_sum_to_small=Não foi inserido qualquer tempo. +issues.cancel_tracking=Cancelar +issues.cancel_tracking_history=`cancelou o contador de tempo %s` +issues.time_spent_total=Total de tempo gasto +issues.time_spent_from_all_authors=`Tempo total gasto: %s` +issues.due_date=Date limite +issues.invalid_due_date_format=O formato da data limite tem que ser 'aaaa-mm-dd'. +issues.error_modifying_due_date=Falha ao modificar a data limite. +issues.error_removing_due_date=Falha ao remover a data limite. +issues.due_date_form=yyyy-mm-dd +issues.due_date_form_add=Adicionar data limite +issues.due_date_form_edit=Editar +issues.due_date_form_remove=Remover +issues.due_date_not_writer=Tem que ter permissões de escrita no repositório para poder modificar o prazo de uma questão. +issues.due_date_not_set=Sem data limite definida. +issues.due_date_added=adicionou a data limite %s %s +issues.due_date_modified=modificou a data limite de %[2]s para %[1]s %[3]s +issues.due_date_remove=removeu a data limite %s %s +issues.due_date_overdue=Em atraso +issues.due_date_invalid=A data limite é inválida ou está fora do intervalo permitido. Por favor, use o formato 'aaaa-mm-dd'. +issues.dependency.title=Dependências +issues.dependency.issue_no_dependencies=Esta questão não tem quaisquer dependências, neste momento. +issues.dependency.pr_no_dependencies=Este pedido de integração não tem quaisquer dependências, neste momento. +issues.dependency.add=Adicionar dependência… +issues.dependency.cancel=Cancelar +issues.dependency.remove=Remover +issues.dependency.remove_info=Remover esta dependência +issues.dependency.added_dependency=`%[2]s adicionou uma nova dependência %[3]s` +issues.dependency.removed_dependency=`%[2]s removeu uma dependência %[3]s` +issues.dependency.issue_closing_blockedby=O encerramento deste pedido de integração está bloqueado pelas seguintes questões +issues.dependency.pr_closing_blockedby=O encerramento desta questão está bloqueado pelas seguintes questões +issues.dependency.issue_close_blocks=Esta questão bloqueia o encerramento das seguintes questões +issues.dependency.pr_close_blocks=Este pedido de integração bloqueia o encerramento das seguintes questões +issues.dependency.issue_close_blocked=Tem que encerrar todas as questões que bloqueiam esta questão antes de a poder encerrar. From 554acdee1c9e4f4e5a40b6d2d0abbe671b5fe530 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 15 Apr 2020 00:16:07 +0200 Subject: [PATCH 052/550] Fix Migration 136 (be less aggressive to open pulls missing git files) (#11072) * be less aggressife to open pulls when migrating * remove unused --- models/migrations/v136.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/models/migrations/v136.go b/models/migrations/v136.go index 115861f344cce..da5706258eb67 100644 --- a/models/migrations/v136.go +++ b/models/migrations/v136.go @@ -42,12 +42,6 @@ func addCommitDivergenceToPulls(x *xorm.Engine) error { for _, pr := range results { divergence, err := pull_service.GetDiverging(pr) if err != nil { - if err = pr.LoadIssue(); err != nil { - return fmt.Errorf("pr.LoadIssue()[%d]: %v", pr.ID, err) - } - if !pr.Issue.IsClosed { - return fmt.Errorf("GetDiverging: %v", err) - } log.Warn("Could not recalculate Divergence for pull: %d", pr.ID) pr.CommitsAhead = 0 pr.CommitsBehind = 0 From cff9949abdb69595cb440a6428fa32132199ef98 Mon Sep 17 00:00:00 2001 From: Kristian Antonsen Date: Wed, 15 Apr 2020 02:44:08 +0200 Subject: [PATCH 053/550] Replace references to cron.update_migration_post_id with cron.update_migration_poster_id in docs (#11068) Across several files, references to cron.update_migration_post_id are made, although the actual setting is called cron.update_migration_poster_id according to modules/setting/cron.go (https://github.com/go-gitea/gitea/blob/10e2f291442fdc7efc31c02f5ffcba79a36db9ac/modules/setting/cron.go#L54). Co-authored-by: Antoine GIRARD --- custom/conf/app.ini.sample | 2 +- docs/content/doc/advanced/config-cheat-sheet.en-us.md | 2 +- docs/content/doc/advanced/config-cheat-sheet.zh-cn.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index 86224ab8c6920..556f93a91daf1 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -853,7 +853,7 @@ SCHEDULE = @every 24h UPDATE_EXISTING = true ; Update migrated repositories' issues and comments' posterid, it will always attempt synchronization when the instance starts. -[cron.update_migration_post_id] +[cron.update_migration_poster_id] ; Interval as a duration between each synchronization. (default every 24h) SCHEDULE = @every 24h diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 2306dd2281e61..00f086e5468e1 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -541,7 +541,7 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false` - `RUN_AT_START`: **true**: Run repository statistics check at start time. - `SCHEDULE`: **@every 24h**: Cron syntax for scheduling repository statistics check. -### Cron - Update Migration Poster ID (`cron.update_migration_post_id`) +### Cron - Update Migration Poster ID (`cron.update_migration_poster_id`) - `SCHEDULE`: **@every 24h** : Interval as a duration between each synchronization, it will always attempt synchronization when the instance starts. diff --git a/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md b/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md index acdee1a56ac6d..082944c8a4a22 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md +++ b/docs/content/doc/advanced/config-cheat-sheet.zh-cn.md @@ -225,7 +225,7 @@ test01.xls: application/vnd.ms-excel; charset=binary - `RUN_AT_START`: 是否启动时自动运行仓库统计。 - `SCHEDULE`: 仓库统计时的Cron 语法,比如:`@every 24h`. -### Cron - Update Migration Poster ID (`cron.update_migration_post_id`) +### Cron - Update Migration Poster ID (`cron.update_migration_poster_id`) - `SCHEDULE`: **@every 24h** : 每次同步的间隔时间。此任务总是在启动时自动进行。 From c2ccac4302db0e91f325b529eb23ea65237b1b80 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 15 Apr 2020 12:42:09 +0800 Subject: [PATCH 054/550] Add translation head on docs site (#11063) Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- docs/config.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/config.yaml b/docs/config.yaml index af4efc1b66daa..4053cba18cc9c 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -52,6 +52,10 @@ menu: url: https://code.gitea.io/ weight: 40 pre: code + - name: Translation + url: https://crowdin.com/project/gitea + weight: 41 + pre: language - name: Downloads url: https://dl.gitea.io/ weight: 50 @@ -100,6 +104,10 @@ languages: url: https://code.gitea.io/ weight: 40 pre: code + - name: 翻译 + url: https://crowdin.com/project/gitea + weight: 41 + pre: language - name: 下载 url: https://dl.gitea.io/ weight: 50 @@ -143,6 +151,10 @@ languages: url: https://code.gitea.io/ weight: 40 pre: code + - name: 翻译 + url: https://crowdin.com/project/gitea + weight: 41 + pre: language - name: 下载 url: https://dl.gitea.io/ weight: 50 @@ -186,6 +198,10 @@ languages: url: https://code.gitea.io/ weight: 40 pre: code + - name: Translation + url: https://crowdin.com/project/gitea + weight: 41 + pre: language - name: Downloads url: https://dl.gitea.io/ weight: 50 @@ -229,6 +245,10 @@ languages: url: https://code.gitea.io/ weight: 40 pre: code + - name: Translation + url: https://crowdin.com/project/gitea + weight: 41 + pre: language - name: Downloads url: https://dl.gitea.io/ weight: 50 @@ -272,6 +292,10 @@ languages: url: https://code.gitea.io/ weight: 40 pre: code + - name: Translation + url: https://crowdin.com/project/gitea + weight: 41 + pre: language - name: Téléchargement url: https://dl.gitea.io/ weight: 50 From a76cb99c076552bd5ec0a302b179ad4dd8abffec Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 15 Apr 2020 06:18:51 +0100 Subject: [PATCH 055/550] Contents API should return 404 on not exist (#10323) * Return 404 on not exist * swagger update and use git.IsErrNotExist * Handle delete too * Handle delete too x2 * Fix pr 10323 (#3) * fix TESTS * leafe a note for fututre * placate golangci-lint Signed-off-by: Andrew Thornton * Update integrations/api_repo_file_delete_test.go Co-Authored-By: 6543 <6543@obermui.de> Co-authored-by: techknowlogick Co-authored-by: Antoine GIRARD Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: guillep2k <18600385+guillep2k@users.noreply.github.com> --- integrations/api_repo_file_delete_test.go | 12 +------ .../api_repo_get_contents_list_test.go | 10 +----- integrations/api_repo_get_contents_test.go | 10 +----- routers/api/v1/repo/file.go | 32 +++++++++++++++++-- templates/swagger/v1_json.tmpl | 15 +++++++++ 5 files changed, 48 insertions(+), 31 deletions(-) diff --git a/integrations/api_repo_file_delete_test.go b/integrations/api_repo_file_delete_test.go index 59b3ff91b68ec..178aec6f5bc3e 100644 --- a/integrations/api_repo_file_delete_test.go +++ b/integrations/api_repo_file_delete_test.go @@ -11,8 +11,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "github.com/stretchr/testify/assert" @@ -109,18 +107,10 @@ func TestAPIDeleteFile(t *testing.T) { treePath = fmt.Sprintf("delete/file%d.txt", fileID) createFile(user2, repo1, treePath) deleteFileOptions = getDeleteFileOptions() - correctSHA := deleteFileOptions.SHA deleteFileOptions.SHA = "badsha" url = fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo1.Name, treePath, token2) req = NewRequestWithJSON(t, "DELETE", url, &deleteFileOptions) - resp = session.MakeRequest(t, req, http.StatusInternalServerError) - expectedAPIError := context.APIError{ - Message: "sha does not match [given: " + deleteFileOptions.SHA + ", expected: " + correctSHA + "]", - URL: setting.API.SwaggerURL, - } - var apiError context.APIError - DecodeJSON(t, resp, &apiError) - assert.Equal(t, expectedAPIError, apiError) + resp = session.MakeRequest(t, req, http.StatusBadRequest) // Test creating a file in repo16 by user4 who does not have write access fileID++ diff --git a/integrations/api_repo_get_contents_list_test.go b/integrations/api_repo_get_contents_list_test.go index abc4f42cf4d3e..ddbd877a40e80 100644 --- a/integrations/api_repo_get_contents_list_test.go +++ b/integrations/api_repo_get_contents_list_test.go @@ -11,7 +11,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -139,14 +138,7 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { // Test file contents a file with a bad ref ref = "badref" req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref) - resp = session.MakeRequest(t, req, http.StatusInternalServerError) - expectedAPIError := context.APIError{ - Message: "object does not exist [id: " + ref + ", rel_path: ]", - URL: setting.API.SwaggerURL, - } - var apiError context.APIError - DecodeJSON(t, resp, &apiError) - assert.Equal(t, expectedAPIError, apiError) + resp = session.MakeRequest(t, req, http.StatusNotFound) // Test accessing private ref with user token that does not have access - should fail req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4) diff --git a/integrations/api_repo_get_contents_test.go b/integrations/api_repo_get_contents_test.go index 184e76831bbd5..3d4a31be81140 100644 --- a/integrations/api_repo_get_contents_test.go +++ b/integrations/api_repo_get_contents_test.go @@ -10,7 +10,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" repo_module "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" @@ -141,14 +140,7 @@ func testAPIGetContents(t *testing.T, u *url.URL) { // Test file contents a file with a bad ref ref = "badref" req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?ref=%s", user2.Name, repo1.Name, treePath, ref) - resp = session.MakeRequest(t, req, http.StatusInternalServerError) - expectedAPIError := context.APIError{ - Message: "object does not exist [id: " + ref + ", rel_path: ]", - URL: setting.API.SwaggerURL, - } - var apiError context.APIError - DecodeJSON(t, resp, &apiError) - assert.Equal(t, expectedAPIError, apiError) + resp = session.MakeRequest(t, req, http.StatusNotFound) // Test accessing private ref with user token that does not have access - should fail req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/contents/%s?token=%s", user2.Name, repo16.Name, treePath, token4) diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 14923984bd765..90a84cd54c30f 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -362,9 +362,15 @@ func DeleteFile(ctx *context.APIContext, apiOpts api.DeleteFileOptions) { // responses: // "200": // "$ref": "#/responses/FileDeleteResponse" + // "400": + // "$ref": "#/responses/error" + // "403": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/error" if !CanWriteFiles(ctx.Repo) { - ctx.Error(http.StatusInternalServerError, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{ + ctx.Error(http.StatusForbidden, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{ UserID: ctx.User.ID, RepoName: ctx.Repo.Repository.LowerName, }) @@ -402,9 +408,23 @@ func DeleteFile(ctx *context.APIContext, apiOpts api.DeleteFileOptions) { } if fileResponse, err := repofiles.DeleteRepoFile(ctx.Repo.Repository, ctx.User, opts); err != nil { + if git.IsErrBranchNotExist(err) || models.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) { + ctx.Error(http.StatusNotFound, "DeleteFile", err) + return + } else if models.IsErrBranchAlreadyExists(err) || + models.IsErrFilenameInvalid(err) || + models.IsErrSHADoesNotMatch(err) || + models.IsErrCommitIDDoesNotMatch(err) || + models.IsErrSHAOrCommitIDNotProvided(err) { + ctx.Error(http.StatusBadRequest, "DeleteFile", err) + return + } else if models.IsErrUserCannotCommit(err) { + ctx.Error(http.StatusForbidden, "DeleteFile", err) + return + } ctx.Error(http.StatusInternalServerError, "DeleteFile", err) } else { - ctx.JSON(http.StatusOK, fileResponse) + ctx.JSON(http.StatusOK, fileResponse) // FIXME on APIv2: return http.StatusNoContent } } @@ -439,6 +459,8 @@ func GetContents(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ContentsResponse" + // "404": + // "$ref": "#/responses/notFound" if !CanReadFiles(ctx.Repo) { ctx.Error(http.StatusInternalServerError, "GetContentsOrList", models.ErrUserDoesNotHaveAccessToRepo{ @@ -452,6 +474,10 @@ func GetContents(ctx *context.APIContext) { ref := ctx.QueryTrim("ref") if fileList, err := repofiles.GetContentsOrList(ctx.Repo.Repository, treePath, ref); err != nil { + if git.IsErrNotExist(err) { + ctx.NotFound("GetContentsOrList", err) + return + } ctx.Error(http.StatusInternalServerError, "GetContentsOrList", err) } else { ctx.JSON(http.StatusOK, fileList) @@ -484,6 +510,8 @@ func GetContentsList(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ContentsListResponse" + // "404": + // "$ref": "#/responses/notFound" // same as GetContents(), this function is here because swagger fails if path is empty in GetContents() interface GetContents(ctx) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 8b10a759901d3..5de98a72ce85d 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -2638,6 +2638,9 @@ "responses": { "200": { "$ref": "#/responses/ContentsListResponse" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -2684,6 +2687,9 @@ "responses": { "200": { "$ref": "#/responses/ContentsResponse" + }, + "404": { + "$ref": "#/responses/notFound" } } }, @@ -2831,6 +2837,15 @@ "responses": { "200": { "$ref": "#/responses/FileDeleteResponse" + }, + "400": { + "$ref": "#/responses/error" + }, + "403": { + "$ref": "#/responses/error" + }, + "404": { + "$ref": "#/responses/error" } } } From 974527d446d095140c610e58a43722c27709c59a Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 15 Apr 2020 15:03:05 +0200 Subject: [PATCH 056/550] document 404 responce and meaning (#11073) --- routers/api/v1/user/watch.go | 2 ++ templates/swagger/v1_json.tmpl | 3 +++ 2 files changed, 5 insertions(+) diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go index e54709b599fb8..1fc736deba5be 100644 --- a/routers/api/v1/user/watch.go +++ b/routers/api/v1/user/watch.go @@ -114,6 +114,8 @@ func IsWatching(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/WatchInfo" + // "404": + // description: User is not watching this repo or repo do not exist if models.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID) { ctx.JSON(http.StatusOK, api.WatchInfo{ diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 5de98a72ce85d..8cb7dbfcc0e72 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -7411,6 +7411,9 @@ "responses": { "200": { "$ref": "#/responses/WatchInfo" + }, + "404": { + "description": "User is not watching this repo or repo do not exist" } } }, From 17dff2986a2e5650310ae1d852e05e7a930e4445 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Wed, 15 Apr 2020 13:04:26 +0000 Subject: [PATCH 057/550] [skip ci] Updated translations via Crowdin --- options/locale/locale_pt-PT.ini | 102 +++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index 65db5494210f1..63bb2df628ea7 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -516,6 +516,7 @@ new_token_desc=Aplicações que usem um código têm acesso total à sua conta. token_name=Nome do código generate_token=Gerar código generate_token_success=O seu novo código foi gerado. Copie-o agora porque não irá ser mostrado novamente. +generate_token_name_duplicate=%s já foi usado como nome de uma aplicação. Tente outro. delete_token=Eliminar access_token_deletion=Eliminar código de acesso access_token_deletion_desc=Eliminar um código revoga o acesso à sua conta nas aplicações que o usem. Quer continuar? @@ -864,6 +865,9 @@ issues.add_milestone_at=`adicionou esta questão à etapa %s %s` issues.change_milestone_at=`modificou a etapa de %s para %s %s` issues.remove_milestone_at=`removeu esta questão da etapa %s %s` issues.deleted_milestone=`(eliminada)` +issues.self_assign_at=`atribuiu a si mesmo(a) esta questão %s` +issues.add_assignee_at=`foi atribuída por %s %s` +issues.remove_assignee_at=`a atribuição foi retirada por %s %s` issues.remove_self_assignment=`removeu a auto-atribuição %s` issues.change_title_at=`mudou o título de %s para %s %s` issues.delete_branch_at=`eliminou o ramo %s %s` @@ -914,6 +918,52 @@ issues.closed_title=Fechadas issues.num_comments=%d comentários issues.commented_at=`comentado %s` issues.delete_comment_confirm=Tem a certeza que quer eliminar este comentário? +issues.context.copy_link=Copiar ligação +issues.context.quote_reply=Citar resposta +issues.context.edit=Editar +issues.context.delete=Eliminar +issues.no_content=Ainda não há conteúdo. +issues.close_issue=Fechar +issues.pull_merged_at=`cometimento %[2]s integrado em %[3]s %[4]s` +issues.close_comment_issue=Comentar e fechar +issues.reopen_issue=Reabrir +issues.reopen_comment_issue=Comentar e reabrir +issues.create_comment=Comentar +issues.closed_at=`fechou a questão %[2]s` +issues.reopened_at=`reabriu a questão %[2]s` +issues.commit_ref_at=`referenciou esta questão num cometimento %[2]s` +issues.ref_issue_from=`referiu esta questão %[4]s %[2]s` +issues.ref_pull_from=`referiu este pedido de integração %[4]s %[2]s` +issues.ref_closing_from=`referiu um pedido de integração %[4]s que fechará esta questão %[2]s` +issues.ref_reopening_from=`referiu um pedido de integração %[4]s que reabrirá esta questão %[2]s` +issues.ref_closed_from=`fechou esta questão %[4]s %[2]s` +issues.ref_reopened_from=`reabriu esta questão %[4]s %[2]s` +issues.ref_from=`de %[1]s` +issues.poster=Autor +issues.collaborator=Colaborador(a) +issues.owner=Proprietário(a) +issues.re_request_review=Voltar a solicitar avaliação +issues.remove_request_review=Remover solicitação de avaliação +issues.remove_request_review_block=Não é possível remover a solicitação de avaliação +issues.sign_in_require_desc=Inicie a sessão para participar neste diálogo. +issues.edit=Editar +issues.cancel=Cancelar +issues.save=Guardar +issues.label_title=Nome da etiqueta +issues.label_description=Descrição da etiqueta +issues.label_color=Cor da etiqueta +issues.label_count=%d etiquetas +issues.label_open_issues=%d questões abertas +issues.label_edit=Editar +issues.label_delete=Eliminar +issues.label_modify=Editar etiqueta +issues.label_deletion=Eliminar etiqueta +issues.label_deletion_desc=Se eliminar uma etiqueta, irá removê-la de todas as questões. Quer continuar? +issues.label_deletion_success=A etiqueta foi eliminada. +issues.label.filter_sort.alphabetically=por ordem alfabética +issues.label.filter_sort.reverse_alphabetically=por ordem alfabética inversa +issues.label.filter_sort.by_size=Menor tamanho +issues.label.filter_sort.reverse_by_size=Maior tamanho issues.attachment.download=`Clique para descarregar "%s"` issues.subscribe=Subscrever issues.unsubscribe=Anular subscrição @@ -986,7 +1036,57 @@ issues.dependency.issue_close_blocks=Esta questão bloqueia o encerramento das s issues.dependency.pr_close_blocks=Este pedido de integração bloqueia o encerramento das seguintes questões issues.dependency.issue_close_blocked=Tem que encerrar todas as questões que bloqueiam esta questão antes de a poder encerrar. - +pulls.cant_reopen_deleted_branch=Este pedido de integração não pode ser reaberto porque o ramo foi eliminado. +pulls.merged=Integração executada +pulls.merged_as=A integração constante no pedido foi executada como %[2]s. +pulls.is_closed=O pedido de integração foi fechado. +pulls.has_merged=A integração constante no pedido foi executada. +pulls.title_wip_desc=`Inicie o título com %s para evitar que o pedido de integração seja executado acidentalmente.` +pulls.cannot_merge_work_in_progress=Este pedido de integração está marcado como um trabalho em andamento. Remova o prefixo %s do título quando estiver pronto +pulls.data_broken=Este pedido de integração está danificado devido à falta de informação da derivação. +pulls.files_conflicted=Este pedido de integração contém alterações que entram em conflito com o ramo de destino. +pulls.is_checking=Está em andamento uma verificação de conflitos na integração. Tente novamente daqui a alguns momentos. +pulls.required_status_check_failed=Algumas das verificações obrigatórias não foram bem sucedidas. +pulls.required_status_check_administrator=Uma vez que é administrador, ainda pode realizar a integração deste pedido. +pulls.blocked_by_approvals=Este pedido de integração ainda não tem aprovações suficientes. Já foram concedidas %d de um total de%d aprovações. +pulls.blocked_by_rejection=Este pedido de integração tem alterações solicitadas por um avaliador oficial. +pulls.can_auto_merge_desc=A integração constante neste pedido pode ser executada automaticamente. +pulls.cannot_auto_merge_desc=A integração constante neste pedido não pode ser executada automaticamente porque existem conflitos. +pulls.cannot_auto_merge_helper=Faça a integração manualmente para resolver os conflitos. +pulls.num_conflicting_files_1=%d ficheiro em conflito +pulls.num_conflicting_files_n=%d ficheiros em conflito +pulls.approve_count_1=%d aprovação +pulls.approve_count_n=%d aprovações +pulls.reject_count_1=%d pedido de alteração +pulls.reject_count_n=%d pedidos de alteração +pulls.waiting_count_1=%d avaliação pendente +pulls.waiting_count_n=%d avaliações pendentes + +pulls.no_merge_desc=A integração constante neste pedido não pode ser executada porque todas as opções de integração do repositório estão desabilitadas. +pulls.no_merge_helper=Habilite as opções de integração nas configurações do repositório ou faça manualmente a integração constante no pedido. +pulls.no_merge_wip=A integração constante neste pedido não pode ser executada porque está marcada como sendo trabalho em andamento. +pulls.no_merge_not_ready=A integração constante neste pedido não pode ser executada. Verifique o estado da revisão e as verificações de estado. +pulls.no_merge_access=Não tem autorização para executar a integração constante neste pedido. +pulls.merge_pull_request=Executar a integração constante neste pedido +pulls.rebase_merge_pull_request=Mudar a base e integrar +pulls.rebase_merge_commit_pull_request=Mudar a base e integrar (--no-ff) +pulls.squash_merge_pull_request=Comprimir e integrar +pulls.require_signed_wont_sign=O ramo requer que os cometimentos sejam assinados mas esta integração não vai ser assinada +pulls.invalid_merge_option=Não pode usar esta opção de integração neste pedido de integração. +pulls.merge_conflict=Integração falhada: Houve um conflito durante a integração: %[1]s
%[2]s
Dica: tente uma estratégia diferente +pulls.rebase_conflict=Integração falhada: Ocorreu um conflito durante a mudança da base no cometimento: %[1]s
%[2]s
%[3]s
Dica: Tente uma estratégia diferente +pulls.unrelated_histories=Integração falhada: A cabeça da integração e a base não partilham um histórico comum. Dica: Tente uma estratégia diferente +pulls.merge_out_of_date=Falhou a integração: Enquanto estava a gerar a integração, a base foi modificada. Dica: Tente de novo. +pulls.push_rejected=Integração falhada: O envio foi rejeitado com a seguinte mensagem:
%s
Reveja os automatismos do git para este repositório +pulls.push_rejected_no_message=Integração falhada: O envio foi rejeitado mas não houve qualquer mensagem remota.
Reveja os automatismos do git para este repositório +pulls.open_unmerged_pull_exists=`Não pode executar uma operação de reabertura porque há um pedido de integração 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 +pulls.status_checks_error=Algumas verificações falharam +pulls.update_branch=Sincronizar ramo +pulls.update_branch_success=A sincronização do ramo foi bem sucedida +pulls.update_not_allowed=Não tem autorização para sincronizar o ramo +pulls.outdated_with_base_branch=Este ramo é obsoleto em relação ao ramo base From 53590f5798f3a177f6fa57a79efc016f34cfb4df Mon Sep 17 00:00:00 2001 From: Lauris BH Date: Wed, 15 Apr 2020 20:40:39 +0300 Subject: [PATCH 058/550] Migrate to go-enry new version (#10906) --- go.mod | 2 +- go.sum | 10 +- models/repo_language_stats.go | 2 +- modules/analyze/code_langauge.go | 2 +- modules/git/repo_language_stats.go | 2 +- modules/indexer/code/bleve.go | 2 +- .../enry => go-enry/go-enry}/v2/.gitignore | 3 +- .../enry => go-enry/go-enry}/v2/.travis.yml | 12 +- .../enry => go-enry/go-enry}/v2/LICENSE | 7 +- .../enry => go-enry/go-enry}/v2/Makefile | 30 +- .../github.com/go-enry/go-enry/v2/README.md | 303 + .../enry => go-enry/go-enry}/v2/classifier.go | 20 +- .../enry => go-enry/go-enry}/v2/common.go | 40 +- .../go-enry/go-enry/v2/data/alias.go | 842 + .../go-enry}/v2/data/colors.go | 22 +- .../go-enry/go-enry/v2/data/commit.go | 7 + .../go-enry}/v2/data/content.go | 110 +- .../enry => go-enry/go-enry}/v2/data/doc.go | 0 .../go-enry}/v2/data/documentation.go | 4 +- .../go-enry}/v2/data/extension.go | 1158 +- .../go-enry}/v2/data/filename.go | 35 +- .../go-enry}/v2/data/frequencies.go | 208850 ++++++++------- .../go-enry/go-enry/v2/data/groups.go | 89 + .../go-enry}/v2/data/heuristics.go | 2 +- .../go-enry}/v2/data/interpreter.go | 13 +- .../go-enry}/v2/data/mimeType.go | 17 +- .../go-enry}/v2/data/rule/rule.go | 0 .../go-enry/go-enry/v2/data/type.go | 560 + .../go-enry}/v2/data/vendor.go | 7 +- .../enry => go-enry/go-enry}/v2/enry.go | 2 +- .../{src-d/enry => go-enry/go-enry}/v2/go.mod | 8 +- .../{src-d/enry => go-enry/go-enry}/v2/go.sum | 9 +- .../go-enry}/v2/internal/tokenizer/common.go | 0 .../internal/tokenizer/flex/lex.linguist_yy.c | 0 .../internal/tokenizer/flex/lex.linguist_yy.h | 0 .../v2/internal/tokenizer/flex/linguist.h | 0 .../v2/internal/tokenizer/flex/tokenize_c.go | 2 + .../v2/internal/tokenizer/tokenize.go | 8 +- .../v2/internal/tokenizer/tokenize_c.go | 2 +- .../go-enry}/v2/regex/oniguruma.go | 2 +- .../go-enry}/v2/regex/standard.go | 0 .../enry => go-enry/go-enry}/v2/utils.go | 6 +- .../{src-d => go-enry}/go-oniguruma/LICENSE | 0 .../{src-d => go-enry}/go-oniguruma/README.md | 14 +- .../{src-d => go-enry}/go-oniguruma/chelper.c | 0 .../{src-d => go-enry}/go-oniguruma/chelper.h | 0 .../go-oniguruma/constants.go | 0 vendor/github.com/go-enry/go-oniguruma/go.mod | 3 + .../go-oniguruma/quotemeta.go | 0 .../{src-d => go-enry}/go-oniguruma/regex.go | 0 .../github.com/src-d/enry/v2/CONTRIBUTING.md | 61 - vendor/github.com/src-d/enry/v2/DCO | 25 - vendor/github.com/src-d/enry/v2/MAINTAINERS | 1 - vendor/github.com/src-d/enry/v2/README.md | 328 - vendor/github.com/src-d/enry/v2/data/alias.go | 783 - .../github.com/src-d/enry/v2/data/commit.go | 7 - vendor/github.com/src-d/enry/v2/data/type.go | 526 - .../github.com/src-d/go-oniguruma/.travis.yml | 20 - vendor/github.com/src-d/go-oniguruma/go.mod | 1 - vendor/gopkg.in/yaml.v2/.travis.yml | 18 +- vendor/gopkg.in/yaml.v2/decode.go | 14 +- vendor/gopkg.in/yaml.v2/scannerc.go | 107 +- vendor/gopkg.in/yaml.v2/yaml.go | 2 +- vendor/gopkg.in/yaml.v2/yamlh.go | 1 + vendor/modules.txt | 22 +- 65 files changed, 111848 insertions(+), 102275 deletions(-) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/.gitignore (85%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/.travis.yml (96%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/LICENSE (99%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/Makefile (73%) create mode 100644 vendor/github.com/go-enry/go-enry/v2/README.md rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/classifier.go (80%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/common.go (91%) create mode 100644 vendor/github.com/go-enry/go-enry/v2/data/alias.go rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/colors.go (92%) create mode 100644 vendor/github.com/go-enry/go-enry/v2/data/commit.go rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/content.go (89%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/doc.go (100%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/documentation.go (82%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/extension.go (53%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/filename.go (88%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/frequencies.go (65%) create mode 100644 vendor/github.com/go-enry/go-enry/v2/data/groups.go rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/heuristics.go (95%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/interpreter.go (89%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/mimeType.go (94%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/rule/rule.go (100%) create mode 100644 vendor/github.com/go-enry/go-enry/v2/data/type.go rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/data/vendor.go (95%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/enry.go (90%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/go.mod (55%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/go.sum (74%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/common.go (100%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/flex/lex.linguist_yy.c (100%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/flex/lex.linguist_yy.h (100%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/flex/linguist.h (100%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/flex/tokenize_c.go (99%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/tokenize.go (96%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/internal/tokenizer/tokenize_c.go (84%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/regex/oniguruma.go (84%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/regex/standard.go (100%) rename vendor/github.com/{src-d/enry => go-enry/go-enry}/v2/utils.go (93%) rename vendor/github.com/{src-d => go-enry}/go-oniguruma/LICENSE (100%) rename vendor/github.com/{src-d => go-enry}/go-oniguruma/README.md (79%) rename vendor/github.com/{src-d => go-enry}/go-oniguruma/chelper.c (100%) rename vendor/github.com/{src-d => go-enry}/go-oniguruma/chelper.h (100%) rename vendor/github.com/{src-d => go-enry}/go-oniguruma/constants.go (100%) create mode 100644 vendor/github.com/go-enry/go-oniguruma/go.mod rename vendor/github.com/{src-d => go-enry}/go-oniguruma/quotemeta.go (100%) rename vendor/github.com/{src-d => go-enry}/go-oniguruma/regex.go (100%) delete mode 100644 vendor/github.com/src-d/enry/v2/CONTRIBUTING.md delete mode 100644 vendor/github.com/src-d/enry/v2/DCO delete mode 100644 vendor/github.com/src-d/enry/v2/MAINTAINERS delete mode 100644 vendor/github.com/src-d/enry/v2/README.md delete mode 100644 vendor/github.com/src-d/enry/v2/data/alias.go delete mode 100644 vendor/github.com/src-d/enry/v2/data/commit.go delete mode 100644 vendor/github.com/src-d/enry/v2/data/type.go delete mode 100644 vendor/github.com/src-d/go-oniguruma/.travis.yml delete mode 100644 vendor/github.com/src-d/go-oniguruma/go.mod diff --git a/go.mod b/go.mod index 0930b0d168a9b..404ca6d5c54df 100644 --- a/go.mod +++ b/go.mod @@ -43,6 +43,7 @@ require ( github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect github.com/gliderlabs/ssh v0.2.2 github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a // indirect + github.com/go-enry/go-enry/v2 v2.3.0 github.com/go-git/go-billy/v5 v5.0.0 github.com/go-git/go-git/v5 v5.0.0 github.com/go-openapi/jsonreference v0.19.3 // indirect @@ -93,7 +94,6 @@ require ( github.com/sergi/go-diff v1.1.0 github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b // indirect github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd - github.com/src-d/enry/v2 v2.1.0 github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect github.com/stretchr/testify v1.4.0 github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect diff --git a/go.sum b/go.sum index 5944cbb5e7725..d904ed86daf6a 100644 --- a/go.sum +++ b/go.sum @@ -183,6 +183,10 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a h1:FQqo github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-enry/go-enry/v2 v2.3.0 h1:o8KwgY6uSplysrIpj+Y42J/xGPp90ogVpxE2Z3s8Unk= +github.com/go-enry/go-enry/v2 v2.3.0/go.mod h1:+xFJwbqWi15bvqFHb2ELUWVRKFQtwB61+sDrkvvxxGI= +github.com/go-enry/go-oniguruma v1.2.0 h1:oBO9XC1IDT9+AoWW5oFsa/7gFeOPacEqDbyXZKWXuDs= +github.com/go-enry/go-oniguruma v1.2.0/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM= @@ -560,10 +564,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/src-d/enry/v2 v2.1.0 h1:z1L8t+B8bh3mmjPkJrgOTnVRpFGmTPJsplHX9wAn6BI= -github.com/src-d/enry/v2 v2.1.0/go.mod h1:qQeCMRwzMF3ckeGr+h0tJLdxXnq+NVZsIDMELj0t028= -github.com/src-d/go-oniguruma v1.1.0 h1:EG+Nm5n2JqWUaCjtM0NtutPxU7ZN5Tp50GWrrV8bTww= -github.com/src-d/go-oniguruma v1.1.0/go.mod h1:chVbff8kcVtmrhxtZ3yBVLLquXbzCS6DrxQaAK/CeqM= github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 h1:JNEGSiWg6D3lcBCMCBqN3ELniXujt+0QNHLhNnO0w3s= github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2/go.mod h1:mjqs7N0Q6m5HpR7QfXVBZXZWSqTjQLeTujjA/xUp2uw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -829,6 +829,8 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/models/repo_language_stats.go b/models/repo_language_stats.go index fd5bcbb8ec670..5f1aed1f30220 100644 --- a/models/repo_language_stats.go +++ b/models/repo_language_stats.go @@ -10,7 +10,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" - "github.com/src-d/enry/v2" + "github.com/go-enry/go-enry/v2" ) // LanguageStat describes language statistics of a repository diff --git a/modules/analyze/code_langauge.go b/modules/analyze/code_langauge.go index f7dd3e7cfc9a2..3bd2d512f97c4 100644 --- a/modules/analyze/code_langauge.go +++ b/modules/analyze/code_langauge.go @@ -7,7 +7,7 @@ package analyze import ( "path/filepath" - "github.com/src-d/enry/v2" + "github.com/go-enry/go-enry/v2" ) // GetCodeLanguageWithCallback detects code language based on file name and content using callback diff --git a/modules/git/repo_language_stats.go b/modules/git/repo_language_stats.go index d18ae02d8b3af..ba58bcc2da228 100644 --- a/modules/git/repo_language_stats.go +++ b/modules/git/repo_language_stats.go @@ -12,10 +12,10 @@ import ( "code.gitea.io/gitea/modules/analyze" + "github.com/go-enry/go-enry/v2" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" - "github.com/src-d/enry/v2" ) const fileSizeLimit int64 = 16 * 1024 * 1024 diff --git a/modules/indexer/code/bleve.go b/modules/indexer/code/bleve.go index 39171d17a64ac..576cc3e5e4839 100644 --- a/modules/indexer/code/bleve.go +++ b/modules/indexer/code/bleve.go @@ -30,7 +30,7 @@ import ( "github.com/blevesearch/bleve/mapping" "github.com/blevesearch/bleve/search/query" "github.com/ethantkoenig/rupture" - "github.com/src-d/enry/v2" + "github.com/go-enry/go-enry/v2" ) const unicodeNormalizeName = "unicodeNormalize" diff --git a/vendor/github.com/src-d/enry/v2/.gitignore b/vendor/github.com/go-enry/go-enry/v2/.gitignore similarity index 85% rename from vendor/github.com/src-d/enry/v2/.gitignore rename to vendor/github.com/go-enry/go-enry/v2/.gitignore index 78b3fb1614d1f..9ab3afa87da85 100644 --- a/vendor/github.com/src-d/enry/v2/.gitignore +++ b/vendor/github.com/go-enry/go-enry/v2/.gitignore @@ -1,4 +1,4 @@ -.linguist +.linguist* benchmarks/output .ci Makefile.main @@ -9,3 +9,4 @@ build/ vendor/ java/lib/ .vscode/ +.venv diff --git a/vendor/github.com/src-d/enry/v2/.travis.yml b/vendor/github.com/go-enry/go-enry/v2/.travis.yml similarity index 96% rename from vendor/github.com/src-d/enry/v2/.travis.yml rename to vendor/github.com/go-enry/go-enry/v2/.travis.yml index 004bc52f99206..c7afb06f27b58 100644 --- a/vendor/github.com/src-d/enry/v2/.travis.yml +++ b/vendor/github.com/go-enry/go-enry/v2/.travis.yml @@ -1,8 +1,9 @@ dist: trusty language: go go: - - '1.12.x' - - '1.11.x' + - '1.14.x' + - '1.13.x' + env: global: - GO_VERSION_FOR_JVM='1.11.x' @@ -12,8 +13,6 @@ env: matrix: - ONIGURUMA=0 - ONIGURUMA=1 -matrix: - fast_finish: true stages: - name: test @@ -22,7 +21,6 @@ stages: - name: publish if: tag IS present -stage: test install: - > if [[ "${ONIGURUMA}" -gt 0 ]]; then @@ -36,7 +34,7 @@ install: sudo dpkg -i "libonig-dev_${ONIGURUMA_VERSION}-1_amd64.deb" fi; script: - - make test-coverage + - go test ./... after_success: - bash <(curl -s https://codecov.io/bash) @@ -98,7 +96,7 @@ jobs: - sudo apt-get install -y --no-install-recommends clang g++ gcc gcc-multilib libc6-dev libc6-dev-i386 mingw-w64 patch xz-utils - cd ${HOME} - curl -sfSL ${OSXCROSS_URL} | tar -C ${HOME} -xzf - - - cd $GOPATH/src/github.com/src-d/enry + - cd $GOPATH/src/github.com/bzz/enry script: make darwin-shared deploy: provider: releases diff --git a/vendor/github.com/src-d/enry/v2/LICENSE b/vendor/github.com/go-enry/go-enry/v2/LICENSE similarity index 99% rename from vendor/github.com/src-d/enry/v2/LICENSE rename to vendor/github.com/go-enry/go-enry/v2/LICENSE index 7f5eae06945ba..7a4a3ea2424c0 100644 --- a/vendor/github.com/src-d/enry/v2/LICENSE +++ b/vendor/github.com/go-enry/go-enry/v2/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2017 Sourced Technologies, S.L. + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -198,4 +199,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. + limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/src-d/enry/v2/Makefile b/vendor/github.com/go-enry/go-enry/v2/Makefile similarity index 73% rename from vendor/github.com/src-d/enry/v2/Makefile rename to vendor/github.com/go-enry/go-enry/v2/Makefile index fb978eb843a64..07bba14837e72 100644 --- a/vendor/github.com/src-d/enry/v2/Makefile +++ b/vendor/github.com/go-enry/go-enry/v2/Makefile @@ -1,26 +1,3 @@ -# Package configuration -PROJECT = enry -COMMANDS = cmd/enry - -# Including ci Makefile -CI_REPOSITORY ?= https://github.com/src-d/ci.git -CI_BRANCH ?= v1 -CI_PATH ?= .ci -MAKEFILE := $(CI_PATH)/Makefile.main -$(MAKEFILE): - git clone --quiet --depth 1 -b $(CI_BRANCH) $(CI_REPOSITORY) $(CI_PATH); --include $(MAKEFILE) - -# Docsrv: configure the languages whose api-doc can be auto generated -LANGUAGES = go -# Docs: do not edit this -DOCS_REPOSITORY := https://github.com/src-d/docs -SHARED_PATH ?= $(shell pwd)/.docsrv-resources -DOCS_PATH ?= $(SHARED_PATH)/.docs -$(DOCS_PATH)/Makefile.inc: - git clone --quiet --depth 1 $(DOCS_REPOSITORY) $(DOCS_PATH); --include $(DOCS_PATH)/Makefile.inc - LINGUIST_PATH = .linguist # shared objects @@ -29,6 +6,7 @@ LINUX_DIR=$(RESOURCES_DIR)/linux-x86-64 LINUX_SHARED_LIB=$(LINUX_DIR)/libenry.so DARWIN_DIR=$(RESOURCES_DIR)/darwin DARWIN_SHARED_LIB=$(DARWIN_DIR)/libenry.dylib +STATIC_LIB=$(RESOURCES_DIR)/libenry.a HEADER_FILE=libenry.h NATIVE_LIB=./shared/enry.go @@ -79,4 +57,10 @@ $(LINUX_SHARED_LIB): CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -buildmode=c-shared -o $(LINUX_SHARED_LIB) $(NATIVE_LIB) && \ mv $(LINUX_DIR)/$(HEADER_FILE) $(RESOURCES_DIR)/$(HEADER_FILE) + +static: $(STATIC_LIB) + +$(STATIC_LIB): + CGO_ENABLED=1 go build -buildmode=c-archive -o $(STATIC_LIB) $(NATIVE_LIB) + .PHONY: benchmarks benchmarks-samples benchmarks-slow diff --git a/vendor/github.com/go-enry/go-enry/v2/README.md b/vendor/github.com/go-enry/go-enry/v2/README.md new file mode 100644 index 0000000000000..3ad9146112e15 --- /dev/null +++ b/vendor/github.com/go-enry/go-enry/v2/README.md @@ -0,0 +1,303 @@ +# go-enry [![GoDoc](https://godoc.org/github.com/go-enry/go-enry?status.svg)](https://pkg.go.dev/github.com/go-enry/go-enry/v2) [![Test](https://github.com/go-enry/go-enry/workflows/Test/badge.svg)](https://github.com/go-enry/go-enry/actions?query=workflow%3ATest+branch%3Amaster) [![codecov](https://codecov.io/gh/go-enry/go-enry/branch/master/graph/badge.svg)](https://codecov.io/gh/go-enry/go-enry) + +Programming language detector and toolbox to ignore binary or vendored files. *enry*, started as a port to _Go_ of the original [Linguist](https://github.com/github/linguist) _Ruby_ library, that has an improved *2x performance*. + +* [CLI](#cli) +* [Library](#library) + * [Use cases](#use-cases) + * [By filename](#by-filename) + * [By text](#by-text) + * [By file](#by-file) + * [Filtering](#filtering-vendoring-binaries-etc) + * [Coloring](#language-colors-and-groups) + * [Languages](#languages) + * [Go](#go) + * [Java bindings](#java-bindings) + * [Python bindings](#python-bindings) +* [Divergences from linguist](#divergences-from-linguist) +* [Benchmarks](#benchmarks) +* [Why Enry?](#why-enry) +* [Development](#development) + * [Sync with github/linguist upstream](#sync-with-githublinguist-upstream) +* [Misc](#misc) +* [License](#license) + +# CLI + +The CLI binary is hosted in a separate repository [go-enry/enry](https://github.com/go-enry/enry). + +# Library + +*enry* is also a Go library for guessing a programming language that exposes API through FFI to multiple programming environments. + +## Use cases + +*enry* guesses a programming language using a sequence of matching *strategies* that are +applied progressively to narrow down the possible options. Each *strategy* varies on the type +of input data that it needs to make a decision: file name, extension, the first line of the file, the full content of the file, etc. + +Depending on available input data, enry API can be roughly divided into the next categories or use cases. + +### By filename +Next functions require only a name of the file to make a guess: + - `GetLanguageByExtension` uses only file extension (wich may be ambiguous) + - `GetLanguageByFilename` useful for cases like `.gitignore`, `.bashrc`, etc + - all [filtering helpers](#filtering) + + Please note that such guesses are expected not to be very accurate. + +### By text +To make a guess only based on the content of the file or a text snippet, use + - `GetLanguageByShebang` reads only the first line of text to identify the [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)). + - `GetLanguageByModeline` for cases when Vim/Emacs modeline e.g. `/* vim: set ft=cpp: */` may be present at a head or a tail of the text. + - `GetLanguageByClassifier` uses a Bayesian classifier trained on all the `./samples/` from Linguist. + + It usually is a last-resort strategy that is used to disambiguate the guess of the previous strategies, and thus it requires a list of "candidate" guesses. One can provide a list of all known languages - keys from the `data.LanguagesLogProbabilities` as possible candidates if more intelligent hypotheses are not available, at the price of possibly suboptimal accuracy. + +### By file +The most accurate guess would be one when both, the file name and the content are available: + - `GetLanguagesByContent` only uses file extension and a set of regexp-based content heuristics. + - `GetLanguages` uses the full set of matching strategies and is expected to be most accurate. + +### Filtering: vendoring, binaries, etc +*enry* expose a set of file-level helpers `Is*` to simplify filtering out the files that are less interesting for the purpose of source code analysis: + - `IsBinary` + - `IsVendor` + - `IsConfiguration` + - `IsDocumentation` + - `IsDotFile` + - `IsImage` + +### Language colors and groups +*enry* exposes function to get language color to use for example in presenting statistics in graphs: + - `GetColor` + - `GetLanguageGroup` can be used to group similar languages together e.g. for `Less` this function will return `CSS` + +## Languages + +### Go + +In a [Go module](https://github.com/golang/go/wiki/Modules), +import `enry` to the module by running: + +```sh +go get github.com/go-enry/go-enry/v2 +``` + +The rest of the examples will assume you have either done this or fetched the +library into your `GOPATH`. + +```go +// The examples here and below assume you have imported the library. +import "github.com/go-enry/go-enry/v2" + +lang, safe := enry.GetLanguageByExtension("foo.go") +fmt.Println(lang, safe) +// result: Go true + +lang, safe := enry.GetLanguageByContent("foo.m", []byte("")) +fmt.Println(lang, safe) +// result: Matlab true + +lang, safe := enry.GetLanguageByContent("bar.m", []byte("")) +fmt.Println(lang, safe) +// result: Objective-C true + +// all strategies together +lang := enry.GetLanguage("foo.cpp", []byte("")) +// result: C++ true +``` + +Note that the returned boolean value `safe` is `true` if there is only one possible language detected. + +A plural version of the same API allows getting a list of all possible languages for a given file. + +```go +langs := enry.GetLanguages("foo.h", []byte("")) +// result: []string{"C", "C++", "Objective-C} + +langs := enry.GetLanguagesByExtension("foo.asc", []byte(""), nil) +// result: []string{"AGS Script", "AsciiDoc", "Public Key"} + +langs := enry.GetLanguagesByFilename("Gemfile", []byte(""), []string{}) +// result: []string{"Ruby"} +``` + +### Java bindings + +Generated Java bindings using a C shared library and JNI are available under [`java`](https://github.com/go-enry/go-enry/blob/master/java). + +A library is published on Maven as [tech.sourced:enry-java](https://mvnrepository.com/artifact/tech.sourced/enry-java) for macOS and linux platforms. Windows support is planned under [src-d/enry#150](https://github.com/src-d/enry/issues/150). + +### Python bindings + +Generated Python bindings using a C shared library and cffi are WIP under [src-d/enry#154](https://github.com/src-d/enry/issues/154). + +A library is going to be published on pypi as [enry](https://pypi.org/project/enry/) for +macOS and linux platforms. Windows support is planned under [src-d/enry#150](https://github.com/src-d/enry/issues/150). + +Divergences from Linguist +------------ + +The `enry` library is based on the data from `github/linguist` version **v7.9.0**. + +Parsing [linguist/samples](https://github.com/github/linguist/tree/master/samples) the following `enry` results are different from the Linguist: + +* [Heuristics for ".es" extension](https://github.com/github/linguist/blob/e761f9b013e5b61161481fcb898b59721ee40e3d/lib/linguist/heuristics.yml#L103) in JavaScript could not be parsed, due to unsupported backreference in RE2 regexp engine. + +* [Heuristics for ".rno" extension](https://github.com/github/linguist/blob/3a1bd3c3d3e741a8aaec4704f782e06f5cd2a00d/lib/linguist/heuristics.yml#L365) in RUNOFF could not be parsed, due to unsupported lookahead in RE2 regexp engine. + +* [Heuristics for ".inc" extension](https://github.com/github/linguist/blob/f0e2d0d7f1ce600b2a5acccaef6b149c87d8b99c/lib/linguist/heuristics.yml#L222) in NASL could not be parsed, due to unsupported possessive quantifier in RE2 regexp engine. + +* As of [Linguist v5.3.2](https://github.com/github/linguist/releases/tag/v5.3.2) it is using [flex-based scanner in C for tokenization](https://github.com/github/linguist/pull/3846). Enry still uses [extract_token](https://github.com/github/linguist/pull/3846/files#diff-d5179df0b71620e3fac4535cd1368d15L60) regex-based algorithm. See [#193](https://github.com/src-d/enry/issues/193). + +* Bayesian classifier can't distinguish "SQL" from "PLpgSQL. See [#194](https://github.com/src-d/enry/issues/194). + +* Detection of [generated files](https://github.com/github/linguist/blob/bf95666fc15e49d556f2def4d0a85338423c25f3/lib/linguist/generated.rb#L53) is not supported yet. + (Thus they are not excluded from CLI output). See [#213](https://github.com/src-d/enry/issues/213). + +* XML detection strategy is not implemented. See [#192](https://github.com/src-d/enry/issues/192). + +* Overriding languages and types though `.gitattributes` is not yet supported. See [#18](https://github.com/src-d/enry/issues/18). + +* `enry` CLI output does NOT exclude `.gitignore`ed files and git submodules, as Linguist does + +In all the cases above that have an issue number - we plan to update enry to match Linguist behavior. + + +Benchmarks +------------ + +Enry's language detection has been compared with Linguist's on [*linguist/samples*](https://github.com/github/linguist/tree/master/samples). + +We got these results: + +![histogram](benchmarks/histogram/distribution.png) + +The histogram shows the _number of files_ (y-axis) per _time interval bucket_ (x-axis). +Most of the files were detected faster by enry. + +There are several cases where enry is slower than Linguist due to +Go regexp engine being slower than Ruby's on, wich is based on [oniguruma](https://github.com/kkos/oniguruma) library, written in C. + +See [instructions](#misc) for running enry with oniguruma. + + +Why Enry? +------------ + +In the movie [My Fair Lady](https://en.wikipedia.org/wiki/My_Fair_Lady), [Professor Henry Higgins](http://www.imdb.com/character/ch0011719/) is a linguist who at the very beginning of the movie enjoys guessing the origin of people based on their accent. + +"Enry Iggins" is how [Eliza Doolittle](http://www.imdb.com/character/ch0011720/), [pronounces](https://www.youtube.com/watch?v=pwNKyTktDIE) the name of the Professor. + +## Development + +To run the tests use: + + go test ./... + +Setting `ENRY_TEST_REPO` to the path to existing checkout of Linguist will avoid cloning it and sepeed tests up. +Setting `ENRY_DEBUG=1` will provide insight in the Bayesian classifier building done by `make code-generate`. + + +### Sync with github/linguist upstream + +*enry* re-uses parts of the original [github/linguist](https://github.com/github/linguist) to generate internal data structures. +In order to update to the latest release of linguist do: + +```bash +$ git clone https://github.com/github/linguist.git .linguist +$ cd .linguist; git checkout ; cd .. + +# put the new release's commit sha in the generator_test.go (to re-generate .gold test fixtures) +# https://github.com/go-enry/go-enry/blob/13d3d66d37a87f23a013246a1b0678c9ee3d524b/internal/code-generator/generator/generator_test.go#L18 + +$ make code-generate +``` + +To stay in sync, enry needs to be updated when a new release of the linguist includes changes to any of the following files: + +* [languages.yml](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml) +* [heuristics.yml](https://github.com/github/linguist/blob/master/lib/linguist/heuristics.yml) +* [vendor.yml](https://github.com/github/linguist/blob/master/lib/linguist/vendor.yml) +* [documentation.yml](https://github.com/github/linguist/blob/master/lib/linguist/documentation.yml) + +There is no automation for detecting the changes in the linguist project, so this process above has to be done manually from time to time. + +When submitting a pull request syncing up to a new release, please make sure it only contains the changes in +the generated files (in [data](https://github.com/go-enry/go-enry/blob/master/data) subdirectory). + +Separating all the necessary "manual" code changes to a different PR that includes some background description and an update to the documentation on ["divergences from linguist"](#divergences-from-linguist) is very much appreciated as it simplifies the maintenance (review/release notes/etc). + + + +## Misc + +
+ Running a benchmark & faster regexp engine + +### Benchmark + +All benchmark scripts are in [*benchmarks*](https://github.com/go-enry/go-enry/blob/master/benchmarks) directory. + + +#### Dependencies +As benchmarks depend on Ruby and Github-Linguist gem make sure you have: + - Ruby (e.g using [`rbenv`](https://github.com/rbenv/rbenv)), [`bundler`](https://bundler.io/) installed + - Docker + - [native dependencies](https://github.com/github/linguist/#dependencies) installed + - Build the gem `cd .linguist && bundle install && rake build_gem && cd -` + - Install it `gem install --no-rdoc --no-ri --local .linguist/github-linguist-*.gem` + + +#### Quick benchmark +To run quicker benchmarks + + make benchmarks + +to get average times for the primary detection function and strategies for the whole samples set. If you want to see measures per sample file use: + + make benchmarks-samples + + +#### Full benchmark +If you want to reproduce the same benchmarks as reported above: + - Make sure all [dependencies](#benchmark-dependencies) are installed + - Install [gnuplot](http://gnuplot.info) (in order to plot the histogram) + - Run `ENRY_TEST_REPO="$PWD/.linguist" benchmarks/run.sh` (takes ~15h) + +It will run the benchmarks for enry and Linguist, parse the output, create csv files and plot the histogram. + +### Faster regexp engine (optional) + +[Oniguruma](https://github.com/kkos/oniguruma) is CRuby's regular expression engine. +It is very fast and performs better than the one built into Go runtime. *enry* supports swapping +between those two engines thanks to [rubex](https://github.com/moovweb/rubex) project. +The typical overall speedup from using Oniguruma is 1.5-2x. However, it requires CGo and the external shared library. +On macOS with [Homebrew](https://brew.sh/), it is: + +``` +brew install oniguruma +``` + +On Ubuntu, it is + +``` +sudo apt install libonig-dev +``` + +To build enry with Oniguruma regexps use the `oniguruma` build tag + +``` +go get -v -t --tags oniguruma ./... +``` + +and then rebuild the project. + +
+ + +License +------------ + +Apache License, Version 2.0. See [LICENSE](LICENSE) diff --git a/vendor/github.com/src-d/enry/v2/classifier.go b/vendor/github.com/go-enry/go-enry/v2/classifier.go similarity index 80% rename from vendor/github.com/src-d/enry/v2/classifier.go rename to vendor/github.com/go-enry/go-enry/v2/classifier.go index e70efc38f0b44..ebc3e3b002963 100644 --- a/vendor/github.com/src-d/enry/v2/classifier.go +++ b/vendor/github.com/go-enry/go-enry/v2/classifier.go @@ -4,16 +4,16 @@ import ( "math" "sort" - "github.com/src-d/enry/v2/internal/tokenizer" + "github.com/go-enry/go-enry/v2/internal/tokenizer" ) -// Classifier is the interface in charge to detect the possible languages of the given content based on a set of +// classifier is the interface in charge to detect the possible languages of the given content based on a set of // candidates. Candidates is a map which can be used to assign weights to languages dynamically. -type Classifier interface { - Classify(content []byte, candidates map[string]float64) (languages []string) +type classifier interface { + classify(content []byte, candidates map[string]float64) (languages []string) } -type classifier struct { +type naiveBayes struct { languagesLogProbabilities map[string]float64 tokensLogProbabilities map[string]map[string]float64 tokensTotal float64 @@ -24,8 +24,8 @@ type scoredLanguage struct { score float64 } -// Classify returns a sorted slice of possible languages sorted by decreasing language's probability -func (c *classifier) Classify(content []byte, candidates map[string]float64) []string { +// classify returns a sorted slice of possible languages sorted by decreasing language's probability +func (c *naiveBayes) classify(content []byte, candidates map[string]float64) []string { var languages map[string]float64 if len(candidates) == 0 { @@ -73,7 +73,7 @@ func sortLanguagesByScore(scoredLangs []*scoredLanguage) []string { return sortedLanguages } -func (c *classifier) knownLangs() map[string]float64 { +func (c *naiveBayes) knownLangs() map[string]float64 { langs := make(map[string]float64, len(c.languagesLogProbabilities)) for lang := range c.languagesLogProbabilities { langs[lang]++ @@ -82,7 +82,7 @@ func (c *classifier) knownLangs() map[string]float64 { return langs } -func (c *classifier) tokensLogProbability(tokens []string, language string) float64 { +func (c *naiveBayes) tokensLogProbability(tokens []string, language string) float64 { var sum float64 for _, token := range tokens { sum += c.tokenProbability(token, language) @@ -91,7 +91,7 @@ func (c *classifier) tokensLogProbability(tokens []string, language string) floa return sum } -func (c *classifier) tokenProbability(token, language string) float64 { +func (c *naiveBayes) tokenProbability(token, language string) float64 { tokenProb, ok := c.tokensLogProbabilities[language][token] if !ok { tokenProb = math.Log(1.000000 / c.tokensTotal) diff --git a/vendor/github.com/src-d/enry/v2/common.go b/vendor/github.com/go-enry/go-enry/v2/common.go similarity index 91% rename from vendor/github.com/src-d/enry/v2/common.go rename to vendor/github.com/go-enry/go-enry/v2/common.go index 058d8848644b0..a5a42485476fc 100644 --- a/vendor/github.com/src-d/enry/v2/common.go +++ b/vendor/github.com/go-enry/go-enry/v2/common.go @@ -6,8 +6,8 @@ import ( "path/filepath" "strings" - "github.com/src-d/enry/v2/data" - "github.com/src-d/enry/v2/regex" + "github.com/go-enry/go-enry/v2/data" + "github.com/go-enry/go-enry/v2/regex" ) // OtherLanguage is used as a zero value when a function can not return a specific language. @@ -26,8 +26,8 @@ var DefaultStrategies = []Strategy{ GetLanguagesByClassifier, } -// DefaultClassifier is a Naive Bayes classifier trained on Linguist samples. -var DefaultClassifier Classifier = &classifier{ +// defaultClassifier is a Naive Bayes classifier trained on Linguist samples. +var defaultClassifier classifier = &naiveBayes{ languagesLogProbabilities: data.LanguagesLogProbabilities, tokensLogProbabilities: data.TokensLogProbabilities, tokensTotal: data.TokensTotal, @@ -92,7 +92,7 @@ func GetLanguageByContent(filename string, content []byte) (language string, saf } // GetLanguageByClassifier returns the most probably language detected for the given content. It uses -// DefaultClassifier, if no candidates are provided it returns OtherLanguage. +// defaultClassifier, if no candidates are provided it returns OtherLanguage. func GetLanguageByClassifier(content []byte, candidates []string) (language string, safe bool) { return getLanguageByStrategy(GetLanguagesByClassifier, "", content, candidates) } @@ -108,10 +108,10 @@ func getFirstLanguageAndSafe(languages []string) (language string, safe bool) { return } -// GetLanguageBySpecificClassifier returns the most probably language for the given content using +// getLanguageBySpecificClassifier returns the most probably language for the given content using // classifier to detect language. -func GetLanguageBySpecificClassifier(content []byte, candidates []string, classifier Classifier) (language string, safe bool) { - languages := GetLanguagesBySpecificClassifier(content, candidates, classifier) +func getLanguageBySpecificClassifier(content []byte, candidates []string, classifier classifier) (language string, safe bool) { + languages := getLanguagesBySpecificClassifier(content, candidates, classifier) return getFirstLanguageAndSafe(languages) } @@ -413,27 +413,28 @@ func GetLanguagesByContent(filename string, content []byte, _ []string) []string return heuristic.Match(content) } -// GetLanguagesByClassifier uses DefaultClassifier as a Classifier and returns a sorted slice of possible languages ordered by -// decreasing language's probability. If there are not candidates it returns nil. It complies with the signature to be a Strategy type. +// GetLanguagesByClassifier returns a sorted slice of possible languages ordered by +// decreasing language's probability. If there are not candidates it returns nil. +// It is a Strategy that uses a pre-trained defaultClassifier. func GetLanguagesByClassifier(filename string, content []byte, candidates []string) (languages []string) { if len(candidates) == 0 { return nil } - return GetLanguagesBySpecificClassifier(content, candidates, DefaultClassifier) + return getLanguagesBySpecificClassifier(content, candidates, defaultClassifier) } -// GetLanguagesBySpecificClassifier returns a slice of possible languages. It takes in a Classifier to be used. -func GetLanguagesBySpecificClassifier(content []byte, candidates []string, classifier Classifier) (languages []string) { +// getLanguagesBySpecificClassifier returns a slice of possible languages. It takes in a Classifier to be used. +func getLanguagesBySpecificClassifier(content []byte, candidates []string, classifier classifier) (languages []string) { mapCandidates := make(map[string]float64) for _, candidate := range candidates { mapCandidates[candidate]++ } - return classifier.Classify(content, mapCandidates) + return classifier.classify(content, mapCandidates) } -// GetLanguageExtensions returns the different extensions being used by the language. +// GetLanguageExtensions returns all extensions associated with the given language. func GetLanguageExtensions(language string) []string { return data.ExtensionsByLanguage[language] } @@ -470,3 +471,12 @@ func GetLanguageByAlias(alias string) (lang string, ok bool) { return } + +// GetLanguageGroup returns language group or empty string if language does not have group. +func GetLanguageGroup(language string) string { + if group, ok := data.LanguagesGroup[language]; ok { + return group + } + + return "" +} diff --git a/vendor/github.com/go-enry/go-enry/v2/data/alias.go b/vendor/github.com/go-enry/go-enry/v2/data/alias.go new file mode 100644 index 0000000000000..baa93446aaef7 --- /dev/null +++ b/vendor/github.com/go-enry/go-enry/v2/data/alias.go @@ -0,0 +1,842 @@ +// Code generated by github.com/go-enry/go-enry/v2/internal/code-generator DO NOT EDIT. +// Extracted from github/linguist commit: 40992ba7f86889f80dfed3ba95e11e1082200bad + +package data + +import "strings" + +// LanguageByAliasMap keeps alias for different languages and use the name of the languages as an alias too. +// All the keys (alias or not) are written in lower case and the whitespaces has been replaced by underscores. +var LanguageByAliasMap = map[string]string{ + "1c_enterprise": "1C Enterprise", + "4d": "4D", + "abap": "ABAP", + "abl": "OpenEdge ABL", + "abnf": "ABNF", + "abuild": "Alpine Abuild", + "acfm": "Adobe Font Metrics", + "aconf": "ApacheConf", + "actionscript": "ActionScript", + "actionscript3": "ActionScript", + "actionscript_3": "ActionScript", + "ada": "Ada", + "ada2005": "Ada", + "ada95": "Ada", + "adobe_composite_font_metrics": "Adobe Font Metrics", + "adobe_font_metrics": "Adobe Font Metrics", + "adobe_multiple_font_metrics": "Adobe Font Metrics", + "advpl": "xBase", + "afdko": "OpenType Feature File", + "agda": "Agda", + "ags": "AGS Script", + "ags_script": "AGS Script", + "ahk": "AutoHotkey", + "alloy": "Alloy", + "alpine_abuild": "Alpine Abuild", + "altium": "Altium Designer", + "altium_designer": "Altium Designer", + "amfm": "Adobe Font Metrics", + "ampl": "AMPL", + "amusewiki": "Muse", + "angelscript": "AngelScript", + "ant_build_system": "Ant Build System", + "antlr": "ANTLR", + "apache": "ApacheConf", + "apacheconf": "ApacheConf", + "apex": "Apex", + "api_blueprint": "API Blueprint", + "apkbuild": "Alpine Abuild", + "apl": "APL", + "apollo_guidance_computer": "Apollo Guidance Computer", + "applescript": "AppleScript", + "arc": "Arc", + "arexx": "REXX", + "as3": "ActionScript", + "asciidoc": "AsciiDoc", + "asm": "Assembly", + "asn.1": "ASN.1", + "asp": "ASP", + "aspectj": "AspectJ", + "aspx": "ASP", + "aspx-vb": "ASP", + "assembly": "Assembly", + "asymptote": "Asymptote", + "ats": "ATS", + "ats2": "ATS", + "au3": "AutoIt", + "augeas": "Augeas", + "autoconf": "M4Sugar", + "autohotkey": "AutoHotkey", + "autoit": "AutoIt", + "autoit3": "AutoIt", + "autoitscript": "AutoIt", + "awk": "Awk", + "b3d": "BlitzBasic", + "ballerina": "Ballerina", + "bash": "Shell", + "bash_session": "ShellSession", + "bat": "Batchfile", + "batch": "Batchfile", + "batchfile": "Batchfile", + "bazel": "Starlark", + "befunge": "Befunge", + "bibtex": "BibTeX", + "bison": "Bison", + "bitbake": "BitBake", + "blade": "Blade", + "blitz3d": "BlitzBasic", + "blitzbasic": "BlitzBasic", + "blitzmax": "BlitzMax", + "blitzplus": "BlitzBasic", + "bluespec": "Bluespec", + "bmax": "BlitzMax", + "boo": "Boo", + "bplus": "BlitzBasic", + "brainfuck": "Brainfuck", + "brightscript": "Brightscript", + "bro": "Zeek", + "bsdmake": "Makefile", + "byond": "DM", + "bzl": "Starlark", + "c": "C", + "c#": "C#", + "c++": "C++", + "c++-objdump": "Cpp-ObjDump", + "c-objdump": "C-ObjDump", + "c2hs": "C2hs Haskell", + "c2hs_haskell": "C2hs Haskell", + "cabal": "Cabal Config", + "cabal_config": "Cabal Config", + "cap'n_proto": "Cap'n Proto", + "carto": "CartoCSS", + "cartocss": "CartoCSS", + "ceylon": "Ceylon", + "cfc": "ColdFusion CFC", + "cfm": "ColdFusion", + "cfml": "ColdFusion", + "chapel": "Chapel", + "charity": "Charity", + "chpl": "Chapel", + "chuck": "ChucK", + "cirru": "Cirru", + "clarion": "Clarion", + "clean": "Clean", + "click": "Click", + "clipper": "xBase", + "clips": "CLIPS", + "clojure": "Clojure", + "closure_templates": "Closure Templates", + "cloud_firestore_security_rules": "Cloud Firestore Security Rules", + "cmake": "CMake", + "cobol": "COBOL", + "coccinelle": "SmPL", + "codeql": "CodeQL", + "coffee": "CoffeeScript", + "coffee-script": "CoffeeScript", + "coffeescript": "CoffeeScript", + "coldfusion": "ColdFusion", + "coldfusion_cfc": "ColdFusion CFC", + "coldfusion_html": "ColdFusion", + "collada": "COLLADA", + "common_lisp": "Common Lisp", + "common_workflow_language": "Common Workflow Language", + "component_pascal": "Component Pascal", + "conll": "CoNLL-U", + "conll-u": "CoNLL-U", + "conll-x": "CoNLL-U", + "console": "ShellSession", + "cool": "Cool", + "coq": "Coq", + "cperl": "Perl", + "cpp": "C++", + "cpp-objdump": "Cpp-ObjDump", + "creole": "Creole", + "crystal": "Crystal", + "csharp": "C#", + "cson": "CSON", + "csound": "Csound", + "csound-csd": "Csound Document", + "csound-orc": "Csound", + "csound-sco": "Csound Score", + "csound_document": "Csound Document", + "csound_score": "Csound Score", + "css": "CSS", + "csv": "CSV", + "cucumber": "Gherkin", + "cuda": "Cuda", + "curl_config": "cURL Config", + "curlrc": "cURL Config", + "cweb": "CWeb", + "cwl": "Common Workflow Language", + "cycript": "Cycript", + "cython": "Cython", + "d": "D", + "d-objdump": "D-ObjDump", + "darcs_patch": "Darcs Patch", + "dart": "Dart", + "dataweave": "DataWeave", + "dcl": "DIGITAL Command Language", + "delphi": "Component Pascal", + "desktop": "desktop", + "dhall": "Dhall", + "diff": "Diff", + "digital_command_language": "DIGITAL Command Language", + "dircolors": "dircolors", + "directx_3d_file": "DirectX 3D File", + "django": "HTML+Django", + "dm": "DM", + "dns_zone": "DNS Zone", + "dockerfile": "Dockerfile", + "dogescript": "Dogescript", + "dosbatch": "Batchfile", + "dosini": "INI", + "dpatch": "Darcs Patch", + "dtrace": "DTrace", + "dtrace-script": "DTrace", + "dylan": "Dylan", + "e": "E", + "eagle": "Eagle", + "easybuild": "Easybuild", + "ebnf": "EBNF", + "ec": "eC", + "ecere_projects": "Ecere Projects", + "ecl": "ECL", + "eclipse": "ECLiPSe", + "ecr": "HTML+ECR", + "editor-config": "EditorConfig", + "editorconfig": "EditorConfig", + "edje_data_collection": "Edje Data Collection", + "edn": "edn", + "eeschema_schematic": "KiCad Schematic", + "eex": "HTML+EEX", + "eiffel": "Eiffel", + "ejs": "EJS", + "elisp": "Emacs Lisp", + "elixir": "Elixir", + "elm": "Elm", + "emacs": "Emacs Lisp", + "emacs_lisp": "Emacs Lisp", + "emacs_muse": "Muse", + "emberscript": "EmberScript", + "eml": "EML", + "eq": "EQ", + "erb": "HTML+ERB", + "erlang": "Erlang", + "f#": "F#", + "f*": "F*", + "factor": "Factor", + "fancy": "Fancy", + "fantom": "Fantom", + "faust": "Faust", + "figfont": "FIGlet Font", + "figlet_font": "FIGlet Font", + "filebench_wml": "Filebench WML", + "filterscript": "Filterscript", + "fish": "fish", + "flex": "Lex", + "flux": "FLUX", + "formatted": "Formatted", + "forth": "Forth", + "fortran": "Fortran", + "foxpro": "xBase", + "freemarker": "FreeMarker", + "frege": "Frege", + "fsharp": "F#", + "fstar": "F*", + "ftl": "FreeMarker", + "fundamental": "Text", + "g-code": "G-code", + "game_maker_language": "Game Maker Language", + "gaml": "GAML", + "gams": "GAMS", + "gap": "GAP", + "gcc_machine_description": "GCC Machine Description", + "gdb": "GDB", + "gdscript": "GDScript", + "genie": "Genie", + "genshi": "Genshi", + "gentoo_ebuild": "Gentoo Ebuild", + "gentoo_eclass": "Gentoo Eclass", + "gerber_image": "Gerber Image", + "gettext_catalog": "Gettext Catalog", + "gf": "Grammatical Framework", + "gherkin": "Gherkin", + "git-ignore": "Ignore List", + "git_attributes": "Git Attributes", + "git_config": "Git Config", + "gitattributes": "Git Attributes", + "gitconfig": "Git Config", + "gitignore": "Ignore List", + "gitmodules": "Git Config", + "glsl": "GLSL", + "glyph": "Glyph", + "glyph_bitmap_distribution_format": "Glyph Bitmap Distribution Format", + "gn": "GN", + "gnuplot": "Gnuplot", + "go": "Go", + "golang": "Go", + "golo": "Golo", + "gosu": "Gosu", + "grace": "Grace", + "gradle": "Gradle", + "grammatical_framework": "Grammatical Framework", + "graph_modeling_language": "Graph Modeling Language", + "graphql": "GraphQL", + "graphviz_(dot)": "Graphviz (DOT)", + "groff": "Roff", + "groovy": "Groovy", + "groovy_server_pages": "Groovy Server Pages", + "gsp": "Groovy Server Pages", + "hack": "Hack", + "haml": "Haml", + "handlebars": "Handlebars", + "haproxy": "HAProxy", + "harbour": "Harbour", + "haskell": "Haskell", + "haxe": "Haxe", + "hbs": "Handlebars", + "hcl": "HCL", + "hiveql": "HiveQL", + "hlsl": "HLSL", + "holyc": "HolyC", + "html": "HTML", + "html+django": "HTML+Django", + "html+django/jinja": "HTML+Django", + "html+ecr": "HTML+ECR", + "html+eex": "HTML+EEX", + "html+erb": "HTML+ERB", + "html+jinja": "HTML+Django", + "html+php": "HTML+PHP", + "html+razor": "HTML+Razor", + "html+ruby": "RHTML", + "htmlbars": "Handlebars", + "htmldjango": "HTML+Django", + "http": "HTTP", + "hxml": "HXML", + "hy": "Hy", + "hylang": "Hy", + "hyphy": "HyPhy", + "i7": "Inform 7", + "idl": "IDL", + "idris": "Idris", + "ignore": "Ignore List", + "ignore_list": "Ignore List", + "igor": "IGOR Pro", + "igor_pro": "IGOR Pro", + "igorpro": "IGOR Pro", + "inc": "PHP", + "inform7": "Inform 7", + "inform_7": "Inform 7", + "ini": "INI", + "inno_setup": "Inno Setup", + "inputrc": "Readline Config", + "io": "Io", + "ioke": "Ioke", + "ipython_notebook": "Jupyter Notebook", + "irc": "IRC log", + "irc_log": "IRC log", + "irc_logs": "IRC log", + "isabelle": "Isabelle", + "isabelle_root": "Isabelle ROOT", + "j": "J", + "jasmin": "Jasmin", + "java": "Java", + "java_properties": "Java Properties", + "java_server_page": "Groovy Server Pages", + "java_server_pages": "Java Server Pages", + "javascript": "JavaScript", + "javascript+erb": "JavaScript+ERB", + "jflex": "JFlex", + "jison": "Jison", + "jison_lex": "Jison Lex", + "jolie": "Jolie", + "jruby": "Ruby", + "js": "JavaScript", + "json": "JSON", + "json5": "JSON5", + "json_with_comments": "JSON with Comments", + "jsonc": "JSON with Comments", + "jsoniq": "JSONiq", + "jsonld": "JSONLD", + "jsonnet": "Jsonnet", + "jsp": "Java Server Pages", + "jsx": "JSX", + "julia": "Julia", + "jupyter_notebook": "Jupyter Notebook", + "kicad_layout": "KiCad Layout", + "kicad_legacy_layout": "KiCad Legacy Layout", + "kicad_schematic": "KiCad Schematic", + "kit": "Kit", + "kotlin": "Kotlin", + "krl": "KRL", + "labview": "LabVIEW", + "lasso": "Lasso", + "lassoscript": "Lasso", + "latex": "TeX", + "latte": "Latte", + "lean": "Lean", + "less": "Less", + "lex": "Lex", + "lfe": "LFE", + "lhaskell": "Literate Haskell", + "lhs": "Literate Haskell", + "lilypond": "LilyPond", + "limbo": "Limbo", + "linker_script": "Linker Script", + "linux_kernel_module": "Linux Kernel Module", + "liquid": "Liquid", + "lisp": "Common Lisp", + "litcoffee": "Literate CoffeeScript", + "literate_agda": "Literate Agda", + "literate_coffeescript": "Literate CoffeeScript", + "literate_haskell": "Literate Haskell", + "live-script": "LiveScript", + "livescript": "LiveScript", + "llvm": "LLVM", + "logos": "Logos", + "logtalk": "Logtalk", + "lolcode": "LOLCODE", + "lookml": "LookML", + "loomscript": "LoomScript", + "ls": "LiveScript", + "lsl": "LSL", + "ltspice_symbol": "LTspice Symbol", + "lua": "Lua", + "m": "M", + "m4": "M4", + "m4sugar": "M4Sugar", + "m68k": "Motorola 68K Assembly", + "macruby": "Ruby", + "make": "Makefile", + "makefile": "Makefile", + "mako": "Mako", + "man": "Roff", + "man-page": "Roff", + "man_page": "Roff", + "manpage": "Roff", + "markdown": "Markdown", + "marko": "Marko", + "markojs": "Marko", + "mask": "Mask", + "mathematica": "Mathematica", + "matlab": "MATLAB", + "maven_pom": "Maven POM", + "max": "Max", + "max/msp": "Max", + "maxmsp": "Max", + "maxscript": "MAXScript", + "mcfunction": "mcfunction", + "mdoc": "Roff", + "mediawiki": "MediaWiki", + "mercury": "Mercury", + "meson": "Meson", + "metal": "Metal", + "mf": "Makefile", + "microsoft_developer_studio_project": "Microsoft Developer Studio Project", + "minid": "MiniD", + "mirah": "Mirah", + "mirc_script": "mIRC Script", + "mlir": "MLIR", + "mma": "Mathematica", + "modelica": "Modelica", + "modula-2": "Modula-2", + "modula-3": "Modula-3", + "module_management_system": "Module Management System", + "monkey": "Monkey", + "moocode": "Moocode", + "moonscript": "MoonScript", + "motorola_68k_assembly": "Motorola 68K Assembly", + "mql4": "MQL4", + "mql5": "MQL5", + "mtml": "MTML", + "muf": "MUF", + "mumps": "M", + "mupad": "mupad", + "muse": "Muse", + "myghty": "Myghty", + "nanorc": "nanorc", + "nasl": "NASL", + "nasm": "Assembly", + "ncl": "NCL", + "nearley": "Nearley", + "nemerle": "Nemerle", + "neosnippet": "Vim Snippet", + "nesc": "nesC", + "netlinx": "NetLinx", + "netlinx+erb": "NetLinx+ERB", + "netlogo": "NetLogo", + "newlisp": "NewLisp", + "nextflow": "Nextflow", + "nginx": "Nginx", + "nginx_configuration_file": "Nginx", + "nim": "Nim", + "ninja": "Ninja", + "nit": "Nit", + "nix": "Nix", + "nixos": "Nix", + "njk": "HTML+Django", + "nl": "NL", + "node": "JavaScript", + "npm_config": "NPM Config", + "npmrc": "NPM Config", + "nroff": "Roff", + "nsis": "NSIS", + "nu": "Nu", + "numpy": "NumPy", + "nunjucks": "HTML+Django", + "nush": "Nu", + "nvim": "Vim script", + "obj-c": "Objective-C", + "obj-c++": "Objective-C++", + "obj-j": "Objective-J", + "objc": "Objective-C", + "objc++": "Objective-C++", + "objdump": "ObjDump", + "object_data_instance_notation": "Object Data Instance Notation", + "objective-c": "Objective-C", + "objective-c++": "Objective-C++", + "objective-j": "Objective-J", + "objectivec": "Objective-C", + "objectivec++": "Objective-C++", + "objectivej": "Objective-J", + "objectpascal": "Component Pascal", + "objectscript": "ObjectScript", + "objj": "Objective-J", + "ocaml": "OCaml", + "octave": "MATLAB", + "odin": "Odin", + "odin-lang": "Odin", + "odinlang": "Odin", + "omgrofl": "Omgrofl", + "oncrpc": "RPC", + "ooc": "ooc", + "opa": "Opa", + "opal": "Opal", + "open_policy_agent": "Open Policy Agent", + "opencl": "OpenCL", + "openedge": "OpenEdge ABL", + "openedge_abl": "OpenEdge ABL", + "openqasm": "OpenQASM", + "openrc": "OpenRC runscript", + "openrc_runscript": "OpenRC runscript", + "openscad": "OpenSCAD", + "openstep_property_list": "OpenStep Property List", + "opentype_feature_file": "OpenType Feature File", + "org": "Org", + "osascript": "AppleScript", + "ox": "Ox", + "oxygene": "Oxygene", + "oz": "Oz", + "p4": "P4", + "pan": "Pan", + "pandoc": "Markdown", + "papyrus": "Papyrus", + "parrot": "Parrot", + "parrot_assembly": "Parrot Assembly", + "parrot_internal_representation": "Parrot Internal Representation", + "pascal": "Pascal", + "pasm": "Parrot Assembly", + "pawn": "Pawn", + "pcbnew": "KiCad Layout", + "pep8": "Pep8", + "perl": "Perl", + "perl-6": "Raku", + "perl6": "Raku", + "php": "PHP", + "pic": "Pic", + "pickle": "Pickle", + "picolisp": "PicoLisp", + "piglatin": "PigLatin", + "pike": "Pike", + "pir": "Parrot Internal Representation", + "plantuml": "PlantUML", + "plpgsql": "PLpgSQL", + "plsql": "PLSQL", + "pod": "Pod", + "pod_6": "Pod 6", + "pogoscript": "PogoScript", + "pony": "Pony", + "posh": "PowerShell", + "postcss": "PostCSS", + "postscr": "PostScript", + "postscript": "PostScript", + "pot": "Gettext Catalog", + "pov-ray": "POV-Ray SDL", + "pov-ray_sdl": "POV-Ray SDL", + "povray": "POV-Ray SDL", + "powerbuilder": "PowerBuilder", + "powershell": "PowerShell", + "prisma": "Prisma", + "processing": "Processing", + "progress": "OpenEdge ABL", + "proguard": "Proguard", + "prolog": "Prolog", + "propeller_spin": "Propeller Spin", + "protobuf": "Protocol Buffer", + "protocol_buffer": "Protocol Buffer", + "protocol_buffers": "Protocol Buffer", + "public_key": "Public Key", + "pug": "Pug", + "puppet": "Puppet", + "pure_data": "Pure Data", + "purebasic": "PureBasic", + "purescript": "PureScript", + "pwsh": "PowerShell", + "pycon": "Python console", + "pyrex": "Cython", + "python": "Python", + "python3": "Python", + "python_console": "Python console", + "python_traceback": "Python traceback", + "q": "q", + "ql": "CodeQL", + "qmake": "QMake", + "qml": "QML", + "quake": "Quake", + "r": "R", + "racket": "Racket", + "ragel": "Ragel", + "ragel-rb": "Ragel", + "ragel-ruby": "Ragel", + "rake": "Ruby", + "raku": "Raku", + "raml": "RAML", + "rascal": "Rascal", + "raw": "Raw token data", + "raw_token_data": "Raw token data", + "razor": "HTML+Razor", + "rb": "Ruby", + "rbx": "Ruby", + "rdoc": "RDoc", + "readline": "Readline Config", + "readline_config": "Readline Config", + "realbasic": "REALbasic", + "reason": "Reason", + "rebol": "Rebol", + "red": "Red", + "red/system": "Red", + "redcode": "Redcode", + "regex": "Regular Expression", + "regexp": "Regular Expression", + "regular_expression": "Regular Expression", + "ren'py": "Ren'Py", + "renderscript": "RenderScript", + "renpy": "Ren'Py", + "restructuredtext": "reStructuredText", + "rexx": "REXX", + "rhtml": "RHTML", + "rich_text_format": "Rich Text Format", + "ring": "Ring", + "riot": "Riot", + "rmarkdown": "RMarkdown", + "robotframework": "RobotFramework", + "roff": "Roff", + "roff_manpage": "Roff Manpage", + "rouge": "Rouge", + "rpc": "RPC", + "rpcgen": "RPC", + "rpm_spec": "RPM Spec", + "rs-274x": "Gerber Image", + "rscript": "R", + "rss": "XML", + "rst": "reStructuredText", + "ruby": "Ruby", + "runoff": "RUNOFF", + "rust": "Rust", + "rusthon": "Python", + "sage": "Sage", + "salt": "SaltStack", + "saltstack": "SaltStack", + "saltstate": "SaltStack", + "sas": "SAS", + "sass": "Sass", + "scala": "Scala", + "scaml": "Scaml", + "scheme": "Scheme", + "scilab": "Scilab", + "scss": "SCSS", + "sed": "sed", + "self": "Self", + "sh": "Shell", + "shaderlab": "ShaderLab", + "shell": "Shell", + "shell-script": "Shell", + "shellsession": "ShellSession", + "shen": "Shen", + "slash": "Slash", + "slice": "Slice", + "slim": "Slim", + "smali": "Smali", + "smalltalk": "Smalltalk", + "smarty": "Smarty", + "sml": "Standard ML", + "smpl": "SmPL", + "smt": "SMT", + "snipmate": "Vim Snippet", + "snippet": "YASnippet", + "solidity": "Solidity", + "sourcemod": "SourcePawn", + "sourcepawn": "SourcePawn", + "soy": "Closure Templates", + "sparql": "SPARQL", + "specfile": "RPM Spec", + "spline_font_database": "Spline Font Database", + "splus": "R", + "sqf": "SQF", + "sql": "SQL", + "sqlpl": "SQLPL", + "squeak": "Smalltalk", + "squirrel": "Squirrel", + "srecode_template": "SRecode Template", + "ssh_config": "SSH Config", + "stan": "Stan", + "standard_ml": "Standard ML", + "starlark": "Starlark", + "stata": "Stata", + "ston": "STON", + "stylus": "Stylus", + "subrip_text": "SubRip Text", + "sugarss": "SugarSS", + "supercollider": "SuperCollider", + "svelte": "Svelte", + "svg": "SVG", + "swift": "Swift", + "swig": "SWIG", + "systemverilog": "SystemVerilog", + "tcl": "Tcl", + "tcsh": "Tcsh", + "tea": "Tea", + "terra": "Terra", + "terraform": "HCL", + "tex": "TeX", + "texinfo": "Texinfo", + "text": "Text", + "textile": "Textile", + "thrift": "Thrift", + "ti_program": "TI Program", + "tl": "Type Language", + "tla": "TLA", + "toml": "TOML", + "troff": "Roff", + "ts": "TypeScript", + "tsql": "TSQL", + "tsx": "TSX", + "turing": "Turing", + "turtle": "Turtle", + "twig": "Twig", + "txl": "TXL", + "type_language": "Type Language", + "typescript": "TypeScript", + "udiff": "Diff", + "ultisnip": "Vim Snippet", + "ultisnips": "Vim Snippet", + "unified_parallel_c": "Unified Parallel C", + "unity3d_asset": "Unity3D Asset", + "unix_assembly": "Unix Assembly", + "uno": "Uno", + "unrealscript": "UnrealScript", + "ur": "UrWeb", + "ur/web": "UrWeb", + "urweb": "UrWeb", + "v": "V", + "vala": "Vala", + "vb.net": "Visual Basic .NET", + "vb6": "VBA", + "vb_.net": "Visual Basic .NET", + "vba": "VBA", + "vbnet": "Visual Basic .NET", + "vbscript": "VBScript", + "vcl": "VCL", + "verilog": "Verilog", + "vhdl": "VHDL", + "vim": "Vim script", + "vim_script": "Vim script", + "vim_snippet": "Vim Snippet", + "viml": "Vim script", + "visual_basic": "Visual Basic .NET", + "visual_basic_.net": "Visual Basic .NET", + "visual_basic_6": "VBA", + "visual_basic_for_applications": "VBA", + "vlang": "V", + "volt": "Volt", + "vue": "Vue", + "wasm": "WebAssembly", + "wast": "WebAssembly", + "wavefront_material": "Wavefront Material", + "wavefront_object": "Wavefront Object", + "wdl": "wdl", + "web_ontology_language": "Web Ontology Language", + "webassembly": "WebAssembly", + "webidl": "WebIDL", + "webvtt": "WebVTT", + "wget_config": "Wget Config", + "wgetrc": "Wget Config", + "winbatch": "Batchfile", + "windows_registry_entries": "Windows Registry Entries", + "wisp": "wisp", + "wollok": "Wollok", + "world_of_warcraft_addon_data": "World of Warcraft Addon Data", + "wsdl": "XML", + "x10": "X10", + "x_bitmap": "X BitMap", + "x_font_directory_index": "X Font Directory Index", + "x_pixmap": "X PixMap", + "xbase": "xBase", + "xbm": "X BitMap", + "xc": "XC", + "xcompose": "XCompose", + "xdr": "RPC", + "xhtml": "HTML", + "xml": "XML", + "xml+genshi": "Genshi", + "xml+kid": "Genshi", + "xml_property_list": "XML Property List", + "xojo": "Xojo", + "xpages": "XPages", + "xpm": "X PixMap", + "xproc": "XProc", + "xquery": "XQuery", + "xs": "XS", + "xsd": "XML", + "xsl": "XSLT", + "xslt": "XSLT", + "xten": "X10", + "xtend": "Xtend", + "yacc": "Yacc", + "yaml": "YAML", + "yang": "YANG", + "yara": "YARA", + "yas": "YASnippet", + "yasnippet": "YASnippet", + "yml": "YAML", + "zap": "ZAP", + "zeek": "Zeek", + "zenscript": "ZenScript", + "zephir": "Zephir", + "zig": "Zig", + "zil": "ZIL", + "zimpl": "Zimpl", + "zsh": "Shell", +} + +// LanguageByAlias looks up the language name by it's alias or name. +// It mirrors the logic of github linguist and is needed e.g for heuristcs.yml +// that mixes names and aliases in a language field (see XPM example). +func LanguageByAlias(langOrAlias string) (lang string, ok bool) { + k := convertToAliasKey(langOrAlias) + lang, ok = LanguageByAliasMap[k] + return +} + +// convertToAliasKey converts language name to a key in LanguageByAliasMap. +// Following +// - internal.code-generator.generator.convertToAliasKey() +// - GetLanguageByAlias() +// conventions. +// It is here to avoid dependency on "generate" and "enry" packages. +func convertToAliasKey(langName string) string { + ak := strings.SplitN(langName, `,`, 2)[0] + ak = strings.Replace(ak, ` `, `_`, -1) + ak = strings.ToLower(ak) + return ak +} diff --git a/vendor/github.com/src-d/enry/v2/data/colors.go b/vendor/github.com/go-enry/go-enry/v2/data/colors.go similarity index 92% rename from vendor/github.com/src-d/enry/v2/data/colors.go rename to vendor/github.com/go-enry/go-enry/v2/data/colors.go index 39d2acc2df192..3e47ce1b3a909 100644 --- a/vendor/github.com/src-d/enry/v2/data/colors.go +++ b/vendor/github.com/go-enry/go-enry/v2/data/colors.go @@ -1,5 +1,5 @@ -// Code generated by github.com/src-d/enry/v2/internal/code-generator DO NOT EDIT. -// Extracted from github/linguist commit: 3a1bd3c3d3e741a8aaec4704f782e06f5cd2a00d +// Code generated by github.com/go-enry/go-enry/v2/internal/code-generator DO NOT EDIT. +// Extracted from github/linguist commit: 40992ba7f86889f80dfed3ba95e11e1082200bad package data @@ -71,11 +71,13 @@ var LanguagesColor = map[string]string{ "Factor": "#636746", "Fancy": "#7b9db4", "Fantom": "#14253c", + "Faust": "#c37240", "Forth": "#341708", "Fortran": "#4d41b1", "FreeMarker": "#0050b2", "Frege": "#00cafe", "G-code": "#D08CF2", + "GAML": "#FFC766", "GDScript": "#355570", "Game Maker Language": "#71b417", "Genie": "#fb855d", @@ -96,6 +98,7 @@ var LanguagesColor = map[string]string{ "HolyC": "#ffefaf", "Hy": "#7790B2", "IDL": "#a3522f", + "IGOR Pro": "#0000cc", "Idris": "#b30000", "Io": "#a9188d", "Ioke": "#078193", @@ -121,6 +124,7 @@ var LanguagesColor = map[string]string{ "Lua": "#000080", "MATLAB": "#e16737", "MAXScript": "#00a6a6", + "MLIR": "#5EC8DB", "MQL4": "#62A8D6", "MQL5": "#4A76B8", "MTML": "#b7e1f4", @@ -149,8 +153,10 @@ var LanguagesColor = map[string]string{ "Objective-C": "#438eff", "Objective-C++": "#6866fb", "Objective-J": "#ff0c5a", + "Odin": "#60AFFE", "Omgrofl": "#cabbff", "Opal": "#f7ede0", + "OpenQASM": "#AA70FF", "Oxygene": "#cdd0e3", "Oz": "#fab738", "P4": "#7055b5", @@ -163,7 +169,6 @@ var LanguagesColor = map[string]string{ "Pawn": "#dbb284", "Pep8": "#C76F5B", "Perl": "#0298c3", - "Perl 6": "#0000fb", "PigLatin": "#fcd7de", "Pike": "#005390", "PogoScript": "#d80074", @@ -184,11 +189,14 @@ var LanguagesColor = map[string]string{ "RUNOFF": "#665a4e", "Racket": "#3c5caa", "Ragel": "#9d5200", + "Raku": "#0000fb", "Rascal": "#fffaa0", + "Reason": "#ff5847", "Rebol": "#358a5b", "Red": "#f50000", "Ren'Py": "#ff7f7f", "Ring": "#2D54CB", + "Riot": "#A71E49", "Roff": "#ecdebe", "Rouge": "#cc0088", "Ruby": "#701516", @@ -204,12 +212,14 @@ var LanguagesColor = map[string]string{ "Shen": "#120F14", "Slash": "#007eff", "Slice": "#003fa2", + "SmPL": "#c94949", "Smalltalk": "#596706", "Solidity": "#AA6746", "SourcePawn": "#5c7611", "Squirrel": "#800000", "Stan": "#b2011d", "Standard ML": "#dc566d", + "Starlark": "#76d275", "SuperCollider": "#46390b", "Swift": "#ffac45", "SystemVerilog": "#DAE1C2", @@ -220,12 +230,15 @@ var LanguagesColor = map[string]string{ "Turing": "#cf142b", "TypeScript": "#2b7489", "UnrealScript": "#a54c4d", + "V": "#5d87bd", + "VBA": "#867db1", + "VBScript": "#15dcdc", "VCL": "#148AA8", "VHDL": "#adb2cb", "Vala": "#fbe5cd", "Verilog": "#b2b7f8", "Vim script": "#199f4b", - "Visual Basic": "#945db7", + "Visual Basic .NET": "#945db7", "Volt": "#1F1F1F", "Vue": "#2c3e50", "WebAssembly": "#04133b", @@ -243,6 +256,7 @@ var LanguagesColor = map[string]string{ "Zephir": "#118f9e", "Zig": "#ec915c", "eC": "#913960", + "mIRC Script": "#926059", "mcfunction": "#E22837", "nesC": "#94B0C7", "ooc": "#b0b77e", diff --git a/vendor/github.com/go-enry/go-enry/v2/data/commit.go b/vendor/github.com/go-enry/go-enry/v2/data/commit.go new file mode 100644 index 0000000000000..abe581387c487 --- /dev/null +++ b/vendor/github.com/go-enry/go-enry/v2/data/commit.go @@ -0,0 +1,7 @@ +// Code generated by github.com/go-enry/go-enry/v2/internal/code-generator DO NOT EDIT. +// Extracted from github/linguist commit: 40992ba7f86889f80dfed3ba95e11e1082200bad + +package data + +// linguist's commit from which files were generated. +var LinguistCommit = "40992ba7f86889f80dfed3ba95e11e1082200bad" diff --git a/vendor/github.com/src-d/enry/v2/data/content.go b/vendor/github.com/go-enry/go-enry/v2/data/content.go similarity index 89% rename from vendor/github.com/src-d/enry/v2/data/content.go rename to vendor/github.com/go-enry/go-enry/v2/data/content.go index dab33dd86680a..8f62f98f249b4 100644 --- a/vendor/github.com/src-d/enry/v2/data/content.go +++ b/vendor/github.com/go-enry/go-enry/v2/data/content.go @@ -1,12 +1,12 @@ -// Code generated by github.com/src-d/enry/v2/internal/code-generator DO NOT EDIT. -// Extracted from github/linguist commit: 3a1bd3c3d3e741a8aaec4704f782e06f5cd2a00d +// Code generated by github.com/go-enry/go-enry/v2/internal/code-generator DO NOT EDIT. +// Extracted from github/linguist commit: 40992ba7f86889f80dfed3ba95e11e1082200bad package data import ( "regexp" - "github.com/src-d/enry/v2/data/rule" + "github.com/go-enry/go-enry/v2/data/rule" ) var ContentHeuristics = map[string]*Heuristics{ @@ -591,6 +591,12 @@ var ContentHeuristics = map[string]*Heuristics{ regexp.MustCompile(`(?m)^(\/\/.+|((import|export)\s+)?(function|int|float|char)\s+((room|repeatedly|on|game)_)?([A-Za-z]+[A-Za-z_0-9]+)\s*[;\(])`), ), }, + ".asm": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Motorola 68K Assembly"), + regexp.MustCompile(`(?m)(?im)\bmoveq(?:\.l)?\s+#(?:\$-?[0-9a-f]{1,3}|%[0-1]{1,8}|-?[0-9]{1,3}),\s*d[0-7]\b|(?im)^\s*move(?:\.[bwl])?\s+(?:sr|usp),\s*[^\s]+|(?im)^\s*move\.[bwl]\s+.*\b[ad]\d|(?im)^\s*movem\.[bwl]\b|(?im)^\s*move[mp](?:\.[wl])?\b|(?im)^\s*btst\b|(?im)^\s*dbra\b`), + ), + }, ".asy": &Heuristics{ rule.Or( rule.MatchingLanguages("LTspice Symbol"), @@ -673,6 +679,16 @@ var ContentHeuristics = map[string]*Heuristics{ regexp.MustCompile(`(?m)([\/\\].*:\s+.*\s\\$|: \\$|^[ %]:|^[\w\s\/\\.]+\w+\.\w+\s*:\s+[\w\s\/\\.]+\w+\.\w+)`), ), }, + ".dsp": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Microsoft Developer Studio Project"), + regexp.MustCompile(`(?m)# Microsoft Developer Studio Generated Build File`), + ), + rule.Or( + rule.MatchingLanguages("Faust"), + regexp.MustCompile(`(?m)\bprocess\s*[(=]|\b(library|import)\s*\(\s*"|\bdeclare\s+(name|version|author|copyright|license)\s+"`), + ), + }, ".ecl": &Heuristics{ rule.Or( rule.MatchingLanguages("ECLiPSe"), @@ -772,6 +788,10 @@ var ContentHeuristics = map[string]*Heuristics{ ), }, ".gs": &Heuristics{ + rule.Or( + rule.MatchingLanguages("GLSL"), + regexp.MustCompile(`(?m)^#version\s+[0-9]+\b`), + ), rule.Or( rule.MatchingLanguages("Gosu"), regexp.MustCompile(`(?m)^uses java\.`), @@ -793,6 +813,16 @@ var ContentHeuristics = map[string]*Heuristics{ regexp.MustCompile(`(?m)<\?hh`), ), }, + ".i": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Motorola 68K Assembly"), + regexp.MustCompile(`(?m)(?im)\bmoveq(?:\.l)?\s+#(?:\$-?[0-9a-f]{1,3}|%[0-1]{1,8}|-?[0-9]{1,3}),\s*d[0-7]\b|(?im)^\s*move(?:\.[bwl])?\s+(?:sr|usp),\s*[^\s]+|(?im)^\s*move\.[bwl]\s+.*\b[ad]\d|(?im)^\s*movem\.[bwl]\b|(?im)^\s*move[mp](?:\.[wl])?\b|(?im)^\s*btst\b|(?im)^\s*dbra\b`), + ), + rule.Or( + rule.MatchingLanguages("SWIG"), + regexp.MustCompile(`(?m)^[ \t]*%[a-z_]+\b|^%[{}]$`), + ), + }, ".ice": &Heuristics{ rule.Or( rule.MatchingLanguages("JSON"), @@ -803,6 +833,10 @@ var ContentHeuristics = map[string]*Heuristics{ ), }, ".inc": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Motorola 68K Assembly"), + regexp.MustCompile(`(?m)(?im)\bmoveq(?:\.l)?\s+#(?:\$-?[0-9a-f]{1,3}|%[0-1]{1,8}|-?[0-9]{1,3}),\s*d[0-7]\b|(?im)^\s*move(?:\.[bwl])?\s+(?:sr|usp),\s*[^\s]+|(?im)^\s*move\.[bwl]\s+.*\b[ad]\d|(?im)^\s*movem\.[bwl]\b|(?im)^\s*move[mp](?:\.[wl])?\b|(?im)^\s*btst\b|(?im)^\s*dbra\b`), + ), rule.Or( rule.MatchingLanguages("PHP"), regexp.MustCompile(`(?m)^<\?(?:php)?`), @@ -931,6 +965,12 @@ var ContentHeuristics = map[string]*Heuristics{ rule.MatchingLanguages("Roff"), ), }, + ".mask": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Unity3d Asset"), + regexp.MustCompile(`(?m)tag:unity3d.com`), + ), + }, ".md": &Heuristics{ rule.Or( rule.MatchingLanguages("Markdown"), @@ -1047,6 +1087,25 @@ var ContentHeuristics = map[string]*Heuristics{ rule.MatchingLanguages("NewLisp"), ), }, + ".odin": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Object Data Instance Notation"), + regexp.MustCompile(`(?m)(?:^|<)\s*[A-Za-z0-9_]+\s*=\s*<`), + ), + rule.Or( + rule.MatchingLanguages("Odin"), + regexp.MustCompile(`(?m)package\s+\w+|\b(?:im|ex)port\s*"[\w:./]+"|\w+\s*::\s*(?:proc|struct)\s*\(|^\s*//\s`), + ), + }, + ".p": &Heuristics{ + rule.Or( + rule.MatchingLanguages("Gnuplot"), + regexp.MustCompile(`(?m)^s?plot\b|^set\s+(term|terminal|out|output|[xy]tics|[xy]label|[xy]range|style)\b`), + ), + rule.Always( + rule.MatchingLanguages("OpenEdge ABL"), + ), + }, ".php": &Heuristics{ rule.Or( rule.MatchingLanguages("Hack"), @@ -1067,17 +1126,26 @@ var ContentHeuristics = map[string]*Heuristics{ regexp.MustCompile(`(?m)\buse\s+(?:strict\b|v?5\.)`), ), rule.Or( - rule.MatchingLanguages("Perl 6"), + rule.MatchingLanguages("Raku"), regexp.MustCompile(`(?m)^\s*(?:use\s+v6\b|\bmodule\b|\b(?:my\s+)?class\b)`), ), }, + ".plist": &Heuristics{ + rule.Or( + rule.MatchingLanguages("XML Property List"), + regexp.MustCompile(`(?m)": -6.085258, + "ASSERT": -5.104429, + "C": -2.619523, + "CONTENT": -7.183871, + "C_COLLECTION": -7.183871, + "C_OBJECT": -4.698964, + "C_TEXT": -4.986646, + "Case": -6.085258, + "Choose": -7.183871, + "Count": -6.085258, + "Current": -6.490724, + "Else": -5.237961, + "End": -4.475821, + "False": -5.797576, + "File": -7.183871, + "Folder": -6.085258, + "For": -6.490724, + "Formula": -5.392111, + "Get": -6.085258, + "HTTP": -6.085258, + "If": -4.986646, + "In": -7.183871, + "Is": -6.085258, + "JSON": -7.183871, + "K": -4.881286, + "Length": -7.183871, + "New": -5.104429, + "Null": -5.392111, + "OBJECT": -7.183871, + "OPEN": -7.183871, + "PAGE": -7.183871, + "PREFERENCE": -7.183871, + "SET": -6.085258, + "String": -5.574433, + "Stringify": -7.183871, + "This": -4.986646, + "True": -5.574433, + "URL": -7.183871, + "VISIBLE": -7.183871, + "Value": -6.490724, + "WA": -5.797576, + "WEB": -6.490724, + "Web": -7.183871, + "Year": -7.183871, + "[": -5.104429, + "\\": -4.544813, + "]": -5.104429, + "ascending": -6.085258, + "attributes": -5.797576, + "base": -6.490724, + "c": -5.797576, + "c.orderBy": -7.183871, + "c.push": -7.183871, + "case": -5.797576, + "cases": -7.183871, + "ck": -6.085258, + "class": -5.797576, + "clear_files": -7.183871, + "collection": -5.797576, + "content": -7.183871, + "database": -7.183871, + "date": -6.490724, + "db": -7.183871, + "each": -5.797576, + "enable": -7.183871, + "error": -7.183871, + "fk": -5.797576, + "folder": -6.490724, + "for": -6.490724, + "from": -6.490724, + "generate_project_plugin_stub": -7.183871, + "generate_project_source": -7.183871, + "generate_project_vs": -7.183871, + "generate_project_xcode": -7.183871, + "get": -7.183871, + "if": -4.986646, + "info": -7.183871, + "initiatialisation": -7.183871, + "inspector": -7.183871, + "macOS": -7.183871, + "newIndex": -6.490724, + "newIndex.getText": -7.183871, + "o": -4.986646, + "o.constructor": -7.183871, + "o.fomulas.push": -7.183871, + "o.functions": -7.183871, + "o.functions.orderBy": -7.183871, + "o.functions.push": -7.183871, + "o.name": -6.085258, + "o.properties": -7.183871, + "o.properties.orderBy": -7.183871, + "o.properties.push": -6.490724, + "o.url": -6.490724, + "object": -5.237961, + "of": -5.797576, + "options.webPortID": -7.183871, + "parameters": -6.085258, + "params": -5.574433, + "params.AUTHOR": -7.183871, + "params.COPYRIGHT_YEAR": -7.183871, + "params.CREATE_DATE": -7.183871, + "params.PRODUCT_NAME": -7.183871, + "params.PRODUCT_VERSION": -7.183871, + "path": -5.797576, + "path.platformPath": -7.183871, + "platform": -6.490724, + "response": -5.797576, + "result": -6.490724, + "result#Null": -7.183871, + "result.success": -7.183871, + "rl": -6.490724, + "rl.path": -7.183871, + "root": -7.183871, + "server": -6.490724, + "settings": -6.085258, + "settings.HTTPEnabled": -7.183871, + "settings.HTTPPort": -7.183871, + "settings.HTTPSEnabled": -7.183871, + "settings.HTTPSPort": -7.183871, + "settings.certificateFolder": -7.183871, + "settings.defaultHomepage": -7.183871, + "settings.rootFolder": -6.490724, + "some": -7.183871, + "statusCode": -5.797576, + "string": -6.490724, + "t": -3.888034, + "the": -7.183871, + "true": -7.183871, + "type": -6.490724, + "using": -7.183871, + "we": -7.183871, + "web": -7.183871, + "webArea": -6.085258, + "webObject": -6.490724, + "webObject.isRunning": -7.183871, + "webObject.start": -7.183871, + "webObject.stop": -7.183871, + "webServer": -7.183871, + "widget": -7.183871, + "{": -5.797576, + "}": -5.797576, + "…": -2.159990, + }, "ABAP": map[string]float64{ - "!": -4.637712, - "\"": -7.202661, - "(": -5.816367, - ")": -5.816367, - "*": -3.619142, - "+": -5.005437, - "-": -0.322277, - ".": -5.005437, - "<-()]>": -6.509514, - "": -6.509514, - "": -5.816367, - "": -6.104049, - "=": -4.900076, - ">": -5.123220, - "ABAP_BOOL": -7.202661, - "C": -7.202661, - "CLASS": -6.509514, - "CL_CSV_PARSER": -5.410902, - "CONSTRUCTOR": -7.202661, - "CSV": -7.202661, - "CSVSTRING": -7.202661, - "CX": -7.202661, - "CX_CSV_PARSE_ERROR": -7.202661, - "DEFINITION": -6.509514, - "DELEGATE": -7.202661, - "Get": -7.202661, - "IF_CSV_PARSER_DELEGATE": -7.202661, - "IMPLEMENTATION": -6.509514, - "Instance": -6.509514, - "Method": -6.509514, - "Parse": -7.202661, - "Private": -7.202661, - "Public": -7.202661, - "REF": -7.202661, - "RETURNING": -7.202661, - "SEPARATOR": -7.202661, - "SIGNATURE": -6.509514, - "SKIP_FIRST_LINE": -7.202661, - "STRING": -7.202661, - "STRINGTAB": -6.104049, - "Space": -6.509514, - "TO": -7.202661, - "TYPE": -5.256751, - "This": -7.202661, - "[": -5.593223, - "]": -5.816367, - "_LINES": -7.202661, - "_csvstring": -6.509514, - "_delegate": -7.202661, - "_lines": -7.202661, - "_lines.": -7.202661, - "_parse_line": -6.509514, - "_separator": -7.202661, - "_skip_first_line": -7.202661, - "_textindicator": -7.202661, - "`": -5.816367, - "abap": -7.202661, - "abap_bool": -6.509514, - "abap_true.": -6.509514, - "an": -7.202661, - "append": -6.509514, - "assigning": -7.202661, - "at": -6.509514, - "c": -6.509514, - "char": -6.509514, - "cl_abap_char_utilities": -7.202661, - "cl_csv_parser": -6.509514, - "cl_object": -7.202661, - "class": -6.509514, - "clear": -7.202661, - "concatenate": -5.816367, - "constants": -7.202661, - "constructor": -6.509514, - "constructor.": -7.202661, - "cr_lf": -7.202661, - "create": -7.202661, - "csv": -7.202661, - "csvstring": -7.202661, - "csvstring.": -7.202661, - "csvvalue": -5.410902, - "csvvalue.": -5.593223, - "csvvalues.": -6.509514, - "cx_csv_parse_error": -6.509514, - "data": -6.104049, - "definition": -7.202661, - "delegate": -7.202661, - "delegate.": -7.202661, - "do": -6.104049, - "e": -7.202661, - "else.": -5.816367, - "endclass.": -7.202661, - "endif.": -5.410902, - "endmethod.": -6.509514, - "endwhile.": -6.509514, - "error": -7.202661, - "exception": -7.202661, - "exporting": -7.202661, - "field": -7.202661, - "files": -6.104049, - "final": -7.202661, - "formatting": -7.202661, - "from": -7.202661, - "here": -6.104049, - "if_csv_parser_delegate": -7.202661, - "implementation.": -7.202661, - "importing": -7.202661, - "in": -7.202661, - "include": -6.104049, - "indicates": -7.202661, - "inheriting": -7.202661, - "into": -5.410902, - "is_first_line": -7.202661, - "line": -7.202661, - "lines": -5.816367, - "loop": -7.202661, - "message": -6.509514, - "method": -6.509514, - "methods": -6.509514, - "msg.": -6.509514, - "not": -6.104049, - "of": -6.509514, - "other": -6.104049, - "parse": -6.509514, - "pools": -7.202661, - "pos": -6.509514, - "private": -7.202661, - "protected": -7.202661, - "public": -6.104049, - "raise": -7.202661, - "raising": -7.202661, - "ref": -7.202661, - "returning.": -7.202661, - "section.": -6.104049, - "separator": -7.202661, - "separator.": -7.202661, - "skip_first_line": -7.202661, - "skip_first_line.": -7.202661, - "source": -6.104049, - "split": -7.202661, - "standard": -6.509514, - "string": -7.202661, - "string.": -6.104049, - "super": -7.202661, - "symbols": -7.202661, - "table": -6.104049, - "text_ended": -7.202661, - "the": -6.104049, - "to": -6.104049, - "type": -4.804766, - "value": -6.509514, - "values": -6.509514, - "|": -5.256751, + "!": -4.570738, + "\"": -7.135687, + "(": -5.749393, + ")": -5.749393, + "*": -3.580339, + "+": -5.056246, + "-": -0.345590, + ".": -4.938463, + "<-()]>": -6.442540, + "": -6.442540, + "": -5.749393, + "": -6.037075, + "=": -4.833102, + ">": -5.056246, + "ABAP_BOOL": -7.135687, + "C": -7.135687, + "CLASS": -6.442540, + "CL_CSV_PARSER": -5.343928, + "CONSTRUCTOR": -7.135687, + "CSV": -7.135687, + "CSVSTRING": -7.135687, + "CX": -7.135687, + "CX_CSV_PARSE_ERROR": -7.135687, + "DEFINITION": -6.442540, + "DELEGATE": -7.135687, + "Get": -7.135687, + "IF_CSV_PARSER_DELEGATE": -7.135687, + "IMPLEMENTATION": -6.442540, + "Instance": -6.442540, + "Method": -6.442540, + "Parse": -7.135687, + "Private": -7.135687, + "Public": -7.135687, + "REF": -7.135687, + "RETURNING": -6.442540, + "SEPARATOR": -7.135687, + "SIGNATURE": -6.442540, + "SKIP_FIRST_LINE": -7.135687, + "STRING": -7.135687, + "STRINGTAB": -6.442540, + "Space": -6.442540, + "TO": -7.135687, + "TYPE": -5.343928, + "This": -7.135687, + "[": -5.526249, + "]": -5.749393, + "_LINES": -7.135687, + "_csvstring": -6.442540, + "_delegate": -7.135687, + "_lines": -7.135687, + "_lines.": -7.135687, + "_parse_line": -6.442540, + "_separator": -7.135687, + "_skip_first_line": -7.135687, + "_textindicator": -7.135687, + "`": -5.749393, + "abap": -7.135687, + "abap_bool": -6.442540, + "abap_true.": -6.442540, + "an": -7.135687, + "append": -6.442540, + "assigning": -7.135687, + "at": -6.442540, + "c": -6.442540, + "char": -6.442540, + "cl_abap_char_utilities": -7.135687, + "cl_csv_parser": -6.442540, + "cl_object": -7.135687, + "class": -6.442540, + "clear": -7.135687, + "concatenate": -5.749393, + "constants": -7.135687, + "constructor": -6.442540, + "constructor.": -7.135687, + "cr_lf": -7.135687, + "create": -7.135687, + "csv": -7.135687, + "csvstring": -7.135687, + "csvstring.": -7.135687, + "csvvalue": -5.343928, + "csvvalue.": -5.526249, + "csvvalues.": -6.442540, + "cx_csv_parse_error": -6.442540, + "data": -6.037075, + "definition": -7.135687, + "delegate": -7.135687, + "delegate.": -7.135687, + "do": -6.037075, + "e": -7.135687, + "else.": -5.749393, + "endclass.": -7.135687, + "endif.": -5.343928, + "endmethod.": -6.442540, + "endwhile.": -6.442540, + "error": -7.135687, + "exception": -7.135687, + "exporting": -7.135687, + "field": -7.135687, + "files": -6.037075, + "final": -7.135687, + "formatting": -7.135687, + "from": -7.135687, + "here": -6.037075, + "if_csv_parser_delegate": -7.135687, + "implementation.": -7.135687, + "importing": -7.135687, + "in": -7.135687, + "include": -6.037075, + "indicates": -7.135687, + "inheriting": -7.135687, + "into": -5.343928, + "is_first_line": -7.135687, + "line": -7.135687, + "lines": -5.749393, + "loop": -7.135687, + "message": -6.442540, + "method": -6.442540, + "methods": -6.442540, + "msg.": -6.442540, + "not": -6.037075, + "of": -6.442540, + "other": -6.037075, + "parse": -6.442540, + "pools": -7.135687, + "pos": -6.442540, + "private": -7.135687, + "protected": -7.135687, + "public": -6.037075, + "raise": -7.135687, + "raising": -7.135687, + "ref": -7.135687, + "returning.": -7.135687, + "section.": -6.037075, + "separator": -7.135687, + "separator.": -7.135687, + "skip_first_line": -7.135687, + "skip_first_line.": -7.135687, + "source": -6.037075, + "split": -7.135687, + "standard": -6.442540, + "string": -7.135687, + "string.": -6.037075, + "super": -7.135687, + "symbols": -7.135687, + "table": -6.037075, + "text_ended": -7.135687, + "the": -6.037075, + "to": -6.037075, + "type": -4.737792, + "value": -6.442540, + "values": -6.442540, + "|": -5.189777, }, "ABNF": map[string]float64{ "%": -3.171745, @@ -1376,266 +1582,269 @@ var TokensLogProbabilities = map[string]map[string]float64{ "–": -5.622211, }, "APL": map[string]float64{ - "!": -7.546446, - "#": -7.546446, - "#.": -6.853299, - "#.DISPLAY": -7.546446, - "#.Files.Dir": -7.546446, - "#.UT.appdir": -6.447834, - "#.UT.expect": -7.546446, - "#.UT.run": -7.546446, - "(": -3.521095, - ")": -3.503395, - "+": -5.061540, - ",": -3.080538, - "-": -5.349222, - "/": -4.907389, - "//tryapl.org/": -7.546446, - "/C": -7.546446, - "/Functions": -7.546446, - "/Page": -7.546446, - "/Z": -7.546446, - "/config": -7.546446, - "/input": -7.546446, - "/lines": -7.546446, - "/usr/local/bin/apl": -7.546446, - ":": -3.341754, - ";": -3.341754, - "": -7.546446, - "": -7.546446, - "": -7.546446, - "": -7.546446, - "": -6.853299, - "": -7.546446, - "": -7.546446, - "": -7.546446, - "
":                              -7.546446,
-		"":                           -7.548556,
+		"":                           -6.855409,
+		"":                              -7.548556,
+		"":                             -7.548556,
+		"":                             -7.548556,
+		"
":                              -7.548556,
+		"":                       -5.793014,
-		"":                       -5.793014,
-		"":                         -5.793014,
-		"":                         -5.793014,
-		"":                         -5.793014,
-		"":         -5.793014,
-		"":           -4.694401,
-		"":                       -5.783825,
+		"":                       -5.783825,
+		"":                         -5.783825,
+		"":                         -5.783825,
+		"":                         -5.783825,
+		"":         -5.783825,
+		"":           -4.685213,
+		"":             -8.567126,
-		"":             -6.082219,
-		"":             -8.567126,
-		"":                -5.234921,
-		"":              -6.775366,
-		"":             -7.180831,
-		"":                -5.928068,
-		"":                -6.487684,
-		"":                  -8.567126,
-		"

": -8.567126, - "": -4.318630, - "": -6.775366, - "
": -7.468513, - "
": -6.775366, - "