From 2ac2a5b0ba9f9a07867ed92792de7d54a8e10d23 Mon Sep 17 00:00:00 2001 From: mrsdizzie Date: Mon, 3 Jun 2019 11:11:20 -0400 Subject: [PATCH 01/30] Refactor submodule URL parsing (#7100) Use combination of url.Parse and regex to parse refURL rather than by hand with indexes & attempt to check if refURL is from same instance and adjust output to match. Also now return empty string instead of our original guess at URL if we are unable to parse it. Fixes #1526 --- modules/git/submodule.go | 88 ++++++++++++++++++++++++----------- modules/git/submodule_test.go | 13 +++++- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/modules/git/submodule.go b/modules/git/submodule.go index 294df3986aded..6fc2e2444fc08 100644 --- a/modules/git/submodule.go +++ b/modules/git/submodule.go @@ -1,10 +1,19 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2015 The Gogs 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 git -import "strings" +import ( + "fmt" + "net" + "net/url" + "regexp" + "strings" +) + +var scpSyntax = regexp.MustCompile(`^([a-zA-Z0-9_]+@)?([a-zA-Z0-9._-]+):(.*)$`) // SubModule submodule is a reference on git repository type SubModule struct { @@ -34,46 +43,73 @@ func getRefURL(refURL, urlPrefix, parentPath string) string { return "" } - url := strings.TrimSuffix(refURL, ".git") - - // git://xxx/user/repo - if strings.HasPrefix(url, "git://") { - return "http://" + strings.TrimPrefix(url, "git://") - } + refURI := strings.TrimSuffix(refURL, ".git") - // http[s]://xxx/user/repo - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { - return url + prefixURL, _ := url.Parse(urlPrefix) + urlPrefixHostname, _, err := net.SplitHostPort(prefixURL.Host) + if err != nil { + urlPrefixHostname = prefixURL.Host } // Relative url prefix check (according to git submodule documentation) - if strings.HasPrefix(url, "./") || strings.HasPrefix(url, "../") { + if strings.HasPrefix(refURI, "./") || strings.HasPrefix(refURI, "../") { // ...construct and return correct submodule url here... idx := strings.Index(parentPath, "/src/") if idx == -1 { - return url + return refURI } - return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + url + return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + refURI } - // sysuser@xxx:user/repo - i := strings.Index(url, "@") - j := strings.LastIndex(url, ":") + if !strings.Contains(refURI, "://") { + // scp style syntax which contains *no* port number after the : (and is not parsed by net/url) + // ex: git@try.gitea.io:go-gitea/gitea + match := scpSyntax.FindAllStringSubmatch(refURI, -1) + if len(match) > 0 { - // Only process when i < j because git+ssh://git@git.forwardbias.in/npploader.git - if i > -1 && j > -1 && i < j { - // fix problem with reverse proxy works only with local server - if strings.Contains(urlPrefix, url[i+1:j]) { - return urlPrefix + url[j+1:] + m := match[0] + refHostname := m[2] + path := m[3] + + if !strings.HasPrefix(path, "/") { + path = "/" + path + } + + if urlPrefixHostname == refHostname { + return prefixURL.Scheme + "://" + urlPrefixHostname + path + } + return "http://" + refHostname + path } - if strings.HasPrefix(url, "ssh://") || strings.HasPrefix(url, "git+ssh://") { - k := strings.Index(url[j+1:], "/") - return "http://" + url[i+1:j] + "/" + url[j+1:][k+1:] + } + + ref, err := url.Parse(refURI) + if err != nil { + return "" + } + + refHostname, _, err := net.SplitHostPort(ref.Host) + if err != nil { + refHostname = ref.Host + } + + supportedSchemes := []string{"http", "https", "git", "ssh", "git+ssh"} + + for _, scheme := range supportedSchemes { + if ref.Scheme == scheme { + if urlPrefixHostname == refHostname { + return prefixURL.Scheme + "://" + prefixURL.Host + ref.Path + } else if ref.Scheme == "http" || ref.Scheme == "https" { + if len(ref.User.Username()) > 0 { + return ref.Scheme + "://" + fmt.Sprintf("%v", ref.User) + "@" + ref.Host + ref.Path + } + return ref.Scheme + "://" + ref.Host + ref.Path + } else { + return "http://" + refHostname + ref.Path + } } - return "http://" + url[i+1:j] + "/" + url[j+1:] } - return url + return "" } // RefURL guesses and returns reference URL. diff --git a/modules/git/submodule_test.go b/modules/git/submodule_test.go index 6a3bb7ec7bab9..fd6c2aa95569d 100644 --- a/modules/git/submodule_test.go +++ b/modules/git/submodule_test.go @@ -19,8 +19,19 @@ func TestGetRefURL(t *testing.T) { }{ {"git://github.com/user1/repo1", "/", "/", "http://github.com/user1/repo1"}, {"https://localhost/user1/repo1.git", "/", "/", "https://localhost/user1/repo1"}, - {"git@github.com/user1/repo1.git", "/", "/", "git@github.com/user1/repo1"}, + {"http://localhost/user1/repo1.git", "/", "/", "http://localhost/user1/repo1"}, + {"git@github.com:user1/repo1.git", "/", "/", "http://github.com/user1/repo1"}, {"ssh://git@git.zefie.net:2222/zefie/lge_g6_kernel_scripts.git", "/", "/", "http://git.zefie.net/zefie/lge_g6_kernel_scripts"}, + {"git@git.zefie.net:2222/zefie/lge_g6_kernel_scripts.git", "/", "/", "http://git.zefie.net/2222/zefie/lge_g6_kernel_scripts"}, + {"git@try.gitea.io:go-gitea/gitea", "https://try.gitea.io/go-gitea/gitea", "/", "https://try.gitea.io/go-gitea/gitea"}, + {"ssh://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/go-gitea/gitea", "/", "https://try.gitea.io/go-gitea/gitea"}, + {"git://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/go-gitea/log", "/", "https://try.gitea.io/go-gitea/gitea"}, + {"ssh://git@127.0.0.1:9999/go-gitea/gitea", "https://127.0.0.1:3000/go-gitea/log", "/", "https://127.0.0.1:3000/go-gitea/gitea"}, + {"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/go-gitea/gitea", "/", "https://gitea.com:3000/user1/repo1"}, + {"https://username:password@github.com/username/repository.git", "/", "/", "https://username:password@github.com/username/repository"}, + {"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", ""}, + {"git@localhost:user/repo", "https://localhost/user/repo2", "/", "https://localhost/user/repo"}, + {"../path/to/repo.git/", "https://localhost/user/repo2/src/branch/master/test", "/", "../path/to/repo.git/"}, } for _, kase := range kases { From 160e7edd047c0e26eb3ab806c8c73551a74f881a Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 3 Jun 2019 15:13:51 +0000 Subject: [PATCH 02/30] [skip ci] Updated translations via Crowdin --- options/locale/locale_fr-FR.ini | 2 +- options/locale/locale_pt-BR.ini | 2 ++ options/locale/locale_zh-CN.ini | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index e6755f8cb5662..45e6dbf20bbd8 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -91,7 +91,7 @@ ssl_mode=SSL charset=Jeu de caractères path=Emplacement sqlite_helper=Chemin d'accès pour la base de données SQLite3.
Entrer un chemin absolu si vous exécutez Gitea en tant que service. -err_empty_db_path=Le chemin de la base de donnée SQLite3 ne peut être vide. +err_empty_db_path=Le chemin de la base de données SQLite3 ne peut être vide. no_admin_and_disable_registration=Vous ne pouvez pas désactiver la création de nouveaux utilisateurs avant d'avoir créé un compte administrateur. err_empty_admin_password=Le mot de passe administrateur ne peut pas être vide. err_empty_admin_email=L'adresse e-mail de l'administrateur ne peut pas être vide. diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 65b26c6ee9101..011b9f9e549b9 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -1521,6 +1521,8 @@ dashboard.delete_repo_archives=Excluir todos os arquivos do repositório dashboard.delete_repo_archives_success=Todos os arquivos do repositório foram excluídos. dashboard.delete_missing_repos=Excluir todos os repositórios que não possuem seus arquivos Git dashboard.delete_missing_repos_success=Todos os repositórios que não possuem seus arquivos Git foram excluídos. +dashboard.delete_generated_repository_avatars=Excluir avatares gerados do repositório +dashboard.delete_generated_repository_avatars_success=Os avatares gerados do repositório foram excluídos. dashboard.git_gc_repos=Coleta de lixo em todos os repositórios dashboard.git_gc_repos_success=Todos os repositórios finalizaram a execução da coleta de lixo. dashboard.resync_all_sshkeys=Atualizar o arquivo '.ssh/authorized_keys' com as chaves SSH do Gitea. (Não necessária para o servidor SSH nativo.) diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 5ac415460d721..1a2ed9fc1f81d 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -926,7 +926,7 @@ issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓 issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 issues.review.approve=已批准这些更改 %s -issues.review.comment=已评审 %s +issues.review.comment=评审于 %s issues.review.content.empty=您需要留下一个注释,表明需要的更改。 issues.review.reject=请求变更 %s issues.review.pending=待定 From 2a8037fe4e95f2197f1123e43e5c626de9826eb8 Mon Sep 17 00:00:00 2001 From: John Olheiser <42128690+jolheiser@users.noreply.github.com> Date: Tue, 4 Jun 2019 14:36:09 -0500 Subject: [PATCH 03/30] Migration Tweaks (#6260) * Adds auto-name if repo name is blank Adds error checking before sanitization in migration Signed-off-by: jolheiser * Changed err from sanitization to a different variable Signed-off-by: jolheiser * Remove handleCreatePost and implement separately Signed-off-by: jolheiser * Make fmt Signed-off-by: jolheiser --- public/js/index.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/public/js/index.js b/public/js/index.js index 96a56a42415c7..ed3198594a3fa 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -2160,6 +2160,14 @@ $(document).ready(function () { break; } } + + var $cloneAddr = $('#clone_addr'); + $cloneAddr.change(function() { + var $repoName = $('#repo_name'); + if ($cloneAddr.val().length > 0 && $repoName.val().length === 0) { // Only modify if repo_name input is blank + $repoName.val($cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3]); + } + }); }); function changeHash(hash) { From 8bf405986e9940be863088e65903d4e2e2fe84ce Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Tue, 4 Jun 2019 23:01:47 +0200 Subject: [PATCH 04/30] Add Rust highlighting (#7125) --- modules/highlight/highlight.go | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go index 6d5e1a97ba769..cb52f6ac2ea9e 100644 --- a/modules/highlight/highlight.go +++ b/modules/highlight/highlight.go @@ -51,6 +51,7 @@ var ( ".php": {}, ".py": {}, ".rb": {}, + ".rs": {}, ".scss": {}, ".sql": {}, ".scala": {}, From 5d3177dbb650b64eed4a1f35c7e469438270b90b Mon Sep 17 00:00:00 2001 From: Nick Meyer Date: Tue, 4 Jun 2019 20:17:17 -0500 Subject: [PATCH 05/30] Exclude pull_request from fetch-tags step, fixes #7108 (#7120) Signed-off-by: Nick Meyer --- .drone.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.drone.yml b/.drone.yml index 6d9cde5ca9539..0b8c8422b63b4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,6 +7,9 @@ pipeline: image: docker:git commands: - git fetch --tags --force + when: + event: + exclude: [ pull_request ] download_translations: image: jonasfranz/crowdin From 3fb54e11c1bb6375b19758af89f88e330018c363 Mon Sep 17 00:00:00 2001 From: katherine Date: Wed, 5 Jun 2019 07:16:06 -0700 Subject: [PATCH 06/30] minor fixes in en-US locale (#7130) a few spelling fixes and one rewritten line Signed-off-by: katherine --- options/locale/locale_en-US.ini | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index ebc6ca31ce30d..71c76fd9b6ada 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -488,7 +488,7 @@ manage_oauth2_applications = Manage OAuth2 Applications edit_oauth2_application = Edit OAuth2 Application oauth2_applications_desc = OAuth2 applications enables your third-party application to securely authenticate users at this Gitea instance. remove_oauth2_application = Remove OAuth2 Application -remove_oauth2_application_desc = Removing an OAuth2 application will revoke access to all signed access tokes. Continue? +remove_oauth2_application_desc = Removing an OAuth2 application will revoke access to all signed access tokens. Continue? remove_oauth2_application_success = The application has been deleted. create_oauth2_application = Create a new OAuth2 Application create_oauth2_application_button = Create Application @@ -620,7 +620,7 @@ migrate.permission_denied = You are not allowed to import local repositories. migrate.invalid_local_path = "The local path is invalid. It does not exist or is not a directory." migrate.failed = Migration failed: %v migrate.lfs_mirror_unsupported = Mirroring LFS objects is not supported - use 'git lfs fetch --all' and 'git lfs push --all' instead. -migrate.migrate_items_options = When you are migrating from github and inputed username, the migration options will be display. +migrate.migrate_items_options = When migrating from github, input a username and migration options will be displayed. mirror_from = mirror of forked_from = forked from @@ -1307,14 +1307,14 @@ settings.archive.button = Archive Repo settings.archive.header = Archive This Repo settings.archive.text = Archiving the repo will make it entirely read-only. It is hidden from the dashboard, cannot be committed to and no issues or pull-requests can be created. settings.archive.success = The repo was successfully archived. -settings.archive.error = An error occured while trying to archive the repo. See the log for more details. +settings.archive.error = An error occurred while trying to archive the repo. See the log for more details. settings.archive.error_ismirror = You cannot archive a mirrored repo. settings.archive.branchsettings_unavailable = Branch settings are not available if the repo is archived. settings.unarchive.button = Un-Archive Repo settings.unarchive.header = Un-Archive This Repo -settings.unarchive.text = Un-Archiving the repo will restore its ability to recieve commits and pushes, as well as new issues and pull-requests. +settings.unarchive.text = Un-Archiving the repo will restore its ability to receive commits and pushes, as well as new issues and pull-requests. settings.unarchive.success = The repo was successfully un-archived. -settings.unarchive.error = An error occured while trying to un-archive the repo. See the log for more details. +settings.unarchive.error = An error occurred while trying to un-archive the repo. See the log for more details. settings.update_avatar_success = The repository avatar has been updated. diff.browse_source = Browse Source From a6fed1542c851e874484392a7bef14118ca19928 Mon Sep 17 00:00:00 2001 From: Lanre Adelowo Date: Wed, 5 Jun 2019 17:24:09 +0100 Subject: [PATCH 07/30] add docs for #6847 (#7132) --- docs/content/doc/usage/command-line.en-us.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/content/doc/usage/command-line.en-us.md b/docs/content/doc/usage/command-line.en-us.md index ab52109e93584..516e46ff0bf20 100644 --- a/docs/content/doc/usage/command-line.en-us.md +++ b/docs/content/doc/usage/command-line.en-us.md @@ -62,6 +62,7 @@ Admin operations: - `--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 From 59e6a7b97f503c12ef2a6096ca7f127f81521b7a Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Wed, 5 Jun 2019 16:26:53 +0000 Subject: [PATCH 08/30] [skip ci] Updated translations via Crowdin --- options/locale/locale_cs-CZ.ini | 4 -- options/locale/locale_de-DE.ini | 5 --- options/locale/locale_fr-FR.ini | 7 +--- options/locale/locale_ja-JP.ini | 5 --- options/locale/locale_lv-LV.ini | 3 -- options/locale/locale_pt-BR.ini | 5 --- options/locale/locale_ru-RU.ini | 66 ++++++++++++++++++++++++++++++++- options/locale/locale_zh-CN.ini | 5 --- 8 files changed, 66 insertions(+), 34 deletions(-) diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index bd503ac5615d5..13bb4f9c05391 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -478,7 +478,6 @@ manage_oauth2_applications=Spravovat OAuth2 aplikace edit_oauth2_application=Upravit OAuth2 aplikaci oauth2_applications_desc=OAuth2 aplikace umožní aplikacím třetích stran bezpečně ověřit uživatele v této instanci Gitea. remove_oauth2_application=Odstranit OAuth2 aplikaci -remove_oauth2_application_desc=Odstraněním OAuth2 aplikace odeberete přístup všem podepsaným přístupovým poukázkám. Pokračovat? remove_oauth2_application_success=Aplikace byla odstraněna. create_oauth2_application=Vytvořit novou OAuth2 aplikaci create_oauth2_application_button=Vytvořit aplikaci @@ -1258,14 +1257,11 @@ settings.archive.button=Archivovat repozitář settings.archive.header=Archivovat tento repozitář settings.archive.text=Archivní repozitář bude kompletně jen pro čtení. Nezobrazuje se v přehledu, nelze přidávat revize ani nové úkoly a požadavky na natažení. settings.archive.success=Repozitář byl úspěšně archivován. -settings.archive.error=Nastala chyba při archivování repozitáře. Prohlédněte si záznam pro více detailů. settings.archive.error_ismirror=Nemůžete archivovat zrcadlený repozitář. settings.archive.branchsettings_unavailable=Nastavení větví není dostupné, pokud je repozitář archivovaný. settings.unarchive.button=Obnovit repozitář settings.unarchive.header=Obnovit tento repozitář -settings.unarchive.text=Obnovení repozitáře vrátí možnost přijímání revizí a nahrávání. Stejně tak se obnoví i možnost zadávání nových úkolů a požadavků na natažení. settings.unarchive.success=Repozitář byl úspěšně obnoven. -settings.unarchive.error=Nastala chyba při obnovování repozitáře. Prohlédněte si záznam pro více detailů. diff.browse_source=Procházet zdrojové kódy diff.parent=rodič diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 7c24abefabe46..7a0b61d2eef95 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -487,7 +487,6 @@ manage_oauth2_applications=OAuth2 Anwendungen verwalten edit_oauth2_application=OAuth2 Anwendung bearbeiten oauth2_applications_desc=OAuth2-Anwendungen ermöglichen die sichere Authentifizierung von Benutzern dieser Gitea-Instanz für deine Drittanwendung. remove_oauth2_application=OAuth2-Anwendung entfernen -remove_oauth2_application_desc=Wenn du diese OAuth2 Anwendung entfernst, werden auch alle davon ausgestellte Access Tokens ungültig. Möchtest du fortfahren? remove_oauth2_application_success=Die Anwendung wurde gelöscht. create_oauth2_application=Neue OAuth2 Anwendung erstellen create_oauth2_application_button=Anwendung erstellen @@ -619,7 +618,6 @@ migrate.permission_denied=Du hast keine Berechtigung zum Importieren lokaler Rep migrate.invalid_local_path=Der lokale Pfad ist ungültig, existiert nicht oder ist kein Ordner. migrate.failed=Fehler bei der Migration: %v migrate.lfs_mirror_unsupported=Spiegeln von LFS-Objekten wird nicht unterstützt - nutze stattdessen 'git lfs fetch --all' und 'git lfs push --all'. -migrate.migrate_items_options=Wenn du von GitHub migrierst und einen Benutzernamen eingegeben hast, werden die Migrationsoptionen angezeigt. mirror_from=Mirror von forked_from=geforkt von @@ -1306,14 +1304,11 @@ settings.archive.button=Repo archivieren settings.archive.header=Dieses Repo archivieren settings.archive.text=Durch die Archivierung des Repos wird es vollständig schreibgeschützt. Es wird auf dem Dashboard versteckt, nimmt keine Commits an und es können keine Issues oder Pull-Requests erstellt werden. settings.archive.success=Das Repo wurde erfolgreich archiviert. -settings.archive.error=Beim Archivieren des Repos trat ein Fehler auf. In den Logs befinden sich mehr Details. settings.archive.error_ismirror=Du kannst keinen Repo-Mirror archivieren. settings.archive.branchsettings_unavailable=Branch-Einstellungen sind nicht verfügbar wenn das Repo archiviert ist. settings.unarchive.button=Archivieren rückgängig machen settings.unarchive.header=Archivieren dieses Repos rückgängig machen -settings.unarchive.text=Das Rückgängig machen dieses Repo-Archivs stellt seine Fähigkeit wieder her, Commits und Pushes anzunehmen, sowie neue Issues und Pull-Requests zu erstellen. settings.unarchive.success=Die Archivierung des Repos wurde erfolgreich wieder rückgängig gemacht. -settings.unarchive.error=Beim Rückgängig machen dieses Repo-Archivs trat ein Fehler auf. In den Logs befinden sich mehr Details. settings.update_avatar_success=Der Repository-Avatar wurde aktualisiert. diff.browse_source=Quellcode durchsuchen diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 45e6dbf20bbd8..0b077d931d57a 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -487,7 +487,6 @@ manage_oauth2_applications=Gérer les applications OAuth2 edit_oauth2_application=Modifier l'application OAuth2 oauth2_applications_desc=Les applications OAuth2 permettent à votre application tiers d'authentifier en toute sécurité les utilisateurs de cette instance Gitea. remove_oauth2_application=Supprimer l'application OAuth2 -remove_oauth2_application_desc=Supprimer une application OAuth2 révoquera l'accès à tous les points d'accès signés. Continuer ? remove_oauth2_application_success=L'application a été supprimée. create_oauth2_application=Créer une nouvelle application OAuth2 create_oauth2_application_button=Créer une application @@ -619,7 +618,6 @@ migrate.permission_denied=Vous n'êtes pas autorisé à importer des dépôts lo migrate.invalid_local_path=Chemin local non valide, non existant ou n'étant pas un dossier. migrate.failed=Echec de migration: %v migrate.lfs_mirror_unsupported=La synchronisation des objets LFS n'est pas supportée - veuillez utiliser 'git lfs fetch --all' et 'git lfs push --all' à la place. -migrate.migrate_items_options=Quand vous migrez depuis github, une fois le nom d'utilisateur saisi, des options de migration supplémentaires seront affichées. mirror_from=miroir de forked_from=bifurqué depuis @@ -1306,14 +1304,11 @@ settings.archive.button=Archiver ce dépôt settings.archive.header=Archiver ce dépôt settings.archive.text=Archiver ce dépôt le rendra en lecture seule. Il sera caché du tableau de bord et vous ne pourrez plus envoyer de révision ni créer de ticket ou demande d'ajout. settings.archive.success=Ce dépôt a été archivé avec succès. -settings.archive.error=Une erreur s'est produite durant l'archivage. Referez-vous au journal pour plus de détails. settings.archive.error_ismirror=Vous ne pouvez pas archiver un dépôt en miroir. settings.archive.branchsettings_unavailable=Le paramétrage des branches n'est pas disponible quand le dépôt est archivé. settings.unarchive.button=Désarchiver ce dépôt settings.unarchive.header=Désarchiver ce dépôt -settings.unarchive.text=Désarchiver le dépôt lui permettra de recevoir des révisions, ainsi que des nouveaux tickets ou demandes d'ajout. settings.unarchive.success=Ce dépôt a été désarchivé avec succès. -settings.unarchive.error=Une erreur s'est produite durant le désarchivage. Referez-vous au journal pour plus de détails. settings.update_avatar_success=L'avatar du dépôt a été mis à jour. diff.browse_source=Parcourir la source @@ -1521,6 +1516,8 @@ dashboard.delete_repo_archives=Supprimer toutes les archives du dépôt dashboard.delete_repo_archives_success=Toutes les archives du dépôt ont été supprimées. dashboard.delete_missing_repos=Supprimer tous les dépôts dont les fichiers Git sont manquants dashboard.delete_missing_repos_success=Tous les dépôts dont les fichiers Git sont manquants ont été supprimés. +dashboard.delete_generated_repository_avatars=Supprimer les avatars de dépôt générés +dashboard.delete_generated_repository_avatars_success=Les avatars de dépôt générés ont été supprimés. dashboard.git_gc_repos=Collecter les déchets des dépôts dashboard.git_gc_repos_success=Les déchets de tous les dépôts ont été collectés. dashboard.resync_all_sshkeys=Ajouter les clefs SSH Gitea au fichier ".ssh/authorized_keys". (Inutile si vous utilisez le serveur SSH intégré). diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 033f78c1f10ef..9dfad59f57fba 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -487,7 +487,6 @@ manage_oauth2_applications=OAuth2アプリケーションの管理 edit_oauth2_application=OAuth2アプリケーションの編集 oauth2_applications_desc=OAuth2はGiteaインスタンスでのサードパーティアプリケーションによる安全な認証を可能にします。 remove_oauth2_application=OAuth2アプリケーションの削除 -remove_oauth2_application_desc=OAuth2アプリケーションを削除すると、すべての署名済みアクセストークンへのアクセス権を取り消します。 続行しますか? remove_oauth2_application_success=アプリケーションを削除しました。 create_oauth2_application=新しいOAuth2アプリケーションの作成 create_oauth2_application_button=アプリケーション作成 @@ -619,7 +618,6 @@ migrate.permission_denied=ローカルリポジトリをインポートする権 migrate.invalid_local_path=ローカルパスが無効です。 存在しないかディレクトリではありません。 migrate.failed=移行に失敗しました: %v migrate.lfs_mirror_unsupported=LFSオブジェクトのミラーはサポートされていません。 代わりに 'git lfs fetch --all' と 'git lfs push --all' を使ってください。 -migrate.migrate_items_options=移行元がGitHubの場合は、ユーザー名を入力すると移行オプションが表示されます。 mirror_from=ミラー元 forked_from=フォーク元 @@ -1306,14 +1304,11 @@ settings.archive.button=アーカイブ settings.archive.header=このリポジトリをアーカイブ settings.archive.text=リポジトリをアーカイブすると、リポジトリ全体が読み出し専用となります。 ダッシュボードには表示されなくなり、コミットも、課題やプルリクエストの作成もできません。 settings.archive.success=リポジトリをアーカイブしました。 -settings.archive.error=リポジトリのアーカイブ設定でエラーが発生しました。 詳細はログを確認してください。 settings.archive.error_ismirror=ミラーのリポジトリはアーカイブできません。 settings.archive.branchsettings_unavailable=ブランチ設定は、アーカイブリポジトリでは使用できません。 settings.unarchive.button=アーカイブ解除 settings.unarchive.header=このリポジトリをアーカイブ解除 -settings.unarchive.text=リポジトリのアーカイブを解除すると、コミット、プッシュ、新規の課題やプルリクエストを受け付けるよう元に戻されます。 settings.unarchive.success=リポジトリのアーカイブを解除しました。 -settings.unarchive.error=リポジトリのアーカイブ解除でエラーが発生しました。 詳細はログを確認してください。 settings.update_avatar_success=リポジトリのアバターを更新しました。 diff.browse_source=ソースを参照 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 87df76d789757..0aa31361e5f32 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -1233,14 +1233,11 @@ settings.archive.button=Arhivēt settings.archive.header=Arhivēt repozitoriju settings.archive.text=Arhivējot repozitoriju, tas paliks tikai skatīšanās režīmā. Tas netiks attēlots infopanelī, tam nevarēs iesūtīt jaunas izmaiņas, kā arī pieteikt jaunas problēmas un veidot jaunus izmaiņu pieprasījumus. settings.archive.success=Repozitorijs veiksmīgi arhivēts. -settings.archive.error=Arhivējot repozitoriju radās neparedzēta kļūda. Pārbaudiet kļūdu žurnālu, lai uzzinātu sīkāk. settings.archive.error_ismirror=Nav iespējams arhivēt spoguļotus repozitorijus. settings.archive.branchsettings_unavailable=Atzaru iestatījumi nav pieejami, ja repozitorijs ir arhivēts. settings.unarchive.button=Atcelt arhivāciju settings.unarchive.header=Atcelt repozitorija arhivāciju -settings.unarchive.text=Atceļot repozitoriju arhivāciju, tam atkal varēs iesūtīt jaunas izmaiņas, kā arī pieteikt problēmas un veidot izmaiņu pieprasījumus. settings.unarchive.success=Repozitorijam veiksmīgi atcelta arhivācija. -settings.unarchive.error=Atceļot repozitorija arhivāciju radās neparedzēta kļūda. Pārbaudiet kļūdu žurnālu, lai uzzinātu sīkāk. diff.browse_source=Pārlūkot izejas kodu diff.parent=vecāks diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 011b9f9e549b9..f68098b2f8067 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -487,7 +487,6 @@ manage_oauth2_applications=Gerenciar aplicativos OAuth2 edit_oauth2_application=Editar aplicativo OAuth2 oauth2_applications_desc=Aplicativos OAuth2 permitem que seus aplicativos de terceiros autentiquem com segurança usuários nesta instância do Gitea. remove_oauth2_application=Remover aplicativo OAuth2 -remove_oauth2_application_desc=Remover um aplicativo OAuth2 irá revogar o acesso a todos os tokens de acesso assinados. Continuar? remove_oauth2_application_success=O aplicativo foi excluído. create_oauth2_application=Criar um novo aplicativo OAuth2 create_oauth2_application_button=Criar aplicativo @@ -619,7 +618,6 @@ migrate.permission_denied=Você não pode importar repositórios locais. migrate.invalid_local_path=O caminho local é inválido. Ele não existe ou não é um diretório. migrate.failed=Migração falhou: %v migrate.lfs_mirror_unsupported=Espelhamento de objetos Git LFS não é suportado; ao invés use 'git lfs fetch --all' e 'git lfs push --all'. -migrate.migrate_items_options=Quando você estiver migrando do github e com nome de usuário inserido, as opções de migração serão exibidas. mirror_from=espelhamento de forked_from=feito fork de @@ -1306,14 +1304,11 @@ settings.archive.button=Arquivar repositório settings.archive.header=Arquivar este repositório settings.archive.text=Arquivando um repositório fará com que o mesmo fique inteiramente em modo somente leitura. Ele ficará oculto no painel, não poderá receber commits e nem será possível criar issues e pull requests. settings.archive.success=O repositório foi arquivado com sucesso. -settings.archive.error=Um erro ocorreu enquanto estava sendo arquivado o repositório. Veja o log para mais detalhes. settings.archive.error_ismirror=Você não pode arquivar um repositório espelhado. settings.archive.branchsettings_unavailable=Configurações do branch não estão disponíveis quando o repositório está arquivado. settings.unarchive.button=Desarquivar repositório settings.unarchive.header=Desarquivar este repositório -settings.unarchive.text=Desarquivando um repositório irá restaurar a capacidade do mesmo receber commits, pushs, assim como novas issues e pull requests. settings.unarchive.success=O repositório foi desarquivado com sucesso. -settings.unarchive.error=Um erro ocorreu enquanto estava sendo desarquivado o repositório. Veja o log para mais detalhes. settings.update_avatar_success=O avatar do repositório foi atualizado. diff.browse_source=Ver código fonte diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index b1e2508db512d..b544b78d30a62 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -86,12 +86,18 @@ host=Хост user=Имя пользователя password=Пароль db_name=Имя базы данных +db_helper=Для пользователей MySQL: пожалуйста, используйте движок InnoDB, и если вы используете "utf8mb4" - ваша версия InnoDB должна быть старше 5.6 . ssl_mode=SSL +charset=Кодировка path=Путь sqlite_helper=Путь к файлу базы данных SQLite3.
Введите абсолютный путь, если вы запускаете Gitea как службу. err_empty_db_path=Путь к базе данных SQLite3 не может быть пустым. no_admin_and_disable_registration=Вы не можете отключить регистрацию до создания учётной записи администратора. err_empty_admin_password=Пароль администратора не может быть пустым. +err_empty_admin_email=Email администратора не может быть пустым. +err_admin_name_is_reserved=Неверное имя администратора, это имя зарезервировано +err_admin_name_pattern_not_allowed=Неверное имя администратора, данный шаблон имени не допускается +err_admin_name_is_invalid=Неверное имя администратора general_title=Основные настройки app_name=Название сайта @@ -205,6 +211,7 @@ sign_up_successful=Учётная запись была успешно созд confirmation_mail_sent_prompt=Новое письмо для подтверждения было направлено на %s, пожалуйста, проверьте ваш почтовый ящик в течение %s для завершения регистрации. must_change_password=Обновить пароль allow_password_change=Требовать смену пароля пользователем (рекомендуется) +reset_password_mail_sent_prompt=Письмо с подтверждением было отправлено на %s. Пожалуйста, проверьте входящую почту в течение %s, чтобы завершить процесс восстановления аккаунта. active_your_account=Активируйте свой аккаунт account_activated=Учётная запись была активирована prohibit_login=Вход запрещен @@ -213,7 +220,11 @@ resent_limit_prompt=Извините, вы уже запросили актив has_unconfirmed_mail=Здравствуйте, %s! У вас есть неподтвержденный адрес электронной почты (%s). Если вам не приходило письмо с подтверждением или нужно выслать новое письмо, нажмите на кнопку ниже. resend_mail=Нажмите здесь, чтобы переотправить активационное письмо email_not_associate=Этот адрес электронной почты не связан ни с одной учетной записью. +send_reset_mail=Отправить письмо для восстановления аккаунта +reset_password=Восстановление аккаунта invalid_code=Этот код подтверждения недействителен или истек. +reset_password_helper=Восстановить аккаунт +reset_password_wrong_user=Вы вошли как %s, но ссылка для восстановления аккаунта %s password_too_short=Длина пароля не может быть меньше, чем %d символов. non_local_account=Нелокальные аккаунты не могут изменить пароль через Gitea. verify=Проверить @@ -224,6 +235,7 @@ twofa_passcode_incorrect=Ваш пароль неверен. Если вы по twofa_scratch_token_incorrect=Неверный scratch-код. login_userpass=Вход login_openid=OpenID +oauth_signup_tab=Зарегистрировать новый аккаунт oauth_signin_submit=Привязать учетную запись openid_connect_submit=Подключить openid_connect_title=Подключение к существующей учетной записи @@ -231,14 +243,19 @@ openid_connect_desc=Выбранный OpenID URI неизвестен. Свяж openid_register_title=Создать новый аккаунт openid_register_desc=Выбранный OpenID URI неизвестен. Свяжите с новой учетной записью здесь. openid_signin_desc=Введите свой OpenID URI. Например: https://anne.me, bob.openid.org.cn или gnusocial.net/carry. +disable_forgot_password_mail=Восстановление аккаунта отключено. Пожалуйста, свяжитесь с администратором сайта. authorize_application=Авторизация приложения +authroize_redirect_notice=Вы будете перенаправлены на %s, если вы авторизуете это приложение. authorize_application_created_by=Это приложение было создано %s. +authorize_application_description=Если вы предоставите доступ, оно сможет получить доступ и редактировать любую информацию о вашей учетной записи, включая содержимое частных репозиториев и организаций. authorize_title=Разрешить «%s» доступ к вашей учетной записи? authorization_failed=Ошибка авторизации +authorization_failed_desc=Ошибка авторизации, обнаружен неверный запрос. Пожалуйста, свяжитесь с автором приложения, которое вы пытались авторизовать. [mail] activate_account=Пожалуйста активируйте свой аккаунт activate_email=Подтвердите адрес своей электронной почты +reset_password=Восстановить учетную запись register_success=Регистрация прошла успешно register_notify=Добро пожаловать на Gitea @@ -283,6 +300,8 @@ password_not_match=Пароли не совпадают. username_been_taken=Имя пользователя уже занято. repo_name_been_taken=Имя репозитория уже используется. +visit_rate_limit=Удаленный вход отклонён в связи с ограничением количества попыток в секунду. +2fa_auth_required=Удаленный вход требует двухфакторную аутентификацию. org_name_been_taken=Название организации уже занято. team_name_been_taken=Название команды уже занято. team_no_units_error=Разрешите доступ хотя бы к одному разделу репозитория. @@ -364,6 +383,7 @@ choose_new_avatar=Выбрать новый аватар update_avatar=Обновить аватар delete_current_avatar=Удалить текущий аватар uploaded_avatar_not_a_image=Загружаемый файл не является изображением. +uploaded_avatar_is_too_big=Загруженный файл превысил максимальный размер. update_avatar_success=Ваш аватар был изменен. change_password=Обновить пароль @@ -379,6 +399,7 @@ manage_emails=Управление Email адресами manage_themes=Выберите тему по умолчанию manage_openid=Управление OpenID email_desc=Ваш основной адрес электронной почты будет использован для уведомлений и других операций. +theme_desc=Это будет темой по умолчанию для всего сайта. primary=Основной primary_email=Сделать основным delete_email=Удалить @@ -458,7 +479,26 @@ access_token_deletion_desc=Удаление токена отменит дост delete_token_success=Токен удалён. Приложения, использующие его, больше не имеют доступа к вашему аккаунту. manage_oauth2_applications=Управление приложениями OAuth2 - +remove_oauth2_application=Удалить OAuth2 приложение +remove_oauth2_application_success=Приложение было удалено. +create_oauth2_application_button=Создать приложение +create_oauth2_application_success=Вы успешно создали новое приложение OAuth2. +update_oauth2_application_success=Изменения настроек приложения OAuth2 успешно применены. +oauth2_application_name=Имя приложения +oauth2_select_type=Какой тип приложения подходит? +oauth2_type_web=Веб (например: Node.JS, Tomcat, Go) +oauth2_type_native=Нативный (например: телефон, ПК, браузер) +oauth2_redirect_uri=URI переадресации +save_application=Сохранить +oauth2_client_secret=Клиентский ключ +oauth2_regenerate_secret=Сгенерировать новый ключ +oauth2_regenerate_secret_hint=Потеряли свой ключ? +oauth2_client_secret_hint=Секретный ключ не будет показан, если вы повторно откроете эту страницу. Пожалуйста сохраните секретный ключ. + +authorized_oauth2_applications=Авторизованные приложения OAuth2 +revoke_key=Отозвать +revoke_oauth2_grant=Отозвать доступ +revoke_oauth2_grant_success=Вы успешно отозвали доступ. twofa_desc=Двухфакторная проверка подлинности повышает уровень безопасности вашей учётной записи. twofa_is_enrolled=Ваша учётная запись в настоящее время использует двухфакторную аутентификацию. @@ -546,6 +586,12 @@ form.name_pattern_not_allowed=Шаблон имени репозитория '%s need_auth=Требуется авторизация migrate_type=Тип миграции migrate_type_helper=Этот репозиторий будет зеркалом +migrate_items_wiki=Вики +migrate_items_milestones=Этапы +migrate_items_labels=Метки +migrate_items_issues=Задачи +migrate_items_pullrequests=Запросы на слияние +migrate_items_releases=Релизы migrate_repo=Перенос репозитория migrate.clone_address=Перенос / Клонирование по URL migrate.clone_address_desc=Это может быть HTTP/HTTPS/GIT адрес или локальный путь существующего репозитория на сервере. @@ -627,11 +673,14 @@ editor.create_new_branch=Создайте новую ветку editor.new_branch_name_desc=Новое название ветки… editor.cancel=Отмена editor.filename_cannot_be_empty=Имя файла не может быть пустым. +editor.filename_is_invalid=Недопустимое имя файла: '%s'. +editor.branch_does_not_exist=Ветка '%s' отсутствует в этом репозитории. editor.branch_already_exists=Ветка «%s» уже существует в этом репозитории. editor.directory_is_a_file=Имя каталога '%s' уже используется в качестве имени файла в этом репозитории. editor.file_is_a_symlink='%s' является символической ссылкой. Символические ссылки нельзя редактировать в веб-редакторе editor.filename_is_a_directory=Имя файла '%s' уже используется в качестве имени каталога в этом репозитории. editor.file_editing_no_longer_exists=Редактируемый файл '%s' больше не существует в этом репозитории. +editor.file_deleting_no_longer_exists=Удаляемый файл '%s' больше не существует в этом репозитории. editor.file_changed_while_editing=Содержимое файла изменилось с момента начала редактирования. Нажмите здесь, чтобы увидеть, что было изменено, или Зафиксировать изменения снова, чтобы заменить их. editor.file_already_exists=Файл с именем '%s' уже существует в репозитории. editor.no_changes_to_show=Нет изменений. @@ -643,6 +692,7 @@ editor.cannot_commit_to_protected_branch=Нельзя коммитить в за commits.desc=Просмотр истории изменений исходного кода. commits.commits=коммитов +commits.no_commits=Ничего общего в коммитах. '%s' и '%s' имеют совершенно разные истории. commits.search=Поиск коммитов… commits.find=Поиск commits.search_all=Все ветки @@ -712,6 +762,8 @@ issues.filter_sort.recentupdate=Недавно обновленные issues.filter_sort.leastupdate=Давно обновленные issues.filter_sort.mostcomment=Больше комментариев issues.filter_sort.leastcomment=Меньше комментариев +issues.filter_sort.nearduedate=Ближайшее по дате завершения +issues.filter_sort.farduedate=Удалённое по дате завершения issues.filter_sort.moststars=Больше звезд issues.filter_sort.feweststars=Меньше звезд issues.filter_sort.mostforks=Больше форков @@ -727,6 +779,7 @@ issues.opened_by=открыта %[1]s %[3]s pulls.merged_by=принят %[1]s %[3]s issues.closed_by=закрыта %[1]s %[3]s issues.opened_by_fake=%[1]s открыта %[2]s +issues.closed_by_fake=%[1]s закрыта пользователем %[2]s issues.previous=Предыдущая страница issues.next=Следующая страница issues.open_title=Открыто @@ -906,6 +959,7 @@ milestones.no_due_date=Срок не указан milestones.open=Открыть milestones.close=Закрыть milestones.new_subheader=Создавайте этапы для организации ваших задач. +milestones.completeness=%d%% выполнено milestones.create=Создать этап milestones.title=Заголовок milestones.desc=Описание @@ -992,6 +1046,7 @@ activity.title.releases_1=%d релиз activity.title.releases_n=%d релизов activity.title.releases_published_by=%s опубликованы %s activity.published_release_label=Опубликовано +activity.no_git_activity=В этот период не было новых коммитов. search=Поиск search.search_repo=Поиск по репозиторию @@ -1102,6 +1157,7 @@ settings.githook_content=Перехватить содержание settings.update_githook=Обновить Hook settings.add_webhook_desc=Gitea будет оправлять POST запросы на указанный URL адрес, с информацией о происходящих событиях. Подробности на странице инструкции по использованию webhooks. settings.payload_url=URL обработчика +settings.http_method=Метод HTTP settings.content_type=Тип содержимого settings.secret=Секретный ключ settings.slack_username=Имя пользователя @@ -1145,6 +1201,8 @@ settings.slack_domain=Домен settings.slack_channel=Канал settings.add_discord_hook_desc=Добавить уведомления о событиях через Discord. settings.add_dingtalk_hook_desc=Добавить интеграцию с Dingtalk в ваш репозиторий. +settings.add_telegram_hook_desc=Добавить интеграцию с Telegram в ваш репозиторий. +settings.add_msteams_hook_desc=Добавить интеграцию с Microsoft Teams в ваш репозиторий. settings.deploy_keys=Ключи развертывания settings.add_deploy_key=Добавить ключ развертывания settings.deploy_key_desc=Ключи развёртывания доступны только для чтения. Это не то же самое что и SSH-ключи аккаунта. @@ -1166,7 +1224,9 @@ settings.protected_branch_can_push_yes=Вы можете выполнять push settings.protected_branch_can_push_no=Вы не можете выполнять push settings.branch_protection=Защита ветки %s settings.protect_this_branch=Защитить эту ветку +settings.protect_this_branch_desc=Запретить push в ветку и защитить от удаления. settings.protect_whitelist_committers=Белый список тех, кто может делать push в эту ветку +settings.protect_whitelist_committers_desc=Разрешить push в эту ветку пользователям или командам из «белого» списка (но не принудительный push). settings.protect_whitelist_users=Пользователи, которые могут делать push в эту ветку: settings.protect_whitelist_search_users=Поиск пользователей… settings.protect_whitelist_teams=Команды, члены которых могут делать push в эту ветку: @@ -1190,6 +1250,8 @@ settings.choose_branch=Выберите ветку… settings.no_protected_branch=Нет защищённых веток. settings.edit_protected_branch=Редактировать settings.protected_branch_required_approvals_min=Число необходимых одобрений не может быть отрицательным. +settings.bot_token=Токен для бота +settings.chat_id=ID чата settings.archive.button=Архивировать репозиторий settings.archive.header=Архивировать этот репозиторий settings.archive.text=Архивация репозитория переведет его в режим read-only. Он будет скрыт из панели управления, создание задач, запросов на слияние, или создание коммитов будут запрещены. @@ -1198,7 +1260,7 @@ settings.archive.error_ismirror=Вы не можете поместить зер settings.unarchive.button=Разархивировать settings.unarchive.header=Разархивировать этот репозиторий settings.unarchive.success=Репозиторий был успешно разархивирован. -settings.unarchive.error=Ошибка при попытке разархивировать репозиторий. Смотрите логи для получения подробностей. +settings.update_avatar_success=Аватар репозитория обновлен. diff.browse_source=Просмотр исходного кода diff.parent=Родитель diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 1a2ed9fc1f81d..da23f30fb6aad 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -480,7 +480,6 @@ manage_oauth2_applications=管理 OAuth2 应用程序 edit_oauth2_application=编辑 OAuth2 应用程序 oauth2_applications_desc=OAuth2 应用允许第三方应用程序在此 Gitea 实例中安全验证用户。 remove_oauth2_application=删除 OAuth2 应用程序 -remove_oauth2_application_desc=删除 OAuth2 应用将撤销所有签名访问令牌。继续吗? remove_oauth2_application_success=该应用已被删除。 create_oauth2_application=创建新的 OAuth2 应用程序 create_oauth2_application_button=创建应用 @@ -612,7 +611,6 @@ migrate.permission_denied=您没有获得导入本地仓库的权限。 migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录! migrate.failed=迁移失败:%v migrate.lfs_mirror_unsupported=不支持镜像 LFS 对象 - 使用 'git lfs fetch --all' 和 'git lfs push --all' 替代。 -migrate.migrate_items_options=当您正在从 github 迁移并且输入了用户名时,迁移选项将会显示。 mirror_from=镜像自地址 forked_from=派生自 @@ -1299,14 +1297,11 @@ settings.archive.button=归档仓库 settings.archive.header=归档此仓库 settings.archive.text=归档后仓库将只有只读权限,并在仪表盘中被隐藏。你将不能再对其建立提交、创建工单或建立合并请求。 settings.archive.success=仓库已成功归档。 -settings.archive.error=仓库在归档时出现异常。请通过日志获取详细信息。 settings.archive.error_ismirror=请不要对镜像仓库归档,谢谢! settings.archive.branchsettings_unavailable=已归档仓库无法进行分支设置。 settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销此仓库归档 -settings.unarchive.text=取消存档将恢复仓库接收提交,推送,新工单和合并请求。 settings.unarchive.success=仓库已成功取消归档。 -settings.unarchive.error=仓库在撤销归档时出现异常。请通过日志获取详细信息。 diff.browse_source=浏览代码 diff.parent=父节点 From de6539fc8c37485afcd6f30092a9ccbc3cae7de5 Mon Sep 17 00:00:00 2001 From: Lanre Adelowo Date: Thu, 6 Jun 2019 01:37:45 +0100 Subject: [PATCH 09/30] Add state param to milestone listing API (#7131) * Support state params * update tests * fix tests * add state=all support * update tests * update swagger * update swagger --- models/fixtures/milestone.yml | 8 +++++++ models/fixtures/repository.yml | 5 ++-- models/issue_milestone.go | 22 +++++++++++++++--- models/issue_milestone_test.go | 39 +++++++++++++++++++++++++------- modules/structs/issue.go | 2 ++ routers/api/v1/repo/milestone.go | 8 +++++-- routers/repo/issue.go | 3 ++- templates/swagger/v1_json.tmpl | 6 +++++ 8 files changed, 77 insertions(+), 16 deletions(-) diff --git a/models/fixtures/milestone.yml b/models/fixtures/milestone.yml index 8192c4fbe1b09..15f422fc3b5c2 100644 --- a/models/fixtures/milestone.yml +++ b/models/fixtures/milestone.yml @@ -13,3 +13,11 @@ content: content2 is_closed: false num_issues: 0 + +- + id: 3 + repo_id: 1 + name: milestone3 + content: content3 + is_closed: true + num_issues: 0 diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index 083182e2bcc13..609f421a9033d 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -8,7 +8,8 @@ num_closed_issues: 1 num_pulls: 2 num_closed_pulls: 0 - num_milestones: 2 + num_milestones: 3 + num_closed_milestones: 1 num_watches: 3 - @@ -495,4 +496,4 @@ num_stars: 0 num_forks: 0 num_issues: 0 - is_mirror: false \ No newline at end of file + is_mirror: false diff --git a/models/issue_milestone.go b/models/issue_milestone.go index 3bde4b558cf65..f279dda195e7d 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -190,10 +190,26 @@ func (milestones MilestoneList) getMilestoneIDs() []int64 { } // GetMilestonesByRepoID returns all opened milestones of a repository. -func GetMilestonesByRepoID(repoID int64) (MilestoneList, error) { +func GetMilestonesByRepoID(repoID int64, state api.StateType) (MilestoneList, error) { + + sess := x.Where("repo_id = ?", repoID) + + switch state { + case api.StateClosed: + sess = sess.And("is_closed = ?", true) + + case api.StateAll: + break + + case api.StateOpen: + fallthrough + + default: + sess = sess.And("is_closed = ?", false) + } + miles := make([]*Milestone, 0, 10) - return miles, x.Where("repo_id = ? AND is_closed = ?", repoID, false). - Asc("deadline_unix").Asc("id").Find(&miles) + return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) } // GetMilestones returns a list of milestones of given repository and status. diff --git a/models/issue_milestone_test.go b/models/issue_milestone_test.go index fb1ee8b7a5c89..f9e51aff318ee 100644 --- a/models/issue_milestone_test.go +++ b/models/issue_milestone_test.go @@ -69,20 +69,43 @@ func TestGetMilestoneByRepoID(t *testing.T) { func TestGetMilestonesByRepoID(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) - test := func(repoID int64) { + test := func(repoID int64, state api.StateType) { repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository) - milestones, err := GetMilestonesByRepoID(repo.ID) + milestones, err := GetMilestonesByRepoID(repo.ID, state) assert.NoError(t, err) - assert.Len(t, milestones, repo.NumMilestones) + + var n int + + switch state { + case api.StateClosed: + n = repo.NumClosedMilestones + + case api.StateAll: + n = repo.NumMilestones + + case api.StateOpen: + fallthrough + + default: + n = repo.NumOpenMilestones + } + + assert.Len(t, milestones, n) for _, milestone := range milestones { assert.EqualValues(t, repoID, milestone.RepoID) } } - test(1) - test(2) - test(3) - - milestones, err := GetMilestonesByRepoID(NonexistentID) + test(1, api.StateOpen) + test(1, api.StateAll) + test(1, api.StateClosed) + test(2, api.StateOpen) + test(2, api.StateAll) + test(2, api.StateClosed) + test(3, api.StateOpen) + test(3, api.StateClosed) + test(3, api.StateAll) + + milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen) assert.NoError(t, err) assert.Len(t, milestones, 0) } diff --git a/modules/structs/issue.go b/modules/structs/issue.go index af6aa6e541527..6d7517bdc7b34 100644 --- a/modules/structs/issue.go +++ b/modules/structs/issue.go @@ -16,6 +16,8 @@ const ( StateOpen StateType = "open" // StateClosed pr is closed StateClosed StateType = "closed" + // StateAll is all + StateAll StateType = "all" ) // PullRequestMeta PR info if an issue is a PR diff --git a/routers/api/v1/repo/milestone.go b/routers/api/v1/repo/milestone.go index 1d010933060e5..14030a2186640 100644 --- a/routers/api/v1/repo/milestone.go +++ b/routers/api/v1/repo/milestone.go @@ -14,7 +14,7 @@ import ( api "code.gitea.io/gitea/modules/structs" ) -// ListMilestones list all the opened milestones for a repository +// ListMilestones list milestones for a repository func ListMilestones(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/milestones issue issueGetMilestonesList // --- @@ -32,10 +32,14 @@ func ListMilestones(ctx *context.APIContext) { // description: name of the repo // type: string // required: true + // - name: state + // in: query + // description: Milestone state, Recognised values are open, closed and all. Defaults to "open" + // type: string // responses: // "200": // "$ref": "#/responses/MilestoneList" - milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID) + milestones, err := models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) if err != nil { ctx.Error(500, "GetMilestonesByRepoID", err) return diff --git a/routers/repo/issue.go b/routers/repo/issue.go index c2749fcb47532..f6030c9823ad6 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "github.com/Unknwon/com" @@ -305,7 +306,7 @@ func Issues(ctx *context.Context) { var err error // Get milestones. - ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID) + ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state"))) if err != nil { ctx.ServerError("GetAllRepoMilestones", err) return diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 77515bb139e61..0bd85fbb6e7c3 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -3892,6 +3892,12 @@ "name": "repo", "in": "path", "required": true + }, + { + "type": "string", + "description": "Milestone state, Recognised values are open, closed and all. Defaults to \"open\"", + "name": "state", + "in": "query" } ], "responses": { From dadc03f5ff07b0aa857ceccaa655bb4fb6e41494 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Thu, 6 Jun 2019 00:40:56 +0000 Subject: [PATCH 10/30] [skip ci] Updated translations via Crowdin --- options/locale/locale_es-ES.ini | 9 +++++---- options/locale/locale_pt-BR.ini | 5 +++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index 28a3952bfa985..d620ebaddd578 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -27,10 +27,11 @@ password=Contraseña re_type=Vuelva a escribir la contraseña captcha=CAPTCHA twofa=Autenticación de doble factor +twofa_scratch=Código de autenticación de doble factor de un sólo uso passcode=Contraseña u2f_insert_key=Inserte su clave de seguridad -u2f_use_twofa=Use un código de dos factores de su celular +u2f_use_twofa=Use un código de doble factor de su celular u2f_reload=Recargar repository=Repositorio @@ -91,7 +92,7 @@ disable_gravatar=Desactivar Gravatar federated_avatar_lookup_popup=Habilitar búsqueda de avatares federador para usar el servicio federado de código abierto basado en libravatar. enable_captcha=Activar CAPTCHA enable_captcha_popup=Requerir CAPTCHA para auto-registro de usuario. -require_sign_in_view=Debes iniciar sesión para ver las páginas +require_sign_in_view=Requerir inicio de sesión para ver páginas admin_password=Contraseña confirm_password=Confirmar Contraseña admin_email=Correo electrónico @@ -107,7 +108,7 @@ invalid_log_root_path=La ruta para los registros no es válida: %v default_keep_email_private=Ocultar direcciones de correo electrónico por defecto default_keep_email_private_popup=Ocultar direcciones de correo electrónico de nuevas cuentas de usuario por defecto. default_allow_create_organization=Permitir la creación de organizaciones por defecto -default_allow_create_organization_popup=Permitir crear organizaciones a las nuevas cuentas de usuario de forma predeterminada. +default_allow_create_organization_popup=Permitir que las nuevas cuentas de usuario creen organizaciones por defecto. default_enable_timetracking=Activar el seguimiento de tiempo por defecto default_enable_timetracking_popup=Activar el seguimiento de tiempo para nuevos repositorios por defecto. no_reply_address=Dominio de correos electrónicos ocultos @@ -345,7 +346,7 @@ unwatch=Dejar de seguir watch=Seguir unstar=Eliminar de favoritos star=Destacar -fork=Bifurcar +fork=Fork no_desc=Sin descripción quick_guide=Guía rápida diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index f68098b2f8067..435b51552e719 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -487,6 +487,7 @@ manage_oauth2_applications=Gerenciar aplicativos OAuth2 edit_oauth2_application=Editar aplicativo OAuth2 oauth2_applications_desc=Aplicativos OAuth2 permitem que seus aplicativos de terceiros autentiquem com segurança usuários nesta instância do Gitea. remove_oauth2_application=Remover aplicativo OAuth2 +remove_oauth2_application_desc=Remover um aplicativo OAuth2 irá revogar o acesso a todos os tokens de acesso assinados. Continuar? remove_oauth2_application_success=O aplicativo foi excluído. create_oauth2_application=Criar um novo aplicativo OAuth2 create_oauth2_application_button=Criar aplicativo @@ -618,6 +619,7 @@ migrate.permission_denied=Você não pode importar repositórios locais. migrate.invalid_local_path=O caminho local é inválido. Ele não existe ou não é um diretório. migrate.failed=Migração falhou: %v migrate.lfs_mirror_unsupported=Espelhamento de objetos Git LFS não é suportado; ao invés use 'git lfs fetch --all' e 'git lfs push --all'. +migrate.migrate_items_options=Ao migrar do github, insira um nome de usuário e as opções de migração serão exibidas. mirror_from=espelhamento de forked_from=feito fork de @@ -1304,11 +1306,14 @@ settings.archive.button=Arquivar repositório settings.archive.header=Arquivar este repositório settings.archive.text=Arquivando um repositório fará com que o mesmo fique inteiramente em modo somente leitura. Ele ficará oculto no painel, não poderá receber commits e nem será possível criar issues e pull requests. settings.archive.success=O repositório foi arquivado com sucesso. +settings.archive.error=Um erro ocorreu enquanto estava sendo arquivado o repositório. Veja o log para mais detalhes. settings.archive.error_ismirror=Você não pode arquivar um repositório espelhado. settings.archive.branchsettings_unavailable=Configurações do branch não estão disponíveis quando o repositório está arquivado. settings.unarchive.button=Desarquivar repositório settings.unarchive.header=Desarquivar este repositório +settings.unarchive.text=Desarquivando um repositório irá restaurar a capacidade do mesmo receber commits, pushs, assim como novas issues e pull requests. settings.unarchive.success=O repositório foi desarquivado com sucesso. +settings.unarchive.error=Um erro ocorreu enquanto estava sendo desarquivado o repositório. Veja o log para mais detalhes. settings.update_avatar_success=O avatar do repositório foi atualizado. diff.browse_source=Ver código fonte From bd55f6ff36d40503bfa3407225780d0ab7d37930 Mon Sep 17 00:00:00 2001 From: zeripath Date: Thu, 6 Jun 2019 06:54:25 +0100 Subject: [PATCH 11/30] Detect noreply email address as user (#7133) --- models/user.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/models/user.go b/models/user.go index 9ee27ddfbd449..e29cf5b32a6c2 100644 --- a/models/user.go +++ b/models/user.go @@ -1334,6 +1334,19 @@ func GetUserByEmail(email string) (*User, error) { return GetUserByID(emailAddress.UID) } + // Finally, if email address is the protected email address: + if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) { + username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) + user := &User{LowerName: username} + has, err := x.Get(user) + if err != nil { + return nil, err + } + if has { + return user, nil + } + } + return nil, ErrUserNotExist{0, email, 0} } From 311ce2d1d06c26d0d5a3b745493995813e2ea6f2 Mon Sep 17 00:00:00 2001 From: Mario Lubenka Date: Fri, 7 Jun 2019 22:29:29 +0200 Subject: [PATCH 12/30] Compare branches, commits and tags with each other (#6991) * Supports tags when comparing commits or branches Signed-off-by: Mario Lubenka * Hide headline when only comparing and don't load unused data Signed-off-by: Mario Lubenka * Merges compare logics to allow comparing branches, commits and tags with eachother Signed-off-by: Mario Lubenka * Display branch or tag instead of commit when used for comparing Signed-off-by: Mario Lubenka * Show pull request form after click on button Signed-off-by: Mario Lubenka * Transfers relevant pull.go changes from master to compare.go Signed-off-by: Mario Lubenka * Fixes error when comparing forks against a commit or tag Signed-off-by: Mario Lubenka * Removes console.log from JavaScript file Signed-off-by: Mario Lubenka * Show icon next to commit reference when comparing branch or tag Signed-off-by: Mario Lubenka * Updates css file Signed-off-by: Mario Lubenka * Fixes import order * Renames template variable * Update routers/repo/compare.go Co-Authored-By: zeripath * Update from master Signed-off-by: Mario Lubenka * Allow short-shas in compare * Renames prInfo to compareInfo Signed-off-by: Mario Lubenka * Check PR permissions only if compare is pull request Signed-off-by: Mario Lubenka * Adjusts comment Signed-off-by: Mario Lubenka * Use compareInfo instead of prInfo --- models/pull.go | 3 +- modules/git/repo_commit.go | 10 + modules/git/{repo_pull.go => repo_compare.go} | 54 +-- ...repo_pull_test.go => repo_compare_test.go} | 0 public/css/index.css | 1 + public/js/index.js | 9 +- public/less/_repository.less | 3 + routers/api/v1/repo/pull.go | 14 +- routers/repo/commit.go | 59 +-- routers/repo/compare.go | 337 ++++++++++++++++++ routers/repo/pull.go | 278 +-------------- routers/routes/routes.go | 9 +- templates/repo/commit_page.tmpl | 89 +++++ templates/repo/commits_table.tmpl | 8 +- templates/repo/diff/compare.tmpl | 74 ++++ templates/repo/diff/page.tmpl | 94 ----- templates/repo/pulls/compare.tmpl | 69 ---- 17 files changed, 584 insertions(+), 527 deletions(-) rename modules/git/{repo_pull.go => repo_compare.go} (55%) rename modules/git/{repo_pull_test.go => repo_compare_test.go} (100%) create mode 100644 routers/repo/compare.go create mode 100644 templates/repo/commit_page.tmpl create mode 100644 templates/repo/diff/compare.tmpl delete mode 100644 templates/repo/diff/page.tmpl delete mode 100644 templates/repo/pulls/compare.tmpl diff --git a/models/pull.go b/models/pull.go index fe18765fc0c78..5ac1126314d1a 100644 --- a/models/pull.go +++ b/models/pull.go @@ -1144,8 +1144,7 @@ func (pr *PullRequest) UpdatePatch() (err error) { defer func() { headGitRepo.RemoveRemote(tmpRemote) }() - remoteBranch := "remotes/" + tmpRemote + "/" + pr.BaseBranch - pr.MergeBase, err = headGitRepo.GetMergeBase(remoteBranch, pr.HeadBranch) + pr.MergeBase, err = headGitRepo.GetMergeBase(tmpRemote, pr.BaseBranch, pr.HeadBranch) if err != nil { return fmt.Errorf("GetMergeBase: %v", err) } else if err = pr.Update(); err != nil { diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index b631f9341e18e..501ea88e4000b 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -27,6 +27,16 @@ func (repo *Repository) GetRefCommitID(name string) (string, error) { return ref.Hash().String(), nil } +// IsCommitExist returns true if given commit exists in current repository. +func (repo *Repository) IsCommitExist(name string) bool { + hash := plumbing.NewHash(name) + _, err := repo.gogitRepo.CommitObject(hash) + if err != nil { + return false + } + return true +} + // GetBranchCommitID returns last commit ID string of given branch. func (repo *Repository) GetBranchCommitID(name string) (string, error) { return repo.GetRefCommitID(BranchPrefix + name) diff --git a/modules/git/repo_pull.go b/modules/git/repo_compare.go similarity index 55% rename from modules/git/repo_pull.go rename to modules/git/repo_compare.go index 65c54145518d3..e7a1d72a8592b 100644 --- a/modules/git/repo_pull.go +++ b/modules/git/repo_compare.go @@ -1,4 +1,5 @@ // Copyright 2015 The Gogs Authors. All rights reserved. +// Copyright 2019 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. @@ -14,55 +15,66 @@ import ( "time" ) -// PullRequestInfo represents needed information for a pull request. -type PullRequestInfo struct { +// CompareInfo represents needed information for comparing references. +type CompareInfo struct { MergeBase string Commits *list.List NumFiles int } // GetMergeBase checks and returns merge base of two branches. -func (repo *Repository) GetMergeBase(base, head string) (string, error) { +func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (string, error) { + if tmpRemote == "" { + tmpRemote = "origin" + } + + if tmpRemote != "origin" { + tmpBaseName := "refs/remotes/" + tmpRemote + "/tmp_" + base + // Fetch commit into a temporary branch in order to be able to handle commits and tags + _, err := NewCommand("fetch", tmpRemote, base+":"+tmpBaseName).RunInDir(repo.Path) + if err == nil { + base = tmpBaseName + } + } + stdout, err := NewCommand("merge-base", base, head).RunInDir(repo.Path) return strings.TrimSpace(stdout), err } -// GetPullRequestInfo generates and returns pull request information -// between base and head branches of repositories. -func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) { - var remoteBranch string +// GetCompareInfo generates and returns compare information between base and head branches of repositories. +func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string) (_ *CompareInfo, err error) { + var ( + remoteBranch string + tmpRemote string + ) // We don't need a temporary remote for same repository. if repo.Path != basePath { // Add a temporary remote - tmpRemote := strconv.FormatInt(time.Now().UnixNano(), 10) + tmpRemote = strconv.FormatInt(time.Now().UnixNano(), 10) if err = repo.AddRemote(tmpRemote, basePath, true); err != nil { return nil, fmt.Errorf("AddRemote: %v", err) } defer repo.RemoveRemote(tmpRemote) - - remoteBranch = "remotes/" + tmpRemote + "/" + baseBranch - } else { - remoteBranch = baseBranch } - prInfo := new(PullRequestInfo) - prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch) + compareInfo := new(CompareInfo) + compareInfo.MergeBase, err = repo.GetMergeBase(tmpRemote, baseBranch, headBranch) if err == nil { // We have a common base - logs, err := NewCommand("log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat).RunInDirBytes(repo.Path) + logs, err := NewCommand("log", compareInfo.MergeBase+"..."+headBranch, prettyLogFormat).RunInDirBytes(repo.Path) if err != nil { return nil, err } - prInfo.Commits, err = repo.parsePrettyFormatLogToList(logs) + compareInfo.Commits, err = repo.parsePrettyFormatLogToList(logs) if err != nil { return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err) } } else { - prInfo.Commits = list.New() - prInfo.MergeBase, err = GetFullCommitID(repo.Path, remoteBranch) + compareInfo.Commits = list.New() + compareInfo.MergeBase, err = GetFullCommitID(repo.Path, remoteBranch) if err != nil { - prInfo.MergeBase = remoteBranch + compareInfo.MergeBase = remoteBranch } } @@ -71,9 +83,9 @@ func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch stri if err != nil { return nil, err } - prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1 + compareInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1 - return prInfo, nil + return compareInfo, nil } // GetPatch generates and returns patch data between given revisions. diff --git a/modules/git/repo_pull_test.go b/modules/git/repo_compare_test.go similarity index 100% rename from modules/git/repo_pull_test.go rename to modules/git/repo_compare_test.go diff --git a/public/css/index.css b/public/css/index.css index 8950cc70386a2..d192f43d1529a 100644 --- a/public/css/index.css +++ b/public/css/index.css @@ -591,6 +591,7 @@ footer .ui.left,footer .ui.right{line-height:40px} .repository .milestone.list>.item .content{padding-top:10px} .repository.new.milestone textarea{height:200px} .repository.new.milestone #deadline{width:150px} +.repository.compare.pull .show-form-container{text-align:left} .repository.compare.pull .choose.branch .octicon{padding-right:10px} .repository.compare.pull .comment.form .content:after,.repository.compare.pull .comment.form .content:before{right:100%;top:20px;border:solid transparent;content:" ";height:0;width:0;position:absolute;pointer-events:none} .repository.compare.pull .comment.form .content:before{border-right-color:#d3d3d4;border-width:9px;margin-top:-9px} diff --git a/public/js/index.js b/public/js/index.js index ed3198594a3fa..28023e1061bbf 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -959,8 +959,15 @@ function initRepository() { }); // Pull request - if ($('.repository.compare.pull').length > 0) { + var $repoComparePull = $('.repository.compare.pull'); + if ($repoComparePull.length > 0) { initFilterSearchDropdown('.choose.branch .dropdown'); + // show pull request form + $repoComparePull.find('button.show-form').on('click', function(e) { + e.preventDefault(); + $repoComparePull.find('.pullrequest-form').show(); + $(this).parent().hide(); + }); } // Branches diff --git a/public/less/_repository.less b/public/less/_repository.less index 9956bbce7492f..fcc153e31e8e9 100644 --- a/public/less/_repository.less +++ b/public/less/_repository.less @@ -1109,6 +1109,9 @@ } &.compare.pull { + .show-form-container { + text-align: left; + } .choose.branch { .octicon { padding-right: 10px; diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index f53ab4b8f3e54..0e1db144b1991 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -188,7 +188,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption ) // Get repo/branch information - headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := parseCompareInfo(ctx, form) + headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := parseCompareInfo(ctx, form) if ctx.Written() { return } @@ -240,7 +240,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption milestoneID = milestone.ID } - patch, err := headGitRepo.GetPatch(prInfo.MergeBase, headBranch) + patch, err := headGitRepo.GetPatch(compareInfo.MergeBase, headBranch) if err != nil { ctx.Error(500, "GetPatch", err) return @@ -277,7 +277,7 @@ func CreatePullRequest(ctx *context.APIContext, form api.CreatePullRequestOption BaseBranch: baseBranch, HeadRepo: headRepo, BaseRepo: repo, - MergeBase: prInfo.MergeBase, + MergeBase: compareInfo.MergeBase, Type: models.PullRequestGitea, } @@ -600,7 +600,7 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) { ctx.Status(200) } -func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.PullRequestInfo, string, string) { +func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) { baseRepo := ctx.Repo.Repository // Get compared branches information @@ -712,11 +712,11 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption) return nil, nil, nil, nil, "", "" } - prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) + compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) if err != nil { - ctx.Error(500, "GetPullRequestInfo", err) + ctx.Error(500, "GetCompareInfo", err) return nil, nil, nil, nil, "", "" } - return headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch + return headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch } diff --git a/routers/repo/commit.go b/routers/repo/commit.go index 870ff568f3516..dde6d8f321550 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -19,9 +19,9 @@ import ( ) const ( - tplCommits base.TplName = "repo/commits" - tplGraph base.TplName = "repo/graph" - tplDiff base.TplName = "repo/diff/page" + tplCommits base.TplName = "repo/commits" + tplGraph base.TplName = "repo/graph" + tplCommitPage base.TplName = "repo/commit_page" ) // RefCommits render commits page @@ -261,7 +261,7 @@ func Diff(ctx *context.Context) { } ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", "commit", commitID) ctx.Data["BranchName"], err = commit.GetBranchName() - ctx.HTML(200, tplDiff) + ctx.HTML(200, tplCommitPage) } // RawDiff dumps diff results of repository in given commit ID to io.Writer @@ -276,54 +276,3 @@ func RawDiff(ctx *context.Context) { return } } - -// CompareDiff show different from one commit to another commit -func CompareDiff(ctx *context.Context) { - ctx.Data["IsRepoToolbarCommits"] = true - ctx.Data["IsDiffCompare"] = true - userName := ctx.Repo.Owner.Name - repoName := ctx.Repo.Repository.Name - beforeCommitID := ctx.Params(":before") - afterCommitID := ctx.Params(":after") - - commit, err := ctx.Repo.GitRepo.GetCommit(afterCommitID) - if err != nil { - ctx.NotFound("GetCommit", err) - return - } - - diff, err := models.GetDiffRange(models.RepoPath(userName, repoName), beforeCommitID, - afterCommitID, setting.Git.MaxGitDiffLines, - setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) - if err != nil { - ctx.NotFound("GetDiffRange", err) - return - } - - commits, err := commit.CommitsBeforeUntil(beforeCommitID) - if err != nil { - ctx.ServerError("CommitsBeforeUntil", err) - return - } - commits = models.ValidateCommitsWithEmails(commits) - commits = models.ParseCommitsWithSignature(commits) - commits = models.ParseCommitsWithStatus(commits, ctx.Repo.Repository) - - ctx.Data["CommitRepoLink"] = ctx.Repo.RepoLink - ctx.Data["Commits"] = commits - ctx.Data["CommitCount"] = commits.Len() - ctx.Data["BeforeCommitID"] = beforeCommitID - ctx.Data["AfterCommitID"] = afterCommitID - ctx.Data["Username"] = userName - ctx.Data["Reponame"] = repoName - ctx.Data["IsImageFile"] = commit.IsImageFile - ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID) + " · " + userName + "/" + repoName - ctx.Data["Commit"] = commit - ctx.Data["Diff"] = diff - ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 - ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", "commit", afterCommitID) - ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "src", "commit", beforeCommitID) - ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", "commit", afterCommitID) - ctx.Data["RequireHighlightJS"] = true - ctx.HTML(200, tplDiff) -} diff --git a/routers/repo/compare.go b/routers/repo/compare.go new file mode 100644 index 0000000000000..a85084791d371 --- /dev/null +++ b/routers/repo/compare.go @@ -0,0 +1,337 @@ +// Copyright 2019 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 repo + +import ( + "path" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" +) + +const ( + tplCompare base.TplName = "repo/diff/compare" +) + +// ParseCompareInfo parse compare info between two commit for preparing comparing references +func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *git.Repository, *git.CompareInfo, string, string) { + baseRepo := ctx.Repo.Repository + + // Get compared branches information + // format: ...[:] + // base<-head: master...head:feature + // same repo: master...feature + + var ( + headUser *models.User + headBranch string + isSameRepo bool + infoPath string + err error + ) + infoPath = ctx.Params("*") + infos := strings.Split(infoPath, "...") + if len(infos) != 2 { + log.Trace("ParseCompareInfo[%d]: not enough compared branches information %s", baseRepo.ID, infos) + ctx.NotFound("CompareAndPullRequest", nil) + return nil, nil, nil, nil, "", "" + } + + baseBranch := infos[0] + ctx.Data["BaseBranch"] = baseBranch + + // If there is no head repository, it means compare between same repository. + headInfos := strings.Split(infos[1], ":") + if len(headInfos) == 1 { + isSameRepo = true + headUser = ctx.Repo.Owner + headBranch = headInfos[0] + + } else if len(headInfos) == 2 { + headUser, err = models.GetUserByName(headInfos[0]) + if err != nil { + if models.IsErrUserNotExist(err) { + ctx.NotFound("GetUserByName", nil) + } else { + ctx.ServerError("GetUserByName", err) + } + return nil, nil, nil, nil, "", "" + } + headBranch = headInfos[1] + isSameRepo = headUser.ID == ctx.Repo.Owner.ID + } else { + ctx.NotFound("CompareAndPullRequest", nil) + return nil, nil, nil, nil, "", "" + } + ctx.Data["HeadUser"] = headUser + ctx.Data["HeadBranch"] = headBranch + ctx.Repo.PullRequest.SameRepo = isSameRepo + + // Check if base branch is valid. + baseIsCommit := ctx.Repo.GitRepo.IsCommitExist(baseBranch) + baseIsBranch := ctx.Repo.GitRepo.IsBranchExist(baseBranch) + baseIsTag := ctx.Repo.GitRepo.IsTagExist(baseBranch) + if !baseIsCommit && !baseIsBranch && !baseIsTag { + // Check if baseBranch is short sha commit hash + if baseCommit, _ := ctx.Repo.GitRepo.GetCommit(baseBranch); baseCommit != nil { + baseBranch = baseCommit.ID.String() + ctx.Data["BaseBranch"] = baseBranch + baseIsCommit = true + } else { + ctx.NotFound("IsRefExist", nil) + return nil, nil, nil, nil, "", "" + } + } + ctx.Data["BaseIsCommit"] = baseIsCommit + ctx.Data["BaseIsBranch"] = baseIsBranch + ctx.Data["BaseIsTag"] = baseIsTag + + // Check if current user has fork of repository or in the same repository. + headRepo, has := models.HasForkedRepo(headUser.ID, baseRepo.ID) + if !has && !isSameRepo { + ctx.Data["PageIsComparePull"] = false + } + + var headGitRepo *git.Repository + if isSameRepo { + headRepo = ctx.Repo.Repository + headGitRepo = ctx.Repo.GitRepo + ctx.Data["BaseName"] = headUser.Name + } else { + headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name)) + ctx.Data["BaseName"] = baseRepo.OwnerName + if err != nil { + ctx.ServerError("OpenRepository", err) + return nil, nil, nil, nil, "", "" + } + } + + // user should have permission to read baseRepo's codes and pulls, NOT headRepo's + permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User) + if err != nil { + ctx.ServerError("GetUserRepoPermission", err) + return nil, nil, nil, nil, "", "" + } + if !permBase.CanRead(models.UnitTypeCode) { + if log.IsTrace() { + log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in baseRepo has Permissions: %-+v", + ctx.User, + baseRepo, + permBase) + } + ctx.NotFound("ParseCompareInfo", nil) + return nil, nil, nil, nil, "", "" + } + + // user should have permission to read headrepo's codes + permHead, err := models.GetUserRepoPermission(headRepo, ctx.User) + if err != nil { + ctx.ServerError("GetUserRepoPermission", err) + return nil, nil, nil, nil, "", "" + } + if !permHead.CanRead(models.UnitTypeCode) { + if log.IsTrace() { + log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v", + ctx.User, + headRepo, + permHead) + } + ctx.NotFound("ParseCompareInfo", nil) + return nil, nil, nil, nil, "", "" + } + + // Check if head branch is valid. + headIsCommit := ctx.Repo.GitRepo.IsCommitExist(headBranch) + headIsBranch := headGitRepo.IsBranchExist(headBranch) + headIsTag := headGitRepo.IsTagExist(headBranch) + if !headIsCommit && !headIsBranch && !headIsTag { + // Check if headBranch is short sha commit hash + if headCommit, _ := ctx.Repo.GitRepo.GetCommit(headBranch); headCommit != nil { + headBranch = headCommit.ID.String() + ctx.Data["HeadBranch"] = headBranch + headIsCommit = true + } else { + ctx.NotFound("IsRefExist", nil) + return nil, nil, nil, nil, "", "" + } + } + ctx.Data["HeadIsCommit"] = headIsCommit + ctx.Data["HeadIsBranch"] = headIsBranch + ctx.Data["HeadIsTag"] = headIsTag + + // Treat as pull request if both references are branches + if ctx.Data["PageIsComparePull"] == nil { + ctx.Data["PageIsComparePull"] = headIsBranch && baseIsBranch + } + + if ctx.Data["PageIsComparePull"] == true && !permBase.CanReadIssuesOrPulls(true) { + if log.IsTrace() { + log.Trace("Permission Denied: User: %-v cannot create/read pull requests in Repo: %-v\nUser in baseRepo has Permissions: %-+v", + ctx.User, + baseRepo, + permBase) + } + ctx.NotFound("ParseCompareInfo", nil) + return nil, nil, nil, nil, "", "" + } + + compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) + if err != nil { + ctx.ServerError("GetCompareInfo", err) + return nil, nil, nil, nil, "", "" + } + ctx.Data["BeforeCommitID"] = compareInfo.MergeBase + + return headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch +} + +// PrepareCompareDiff renders compare diff page +func PrepareCompareDiff( + ctx *context.Context, + headUser *models.User, + headRepo *models.Repository, + headGitRepo *git.Repository, + compareInfo *git.CompareInfo, + baseBranch, headBranch string) bool { + + var ( + repo = ctx.Repo.Repository + err error + title string + ) + + // Get diff information. + ctx.Data["CommitRepoLink"] = headRepo.Link() + + headCommitID := headBranch + if ctx.Data["HeadIsCommit"] == false { + if ctx.Data["HeadIsTag"] == true { + headCommitID, err = headGitRepo.GetTagCommitID(headBranch) + } else { + headCommitID, err = headGitRepo.GetBranchCommitID(headBranch) + } + if err != nil { + ctx.ServerError("GetRefCommitID", err) + return false + } + } + + ctx.Data["AfterCommitID"] = headCommitID + + if headCommitID == compareInfo.MergeBase { + ctx.Data["IsNothingToCompare"] = true + return true + } + + diff, err := models.GetDiffRange(models.RepoPath(headUser.Name, headRepo.Name), + compareInfo.MergeBase, headCommitID, setting.Git.MaxGitDiffLines, + setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) + if err != nil { + ctx.ServerError("GetDiffRange", err) + return false + } + ctx.Data["Diff"] = diff + ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 + + headCommit, err := headGitRepo.GetCommit(headCommitID) + if err != nil { + ctx.ServerError("GetCommit", err) + return false + } + + compareInfo.Commits = models.ValidateCommitsWithEmails(compareInfo.Commits) + compareInfo.Commits = models.ParseCommitsWithSignature(compareInfo.Commits) + compareInfo.Commits = models.ParseCommitsWithStatus(compareInfo.Commits, headRepo) + ctx.Data["Commits"] = compareInfo.Commits + ctx.Data["CommitCount"] = compareInfo.Commits.Len() + if ctx.Data["CommitCount"] == 0 { + ctx.Data["PageIsComparePull"] = false + } + + if compareInfo.Commits.Len() == 1 { + c := compareInfo.Commits.Front().Value.(models.SignCommitWithStatuses) + title = strings.TrimSpace(c.UserCommit.Summary()) + + body := strings.Split(strings.TrimSpace(c.UserCommit.Message()), "\n") + if len(body) > 1 { + ctx.Data["content"] = strings.Join(body[1:], "\n") + } + } else { + title = headBranch + } + + ctx.Data["title"] = title + ctx.Data["Username"] = headUser.Name + ctx.Data["Reponame"] = headRepo.Name + ctx.Data["IsImageFile"] = headCommit.IsImageFile + + headTarget := path.Join(headUser.Name, repo.Name) + ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", headCommitID) + ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", compareInfo.MergeBase) + ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(headTarget, "raw", "commit", headCommitID) + return false +} + +// CompareDiff show different from one commit to another commit +func CompareDiff(ctx *context.Context) { + headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch := ParseCompareInfo(ctx) + if ctx.Written() { + return + } + + nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, compareInfo, baseBranch, headBranch) + if ctx.Written() { + return + } + + if ctx.Data["PageIsComparePull"] == true { + pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) + if err != nil { + if !models.IsErrPullRequestNotExist(err) { + ctx.ServerError("GetUnmergedPullRequest", err) + return + } + } else { + ctx.Data["HasPullRequest"] = true + ctx.Data["PullRequest"] = pr + ctx.HTML(200, tplCompareDiff) + return + } + + if !nothingToCompare { + // Setup information for new form. + RetrieveRepoMetas(ctx, ctx.Repo.Repository) + if ctx.Written() { + return + } + } + + headBranches, err := headGitRepo.GetBranches() + if err != nil { + ctx.ServerError("GetBranches", err) + return + } + ctx.Data["HeadBranches"] = headBranches + } + beforeCommitID := ctx.Data["BeforeCommitID"].(string) + afterCommitID := ctx.Data["AfterCommitID"].(string) + + ctx.Data["Title"] = "Comparing " + base.ShortSha(beforeCommitID) + "..." + base.ShortSha(afterCommitID) + + ctx.Data["IsRepoToolbarCommits"] = true + ctx.Data["IsDiffCompare"] = true + ctx.Data["RequireHighlightJS"] = true + ctx.Data["RequireTribute"] = true + ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes + setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates) + renderAttachmentSettings(ctx) + + ctx.HTML(200, tplCompare) +} diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 412750dd55d28..182f715545237 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -28,7 +28,7 @@ import ( const ( tplFork base.TplName = "repo/pulls/fork" - tplComparePull base.TplName = "repo/pulls/compare" + tplCompareDiff base.TplName = "repo/diff/compare" tplPullCommits base.TplName = "repo/pulls/commits" tplPullFiles base.TplName = "repo/pulls/files" @@ -280,13 +280,13 @@ func setMergeTarget(ctx *context.Context, pull *models.PullRequest) { } // PrepareMergedViewPullInfo show meta information for a merged pull request view page -func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullRequestInfo { +func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.CompareInfo { pull := issue.PullRequest setMergeTarget(ctx, pull) ctx.Data["HasMerged"] = true - prInfo, err := ctx.Repo.GitRepo.GetPullRequestInfo(ctx.Repo.Repository.RepoPath(), + prInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), pull.MergeBase, pull.GetGitRefName()) if err != nil { @@ -298,7 +298,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.P return nil } - ctx.ServerError("GetPullRequestInfo", err) + ctx.ServerError("GetCompareInfo", err) return nil } ctx.Data["NumCommits"] = prInfo.Commits.Len() @@ -307,7 +307,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.P } // PrepareViewPullInfo show meta information for a pull request preview page -func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullRequestInfo { +func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.CompareInfo { repo := ctx.Repo.Repository pull := issue.PullRequest @@ -336,7 +336,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq return nil } - prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(repo.Owner.Name, repo.Name), + prInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(repo.Owner.Name, repo.Name), pull.BaseBranch, pull.HeadBranch) if err != nil { if strings.Contains(err.Error(), "fatal: Not a valid object name") { @@ -347,7 +347,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq return nil } - ctx.ServerError("GetPullRequestInfo", err) + ctx.ServerError("GetCompareInfo", err) return nil } @@ -628,266 +628,6 @@ func stopTimerIfAvailable(user *models.User, issue *models.Issue) error { return nil } -// ParseCompareInfo parse compare info between two commit for preparing pull request -func ParseCompareInfo(ctx *context.Context) (*models.User, *models.Repository, *git.Repository, *git.PullRequestInfo, string, string) { - baseRepo := ctx.Repo.Repository - - // Get compared branches information - // format: ...[:] - // base<-head: master...head:feature - // same repo: master...feature - - var ( - headUser *models.User - headBranch string - isSameRepo bool - infoPath string - err error - ) - infoPath = ctx.Params("*") - infos := strings.Split(infoPath, "...") - if len(infos) != 2 { - log.Trace("ParseCompareInfo[%d]: not enough compared branches information %s", baseRepo.ID, infos) - ctx.NotFound("CompareAndPullRequest", nil) - return nil, nil, nil, nil, "", "" - } - - baseBranch := infos[0] - ctx.Data["BaseBranch"] = baseBranch - - // If there is no head repository, it means pull request between same repository. - headInfos := strings.Split(infos[1], ":") - if len(headInfos) == 1 { - isSameRepo = true - headUser = ctx.Repo.Owner - headBranch = headInfos[0] - - } else if len(headInfos) == 2 { - headUser, err = models.GetUserByName(headInfos[0]) - if err != nil { - if models.IsErrUserNotExist(err) { - ctx.NotFound("GetUserByName", nil) - } else { - ctx.ServerError("GetUserByName", err) - } - return nil, nil, nil, nil, "", "" - } - headBranch = headInfos[1] - isSameRepo = headUser.ID == ctx.Repo.Owner.ID - } else { - ctx.NotFound("CompareAndPullRequest", nil) - return nil, nil, nil, nil, "", "" - } - ctx.Data["HeadUser"] = headUser - ctx.Data["HeadBranch"] = headBranch - ctx.Repo.PullRequest.SameRepo = isSameRepo - - // Check if base branch is valid. - if !ctx.Repo.GitRepo.IsBranchExist(baseBranch) { - ctx.NotFound("IsBranchExist", nil) - return nil, nil, nil, nil, "", "" - } - - // Check if current user has fork of repository or in the same repository. - headRepo, has := models.HasForkedRepo(headUser.ID, baseRepo.ID) - if !has && !isSameRepo { - log.Trace("ParseCompareInfo[%d]: does not have fork or in same repository", baseRepo.ID) - ctx.NotFound("ParseCompareInfo", nil) - return nil, nil, nil, nil, "", "" - } - - var headGitRepo *git.Repository - if isSameRepo { - headRepo = ctx.Repo.Repository - headGitRepo = ctx.Repo.GitRepo - ctx.Data["BaseName"] = headUser.Name - } else { - headGitRepo, err = git.OpenRepository(models.RepoPath(headUser.Name, headRepo.Name)) - ctx.Data["BaseName"] = baseRepo.OwnerName - if err != nil { - ctx.ServerError("OpenRepository", err) - return nil, nil, nil, nil, "", "" - } - } - - // user should have permission to read baseRepo's codes and pulls, NOT headRepo's - permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User) - if err != nil { - ctx.ServerError("GetUserRepoPermission", err) - return nil, nil, nil, nil, "", "" - } - if !permBase.CanReadIssuesOrPulls(true) || !permBase.CanRead(models.UnitTypeCode) { - if log.IsTrace() { - log.Trace("Permission Denied: User: %-v cannot create/read pull requests or cannot read code in Repo: %-v\nUser in baseRepo has Permissions: %-+v", - ctx.User, - baseRepo, - permBase) - } - ctx.NotFound("ParseCompareInfo", nil) - return nil, nil, nil, nil, "", "" - } - - // user should have permission to read headrepo's codes - permHead, err := models.GetUserRepoPermission(headRepo, ctx.User) - if err != nil { - ctx.ServerError("GetUserRepoPermission", err) - return nil, nil, nil, nil, "", "" - } - if !permHead.CanRead(models.UnitTypeCode) { - if log.IsTrace() { - log.Trace("Permission Denied: User: %-v cannot read code requests in Repo: %-v\nUser in headRepo has Permissions: %-+v", - ctx.User, - headRepo, - permHead) - } - ctx.NotFound("ParseCompareInfo", nil) - return nil, nil, nil, nil, "", "" - } - - // Check if head branch is valid. - if !headGitRepo.IsBranchExist(headBranch) { - ctx.NotFound("IsBranchExist", nil) - return nil, nil, nil, nil, "", "" - } - - headBranches, err := headGitRepo.GetBranches() - if err != nil { - ctx.ServerError("GetBranches", err) - return nil, nil, nil, nil, "", "" - } - ctx.Data["HeadBranches"] = headBranches - - prInfo, err := headGitRepo.GetPullRequestInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch) - if err != nil { - ctx.ServerError("GetPullRequestInfo", err) - return nil, nil, nil, nil, "", "" - } - ctx.Data["BeforeCommitID"] = prInfo.MergeBase - - return headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch -} - -// PrepareCompareDiff render pull request preview diff page -func PrepareCompareDiff( - ctx *context.Context, - headUser *models.User, - headRepo *models.Repository, - headGitRepo *git.Repository, - prInfo *git.PullRequestInfo, - baseBranch, headBranch string) bool { - - var ( - repo = ctx.Repo.Repository - err error - title string - ) - - // Get diff information. - ctx.Data["CommitRepoLink"] = headRepo.Link() - - headCommitID, err := headGitRepo.GetBranchCommitID(headBranch) - if err != nil { - ctx.ServerError("GetBranchCommitID", err) - return false - } - ctx.Data["AfterCommitID"] = headCommitID - - if headCommitID == prInfo.MergeBase { - ctx.Data["IsNothingToCompare"] = true - return true - } - - diff, err := models.GetDiffRange(models.RepoPath(headUser.Name, headRepo.Name), - prInfo.MergeBase, headCommitID, setting.Git.MaxGitDiffLines, - setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) - if err != nil { - ctx.ServerError("GetDiffRange", err) - return false - } - ctx.Data["Diff"] = diff - ctx.Data["DiffNotAvailable"] = diff.NumFiles() == 0 - - headCommit, err := headGitRepo.GetCommit(headCommitID) - if err != nil { - ctx.ServerError("GetCommit", err) - return false - } - - prInfo.Commits = models.ValidateCommitsWithEmails(prInfo.Commits) - prInfo.Commits = models.ParseCommitsWithSignature(prInfo.Commits) - prInfo.Commits = models.ParseCommitsWithStatus(prInfo.Commits, headRepo) - ctx.Data["Commits"] = prInfo.Commits - ctx.Data["CommitCount"] = prInfo.Commits.Len() - - if prInfo.Commits.Len() == 1 { - c := prInfo.Commits.Front().Value.(models.SignCommitWithStatuses) - title = strings.TrimSpace(c.UserCommit.Summary()) - - body := strings.Split(strings.TrimSpace(c.UserCommit.Message()), "\n") - if len(body) > 1 { - ctx.Data["content"] = strings.Join(body[1:], "\n") - } - } else { - title = headBranch - } - - ctx.Data["title"] = title - ctx.Data["Username"] = headUser.Name - ctx.Data["Reponame"] = headRepo.Name - ctx.Data["IsImageFile"] = headCommit.IsImageFile - - headTarget := path.Join(headUser.Name, repo.Name) - ctx.Data["SourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", headCommitID) - ctx.Data["BeforeSourcePath"] = setting.AppSubURL + "/" + path.Join(headTarget, "src", "commit", prInfo.MergeBase) - ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(headTarget, "raw", "commit", headCommitID) - return false -} - -// CompareAndPullRequest render pull request preview page -func CompareAndPullRequest(ctx *context.Context) { - ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes") - ctx.Data["PageIsComparePull"] = true - ctx.Data["IsDiffCompare"] = true - ctx.Data["RequireHighlightJS"] = true - ctx.Data["RequireTribute"] = true - ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes - setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates) - renderAttachmentSettings(ctx) - - headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch := ParseCompareInfo(ctx) - if ctx.Written() { - return - } - - pr, err := models.GetUnmergedPullRequest(headRepo.ID, ctx.Repo.Repository.ID, headBranch, baseBranch) - if err != nil { - if !models.IsErrPullRequestNotExist(err) { - ctx.ServerError("GetUnmergedPullRequest", err) - return - } - } else { - ctx.Data["HasPullRequest"] = true - ctx.Data["PullRequest"] = pr - ctx.HTML(200, tplComparePull) - return - } - - nothingToCompare := PrepareCompareDiff(ctx, headUser, headRepo, headGitRepo, prInfo, baseBranch, headBranch) - if ctx.Written() { - return - } - - if !nothingToCompare { - // Setup information for new form. - RetrieveRepoMetas(ctx, ctx.Repo.Repository) - if ctx.Written() { - return - } - } - - ctx.HTML(200, tplComparePull) -} - // CompareAndPullRequestPost response for creating pull request func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) { ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes") @@ -926,7 +666,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) return } - ctx.HTML(200, tplComparePull) + ctx.HTML(200, tplCompareDiff) return } @@ -936,7 +676,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) return } - ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplComparePull, form) + ctx.RenderWithErr(ctx.Tr("repo.issues.new.title_empty"), tplCompareDiff, form) return } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index eb5f73768e38e..4c736f63ed40e 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -732,9 +732,9 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/milestone", func() { m.Get("/:id", repo.MilestoneIssuesAndPulls) }, reqRepoIssuesOrPullsReader, context.RepoRef()) - m.Combo("/compare/*", context.RepoMustNotBeArchived(), reqRepoCodeReader, reqRepoPullsReader, repo.MustAllowPulls, repo.SetEditorconfigIfExists). - Get(repo.SetDiffViewStyle, repo.CompareAndPullRequest). - Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost) + m.Combo("/compare/*", repo.MustBeNotEmpty, reqRepoCodeReader, repo.SetEditorconfigIfExists). + Get(repo.SetDiffViewStyle, repo.CompareDiff). + Post(context.RepoMustNotBeArchived(), reqRepoPullsReader, repo.MustAllowPulls, bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost) m.Group("", func() { m.Group("", func() { @@ -906,9 +906,6 @@ func RegisterRoutes(m *macaron.Macaron) { }, context.RepoRef(), reqRepoCodeReader) m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff) - - m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, - repo.SetDiffViewStyle, repo.MustBeNotEmpty, reqRepoCodeReader, repo.CompareDiff) }, ignSignIn, context.RepoAssignment(), context.UnitTypes()) m.Group("/:username/:reponame", func() { m.Get("/stars", repo.Stars) diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl new file mode 100644 index 0000000000000..0cfdf5156d480 --- /dev/null +++ b/templates/repo/commit_page.tmpl @@ -0,0 +1,89 @@ +{{template "base/head" .}} +
+ {{template "repo/header" .}} +
+
+ + {{.i18n.Tr "repo.diff.browse_source"}} + +

{{RenderCommitMessage .Commit.Message $.RepoLink $.Repository.ComposeMetas}}{{template "repo/commit_status" .CommitStatus}}

+ {{if IsMultilineCommitMessage .Commit.Message}} +
{{RenderCommitBody .Commit.Message $.RepoLink $.Repository.ComposeMetas}}
+ {{end}} + {{.BranchName}} +
+
+
+
+ {{if .Author}} + + {{if .Author.FullName}} + {{.Author.FullName}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} + {{else}} + {{.Commit.Author.Name}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} + {{end}} + {{else}} + + {{.Commit.Author.Name}} + {{end}} + {{TimeSince .Commit.Author.When $.Lang}} +
+
+
+ {{if .Parents}} +
+ {{.i18n.Tr "repo.diff.parent"}} +
+
+ {{range .Parents}} + {{ShortSha .}} + {{end}} +
+ {{end}} +
+
{{.i18n.Tr "repo.diff.commit"}}
+
{{ShortSha .CommitID}}
+
+
+
+
+ {{if .Commit.Signature}} + {{if .Verification.Verified }} +
+ + {{.i18n.Tr "repo.commits.signed_by"}}: + {{.Commit.Committer.Name}} <{{.Commit.Committer.Email}}> + {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} +
+ {{else}} +
+ + {{.i18n.Tr .Verification.Reason}} +
+ {{end}} + {{end}} + {{if .Note}} +
+ + {{.i18n.Tr "repo.diff.git-notes"}}: + {{if .NoteAuthor}} + + {{if .NoteAuthor.FullName}} + {{.NoteAuthor.FullName}} + {{else}} + {{.NoteCommit.Author.Name}} + {{end}} + + {{else}} + {{.NoteCommit.Author.Name}} + {{end}} + {{TimeSince .NoteCommit.Author.When $.Lang}} +
+
+
{{RenderNote .Note $.RepoLink $.Repository.ComposeMetas}}
+
+ {{end}} + {{template "repo/diff/box" .}} +
+
+{{template "base/footer" .}} diff --git a/templates/repo/commits_table.tmpl b/templates/repo/commits_table.tmpl index 66bfd0d831eb4..10f4b6048360a 100644 --- a/templates/repo/commits_table.tmpl +++ b/templates/repo/commits_table.tmpl @@ -1,13 +1,13 @@

-
+
{{if or .PageIsCommits (gt .CommitCount 0)}} {{.CommitCount}} {{.i18n.Tr "repo.commits.commits"}} {{if .Branch}}({{.Branch}}){{end}} {{else}} {{.i18n.Tr "repo.commits.no_commits" $.BaseBranch $.HeadBranch }} {{if .Branch}}({{.Branch}}){{end}} {{end}}
-
+ diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl new file mode 100644 index 0000000000000..cc727422d7e46 --- /dev/null +++ b/templates/repo/diff/compare.tmpl @@ -0,0 +1,74 @@ +{{template "base/head" .}} +
+ {{template "repo/header" .}} +
+ + {{if .PageIsComparePull}} +

+ {{.i18n.Tr "repo.pulls.compare_changes"}} +
{{.i18n.Tr "repo.pulls.compare_changes_desc"}}
+

+
+ + + ... + +
+ {{end}} + + {{if .IsNothingToCompare}} +
{{.i18n.Tr "repo.pulls.nothing_to_compare"}}
+ {{else if .PageIsComparePull}} + {{if .HasPullRequest}} +
+ {{.i18n.Tr "repo.pulls.has_pull_request" $.RepoLink $.RepoRelPath .PullRequest.Index | Safe}} +
+ {{else}} +
+ +
+ + {{template "repo/commits_table" .}} + {{template "repo/diff/box" .}} + {{end}} + {{else}} + {{template "repo/commits_table" .}} + {{template "repo/diff/box" .}} + {{end}} +
+
+{{template "base/footer" .}} diff --git a/templates/repo/diff/page.tmpl b/templates/repo/diff/page.tmpl deleted file mode 100644 index c35e2a415b4b9..0000000000000 --- a/templates/repo/diff/page.tmpl +++ /dev/null @@ -1,94 +0,0 @@ -{{template "base/head" .}} -
- {{template "repo/header" .}} -
- {{if .IsDiffCompare }} - {{template "repo/commits_table" .}} - {{else}} -
- - {{.i18n.Tr "repo.diff.browse_source"}} - -

{{RenderCommitMessage .Commit.Message $.RepoLink $.Repository.ComposeMetas}}{{template "repo/commit_status" .CommitStatus}}

- {{if IsMultilineCommitMessage .Commit.Message}} -
{{RenderCommitBody .Commit.Message $.RepoLink $.Repository.ComposeMetas}}
- {{end}} - {{.BranchName}} -
-
-
-
- {{if .Author}} - - {{if .Author.FullName}} - {{.Author.FullName}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} - {{else}} - {{.Commit.Author.Name}} {{if .IsSigned}}<{{.Commit.Author.Email}}>{{end}} - {{end}} - {{else}} - - {{.Commit.Author.Name}} - {{end}} - {{TimeSince .Commit.Author.When $.Lang}} -
-
-
- {{if .Parents}} -
- {{.i18n.Tr "repo.diff.parent"}} -
-
- {{range .Parents}} - {{ShortSha .}} - {{end}} -
- {{end}} -
-
{{.i18n.Tr "repo.diff.commit"}}
-
{{ShortSha .CommitID}}
-
-
-
-
- {{if .Commit.Signature}} - {{if .Verification.Verified }} -
- - {{.i18n.Tr "repo.commits.signed_by"}}: - {{.Commit.Committer.Name}} <{{.Commit.Committer.Email}}> - {{.i18n.Tr "repo.commits.gpg_key_id"}}: {{.Verification.SigningKey.KeyID}} -
- {{else}} -
- - {{.i18n.Tr .Verification.Reason}} -
- {{end}} - {{end}} - {{if .Note}} -
- - {{.i18n.Tr "repo.diff.git-notes"}}: - {{if .NoteAuthor}} - - {{if .NoteAuthor.FullName}} - {{.NoteAuthor.FullName}} - {{else}} - {{.NoteCommit.Author.Name}} - {{end}} - - {{else}} - {{.NoteCommit.Author.Name}} - {{end}} - {{TimeSince .NoteCommit.Author.When $.Lang}} -
-
-
{{RenderNote .Note $.RepoLink $.Repository.ComposeMetas}}
-
- {{end}} - {{end}} - - {{template "repo/diff/box" .}} -
-
-{{template "base/footer" .}} diff --git a/templates/repo/pulls/compare.tmpl b/templates/repo/pulls/compare.tmpl deleted file mode 100644 index 2296acf1df9a4..0000000000000 --- a/templates/repo/pulls/compare.tmpl +++ /dev/null @@ -1,69 +0,0 @@ -{{template "base/head" .}} -
- {{template "repo/header" .}} -
-
-

- {{.i18n.Tr "repo.pulls.compare_changes"}} -
{{.i18n.Tr "repo.pulls.compare_changes_desc"}}
-

-
- - - ... - -
- - {{if .IsNothingToCompare}} -
- {{.i18n.Tr "repo.pulls.nothing_to_compare"}} -
- {{else if .HasPullRequest}} -
- {{.i18n.Tr "repo.pulls.has_pull_request" $.RepoLink $.RepoRelPath .PullRequest.Index | Safe}} -
- {{else if eq .CommitCount 0 }} - {{template "repo/commits_table" .}} - {{template "repo/diff/box" .}} - {{else}} - {{template "repo/issue/new_form" .}} - {{template "repo/commits_table" .}} - {{template "repo/diff/box" .}} - {{end}} -
- -
-
-{{template "base/footer" .}} From ca58eee6bfcaab9970391a7a3d57391cb5bf2d87 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Fri, 7 Jun 2019 20:32:49 +0000 Subject: [PATCH 13/30] [skip ci] Updated translations via Crowdin --- options/locale/locale_ja-JP.ini | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 9dfad59f57fba..c5028af841178 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -487,6 +487,7 @@ manage_oauth2_applications=OAuth2アプリケーションの管理 edit_oauth2_application=OAuth2アプリケーションの編集 oauth2_applications_desc=OAuth2はGiteaインスタンスでのサードパーティアプリケーションによる安全な認証を可能にします。 remove_oauth2_application=OAuth2アプリケーションの削除 +remove_oauth2_application_desc=OAuth2アプリケーションを削除すると、すべての署名済みアクセストークンが利用できなくなります。 続行しますか? remove_oauth2_application_success=アプリケーションを削除しました。 create_oauth2_application=新しいOAuth2アプリケーションの作成 create_oauth2_application_button=アプリケーション作成 @@ -618,6 +619,7 @@ migrate.permission_denied=ローカルリポジトリをインポートする権 migrate.invalid_local_path=ローカルパスが無効です。 存在しないかディレクトリではありません。 migrate.failed=移行に失敗しました: %v migrate.lfs_mirror_unsupported=LFSオブジェクトのミラーはサポートされていません。 代わりに 'git lfs fetch --all' と 'git lfs push --all' を使ってください。 +migrate.migrate_items_options=移行元がGitHubの場合は、ユーザー名を入力すると移行オプションが表示されます。 mirror_from=ミラー元 forked_from=フォーク元 @@ -1304,11 +1306,14 @@ settings.archive.button=アーカイブ settings.archive.header=このリポジトリをアーカイブ settings.archive.text=リポジトリをアーカイブすると、リポジトリ全体が読み出し専用となります。 ダッシュボードには表示されなくなり、コミットも、課題やプルリクエストの作成もできません。 settings.archive.success=リポジトリをアーカイブしました。 +settings.archive.error=リポジトリのアーカイブ設定でエラーが発生しました。 詳細はログを確認してください。 settings.archive.error_ismirror=ミラーのリポジトリはアーカイブできません。 settings.archive.branchsettings_unavailable=ブランチ設定は、アーカイブリポジトリでは使用できません。 settings.unarchive.button=アーカイブ解除 settings.unarchive.header=このリポジトリをアーカイブ解除 +settings.unarchive.text=リポジトリのアーカイブを解除すると、コミット、プッシュ、新規の課題やプルリクエストを受け付けるよう元に戻されます。 settings.unarchive.success=リポジトリのアーカイブを解除しました。 +settings.unarchive.error=リポジトリのアーカイブ解除でエラーが発生しました。 詳細はログを確認してください。 settings.update_avatar_success=リポジトリのアバターを更新しました。 diff.browse_source=ソースを参照 From 6fb31a54610d319fbcb6c930d2c4457c8be82c96 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 8 Jun 2019 19:47:46 +0800 Subject: [PATCH 14/30] fix GCArgs load from ini (#7156) --- modules/setting/git.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/setting/git.go b/modules/setting/git.go index 673bff207e539..4163f1039d4ee 100644 --- a/modules/setting/git.go +++ b/modules/setting/git.go @@ -20,7 +20,7 @@ var ( MaxGitDiffLines int MaxGitDiffLineCharacters int MaxGitDiffFiles int - GCArgs []string `delim:" "` + GCArgs []string `ini:"GC_ARGS" delim:" "` EnableAutoGitWireProtocol bool Timeout struct { Default int From 23a2ee3510ad1b1e7e89edc526ed394c71a8ba24 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 8 Jun 2019 21:53:45 +0800 Subject: [PATCH 15/30] Add command to convert mysql database from utf8 to utf8mb4 (#7144) * add command to convert mysql database from utf8 to utf8mb4 * Update cmd/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> * Update cmd/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> * Update cmd/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> * Update models/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> * Update models/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> * Update cmd/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> * Update cmd/convert.go Co-Authored-By: John Olheiser <42128690+jolheiser@users.noreply.github.com> --- cmd/convert.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++ main.go | 1 + models/convert.go | 27 ++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 cmd/convert.go create mode 100644 models/convert.go diff --git a/cmd/convert.go b/cmd/convert.go new file mode 100644 index 0000000000000..cb0510c722fc8 --- /dev/null +++ b/cmd/convert.go @@ -0,0 +1,49 @@ +// Copyright 2019 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 cmd + +import ( + "fmt" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + + "github.com/urfave/cli" +) + +// CmdConvert represents the available convert sub-command. +var CmdConvert = cli.Command{ + Name: "convert", + Usage: "Convert the database", + Description: "A command to convert an existing MySQL database from utf8 to utf8mb4", + Action: runConvert, +} + +func runConvert(ctx *cli.Context) error { + if err := initDB(); err != nil { + return err + } + + log.Trace("AppPath: %s", setting.AppPath) + log.Trace("AppWorkPath: %s", setting.AppWorkPath) + log.Trace("Custom path: %s", setting.CustomPath) + log.Trace("Log path: %s", setting.LogRootPath) + models.LoadConfigs() + + if models.DbCfg.Type != "mysql" { + fmt.Println("This command can only be used with a MySQL database") + return nil + } + + if err := models.ConvertUtf8ToUtf8mb4(); err != nil { + log.Fatal("Failed to convert database from utf8 to utf8mb4: %v", err) + return err + } + + fmt.Println("Converted successfully, please confirm your database's character set is now utf8mb4") + + return nil +} diff --git a/main.go b/main.go index d8c37fee2f097..79c9b01114b05 100644 --- a/main.go +++ b/main.go @@ -67,6 +67,7 @@ arguments - which can alternatively be run by running the subcommand web.` cmd.CmdGenerate, cmd.CmdMigrate, cmd.CmdKeys, + cmd.CmdConvert, } // Now adjust these commands to add our global configuration options diff --git a/models/convert.go b/models/convert.go new file mode 100644 index 0000000000000..c34be973c6b53 --- /dev/null +++ b/models/convert.go @@ -0,0 +1,27 @@ +// Copyright 2019 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 models + +import "fmt" + +// ConvertUtf8ToUtf8mb4 converts database and tables from utf8 to utf8mb4 if it's mysql +func ConvertUtf8ToUtf8mb4() error { + _, err := x.Exec(fmt.Sprintf("ALTER DATABASE `%s` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci", DbCfg.Name)) + if err != nil { + return err + } + + tables, err := x.DBMetas() + if err != nil { + return err + } + for _, table := range tables { + if _, err := x.Exec(fmt.Sprintf("ALTER TABLE `%s` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;", table.Name)); err != nil { + return err + } + } + + return nil +} From 8de0b0a3f06fe7879fb014d2624209e0e48455a0 Mon Sep 17 00:00:00 2001 From: Richard Mahn Date: Sat, 8 Jun 2019 10:31:11 -0400 Subject: [PATCH 16/30] Fixes #2738 - Adds the /git/tags API endpoint (#7138) * Fixes #2738 - /git/tags API * proper URLs * Adds function comments * Updates swagger * Removes newline from tag message * Removes trailing newline from commit message * Adds integration test * Removed debugging * Adds tests * Fixes bug where multiple tags of same commit show wrong tag name * Fix formatting * Removes unused varaible * Fix to annotated tag function names and response * Update modules/git/repo_tag.go Co-Authored-By: Lauris BH * Uses TagPrefix * Changes per review, better error handling for getting tag and commit IDs * Fix to getting commit ID * Fix to getting commit ID * Fix to getting commit ID * Fix to getting commit ID --- integrations/api_repo_file_create_test.go | 4 +- integrations/api_repo_file_update_test.go | 8 +- integrations/api_repo_git_tags_test.go | 59 +++++++++ integrations/api_repo_tags_test.go | 7 +- models/repo_tag.go | 2 +- modules/git/repo_ref.go | 12 +- modules/git/repo_tag.go | 147 ++++++++++++++++++++-- modules/git/repo_tag_test.go | 80 +++++++++++- modules/git/tag.go | 3 +- modules/structs/repo_tag.go | 30 +++-- routers/api/v1/api.go | 2 + routers/api/v1/convert/convert.go | 98 ++++++++++----- routers/api/v1/repo/git_ref.go | 3 +- routers/api/v1/repo/tag.go | 45 +++++++ routers/api/v1/swagger/repo.go | 16 ++- templates/swagger/v1_json.tmpl | 120 ++++++++++++++++-- 16 files changed, 551 insertions(+), 85 deletions(-) create mode 100644 integrations/api_repo_git_tags_test.go diff --git a/integrations/api_repo_file_create_test.go b/integrations/api_repo_file_create_test.go index 28097179a060d..3bb2ecb812860 100644 --- a/integrations/api_repo_file_create_test.go +++ b/integrations/api_repo_file_create_test.go @@ -146,8 +146,8 @@ func TestAPICreateFile(t *testing.T) { var fileResponse api.FileResponse DecodeJSON(t, resp, &fileResponse) expectedSHA := "a635aa942442ddfdba07468cf9661c08fbdf0ebf" - expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/new/file%d.txt", fileID) - expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID) + expectedHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/blob/new_branch/new/file%d.txt", fileID) + expectedDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/new/file%d.txt", fileID) assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA) assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL) assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL) diff --git a/integrations/api_repo_file_update_test.go b/integrations/api_repo_file_update_test.go index 37438339bbd31..eab7090df68f5 100644 --- a/integrations/api_repo_file_update_test.go +++ b/integrations/api_repo_file_update_test.go @@ -136,8 +136,8 @@ func TestAPIUpdateFile(t *testing.T) { var fileResponse api.FileResponse DecodeJSON(t, resp, &fileResponse) expectedSHA := "08bd14b2e2852529157324de9c226b3364e76136" - expectedHTMLURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/new_branch/update/file%d.txt", fileID) - expectedDownloadURL := fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID) + expectedHTMLURL := fmt.Sprintf(setting.AppURL+"user2/repo1/blob/new_branch/update/file%d.txt", fileID) + expectedDownloadURL := fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/new_branch/update/file%d.txt", fileID) assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA) assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL) assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL) @@ -155,8 +155,8 @@ func TestAPIUpdateFile(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusOK) DecodeJSON(t, resp, &fileResponse) expectedSHA = "08bd14b2e2852529157324de9c226b3364e76136" - expectedHTMLURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/blob/master/rename/update/file%d.txt", fileID) - expectedDownloadURL = fmt.Sprintf("http://localhost:"+setting.HTTPPort+"/user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID) + expectedHTMLURL = fmt.Sprintf(setting.AppURL+"user2/repo1/blob/master/rename/update/file%d.txt", fileID) + expectedDownloadURL = fmt.Sprintf(setting.AppURL+"user2/repo1/raw/branch/master/rename/update/file%d.txt", fileID) assert.EqualValues(t, expectedSHA, fileResponse.Content.SHA) assert.EqualValues(t, expectedHTMLURL, fileResponse.Content.HTMLURL) assert.EqualValues(t, expectedDownloadURL, fileResponse.Content.DownloadURL) diff --git a/integrations/api_repo_git_tags_test.go b/integrations/api_repo_git_tags_test.go new file mode 100644 index 0000000000000..ae519249e03b0 --- /dev/null +++ b/integrations/api_repo_git_tags_test.go @@ -0,0 +1,59 @@ +// Copyright 2018 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 integrations + +import ( + "net/http" + "testing" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" + + "github.com/stretchr/testify/assert" +) + +func TestAPIGitTags(t *testing.T) { + prepareTestEnv(t) + user := models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + // Login as User2. + session := loginUser(t, user.Name) + token := getTokenForLoggedInUser(t, session) + + // Set up git config for the tagger + git.NewCommand("config", "user.name", user.Name).RunInDir(repo.RepoPath()) + git.NewCommand("config", "user.email", user.Email).RunInDir(repo.RepoPath()) + + gitRepo, _ := git.OpenRepository(repo.RepoPath()) + commit, _ := gitRepo.GetBranchCommit("master") + lTagName := "lightweightTag" + gitRepo.CreateTag(lTagName, commit.ID.String()) + + aTagName := "annotatedTag" + aTagMessage := "my annotated message" + gitRepo.CreateAnnotatedTag(aTagName, aTagMessage, commit.ID.String()) + aTag, _ := gitRepo.GetTag(aTagName) + + // SHOULD work for annotated tags + req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/tags/%s?token=%s", user.Name, repo.Name, aTag.ID.String(), token) + res := session.MakeRequest(t, req, http.StatusOK) + + var tag *api.AnnotatedTag + DecodeJSON(t, res, &tag) + + assert.Equal(t, aTagName, tag.Tag) + assert.Equal(t, aTag.ID.String(), tag.SHA) + assert.Equal(t, commit.ID.String(), tag.Object.SHA) + assert.Equal(t, aTagMessage, tag.Message) + assert.Equal(t, user.Name, tag.Tagger.Name) + assert.Equal(t, user.Email, tag.Tagger.Email) + assert.Equal(t, util.URLJoin(repo.APIURL(), "git/tags", aTag.ID.String()), tag.URL) + + // Should NOT work for lightweight tags + badReq := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/git/tags/%s?token=%s", user.Name, repo.Name, commit.ID.String(), token) + session.MakeRequest(t, badReq, http.StatusBadRequest) +} diff --git a/integrations/api_repo_tags_test.go b/integrations/api_repo_tags_test.go index 13b446fb9637c..252037bd4a570 100644 --- a/integrations/api_repo_tags_test.go +++ b/integrations/api_repo_tags_test.go @@ -6,7 +6,6 @@ package integrations import ( "net/http" - "path" "testing" "code.gitea.io/gitea/models" @@ -32,7 +31,7 @@ func TestAPIReposGetTags(t *testing.T) { assert.EqualValues(t, 1, len(tags)) assert.Equal(t, "v1.1", tags[0].Name) assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.SHA) - assert.Equal(t, path.Join(setting.AppSubURL, "/user2/repo1/commit/65f1bf27bc3bf70f64657658635e66094edbcb4d"), tags[0].Commit.URL) - assert.Equal(t, path.Join(setting.AppSubURL, "/user2/repo1/archive/v1.1.zip"), tags[0].ZipballURL) - assert.Equal(t, path.Join(setting.AppSubURL, "/user2/repo1/archive/v1.1.tar.gz"), tags[0].TarballURL) + assert.Equal(t, setting.AppURL+"api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.URL) + assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.zip", tags[0].ZipballURL) + assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.tar.gz", tags[0].TarballURL) } diff --git a/models/repo_tag.go b/models/repo_tag.go index fa3f19bb292cb..3864b7a12a7c9 100644 --- a/models/repo_tag.go +++ b/models/repo_tag.go @@ -8,7 +8,7 @@ import ( "code.gitea.io/gitea/modules/git" ) -// GetTagsByPath returns repo tags by it's path +// GetTagsByPath returns repo tags by its path func GetTagsByPath(path string) ([]*git.Tag, error) { gitRepo, err := git.OpenRepository(path) if err != nil { diff --git a/modules/git/repo_ref.go b/modules/git/repo_ref.go index e1ab46e0902dc..95a6c2ae69390 100644 --- a/modules/git/repo_ref.go +++ b/modules/git/repo_ref.go @@ -31,15 +31,19 @@ func (repo *Repository) GetRefsFiltered(pattern string) ([]*Reference, error) { if err = refsIter.ForEach(func(ref *plumbing.Reference) error { if ref.Name() != plumbing.HEAD && !ref.Name().IsRemote() && (pattern == "" || strings.HasPrefix(ref.Name().String(), pattern)) { + refType := string(ObjectCommit) + if ref.Name().IsTag() { + // tags can be of type `commit` (lightweight) or `tag` (annotated) + if tagType, _ := repo.GetTagType(SHA1(ref.Hash())); err == nil { + refType = tagType + } + } r := &Reference{ Name: ref.Name().String(), Object: SHA1(ref.Hash()), - Type: string(ObjectCommit), + Type: refType, repo: repo, } - if ref.Name().IsTag() { - r.Type = string(ObjectTag) - } refs = append(refs, r) } return nil diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index 8c72528933ccd..08d66262c17d1 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -6,6 +6,7 @@ package git import ( + "fmt" "strings" "github.com/mcuadros/go-version" @@ -35,34 +36,78 @@ func (repo *Repository) CreateTag(name, revision string) error { return err } +// CreateAnnotatedTag create one annotated tag in the repository +func (repo *Repository) CreateAnnotatedTag(name, message, revision string) error { + _, err := NewCommand("tag", "-a", "-m", message, name, revision).RunInDir(repo.Path) + return err +} + func (repo *Repository) getTag(id SHA1) (*Tag, error) { t, ok := repo.tagCache.Get(id.String()) if ok { log("Hit cache: %s", id) - return t.(*Tag), nil + tagClone := *t.(*Tag) + return &tagClone, nil } - // Get tag type - tp, err := NewCommand("cat-file", "-t", id.String()).RunInDir(repo.Path) + // Get tag name + name, err := repo.GetTagNameBySHA(id.String()) + if err != nil { + return nil, err + } + + tp, err := repo.GetTagType(id) if err != nil { return nil, err } - tp = strings.TrimSpace(tp) - // Tag is a commit. + // Get the commit ID and tag ID (may be different for annotated tag) for the returned tag object + commitIDStr, err := repo.GetTagCommitID(name) + if err != nil { + // every tag should have a commit ID so return all errors + return nil, err + } + commitID, err := NewIDFromString(commitIDStr) + if err != nil { + return nil, err + } + + // tagID defaults to the commit ID as the tag ID and then tries to get a tag ID (only annotated tags) + tagID := commitID + if tagIDStr, err := repo.GetTagID(name); err != nil { + // if the err is NotExist then we can ignore and just keep tagID as ID (is lightweight tag) + // all other errors we return + if !IsErrNotExist(err) { + return nil, err + } + } else { + tagID, err = NewIDFromString(tagIDStr) + if err != nil { + return nil, err + } + } + + // If type is "commit, the tag is a lightweight tag if ObjectType(tp) == ObjectCommit { + commit, err := repo.GetCommit(id.String()) + if err != nil { + return nil, err + } tag := &Tag{ - ID: id, - Object: id, - Type: string(ObjectCommit), - repo: repo, + Name: name, + ID: tagID, + Object: commitID, + Type: string(ObjectCommit), + Tagger: commit.Committer, + Message: commit.Message(), + repo: repo, } repo.tagCache.Set(id.String(), tag) return tag, nil } - // Tag with message. + // The tag is an annotated tag with a message. data, err := NewCommand("cat-file", "-p", id.String()).RunInDirBytes(repo.Path) if err != nil { return nil, err @@ -73,16 +118,57 @@ func (repo *Repository) getTag(id SHA1) (*Tag, error) { return nil, err } + tag.Name = name tag.ID = id tag.repo = repo + tag.Type = tp repo.tagCache.Set(id.String(), tag) return tag, nil } +// GetTagNameBySHA returns the name of a tag from its tag object SHA or commit SHA +func (repo *Repository) GetTagNameBySHA(sha string) (string, error) { + if len(sha) < 5 { + return "", fmt.Errorf("SHA is too short: %s", sha) + } + + stdout, err := NewCommand("show-ref", "--tags", "-d").RunInDir(repo.Path) + if err != nil { + return "", err + } + + tagRefs := strings.Split(stdout, "\n") + for _, tagRef := range tagRefs { + if len(strings.TrimSpace(tagRef)) > 0 { + fields := strings.Fields(tagRef) + if strings.HasPrefix(fields[0], sha) && strings.HasPrefix(fields[1], TagPrefix) { + name := fields[1][len(TagPrefix):] + // annotated tags show up twice, their name for commit ID is suffixed with ^{} + name = strings.TrimSuffix(name, "^{}") + return name, nil + } + } + } + return "", ErrNotExist{ID: sha} +} + +// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA) +func (repo *Repository) GetTagID(name string) (string, error) { + stdout, err := NewCommand("show-ref", name).RunInDir(repo.Path) + if err != nil { + return "", err + } + fields := strings.Fields(stdout) + if len(fields) != 2 { + return "", ErrNotExist{ID: name} + } + return fields[0], nil +} + // GetTag returns a Git tag by given name. func (repo *Repository) GetTag(name string) (*Tag, error) { - idStr, err := repo.GetTagCommitID(name) + idStr, err := repo.GetTagID(name) if err != nil { return nil, err } @@ -96,7 +182,6 @@ func (repo *Repository) GetTag(name string) (*Tag, error) { if err != nil { return nil, err } - tag.Name = name return tag, nil } @@ -108,7 +193,7 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) { return nil, err } - tagNames := strings.Split(stdout, "\n") + tagNames := strings.Split(strings.TrimRight(stdout, "\n"), "\n") var tags = make([]*Tag, 0, len(tagNames)) for _, tagName := range tagNames { tagName = strings.TrimSpace(tagName) @@ -120,6 +205,7 @@ func (repo *Repository) GetTagInfos() ([]*Tag, error) { if err != nil { return nil, err } + tag.Name = tagName tags = append(tags, tag) } sortTagsByTime(tags) @@ -150,3 +236,38 @@ func (repo *Repository) GetTags() ([]string, error) { return tagNames, nil } + +// GetTagType gets the type of the tag, either commit (simple) or tag (annotated) +func (repo *Repository) GetTagType(id SHA1) (string, error) { + // Get tag type + stdout, err := NewCommand("cat-file", "-t", id.String()).RunInDir(repo.Path) + if err != nil { + return "", err + } + if len(stdout) == 0 { + return "", ErrNotExist{ID: id.String()} + } + return strings.TrimSpace(stdout), nil +} + +// GetAnnotatedTag returns a Git tag by its SHA, must be an annotated tag +func (repo *Repository) GetAnnotatedTag(sha string) (*Tag, error) { + id, err := NewIDFromString(sha) + if err != nil { + return nil, err + } + + // Tag type must be "tag" (annotated) and not a "commit" (lightweight) tag + if tagType, err := repo.GetTagType(id); err != nil { + return nil, err + } else if ObjectType(tagType) != ObjectTag { + // not an annotated tag + return nil, ErrNotExist{ID: id.String()} + } + + tag, err := repo.getTag(id) + if err != nil { + return nil, err + } + return tag, nil +} diff --git a/modules/git/repo_tag_test.go b/modules/git/repo_tag_test.go index ccb2d57ac2401..4f727c6c66fa8 100644 --- a/modules/git/repo_tag_test.go +++ b/modules/git/repo_tag_test.go @@ -21,8 +21,8 @@ func TestRepository_GetTags(t *testing.T) { assert.NoError(t, err) assert.Len(t, tags, 1) assert.EqualValues(t, "test", tags[0].Name) - assert.EqualValues(t, "37991dec2c8e592043f47155ce4808d4580f9123", tags[0].ID.String()) - assert.EqualValues(t, "commit", tags[0].Type) + assert.EqualValues(t, "3ad28a9149a2864384548f3d17ed7f38014c9e8a", tags[0].ID.String()) + assert.EqualValues(t, "tag", tags[0].Type) } func TestRepository_GetTag(t *testing.T) { @@ -35,10 +35,78 @@ func TestRepository_GetTag(t *testing.T) { bareRepo1, err := OpenRepository(clonedPath) assert.NoError(t, err) - tag, err := bareRepo1.GetTag("test") + lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1" + lTagName := "lightweightTag" + bareRepo1.CreateTag(lTagName, lTagCommitID) + + aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0" + aTagName := "annotatedTag" + aTagMessage := "my annotated message" + bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID) + aTagID, _ := bareRepo1.GetTagID(aTagName) + + lTag, err := bareRepo1.GetTag(lTagName) + lTag.repo = nil + assert.NoError(t, err) + assert.NotNil(t, lTag) + assert.EqualValues(t, lTagName, lTag.Name) + assert.EqualValues(t, lTagCommitID, lTag.ID.String()) + assert.EqualValues(t, lTagCommitID, lTag.Object.String()) + assert.EqualValues(t, "commit", lTag.Type) + + aTag, err := bareRepo1.GetTag(aTagName) + assert.NoError(t, err) + assert.NotNil(t, aTag) + assert.EqualValues(t, aTagName, aTag.Name) + assert.EqualValues(t, aTagID, aTag.ID.String()) + assert.NotEqual(t, aTagID, aTag.Object.String()) + assert.EqualValues(t, aTagCommitID, aTag.Object.String()) + assert.EqualValues(t, "tag", aTag.Type) +} + +func TestRepository_GetAnnotatedTag(t *testing.T) { + bareRepo1Path := filepath.Join(testReposDir, "repo1_bare") + + clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestRepository_GetTag") + assert.NoError(t, err) + defer os.RemoveAll(clonedPath) + + bareRepo1, err := OpenRepository(clonedPath) + assert.NoError(t, err) + + lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1" + lTagName := "lightweightTag" + bareRepo1.CreateTag(lTagName, lTagCommitID) + + aTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0" + aTagName := "annotatedTag" + aTagMessage := "my annotated message" + bareRepo1.CreateAnnotatedTag(aTagName, aTagMessage, aTagCommitID) + aTagID, _ := bareRepo1.GetTagID(aTagName) + + // Try an annotated tag + tag, err := bareRepo1.GetAnnotatedTag(aTagID) assert.NoError(t, err) assert.NotNil(t, tag) - assert.EqualValues(t, "test", tag.Name) - assert.EqualValues(t, "37991dec2c8e592043f47155ce4808d4580f9123", tag.ID.String()) - assert.EqualValues(t, "commit", tag.Type) + assert.EqualValues(t, aTagName, tag.Name) + assert.EqualValues(t, aTagID, tag.ID.String()) + assert.EqualValues(t, "tag", tag.Type) + + // Annotated tag's Commit ID should fail + tag2, err := bareRepo1.GetAnnotatedTag(aTagCommitID) + assert.Error(t, err) + assert.True(t, IsErrNotExist(err)) + assert.Nil(t, tag2) + + // Annotated tag's name should fail + tag3, err := bareRepo1.GetAnnotatedTag(aTagName) + assert.Error(t, err) + assert.Errorf(t, err, "Length must be 40: %d", len(aTagName)) + assert.Nil(t, tag3) + + // Lightweight Tag should fail + tag4, err := bareRepo1.GetAnnotatedTag(lTagCommitID) + assert.Error(t, err) + assert.True(t, IsErrNotExist(err)) + assert.Nil(t, tag4) } diff --git a/modules/git/tag.go b/modules/git/tag.go index 500fd274914c4..c97f574fa62b9 100644 --- a/modules/git/tag.go +++ b/modules/git/tag.go @@ -7,6 +7,7 @@ package git import ( "bytes" "sort" + "strings" ) // Tag represents a Git tag. @@ -59,7 +60,7 @@ l: } nextline += eol + 1 case eol == 0: - tag.Message = string(data[nextline+1:]) + tag.Message = strings.TrimRight(string(data[nextline+1:]), "\n") break l default: break l diff --git a/modules/structs/repo_tag.go b/modules/structs/repo_tag.go index 6294a8099db10..b62395cac4983 100644 --- a/modules/structs/repo_tag.go +++ b/modules/structs/repo_tag.go @@ -6,11 +6,27 @@ package structs // Tag represents a repository tag type Tag struct { - Name string `json:"name"` - Commit struct { - SHA string `json:"sha"` - URL string `json:"url"` - } `json:"commit"` - ZipballURL string `json:"zipball_url"` - TarballURL string `json:"tarball_url"` + Name string `json:"name"` + ID string `json:"id"` + Commit *CommitMeta `json:"commit"` + ZipballURL string `json:"zipball_url"` + TarballURL string `json:"tarball_url"` +} + +// AnnotatedTag represents an annotated tag +type AnnotatedTag struct { + Tag string `json:"tag"` + SHA string `json:"sha"` + URL string `json:"url"` + Message string `json:"message"` + Tagger *CommitUser `json:"tagger"` + Object *AnnotatedTagObject `json:"object"` + Verification *PayloadCommitVerification `json:"verification"` +} + +// AnnotatedTagObject contains meta information of the tag object +type AnnotatedTagObject struct { + Type string `json:"type"` + URL string `json:"url"` + SHA string `json:"sha"` } diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index c1561200cdbcc..2268c1be38e05 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -751,6 +751,7 @@ func RegisterRoutes(m *macaron.Macaron) { Post(reqToken(), bind(api.CreateStatusOption{}), repo.NewCommitStatus) }, reqRepoReader(models.UnitTypeCode)) m.Group("/commits/:ref", func() { + // TODO: Add m.Get("") for single commit (https://developer.github.com/v3/repos/commits/#get-a-single-commit) m.Get("/status", repo.GetCombinedCommitStatusByRef) m.Get("/statuses", repo.GetCommitStatusesByRef) }, reqRepoReader(models.UnitTypeCode)) @@ -762,6 +763,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Get("/refs/*", repo.GetGitRefs) m.Get("/trees/:sha", context.RepoRef(), repo.GetTree) m.Get("/blobs/:sha", context.RepoRef(), repo.GetBlob) + m.Get("/tags/:sha", context.RepoRef(), repo.GetTag) }, reqRepoReader(models.UnitTypeCode)) m.Group("/contents", func() { m.Get("/*", repo.GetFileContents) diff --git a/routers/api/v1/convert/convert.go b/routers/api/v1/convert/convert.go index ba61c7e46c938..a982cb8d371eb 100644 --- a/routers/api/v1/convert/convert.go +++ b/routers/api/v1/convert/convert.go @@ -6,6 +6,7 @@ package convert import ( "fmt" + "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" @@ -26,7 +27,7 @@ func ToEmail(email *models.EmailAddress) *api.Email { } } -// ToBranch convert a commit and branch to an api.Branch +// ToBranch convert a git.Commit and git.Branch to an api.Branch func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit) *api.Branch { return &api.Branch{ Name: b.Name, @@ -34,23 +35,18 @@ func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit) *api.Branch } } -// ToTag convert a tag to an api.Tag +// ToTag convert a git.Tag to an api.Tag func ToTag(repo *models.Repository, t *git.Tag) *api.Tag { return &api.Tag{ - Name: t.Name, - Commit: struct { - SHA string `json:"sha"` - URL string `json:"url"` - }{ - SHA: t.ID.String(), - URL: util.URLJoin(repo.Link(), "commit", t.ID.String()), - }, - ZipballURL: util.URLJoin(repo.Link(), "archive", t.Name+".zip"), - TarballURL: util.URLJoin(repo.Link(), "archive", t.Name+".tar.gz"), + Name: t.Name, + ID: t.ID.String(), + Commit: ToCommitMeta(repo, t), + ZipballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".zip"), + TarballURL: util.URLJoin(repo.HTMLURL(), "archive", t.Name+".tar.gz"), } } -// ToCommit convert a commit to api.PayloadCommit +// ToCommit convert a git.Commit to api.PayloadCommit func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit { authorUsername := "" if author, err := models.GetUserByEmail(c.Author.Email); err == nil { @@ -66,17 +62,10 @@ func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit { log.Error("GetUserByEmail: %v", err) } - verif := models.ParseCommitWithSignature(c) - var signature, payload string - if c.Signature != nil { - signature = c.Signature.Signature - payload = c.Signature.Payload - } - return &api.PayloadCommit{ ID: c.ID.String(), Message: c.Message(), - URL: util.URLJoin(repo.Link(), "commit", c.ID.String()), + URL: util.URLJoin(repo.HTMLURL(), "commit", c.ID.String()), Author: &api.PayloadUser{ Name: c.Author.Name, Email: c.Author.Email, @@ -87,13 +76,24 @@ func ToCommit(repo *models.Repository, c *git.Commit) *api.PayloadCommit { Email: c.Committer.Email, UserName: committerUsername, }, - Timestamp: c.Author.When, - Verification: &api.PayloadCommitVerification{ - Verified: verif.Verified, - Reason: verif.Reason, - Signature: signature, - Payload: payload, - }, + Timestamp: c.Author.When, + Verification: ToVerification(c), + } +} + +// ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification +func ToVerification(c *git.Commit) *api.PayloadCommitVerification { + verif := models.ParseCommitWithSignature(c) + var signature, payload string + if c.Signature != nil { + signature = c.Signature.Signature + payload = c.Signature.Payload + } + return &api.PayloadCommitVerification{ + Verified: verif.Verified, + Reason: verif.Reason, + Signature: signature, + Payload: payload, } } @@ -242,3 +242,45 @@ func ToUser(user *models.User, signed, admin bool) *api.User { } return result } + +// ToAnnotatedTag convert git.Tag to api.AnnotatedTag +func ToAnnotatedTag(repo *models.Repository, t *git.Tag, c *git.Commit) *api.AnnotatedTag { + return &api.AnnotatedTag{ + Tag: t.Name, + SHA: t.ID.String(), + Object: ToAnnotatedTagObject(repo, c), + Message: t.Message, + URL: util.URLJoin(repo.APIURL(), "git/tags", t.ID.String()), + Tagger: ToCommitUser(t.Tagger), + Verification: ToVerification(c), + } +} + +// ToAnnotatedTagObject convert a git.Commit to an api.AnnotatedTagObject +func ToAnnotatedTagObject(repo *models.Repository, commit *git.Commit) *api.AnnotatedTagObject { + return &api.AnnotatedTagObject{ + SHA: commit.ID.String(), + Type: string(git.ObjectCommit), + URL: util.URLJoin(repo.APIURL(), "git/commits", commit.ID.String()), + } +} + +// ToCommitUser convert a git.Signature to an api.CommitUser +func ToCommitUser(sig *git.Signature) *api.CommitUser { + return &api.CommitUser{ + Identity: api.Identity{ + Name: sig.Name, + Email: sig.Email, + }, + Date: sig.When.UTC().Format(time.RFC3339), + } +} + +// ToCommitMeta convert a git.Tag to an api.CommitMeta +func ToCommitMeta(repo *models.Repository, tag *git.Tag) *api.CommitMeta { + return &api.CommitMeta{ + SHA: tag.ID.String(), + // TODO: Add the /commits API endpoint and use it here (https://developer.github.com/v3/repos/commits/#get-a-single-commit) + URL: util.URLJoin(repo.APIURL(), "git/commits", tag.ID.String()), + } +} diff --git a/routers/api/v1/repo/git_ref.go b/routers/api/v1/repo/git_ref.go index 2ec8749058a8b..e15f699a1dae8 100644 --- a/routers/api/v1/repo/git_ref.go +++ b/routers/api/v1/repo/git_ref.go @@ -100,8 +100,7 @@ func getGitRefsInternal(ctx *context.APIContext, filter string) { Object: &api.GitObject{ SHA: refs[i].Object.String(), Type: refs[i].Type, - // TODO: Add commit/tag info URL - //URL: ctx.Repo.Repository.APIURL() + "/git/" + refs[i].Type + "s/" + refs[i].Object.String(), + URL: ctx.Repo.Repository.APIURL() + "/git/" + refs[i].Type + "s/" + refs[i].Object.String(), }, } } diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go index dd1b5aa7c1892..ecf580e1b08c4 100644 --- a/routers/api/v1/repo/tag.go +++ b/routers/api/v1/repo/tag.go @@ -7,6 +7,7 @@ package repo import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/routers/api/v1/convert" + "net/http" api "code.gitea.io/gitea/modules/structs" ) @@ -45,3 +46,47 @@ func ListTags(ctx *context.APIContext) { ctx.JSON(200, &apiTags) } + +// GetTag get the tag of a repository. +func GetTag(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/git/tags/{sha} repository GetTag + // --- + // summary: Gets the tag of a repository. + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: sha + // in: path + // description: sha of the tag + // type: string + // required: true + // responses: + // "200": + // "$ref": "#/responses/AnnotatedTag" + + sha := ctx.Params("sha") + if len(sha) == 0 { + ctx.Error(http.StatusBadRequest, "", "SHA not provided") + return + } + + if tag, err := ctx.Repo.GitRepo.GetAnnotatedTag(sha); err != nil { + ctx.Error(http.StatusBadRequest, "GetTag", err) + } else { + commit, err := tag.Commit() + if err != nil { + ctx.Error(http.StatusBadRequest, "GetTag", err) + } + ctx.JSON(http.StatusOK, convert.ToAnnotatedTag(ctx.Repo.Repository, tag, commit)) + } +} diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index e7df0b8f71134..25354b3d66698 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -38,11 +38,25 @@ type swaggerResponseBranchList struct { // TagList // swagger:response TagList -type swaggerReponseTagList struct { +type swaggerResponseTagList struct { // in:body Body []api.Tag `json:"body"` } +// Tag +// swagger:response Tag +type swaggerResponseTag struct { + // in:body + Body api.Tag `json:"body"` +} + +// AnnotatedTag +// swagger:response AnnotatedTag +type swaggerResponseAnnotatedTag struct { + // in:body + Body api.AnnotatedTag `json:"body"` +} + // Reference // swagger:response Reference type swaggerResponseReference struct { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 0bd85fbb6e7c3..2b40c89791a05 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -2036,6 +2036,46 @@ } } }, + "/repos/{owner}/{repo}/git/tags/{sha}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Gets the tag of a repository.", + "operationId": "GetTag", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "sha of the tag", + "name": "sha", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/AnnotatedTag" + } + } + } + }, "/repos/{owner}/{repo}/git/trees/{sha}": { "get": { "produces": [ @@ -6762,6 +6802,57 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "AnnotatedTag": { + "description": "AnnotatedTag represents an annotated tag", + "type": "object", + "properties": { + "message": { + "type": "string", + "x-go-name": "Message" + }, + "object": { + "$ref": "#/definitions/AnnotatedTagObject" + }, + "sha": { + "type": "string", + "x-go-name": "SHA" + }, + "tag": { + "type": "string", + "x-go-name": "Tag" + }, + "tagger": { + "$ref": "#/definitions/CommitUser" + }, + "url": { + "type": "string", + "x-go-name": "URL" + }, + "verification": { + "$ref": "#/definitions/PayloadCommitVerification" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "AnnotatedTagObject": { + "description": "AnnotatedTagObject contains meta information of the tag object", + "type": "object", + "properties": { + "sha": { + "type": "string", + "x-go-name": "SHA" + }, + "type": { + "type": "string", + "x-go-name": "Type" + }, + "url": { + "type": "string", + "x-go-name": "URL" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "Attachment": { "description": "Attachment a generic attachment", "type": "object", @@ -9458,18 +9549,11 @@ "type": "object", "properties": { "commit": { - "type": "object", - "properties": { - "sha": { - "type": "string", - "x-go-name": "SHA" - }, - "url": { - "type": "string", - "x-go-name": "URL" - } - }, - "x-go-name": "Commit" + "$ref": "#/definitions/CommitMeta" + }, + "id": { + "type": "string", + "x-go-name": "ID" }, "name": { "type": "string", @@ -9735,6 +9819,12 @@ "AccessTokenList": { "description": "AccessTokenList represents a list of API access token." }, + "AnnotatedTag": { + "description": "AnnotatedTag", + "schema": { + "$ref": "#/definitions/AnnotatedTag" + } + }, "Attachment": { "description": "Attachment", "schema": { @@ -10056,6 +10146,12 @@ } } }, + "Tag": { + "description": "Tag", + "schema": { + "$ref": "#/definitions/Tag" + } + }, "TagList": { "description": "TagList", "schema": { From 3e05661d8d52315d6dbb601950df2354428ac119 Mon Sep 17 00:00:00 2001 From: Lanre Adelowo Date: Mon, 10 Jun 2019 02:02:42 +0100 Subject: [PATCH 17/30] archived repos can be starred and watched (#7163) --- routers/routes/routes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 4c736f63ed40e..f7ccfc43d24b5 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -674,7 +674,7 @@ func RegisterRoutes(m *macaron.Macaron) { }) }, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.UnitTypes(), context.RepoRef()) - m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), context.RepoMustNotBeArchived(), repo.Action) + m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action) m.Group("/:username/:reponame", func() { m.Group("/issues", func() { From b1be6fd31f6f9f1512de16cd93d30775319b3c75 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 10 Jun 2019 01:06:14 +0000 Subject: [PATCH 18/30] [skip ci] Updated translations via Crowdin --- options/locale/locale_de-DE.ini | 4 ++++ options/locale/locale_zh-CN.ini | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 7a0b61d2eef95..7176b23f56040 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -618,6 +618,7 @@ migrate.permission_denied=Du hast keine Berechtigung zum Importieren lokaler Rep migrate.invalid_local_path=Der lokale Pfad ist ungültig, existiert nicht oder ist kein Ordner. migrate.failed=Fehler bei der Migration: %v migrate.lfs_mirror_unsupported=Spiegeln von LFS-Objekten wird nicht unterstützt - nutze stattdessen 'git lfs fetch --all' und 'git lfs push --all'. +migrate.migrate_items_options=Wenn du von GitHub migrierst und einen Benutzernamen eingegeben hast, werden die Migrationsoptionen angezeigt. mirror_from=Mirror von forked_from=geforkt von @@ -1304,11 +1305,14 @@ settings.archive.button=Repo archivieren settings.archive.header=Dieses Repo archivieren settings.archive.text=Durch die Archivierung des Repos wird es vollständig schreibgeschützt. Es wird auf dem Dashboard versteckt, nimmt keine Commits an und es können keine Issues oder Pull-Requests erstellt werden. settings.archive.success=Das Repo wurde erfolgreich archiviert. +settings.archive.error=Beim Versuch, das Repository zu archivieren, ist ein Fehler aufgetreten. Weitere Details finden sich im Log. settings.archive.error_ismirror=Du kannst keinen Repo-Mirror archivieren. settings.archive.branchsettings_unavailable=Branch-Einstellungen sind nicht verfügbar wenn das Repo archiviert ist. settings.unarchive.button=Archivieren rückgängig machen settings.unarchive.header=Archivieren dieses Repos rückgängig machen +settings.unarchive.text=Durch das Aufheben der Archivierung kann das Repo wieder Commits und Pushes sowie neue Issues und Pull-Requests empfangen. settings.unarchive.success=Die Archivierung des Repos wurde erfolgreich wieder rückgängig gemacht. +settings.unarchive.error=Beim Versuch, die Archivierung des Repos aufzuheben, ist ein Fehler aufgetreten. Weitere Details finden sich im Log. settings.update_avatar_success=Der Repository-Avatar wurde aktualisiert. diff.browse_source=Quellcode durchsuchen diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index da23f30fb6aad..6b495bee87388 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -86,12 +86,18 @@ host=数据库主机 user=用户名 password=数据库用户密码 db_name=数据库名称 +db_helper=MySQL 用户注意:请使用InnoDB 存储引擎,如果您使用“utf8mb4”,您的 InnoDB 版本必须大于5.6。 ssl_mode=SSL +charset=字符集 path=数据库文件路径 sqlite_helper=SQLite3 数据库的文件路径。
如果以服务的方式运行 Gitea,请输入绝对路径。 err_empty_db_path=SQLite 数据库文件路径不能为空。 no_admin_and_disable_registration=您不能够在未创建管理员用户的情况下禁止注册。 err_empty_admin_password=管理员密码不能为空。 +err_empty_admin_email=管理员电子邮件不能为空。 +err_admin_name_is_reserved=管理员用户名无效,用户名是保留的 +err_admin_name_pattern_not_allowed=管理员用户名无效,用户名不符合要求 +err_admin_name_is_invalid=管理员用户名无效 general_title=一般设置 app_name=站点名称 @@ -382,6 +388,7 @@ choose_new_avatar=选择新的头像 update_avatar=更新头像 delete_current_avatar=删除当前头像 uploaded_avatar_not_a_image=上传的文件不是一张图片。 +uploaded_avatar_is_too_big=上传的文件超过了最大大小。 update_avatar_success=您的头像已更新。 change_password=更新密码 @@ -480,6 +487,7 @@ manage_oauth2_applications=管理 OAuth2 应用程序 edit_oauth2_application=编辑 OAuth2 应用程序 oauth2_applications_desc=OAuth2 应用允许第三方应用程序在此 Gitea 实例中安全验证用户。 remove_oauth2_application=删除 OAuth2 应用程序 +remove_oauth2_application_desc=删除 OAuth2 应用将撤销所有签名的访问令牌。继续吗? remove_oauth2_application_success=该应用已被删除。 create_oauth2_application=创建新的 OAuth2 应用程序 create_oauth2_application_button=创建应用 @@ -611,6 +619,7 @@ migrate.permission_denied=您没有获得导入本地仓库的权限。 migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录! migrate.failed=迁移失败:%v migrate.lfs_mirror_unsupported=不支持镜像 LFS 对象 - 使用 'git lfs fetch --all' 和 'git lfs push --all' 替代。 +migrate.migrate_items_options=当从 github 迁移并且输入了用户名时,迁移选项将会显示。 mirror_from=镜像自地址 forked_from=派生自 @@ -923,7 +932,7 @@ issues.dependency.add_error_cannot_create_circular=您不能创建依赖, 使得 issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓库。 issues.review.self.approval=您不能批准您自己的合并请求。 issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。 -issues.review.approve=已批准这些更改 %s +issues.review.approve=已于 %s 批准这些更改 issues.review.comment=评审于 %s issues.review.content.empty=您需要留下一个注释,表明需要的更改。 issues.review.reject=请求变更 %s @@ -1297,15 +1306,20 @@ settings.archive.button=归档仓库 settings.archive.header=归档此仓库 settings.archive.text=归档后仓库将只有只读权限,并在仪表盘中被隐藏。你将不能再对其建立提交、创建工单或建立合并请求。 settings.archive.success=仓库已成功归档。 +settings.archive.error=仓库在归档时出现异常。请通过日志获取详细信息。 settings.archive.error_ismirror=请不要对镜像仓库归档,谢谢! settings.archive.branchsettings_unavailable=已归档仓库无法进行分支设置。 settings.unarchive.button=撤销仓库归档 settings.unarchive.header=撤销此仓库归档 +settings.unarchive.text=取消存档将恢复仓库接收提交,推送,新工单和合并请求。 settings.unarchive.success=仓库已成功取消归档。 +settings.unarchive.error=仓库在撤销归档时出现异常。请通过日志获取详细信息。 +settings.update_avatar_success=仓库头像已经更新。 diff.browse_source=浏览代码 diff.parent=父节点 diff.commit=当前提交 +diff.git-notes=Notes diff.data_not_available=比较内容不可用 diff.show_diff_stats=显示文件统计 diff.show_split_view=分列视图 @@ -1507,6 +1521,8 @@ dashboard.delete_repo_archives=删除所有仓库存档 dashboard.delete_repo_archives_success=所有仓库存档清除成功! dashboard.delete_missing_repos=删除所有丢失 Git 文件的仓库 dashboard.delete_missing_repos_success=所有丢失对应 Git 文件的仓库已被删除。 +dashboard.delete_generated_repository_avatars=删除生成的仓库头像 +dashboard.delete_generated_repository_avatars_success=生成的仓库头像已删除。 dashboard.git_gc_repos=对仓库进行垃圾回收 dashboard.git_gc_repos_success=所有仓库已完成执行垃圾回收。 dashboard.resync_all_sshkeys=重新生成 '.ssh/authorized_keys' 文件。(仅对非内置SSH服务有效) From d93e6232e829a1ade1f9540a701061967aa7d61d Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 10 Jun 2019 19:35:13 +0800 Subject: [PATCH 19/30] Move PushUpdate dependency from models to repofiles (#6763) * remove push_update * move models.PushUpdate to repofiles.PushUpdate --- models/update.go | 4 --- modules/repofiles/delete.go | 5 ++- modules/repofiles/update.go | 18 +++++++++-- modules/repofiles/upload.go | 4 +-- routers/private/hook.go | 11 ++++++- routers/private/push_update.go | 56 ++++++++++++++++++++++++++++++++++ routers/repo/branch.go | 21 +++++++------ 7 files changed, 98 insertions(+), 21 deletions(-) create mode 100644 routers/private/push_update.go diff --git a/models/update.go b/models/update.go index 1492d6c0d351d..0883cb0e0116f 100644 --- a/models/update.go +++ b/models/update.go @@ -263,10 +263,6 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) { commits = ListToPushCommits(l) } - if opts.RefFullName == git.BranchPrefix+repo.DefaultBranch { - UpdateRepoIndexer(repo) - } - if err := CommitRepoAction(CommitRepoActionOptions{ PusherName: opts.PusherName, RepoOwnerID: owner.ID, diff --git a/modules/repofiles/delete.go b/modules/repofiles/delete.go index ccf90f43b3071..09a4dbb44c9b1 100644 --- a/modules/repofiles/delete.go +++ b/modules/repofiles/delete.go @@ -183,7 +183,8 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo if err = repo.GetOwner(); err != nil { return nil, fmt.Errorf("GetOwner: %v", err) } - err = models.PushUpdate( + err = PushUpdate( + repo, opts.NewBranch, models.PushUpdateOptions{ PusherID: doer.ID, @@ -199,8 +200,6 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo return nil, fmt.Errorf("PushUpdate: %v", err) } - // FIXME: Should we UpdateRepoIndexer(repo) here? - file, err := GetFileResponseFromCommit(repo, commit, opts.NewBranch, treePath) if err != nil { return nil, err diff --git a/modules/repofiles/update.go b/modules/repofiles/update.go index 66e3f2babced3..569c89ac51d51 100644 --- a/modules/repofiles/update.go +++ b/modules/repofiles/update.go @@ -394,7 +394,8 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up if err = repo.GetOwner(); err != nil { return nil, fmt.Errorf("GetOwner: %v", err) } - err = models.PushUpdate( + err = PushUpdate( + repo, opts.NewBranch, models.PushUpdateOptions{ PusherID: doer.ID, @@ -409,7 +410,6 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up if err != nil { return nil, fmt.Errorf("PushUpdate: %v", err) } - models.UpdateRepoIndexer(repo) commit, err = t.GetCommit(commitHash) if err != nil { @@ -422,3 +422,17 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up } return file, nil } + +// PushUpdate must be called for any push actions in order to +// generates necessary push action history feeds and other operations +func PushUpdate(repo *models.Repository, branch string, opts models.PushUpdateOptions) error { + err := models.PushUpdate(branch, opts) + if err != nil { + return fmt.Errorf("PushUpdate: %v", err) + } + + if opts.RefFullName == git.BranchPrefix+repo.DefaultBranch { + models.UpdateRepoIndexer(repo) + } + return nil +} diff --git a/modules/repofiles/upload.go b/modules/repofiles/upload.go index ed6a9438c70f8..5f428c3139a43 100644 --- a/modules/repofiles/upload.go +++ b/modules/repofiles/upload.go @@ -188,7 +188,8 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep if err = repo.GetOwner(); err != nil { return fmt.Errorf("GetOwner: %v", err) } - err = models.PushUpdate( + err = PushUpdate( + repo, opts.NewBranch, models.PushUpdateOptions{ PusherID: doer.ID, @@ -203,7 +204,6 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep if err != nil { return fmt.Errorf("PushUpdate: %v", err) } - // FIXME: Should we models.UpdateRepoIndexer(repo) here? return models.DeleteUploads(uploads...) } diff --git a/routers/private/hook.go b/routers/private/hook.go index 700c8bf332790..a5985f161e719 100644 --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/private" + "code.gitea.io/gitea/modules/repofiles" "code.gitea.io/gitea/modules/util" macaron "gopkg.in/macaron.v1" @@ -117,7 +118,15 @@ func HookPostReceive(ctx *macaron.Context) { // or other less-standard refs spaces are ignored since there // may be a very large number of them). if strings.HasPrefix(refFullName, git.BranchPrefix) || strings.HasPrefix(refFullName, git.TagPrefix) { - if err := models.PushUpdate(branch, models.PushUpdateOptions{ + repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName) + if err != nil { + log.Error("Failed to get repository: %s/%s Error: %v", ownerName, repoName, err) + ctx.JSON(http.StatusInternalServerError, map[string]interface{}{ + "err": fmt.Sprintf("Failed to get repository: %s/%s Error: %v", ownerName, repoName, err), + }) + return + } + if err := repofiles.PushUpdate(repo, branch, models.PushUpdateOptions{ RefFullName: refFullName, OldCommitID: oldCommitID, NewCommitID: newCommitID, diff --git a/routers/private/push_update.go b/routers/private/push_update.go new file mode 100644 index 0000000000000..733490ce1cd75 --- /dev/null +++ b/routers/private/push_update.go @@ -0,0 +1,56 @@ +// Copyright 2017 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 private + +import ( + "encoding/json" + "strings" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/repofiles" + + macaron "gopkg.in/macaron.v1" +) + +// PushUpdate update public key updates +func PushUpdate(ctx *macaron.Context) { + var opt models.PushUpdateOptions + if err := json.NewDecoder(ctx.Req.Request.Body).Decode(&opt); err != nil { + ctx.JSON(500, map[string]interface{}{ + "err": err.Error(), + }) + return + } + + branch := strings.TrimPrefix(opt.RefFullName, git.BranchPrefix) + if len(branch) == 0 || opt.PusherID <= 0 { + ctx.Error(404) + log.Trace("PushUpdate: branch or secret is empty, or pusher ID is not valid") + return + } + + repo, err := models.GetRepositoryByOwnerAndName(opt.RepoUserName, opt.RepoName) + if err != nil { + ctx.JSON(500, map[string]interface{}{ + "err": err.Error(), + }) + return + } + + err = repofiles.PushUpdate(repo, branch, opt) + if err != nil { + if models.IsErrUserNotExist(err) { + ctx.Error(404) + } else { + ctx.JSON(500, map[string]interface{}{ + "err": err.Error(), + }) + } + return + } + ctx.Status(202) +} diff --git a/routers/repo/branch.go b/routers/repo/branch.go index ae87aa5b3a09d..05d64fb4c8d0e 100644 --- a/routers/repo/branch.go +++ b/routers/repo/branch.go @@ -131,15 +131,18 @@ func deleteBranch(ctx *context.Context, branchName string) error { } // Don't return error below this - if err := models.PushUpdate(branchName, models.PushUpdateOptions{ - RefFullName: git.BranchPrefix + branchName, - OldCommitID: commit.ID.String(), - NewCommitID: git.EmptySHA, - PusherID: ctx.User.ID, - PusherName: ctx.User.Name, - RepoUserName: ctx.Repo.Owner.Name, - RepoName: ctx.Repo.Repository.Name, - }); err != nil { + if err := repofiles.PushUpdate( + ctx.Repo.Repository, + branchName, + models.PushUpdateOptions{ + RefFullName: git.BranchPrefix + branchName, + OldCommitID: commit.ID.String(), + NewCommitID: git.EmptySHA, + PusherID: ctx.User.ID, + PusherName: ctx.User.Name, + RepoUserName: ctx.Repo.Owner.Name, + RepoName: ctx.Repo.Repository.Name, + }); err != nil { log.Error("Update: %v", err) } From 7162fbf3d6adf0a1f5b7ce95df5603d995b35d85 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 10 Jun 2019 22:16:02 +0800 Subject: [PATCH 20/30] if milestone id is zero don't get it from database (#7169) --- routers/repo/issue.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/routers/repo/issue.go b/routers/repo/issue.go index f6030c9823ad6..cd384da0d669f 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -426,12 +426,14 @@ func NewIssue(ctx *context.Context) { ctx.Data["BodyQuery"] = body milestoneID := ctx.QueryInt64("milestone") - milestone, err := models.GetMilestoneByID(milestoneID) - if err != nil { - log.Error("GetMilestoneByID: %d: %v", milestoneID, err) - } else { - ctx.Data["milestone_id"] = milestoneID - ctx.Data["Milestone"] = milestone + if milestoneID > 0 { + milestone, err := models.GetMilestoneByID(milestoneID) + if err != nil { + log.Error("GetMilestoneByID: %d: %v", milestoneID, err) + } else { + ctx.Data["milestone_id"] = milestoneID + ctx.Data["Milestone"] = milestone + } } setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates) From 835b53fc259c82f38945a3e107a4eb51478967d5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 10 Jun 2019 23:20:49 +0800 Subject: [PATCH 21/30] make modules/structs as a spereate go mod (#7127) --- modules/structs/attachment.go | 1 + modules/structs/go.mod | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 modules/structs/go.mod diff --git a/modules/structs/attachment.go b/modules/structs/attachment.go index 954956f328747..7becd9433542b 100644 --- a/modules/structs/attachment.go +++ b/modules/structs/attachment.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. package structs // import "code.gitea.io/gitea/modules/structs" + import ( "time" ) diff --git a/modules/structs/go.mod b/modules/structs/go.mod new file mode 100644 index 0000000000000..96826f2f07f5a --- /dev/null +++ b/modules/structs/go.mod @@ -0,0 +1,3 @@ +module code.gitea.io/gitea/modules/structs + +go 1.12 From b3b468444b1dcc6c4353df232b6a74b2017e83db Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 11 Jun 2019 03:55:58 +0800 Subject: [PATCH 22/30] Revert "make modules/structs as a spereate go mod (#7127)" (#7175) This reverts commit 835b53fc259c82f38945a3e107a4eb51478967d5. --- modules/structs/attachment.go | 1 - modules/structs/go.mod | 3 --- 2 files changed, 4 deletions(-) delete mode 100644 modules/structs/go.mod diff --git a/modules/structs/attachment.go b/modules/structs/attachment.go index 7becd9433542b..954956f328747 100644 --- a/modules/structs/attachment.go +++ b/modules/structs/attachment.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. package structs // import "code.gitea.io/gitea/modules/structs" - import ( "time" ) diff --git a/modules/structs/go.mod b/modules/structs/go.mod deleted file mode 100644 index 96826f2f07f5a..0000000000000 --- a/modules/structs/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module code.gitea.io/gitea/modules/structs - -go 1.12 From 74690f64514424ac643a8007828de1a785705793 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Tue, 11 Jun 2019 09:13:24 +0800 Subject: [PATCH 23/30] fix pusher name via ssh push (#7167) --- cmd/serv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/serv.go b/cmd/serv.go index 0b0a4e8efba78..c0cb3cd50fd37 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -209,7 +209,7 @@ func runServ(c *cli.Context) error { os.Setenv(models.EnvRepoIsWiki, strconv.FormatBool(results.IsWiki)) os.Setenv(models.EnvRepoName, results.RepoName) os.Setenv(models.EnvRepoUsername, results.OwnerName) - os.Setenv(models.EnvPusherName, username) + os.Setenv(models.EnvPusherName, results.UserName) os.Setenv(models.EnvPusherID, strconv.FormatInt(results.UserID, 10)) os.Setenv(models.ProtectedBranchRepoID, strconv.FormatInt(results.RepoID, 10)) From 499a8a1cdd815cc25554371598140f5fb01e216f Mon Sep 17 00:00:00 2001 From: silverwind Date: Tue, 11 Jun 2019 21:27:38 +0200 Subject: [PATCH 24/30] Various fixes for issue mail notifications (#7165) - Send individual mails for actions and comments - Send mail for new issues/prs without a comment - Use correct sender for reopen/close actions - Hopefully fixed all bugs related to missing mails Fixes: https://github.com/go-gitea/gitea/issues/7124 Fixes: https://github.com/go-gitea/gitea/issues/5977 --- models/issue_comment.go | 19 +++++++++++------ models/issue_mail.go | 35 ++++++++++++++++++++++--------- modules/notification/mail/mail.go | 6 +++--- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/models/issue_comment.go b/models/issue_comment.go index 60fb5b0420e56..0d2e917f857f1 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -403,16 +403,23 @@ func (c *Comment) mailParticipants(e Engine, opType ActionType, issue *Issue) (e return fmt.Errorf("UpdateIssueMentions [%d]: %v", c.IssueID, err) } - content := c.Content + if len(c.Content) > 0 { + if err = mailIssueCommentToParticipants(e, issue, c.Poster, c.Content, c, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } + } switch opType { case ActionCloseIssue: - content = fmt.Sprintf("Closed #%d", issue.Index) + ct := fmt.Sprintf("Closed #%d.", issue.Index) + if err = mailIssueCommentToParticipants(e, issue, c.Poster, ct, c, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } case ActionReopenIssue: - content = fmt.Sprintf("Reopened #%d", issue.Index) - } - if err = mailIssueCommentToParticipants(e, issue, c.Poster, content, c, mentions); err != nil { - log.Error("mailIssueCommentToParticipants: %v", err) + ct := fmt.Sprintf("Reopened #%d.", issue.Index) + if err = mailIssueCommentToParticipants(e, issue, c.Poster, ct, c, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } } return nil diff --git a/models/issue_mail.go b/models/issue_mail.go index 16f85ba37821f..01a12b16d2a8e 100644 --- a/models/issue_mail.go +++ b/models/issue_mail.go @@ -118,26 +118,41 @@ func mailIssueCommentToParticipants(e Engine, issue *Issue, doer *User, content // MailParticipants sends new issue thread created emails to repository watchers // and mentioned people. -func (issue *Issue) MailParticipants(opType ActionType) (err error) { - return issue.mailParticipants(x, opType) +func (issue *Issue) MailParticipants(doer *User, opType ActionType) (err error) { + return issue.mailParticipants(x, doer, opType) } -func (issue *Issue) mailParticipants(e Engine, opType ActionType) (err error) { +func (issue *Issue) mailParticipants(e Engine, doer *User, opType ActionType) (err error) { mentions := markup.FindAllMentions(issue.Content) + if err = UpdateIssueMentions(e, issue.ID, mentions); err != nil { return fmt.Errorf("UpdateIssueMentions [%d]: %v", issue.ID, err) } - var content = issue.Content + if len(issue.Content) > 0 { + if err = mailIssueCommentToParticipants(e, issue, doer, issue.Content, nil, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } + } + switch opType { + case ActionCreateIssue, ActionCreatePullRequest: + if len(issue.Content) == 0 { + ct := fmt.Sprintf("Created #%d.", issue.Index) + if err = mailIssueCommentToParticipants(e, issue, doer, ct, nil, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } + } case ActionCloseIssue, ActionClosePullRequest: - content = fmt.Sprintf("Closed #%d", issue.Index) + ct := fmt.Sprintf("Closed #%d.", issue.Index) + if err = mailIssueCommentToParticipants(e, issue, doer, ct, nil, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } case ActionReopenIssue, ActionReopenPullRequest: - content = fmt.Sprintf("Reopened #%d", issue.Index) - } - - if err = mailIssueCommentToParticipants(e, issue, issue.Poster, content, nil, mentions); err != nil { - log.Error("mailIssueCommentToParticipants: %v", err) + ct := fmt.Sprintf("Reopened #%d.", issue.Index) + if err = mailIssueCommentToParticipants(e, issue, doer, ct, nil, mentions); err != nil { + log.Error("mailIssueCommentToParticipants: %v", err) + } } return nil diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index 9689f4d4ab54b..9d0db4f415197 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -42,7 +42,7 @@ func (m *mailNotifier) NotifyCreateIssueComment(doer *models.User, repo *models. } func (m *mailNotifier) NotifyNewIssue(issue *models.Issue) { - if err := issue.MailParticipants(models.ActionCreateIssue); err != nil { + if err := issue.MailParticipants(issue.Poster, models.ActionCreateIssue); err != nil { log.Error("MailParticipants: %v", err) } } @@ -63,13 +63,13 @@ func (m *mailNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models. } } - if err := issue.MailParticipants(actionType); err != nil { + if err := issue.MailParticipants(doer, actionType); err != nil { log.Error("MailParticipants: %v", err) } } func (m *mailNotifier) NotifyNewPullRequest(pr *models.PullRequest) { - if err := pr.Issue.MailParticipants(models.ActionCreatePullRequest); err != nil { + if err := pr.Issue.MailParticipants(pr.Issue.Poster, models.ActionCreatePullRequest); err != nil { log.Error("MailParticipants: %v", err) } } From 1608f63e396c78bcbea3605b812556ddf441a6c4 Mon Sep 17 00:00:00 2001 From: Mario Lubenka Date: Wed, 12 Jun 2019 01:32:08 +0200 Subject: [PATCH 25/30] Fixes diff on merged pull requests (#7171) --- models/pull.go | 2 +- modules/git/repo_compare.go | 8 ++++---- routers/repo/pull.go | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/models/pull.go b/models/pull.go index 5ac1126314d1a..1f03dd9b0f5a9 100644 --- a/models/pull.go +++ b/models/pull.go @@ -1144,7 +1144,7 @@ func (pr *PullRequest) UpdatePatch() (err error) { defer func() { headGitRepo.RemoveRemote(tmpRemote) }() - pr.MergeBase, err = headGitRepo.GetMergeBase(tmpRemote, pr.BaseBranch, pr.HeadBranch) + pr.MergeBase, _, err = headGitRepo.GetMergeBase(tmpRemote, pr.BaseBranch, pr.HeadBranch) if err != nil { return fmt.Errorf("GetMergeBase: %v", err) } else if err = pr.Update(); err != nil { diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index e7a1d72a8592b..42f0b9ad0cd76 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -22,8 +22,8 @@ type CompareInfo struct { NumFiles int } -// GetMergeBase checks and returns merge base of two branches. -func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (string, error) { +// GetMergeBase checks and returns merge base of two branches and the reference used as base. +func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (string, string, error) { if tmpRemote == "" { tmpRemote = "origin" } @@ -38,7 +38,7 @@ func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (strin } stdout, err := NewCommand("merge-base", base, head).RunInDir(repo.Path) - return strings.TrimSpace(stdout), err + return strings.TrimSpace(stdout), base, err } // GetCompareInfo generates and returns compare information between base and head branches of repositories. @@ -59,7 +59,7 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string) } compareInfo := new(CompareInfo) - compareInfo.MergeBase, err = repo.GetMergeBase(tmpRemote, baseBranch, headBranch) + compareInfo.MergeBase, remoteBranch, err = repo.GetMergeBase(tmpRemote, baseBranch, headBranch) if err == nil { // We have a common base logs, err := NewCommand("log", compareInfo.MergeBase+"..."+headBranch, prettyLogFormat).RunInDirBytes(repo.Path) diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 182f715545237..71c684356db2a 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -286,7 +286,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.C setMergeTarget(ctx, pull) ctx.Data["HasMerged"] = true - prInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), + compareInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), pull.MergeBase, pull.GetGitRefName()) if err != nil { @@ -301,9 +301,9 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.C ctx.ServerError("GetCompareInfo", err) return nil } - ctx.Data["NumCommits"] = prInfo.Commits.Len() - ctx.Data["NumFiles"] = prInfo.NumFiles - return prInfo + ctx.Data["NumCommits"] = compareInfo.Commits.Len() + ctx.Data["NumFiles"] = compareInfo.NumFiles + return compareInfo } // PrepareViewPullInfo show meta information for a pull request preview page @@ -336,7 +336,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare return nil } - prInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(repo.Owner.Name, repo.Name), + compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(repo.Owner.Name, repo.Name), pull.BaseBranch, pull.HeadBranch) if err != nil { if strings.Contains(err.Error(), "fatal: Not a valid object name") { @@ -361,9 +361,9 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare ctx.Data["ConflictedFiles"] = pull.ConflictedFiles } - ctx.Data["NumCommits"] = prInfo.Commits.Len() - ctx.Data["NumFiles"] = prInfo.NumFiles - return prInfo + ctx.Data["NumCommits"] = compareInfo.Commits.Len() + ctx.Data["NumFiles"] = compareInfo.NumFiles + return compareInfo } // ViewPullCommits show commits for a pull request From 5832f8d90df2d72cb38698c3e9050f2b29717dc7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 12 Jun 2019 08:12:13 +0800 Subject: [PATCH 26/30] Fix database lock when use random repository fallback image (#7166) * fix database lock when use random repository fallback image * remove unused function --- models/repo.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/models/repo.go b/models/repo.go index d5eca3d22502e..a855c84939cc4 100644 --- a/models/repo.go +++ b/models/repo.go @@ -331,7 +331,7 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) AllowRebase: allowRebase, AllowRebaseMerge: allowRebaseMerge, AllowSquash: allowSquash, - AvatarURL: repo.AvatarLink(), + AvatarURL: repo.avatarLink(e), } } @@ -2528,11 +2528,7 @@ func (repo *Repository) CustomAvatarPath() string { return filepath.Join(setting.RepositoryAvatarUploadPath, repo.Avatar) } -// GenerateRandomAvatar generates a random avatar for repository. -func (repo *Repository) GenerateRandomAvatar() error { - return repo.generateRandomAvatar(x) -} - +// generateRandomAvatar generates a random avatar for repository. func (repo *Repository) generateRandomAvatar(e Engine) error { idToString := fmt.Sprintf("%d", repo.ID) @@ -2585,7 +2581,10 @@ func RemoveRandomAvatars() error { // RelAvatarLink returns a relative link to the repository's avatar. func (repo *Repository) RelAvatarLink() string { + return repo.relAvatarLink(x) +} +func (repo *Repository) relAvatarLink(e Engine) string { // If no avatar - path is empty avatarPath := repo.CustomAvatarPath() if len(avatarPath) <= 0 || !com.IsFile(avatarPath) { @@ -2593,8 +2592,8 @@ func (repo *Repository) RelAvatarLink() string { case "image": return setting.RepositoryAvatarFallbackImage case "random": - if err := repo.GenerateRandomAvatar(); err != nil { - log.Error("GenerateRandomAvatar: %v", err) + if err := repo.generateRandomAvatar(e); err != nil { + log.Error("generateRandomAvatar: %v", err) } default: // default behaviour: do not display avatar @@ -2604,9 +2603,9 @@ func (repo *Repository) RelAvatarLink() string { return setting.AppSubURL + "/repo-avatars/" + repo.Avatar } -// AvatarLink returns user avatar absolute link. -func (repo *Repository) AvatarLink() string { - link := repo.RelAvatarLink() +// avatarLink returns user avatar absolute link. +func (repo *Repository) avatarLink(e Engine) string { + link := repo.relAvatarLink(e) // link may be empty! if len(link) > 0 { if link[0] == '/' && link[1] != '/' { From f9ec2f89f2265bc1371a6c62359de9816534fa6b Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 12 Jun 2019 21:41:28 +0200 Subject: [PATCH 27/30] Add golangci (#6418) --- .drone.yml | 6 +- .golangci.yml | 97 ++++++++++++++ Makefile | 11 ++ cmd/admin.go | 2 +- cmd/cert.go | 21 ++- cmd/serv.go | 7 +- cmd/web.go | 9 +- contrib/pr/checkout.go | 3 +- integrations/branches_test.go | 2 +- integrations/editor_test.go | 6 +- integrations/integration_test.go | 11 +- integrations/lfs_getobject_test.go | 2 +- integrations/migration-test/migration_test.go | 15 --- integrations/testlogger.go | 2 +- main.go | 6 +- models/access_test.go | 7 - models/branches.go | 8 +- models/git_blame.go | 4 +- models/git_diff.go | 13 +- models/git_diff_test.go | 6 - models/issue.go | 11 +- models/issue_comment.go | 17 +-- models/issue_comment_list.go | 38 +++--- models/issue_label.go | 8 -- models/issue_list.go | 125 ++++++++++++------ models/log.go | 17 ++- models/login_source.go | 21 +-- models/mail.go | 7 +- models/migrations/migrations.go | 8 +- models/migrations/v27.go | 4 +- models/migrations/v78.go | 3 + models/migrations/v85.go | 3 + models/models.go | 9 +- models/notification.go | 5 +- models/oauth2.go | 5 +- models/oauth2_application.go | 7 +- models/org.go | 17 ++- models/org_team.go | 31 ++++- models/org_test.go | 6 +- models/pull.go | 25 +++- models/pull_test.go | 6 +- models/release.go | 14 +- models/repo.go | 32 ++--- models/repo_activity.go | 2 +- models/repo_branch.go | 12 +- models/repo_collaboration.go | 2 +- models/repo_list.go | 26 ++-- models/repo_redirect.go | 15 ++- models/ssh_key.go | 10 +- models/status.go | 12 +- models/token_test.go | 4 +- models/update.go | 4 +- models/user.go | 29 ++-- models/user_mail.go | 2 +- models/user_openid_test.go | 4 +- models/webhook.go | 8 +- models/webhook_discord.go | 2 +- models/wiki.go | 12 +- modules/auth/auth.go | 12 +- modules/auth/oauth2/oauth2.go | 3 +- modules/auth/openid/discovery_cache_test.go | 2 +- modules/auth/user_form.go | 2 +- modules/base/tool.go | 28 ++-- modules/base/tool_test.go | 15 +-- modules/cache/cache.go | 12 +- modules/context/context.go | 3 +- modules/context/pagination.go | 2 +- modules/context/repo.go | 14 +- modules/git/blob.go | 6 +- modules/git/commit.go | 7 +- modules/git/commit_info.go | 10 -- modules/git/repo.go | 12 +- modules/git/repo_branch.go | 7 +- modules/git/repo_commit.go | 5 +- modules/git/repo_compare.go | 8 +- modules/git/repo_tag.go | 7 +- modules/git/utils.go | 8 -- modules/gzip/gzip.go | 6 +- modules/httplib/httplib.go | 35 +++-- modules/indexer/indexer.go | 17 --- modules/indexer/issues/indexer.go | 13 +- modules/indexer/issues/queue_channel.go | 6 +- modules/indexer/issues/queue_disk.go | 4 +- modules/indexer/issues/queue_redis.go | 4 +- modules/lfs/locks.go | 17 +-- modules/lfs/server.go | 12 +- modules/log/colors.go | 8 +- modules/log/conn.go | 5 +- modules/log/conn_test.go | 1 - modules/log/event.go | 4 +- modules/log/file.go | 4 +- modules/log/file_test.go | 8 +- modules/log/flags.go | 2 +- modules/log/log.go | 2 +- modules/log/smtp.go | 4 - modules/log/writer.go | 5 +- modules/mailer/mailer.go | 15 +-- modules/markup/html.go | 34 +---- modules/markup/html_internal_test.go | 5 - modules/notification/ui/ui.go | 9 +- modules/pprof/pprof.go | 12 +- modules/repofiles/delete.go | 10 +- modules/repofiles/file.go | 4 +- modules/repofiles/tree.go | 11 +- modules/repofiles/update.go | 14 +- modules/repofiles/upload.go | 8 +- modules/repofiles/verification.go | 6 +- modules/session/virtual.go | 6 +- modules/setting/log.go | 12 +- modules/setting/setting.go | 7 +- modules/ssh/ssh.go | 50 +++++-- modules/structs/user_search.go | 5 - modules/structs/utils.go | 6 - modules/templates/dynamic.go | 10 +- modules/templates/helper.go | 2 +- modules/user/user_test.go | 2 +- modules/validation/binding_test.go | 6 - routers/admin/admin.go | 4 - routers/api/v1/misc/markdown.go | 27 +++- routers/api/v1/repo/pull.go | 12 +- routers/api/v1/repo/repo.go | 9 -- routers/api/v1/user/gpg_key.go | 5 - routers/init.go | 2 +- routers/org/teams.go | 7 +- routers/private/hook.go | 1 - routers/private/serv.go | 2 - routers/repo/blame.go | 2 +- routers/repo/commit.go | 3 + routers/repo/download.go | 20 ++- routers/repo/editor.go | 12 +- routers/repo/http.go | 57 ++++---- routers/repo/issue.go | 11 +- routers/repo/issue_label.go | 1 - routers/repo/milestone.go | 3 +- routers/repo/pull.go | 4 +- routers/repo/setting.go | 5 +- routers/repo/view.go | 4 +- routers/repo/webhook.go | 14 +- routers/routes/routes.go | 35 ++--- routers/user/auth.go | 113 +++++++++++----- routers/user/auth_openid.go | 32 ++++- routers/user/oauth.go | 36 ++++- routers/user/profile.go | 1 - routers/user/setting/profile.go | 8 +- routers/user/setting/security_twofa.go | 28 +++- routers/user/setting/security_u2f.go | 7 +- templates/user/meta/stars.tmpl | 0 147 files changed, 1046 insertions(+), 774 deletions(-) create mode 100644 .golangci.yml delete mode 100644 modules/structs/user_search.go delete mode 100644 templates/user/meta/stars.tmpl diff --git a/.drone.yml b/.drone.yml index 0b8c8422b63b4..ec90c158b10dd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -74,12 +74,10 @@ pipeline: commands: - make clean - make generate - - make vet - - make lint - - make fmt-check + - make golangci-lint + - make revive - make swagger-check - make swagger-validate - - make misspell-check - make test-vendor - make build when: diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000000000..82d0e46694e1d --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,97 @@ +linters: + enable: + - gosimple + - deadcode + - typecheck + - govet + - errcheck + - staticcheck + - unused + - structcheck + - varcheck + - golint + - dupl + #- gocyclo # The cyclomatic complexety of a lot of functions is too high, we should refactor those another time. + - gofmt + - misspell + - gocritic + enable-all: false + disable-all: true + fast: false + +linters-settings: + gocritic: + disabled-checks: + - ifElseChain + - singleCaseSwitch # Every time this occured in the code, there was no other way. + +issues: + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - errcheck + - dupl + - gosec + - unparam + - staticcheck + - path: models/migrations/v + linters: + - gocyclo + - errcheck + - dupl + - gosec + - linters: + - dupl + text: "webhook" + - linters: + - gocritic + text: "`ID' should not be capitalized" + - path: modules/templates/helper.go + linters: + - gocritic + - linters: + - unused + - deadcode + text: "swagger" + - path: contrib/pr/checkout.go + linters: + - errcheck + - path: models/issue.go + linters: + - errcheck + - path: models/migrations/ + linters: + - errcheck + - path: modules/log/ + linters: + - errcheck + - path: routers/routes/routes.go + linters: + - dupl + - path: routers/repo/view.go + linters: + - dupl + - path: models/migrations/ + linters: + - unused + - linters: + - staticcheck + text: "argument x is overwritten before first use" + - path: modules/httplib/httplib.go + linters: + - staticcheck + # Enabling this would require refactoring the methods and how they are called. + - path: models/issue_comment_list.go + linters: + - dupl + # "Destroy" is misspelled in github.com/go-macaron/session/session.go:213 so it's not our responsability to fix it + - path: modules/session/virtual.go + linters: + - misspell + text: '`Destory` is a misspelling of `Destroy`' + - path: modules/session/memory.go + linters: + - misspell + text: '`Destory` is a misspelling of `Destroy`' diff --git a/Makefile b/Makefile index f175b95ae14b2..d7f27a8a94bc4 100644 --- a/Makefile +++ b/Makefile @@ -135,6 +135,10 @@ errcheck: .PHONY: lint lint: + @echo 'make lint is depricated. Use "make revive" if you want to use the old lint tool, or "make golangci-lint" to run a complete code check.' + +.PHONY: revive +revive: @hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ $(GO) get -u github.com/mgechev/revive; \ fi @@ -461,3 +465,10 @@ generate-images: .PHONY: pr pr: $(GO) run contrib/pr/checkout.go $(PR) + +.PHONY: golangci-lint +golangci-lint: + @hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.16.0; \ + fi + golangci-lint run diff --git a/cmd/admin.go b/cmd/admin.go index ecb4eb48a6dc3..6234ab828db8d 100644 --- a/cmd/admin.go +++ b/cmd/admin.go @@ -481,7 +481,7 @@ func runUpdateOauth(c *cli.Context) error { } // update custom URL mapping - var customURLMapping *oauth2.CustomURLMapping + var customURLMapping = &oauth2.CustomURLMapping{} if oAuth2Config.CustomURLMapping != nil { customURLMapping.TokenURL = oAuth2Config.CustomURLMapping.TokenURL diff --git a/cmd/cert.go b/cmd/cert.go index 46473c0042e72..b62319f80854a 100644 --- a/cmd/cert.go +++ b/cmd/cert.go @@ -170,17 +170,28 @@ func runCert(c *cli.Context) error { if err != nil { log.Fatalf("Failed to open cert.pem for writing: %v", err) } - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - certOut.Close() + err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + if err != nil { + log.Fatalf("Failed to encode certificate: %v", err) + } + err = certOut.Close() + if err != nil { + log.Fatalf("Failed to write cert: %v", err) + } log.Println("Written cert.pem") keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) if err != nil { log.Fatalf("Failed to open key.pem for writing: %v", err) } - pem.Encode(keyOut, pemBlockForKey(priv)) - keyOut.Close() + err = pem.Encode(keyOut, pemBlockForKey(priv)) + if err != nil { + log.Fatalf("Failed to encode key: %v", err) + } + err = keyOut.Close() + if err != nil { + log.Fatalf("Failed to write key: %v", err) + } log.Println("Written key.pem") - return nil } diff --git a/cmd/serv.go b/cmd/serv.go index c0cb3cd50fd37..c1c8fd3a97596 100644 --- a/cmd/serv.go +++ b/cmd/serv.go @@ -30,7 +30,6 @@ import ( ) const ( - accessDenied = "Repository does not exist or you do not have access" lfsAuthenticateVerb = "git-lfs-authenticate" ) @@ -67,7 +66,7 @@ func checkLFSVersion() { } func setup(logPath string) { - log.DelLogger("console") + _ = log.DelLogger("console") setting.NewContext() checkLFSVersion() } @@ -112,7 +111,9 @@ func runServ(c *cli.Context) error { } if len(c.Args()) < 1 { - cli.ShowSubcommandHelp(c) + if err := cli.ShowSubcommandHelp(c); err != nil { + fmt.Printf("error showing subcommand help: %v\n", err) + } return nil } diff --git a/cmd/web.go b/cmd/web.go index e6d0300a15504..e211674b4d713 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -178,11 +178,16 @@ func runWeb(ctx *cli.Context) error { } err = runHTTPS(listenAddr, setting.CertFile, setting.KeyFile, context2.ClearHandler(m)) case setting.FCGI: - listener, err := net.Listen("tcp", listenAddr) + var listener net.Listener + listener, err = net.Listen("tcp", listenAddr) if err != nil { log.Fatal("Failed to bind %s: %v", listenAddr, err) } - defer listener.Close() + defer func() { + if err := listener.Close(); err != nil { + log.Fatal("Failed to stop server: %v", err) + } + }() err = fcgi.Serve(listener, context2.ClearHandler(m)) case setting.UnixSocket: if err := os.Remove(listenAddr); err != nil && !os.IsNotExist(err) { diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go index 880c029510c23..a837cb5812a08 100644 --- a/contrib/pr/checkout.go +++ b/contrib/pr/checkout.go @@ -91,8 +91,7 @@ func runPR() { routers.NewServices() //x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared") - var helper testfixtures.Helper - helper = &testfixtures.SQLite{} + var helper testfixtures.Helper = &testfixtures.SQLite{} models.NewEngine(func(_ *xorm.Engine) error { return nil }) diff --git a/integrations/branches_test.go b/integrations/branches_test.go index 01c6dd2a4b2af..e74f338aa2f3e 100644 --- a/integrations/branches_test.go +++ b/integrations/branches_test.go @@ -62,7 +62,7 @@ func branchAction(t *testing.T, button string) (*HTMLDoc, string) { req = NewRequestWithValues(t, "POST", link, map[string]string{ "_csrf": getCsrf(t, htmlDoc.doc), }) - resp = session.MakeRequest(t, req, http.StatusOK) + session.MakeRequest(t, req, http.StatusOK) url, err := url.Parse(link) assert.NoError(t, err) diff --git a/integrations/editor_test.go b/integrations/editor_test.go index 8e6effe7ebd8d..a46712293e86c 100644 --- a/integrations/editor_test.go +++ b/integrations/editor_test.go @@ -34,7 +34,7 @@ func TestCreateFile(t *testing.T) { "content": "Content", "commit_choice": "direct", }) - resp = session.MakeRequest(t, req, http.StatusFound) + session.MakeRequest(t, req, http.StatusFound) }) } @@ -48,7 +48,7 @@ func TestCreateFileOnProtectedBranch(t *testing.T) { "_csrf": csrf, "protected": "on", }) - resp := session.MakeRequest(t, req, http.StatusFound) + session.MakeRequest(t, req, http.StatusFound) // Check if master branch has been locked successfully flashCookie := session.GetCookie("macaron_flash") assert.NotNil(t, flashCookie) @@ -56,7 +56,7 @@ func TestCreateFileOnProtectedBranch(t *testing.T) { // Request editor page req = NewRequest(t, "GET", "/user2/repo1/_new/master/") - resp = session.MakeRequest(t, req, http.StatusOK) + resp := session.MakeRequest(t, req, http.StatusOK) doc := NewHTMLParser(t, resp.Body) lastCommit := doc.GetInputValueByName("last_commit") diff --git a/integrations/integration_test.go b/integrations/integration_test.go index 80a42efb5c2e7..e9b46ffcb9b9e 100644 --- a/integrations/integration_test.go +++ b/integrations/integration_test.go @@ -42,7 +42,7 @@ type NilResponseRecorder struct { } func (n *NilResponseRecorder) Write(b []byte) (int, error) { - n.Length = n.Length + len(b) + n.Length += len(b) return len(b), nil } @@ -141,8 +141,7 @@ func initIntegrationTest() { if err != nil { log.Fatalf("sql.Open: %v", err) } - rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", - models.DbCfg.Name)) + rows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", models.DbCfg.Name)) if err != nil { log.Fatalf("db.Query: %v", err) } @@ -210,7 +209,7 @@ func (s *TestSession) MakeRequest(t testing.TB, req *http.Request, expectedStatu resp := MakeRequest(t, req, expectedStatus) ch := http.Header{} - ch.Add("Cookie", strings.Join(resp.HeaderMap["Set-Cookie"], ";")) + ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";")) cr := http.Request{Header: ch} s.jar.SetCookies(baseURL, cr.Cookies()) @@ -226,7 +225,7 @@ func (s *TestSession) MakeRequestNilResponseRecorder(t testing.TB, req *http.Req resp := MakeRequestNilResponseRecorder(t, req, expectedStatus) ch := http.Header{} - ch.Add("Cookie", strings.Join(resp.HeaderMap["Set-Cookie"], ";")) + ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";")) cr := http.Request{Header: ch} s.jar.SetCookies(baseURL, cr.Cookies()) @@ -266,7 +265,7 @@ func loginUserWithPassword(t testing.TB, userName, password string) *TestSession resp = MakeRequest(t, req, http.StatusFound) ch := http.Header{} - ch.Add("Cookie", strings.Join(resp.HeaderMap["Set-Cookie"], ";")) + ch.Add("Cookie", strings.Join(resp.Header()["Set-Cookie"], ";")) cr := http.Request{Header: ch} session := emptyTestSession(t) diff --git a/integrations/lfs_getobject_test.go b/integrations/lfs_getobject_test.go index 8f01d712a3d87..567cf13b45b6d 100644 --- a/integrations/lfs_getobject_test.go +++ b/integrations/lfs_getobject_test.go @@ -45,7 +45,7 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string lfsMetaObject = &models.LFSMetaObject{Oid: oid, Size: int64(len(*content)), RepositoryID: repositoryID} } - lfsID = lfsID + 1 + lfsID++ lfsMetaObject, err = models.NewLFSMetaObject(lfsMetaObject) assert.NoError(t, err) contentStore := &lfs.ContentStore{BasePath: setting.LFS.ContentPath} diff --git a/integrations/migration-test/migration_test.go b/integrations/migration-test/migration_test.go index f168424865201..15b086c6e6229 100644 --- a/integrations/migration-test/migration_test.go +++ b/integrations/migration-test/migration_test.go @@ -57,21 +57,6 @@ func initMigrationTest(t *testing.T) { setting.NewLogServices(true) } -func getDialect() string { - dialect := "sqlite" - switch { - case setting.UseSQLite3: - dialect = "sqlite" - case setting.UseMySQL: - dialect = "mysql" - case setting.UsePostgreSQL: - dialect = "pgsql" - case setting.UseMSSQL: - dialect = "mssql" - } - return dialect -} - func availableVersions() ([]string, error) { migrationsDir, err := os.Open("integrations/migration-test") if err != nil { diff --git a/integrations/testlogger.go b/integrations/testlogger.go index c50daead9b4c2..43a1471f66040 100644 --- a/integrations/testlogger.go +++ b/integrations/testlogger.go @@ -73,7 +73,7 @@ func PrintCurrentTest(t testing.TB, skip ...int) { _, filename, line, _ := runtime.Caller(actualSkip) if log.CanColorStdout { - fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", log.NewColoredValue(t.Name()), strings.TrimPrefix(filename, prefix), line) + fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", fmt.Formatter(log.NewColoredValue(t.Name())), strings.TrimPrefix(filename, prefix), line) } else { fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", t.Name(), strings.TrimPrefix(filename, prefix), line) } diff --git a/main.go b/main.go index 79c9b01114b05..30dbf2766224c 100644 --- a/main.go +++ b/main.go @@ -42,7 +42,7 @@ var ( func init() { setting.AppVer = Version - setting.AppBuiltWith = formatBuiltWith(Tags) + setting.AppBuiltWith = formatBuiltWith() // Grab the original help templates originalAppHelpTemplate = cli.AppHelpTemplate @@ -56,7 +56,7 @@ func main() { app.Usage = "A painless self-hosted Git service" app.Description = `By default, gitea will start serving using the webserver with no arguments - which can alternatively be run by running the subcommand web.` - app.Version = Version + formatBuiltWith(Tags) + app.Version = Version + formatBuiltWith() app.Commands = []cli.Command{ cmd.CmdWeb, cmd.CmdServ, @@ -179,7 +179,7 @@ DEFAULT CONFIGURATION: `, originalTemplate, setting.CustomPath, overrided, setting.CustomConf, setting.AppPath, setting.AppWorkPath) } -func formatBuiltWith(makeTags string) string { +func formatBuiltWith() string { var version = runtime.Version() if len(MakeVersion) > 0 { version = MakeVersion + ", " + runtime.Version() diff --git a/models/access_test.go b/models/access_test.go index d6a1c92b90202..db6f655a670dc 100644 --- a/models/access_test.go +++ b/models/access_test.go @@ -10,13 +10,6 @@ import ( "github.com/stretchr/testify/assert" ) -var accessModes = []AccessMode{ - AccessModeRead, - AccessModeWrite, - AccessModeAdmin, - AccessModeOwner, -} - func TestAccessLevel(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) diff --git a/models/branches.go b/models/branches.go index abefa60f48420..df3b69aa21888 100644 --- a/models/branches.go +++ b/models/branches.go @@ -126,14 +126,14 @@ func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) } // GetProtectedBranchByRepoID getting protected branch by repo ID -func GetProtectedBranchByRepoID(RepoID int64) ([]*ProtectedBranch, error) { +func GetProtectedBranchByRepoID(repoID int64) ([]*ProtectedBranch, error) { protectedBranches := make([]*ProtectedBranch, 0) - return protectedBranches, x.Where("repo_id = ?", RepoID).Desc("updated_unix").Find(&protectedBranches) + return protectedBranches, x.Where("repo_id = ?", repoID).Desc("updated_unix").Find(&protectedBranches) } // GetProtectedBranchBy getting protected branch by ID/Name -func GetProtectedBranchBy(repoID int64, BranchName string) (*ProtectedBranch, error) { - rel := &ProtectedBranch{RepoID: repoID, BranchName: BranchName} +func GetProtectedBranchBy(repoID int64, branchName string) (*ProtectedBranch, error) { + rel := &ProtectedBranch{RepoID: repoID, BranchName: branchName} has, err := x.Get(rel) if err != nil { return nil, err diff --git a/models/git_blame.go b/models/git_blame.go index 7b4fb64a7081c..2b439a23b9d82 100644 --- a/models/git_blame.go +++ b/models/git_blame.go @@ -40,7 +40,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) { scanner := r.scanner if r.lastSha != nil { - blamePart = &BlamePart{*r.lastSha, make([]string, 0, 0)} + blamePart = &BlamePart{*r.lastSha, make([]string, 0)} } for scanner.Scan() { @@ -56,7 +56,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) { sha1 := lines[1] if blamePart == nil { - blamePart = &BlamePart{sha1, make([]string, 0, 0)} + blamePart = &BlamePart{sha1, make([]string, 0)} } if blamePart.Sha != sha1 { diff --git a/models/git_diff.go b/models/git_diff.go index ac2a5f90d74e8..a6ea7306d491f 100644 --- a/models/git_diff.go +++ b/models/git_diff.go @@ -384,13 +384,9 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi // headers + hunk header newHunk := make([]string, headerLines) // transfer existing headers - for idx, lof := range hunk[:headerLines] { - newHunk[idx] = lof - } + copy(newHunk, hunk[:headerLines]) // transfer last n lines - for _, lof := range hunk[len(hunk)-numbersOfLine-1:] { - newHunk = append(newHunk, lof) - } + newHunk = append(newHunk, hunk[len(hunk)-numbersOfLine-1:]...) // calculate newBegin, ... by counting lines for i := len(hunk) - 1; i >= len(hunk)-numbersOfLine; i-- { switch hunk[i][0] { @@ -582,7 +578,10 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D diff.Files = append(diff.Files, curFile) if len(diff.Files) >= maxFiles { diff.IsIncomplete = true - io.Copy(ioutil.Discard, reader) + _, err := io.Copy(ioutil.Discard, reader) + if err != nil { + return nil, fmt.Errorf("Copy: %v", err) + } break } curFileLinesCount = 0 diff --git a/models/git_diff_test.go b/models/git_diff_test.go index 2111e9044f994..deca7c8d4affa 100644 --- a/models/git_diff_test.go +++ b/models/git_diff_test.go @@ -17,12 +17,6 @@ func assertEqual(t *testing.T, s1 string, s2 template.HTML) { } } -func assertLineEqual(t *testing.T, d1 *DiffLine, d2 *DiffLine) { - if d1 != d2 { - t.Errorf("%v should be equal %v", d1, d2) - } -} - func TestDiffToHTML(t *testing.T) { assertEqual(t, "+foo bar biz", diffToHTML([]dmp.Diff{ {Type: dmp.DiffEqual, Text: "foo "}, diff --git a/models/issue.go b/models/issue.go index 999bd2f7a9b4d..27298b8a86d2f 100644 --- a/models/issue.go +++ b/models/issue.go @@ -1330,7 +1330,7 @@ func sortIssuesSession(sess *xorm.Session, sortType string) { } } -func (opts *IssuesOptions) setupSession(sess *xorm.Session) error { +func (opts *IssuesOptions) setupSession(sess *xorm.Session) { if opts.Page >= 0 && opts.PageSize > 0 { var start int if opts.Page == 0 { @@ -1389,7 +1389,6 @@ func (opts *IssuesOptions) setupSession(sess *xorm.Session) error { fmt.Sprintf("issue.id = il%[1]d.issue_id AND il%[1]d.label_id = %[2]d", i, labelID)) } } - return nil } // CountIssuesByRepo map from repoID to number of issues matching the options @@ -1397,9 +1396,7 @@ func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) { sess := x.NewSession() defer sess.Close() - if err := opts.setupSession(sess); err != nil { - return nil, err - } + opts.setupSession(sess) countsSlice := make([]*struct { RepoID int64 @@ -1424,9 +1421,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) { sess := x.NewSession() defer sess.Close() - if err := opts.setupSession(sess); err != nil { - return nil, err - } + opts.setupSession(sess) sortIssuesSession(sess, opts.SortType) issues := make([]*Issue, 0, setting.UI.IssuePagingNum) diff --git a/models/issue_comment.go b/models/issue_comment.go index 0d2e917f857f1..d75d9d7db1f6e 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -171,17 +171,6 @@ func (c *Comment) loadPoster(e Engine) (err error) { return err } -func (c *Comment) loadAttachments(e Engine) (err error) { - if len(c.Attachments) > 0 { - return - } - c.Attachments, err = getAttachmentsByCommentID(e, c.ID) - if err != nil { - log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err) - } - return err -} - // AfterDelete is invoked from XORM after the object is deleted. func (c *Comment) AfterDelete() { if c.ID <= 0 { @@ -463,7 +452,7 @@ func (c *Comment) LoadReview() error { return c.loadReview(x) } -func (c *Comment) checkInvalidation(e Engine, doer *User, repo *git.Repository, branch string) error { +func (c *Comment) checkInvalidation(doer *User, repo *git.Repository, branch string) error { // FIXME differentiate between previous and proposed line commit, err := repo.LineBlame(branch, repo.Path, c.TreePath, uint(c.UnsignedLine())) if err != nil { @@ -479,7 +468,7 @@ func (c *Comment) checkInvalidation(e Engine, doer *User, repo *git.Repository, // CheckInvalidation checks if the line of code comment got changed by another commit. // If the line got changed the comment is going to be invalidated. func (c *Comment) CheckInvalidation(repo *git.Repository, doer *User, branch string) error { - return c.checkInvalidation(x, doer, repo, branch) + return c.checkInvalidation(doer, repo, branch) } // DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes. @@ -915,7 +904,7 @@ func CreateCodeComment(doer *User, repo *Repository, issue *Issue, content, tree commit, err := gitRepo.LineBlame(pr.GetGitRefName(), gitRepo.Path, treePath, uint(line)) if err == nil { commitID = commit.ID.String() - } else if err != nil && !strings.Contains(err.Error(), "exit status 128 - fatal: no such path") { + } else if !strings.Contains(err.Error(), "exit status 128 - fatal: no such path") { return nil, fmt.Errorf("LineBlame[%s, %s, %s, %d]: %v", pr.GetGitRefName(), gitRepo.Path, treePath, line, err) } } diff --git a/models/issue_comment_list.go b/models/issue_comment_list.go index a8c8123280c7f..ae2a89a01ac77 100644 --- a/models/issue_comment_list.go +++ b/models/issue_comment_list.go @@ -36,7 +36,7 @@ func (comments CommentList) loadPosters(e Engine) error { if err != nil { return err } - left = left - limit + left -= limit posterIDs = posterIDs[limit:] } @@ -94,13 +94,13 @@ func (comments CommentList) loadLabels(e Engine) error { var label Label err = rows.Scan(&label) if err != nil { - rows.Close() + _ = rows.Close() return err } commentLabels[label.ID] = &label } - rows.Close() - left = left - limit + _ = rows.Close() + left -= limit labelIDs = labelIDs[limit:] } @@ -143,7 +143,7 @@ func (comments CommentList) loadMilestones(e Engine) error { if err != nil { return err } - left = left - limit + left -= limit milestoneIDs = milestoneIDs[limit:] } @@ -186,7 +186,7 @@ func (comments CommentList) loadOldMilestones(e Engine) error { if err != nil { return err } - left = left - limit + left -= limit milestoneIDs = milestoneIDs[limit:] } @@ -236,9 +236,9 @@ func (comments CommentList) loadAssignees(e Engine) error { assignees[user.ID] = &user } - rows.Close() + _ = rows.Close() - left = left - limit + left -= limit assigneeIDs = assigneeIDs[limit:] } @@ -310,9 +310,9 @@ func (comments CommentList) loadIssues(e Engine) error { issues[issue.ID] = &issue } - rows.Close() + _ = rows.Close() - left = left - limit + left -= limit issueIDs = issueIDs[limit:] } @@ -361,15 +361,15 @@ func (comments CommentList) loadDependentIssues(e Engine) error { var issue Issue err = rows.Scan(&issue) if err != nil { - rows.Close() + _ = rows.Close() return err } issues[issue.ID] = &issue } - rows.Close() + _ = rows.Close() - left = left - limit + left -= limit issueIDs = issueIDs[limit:] } @@ -406,14 +406,14 @@ func (comments CommentList) loadAttachments(e Engine) (err error) { var attachment Attachment err = rows.Scan(&attachment) if err != nil { - rows.Close() + _ = rows.Close() return err } attachments[attachment.CommentID] = append(attachments[attachment.CommentID], &attachment) } - rows.Close() - left = left - limit + _ = rows.Close() + left -= limit commentsIDs = commentsIDs[limit:] } @@ -457,15 +457,15 @@ func (comments CommentList) loadReviews(e Engine) error { var review Review err = rows.Scan(&review) if err != nil { - rows.Close() + _ = rows.Close() return err } reviews[review.ID] = &review } - rows.Close() + _ = rows.Close() - left = left - limit + left -= limit reviewIDs = reviewIDs[limit:] } diff --git a/models/issue_label.go b/models/issue_label.go index 38266f3e7c9dd..363d4bb814f46 100644 --- a/models/issue_label.go +++ b/models/issue_label.go @@ -401,14 +401,6 @@ func NewIssueLabels(issue *Issue, labels []*Label, doer *User) (err error) { return sess.Commit() } -func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) { - issueLabels := make([]*IssueLabel, 0, 10) - return issueLabels, e. - Where("issue_id=?", issueID). - Asc("label_id"). - Find(&issueLabels) -} - func deleteIssueLabel(e *xorm.Session, issue *Issue, label *Label, doer *User) (err error) { if count, err := e.Delete(&IssueLabel{ IssueID: issue.ID, diff --git a/models/issue_list.go b/models/issue_list.go index a1aab488fcb91..4ddb32da1311d 100644 --- a/models/issue_list.go +++ b/models/issue_list.go @@ -7,6 +7,8 @@ package models import ( "fmt" + "code.gitea.io/gitea/modules/log" + "github.com/go-xorm/builder" ) @@ -47,7 +49,7 @@ func (issues IssueList) loadRepositories(e Engine) ([]*Repository, error) { if err != nil { return nil, fmt.Errorf("find repository: %v", err) } - left = left - limit + left -= limit repoIDs = repoIDs[limit:] } @@ -91,7 +93,7 @@ func (issues IssueList) loadPosters(e Engine) error { if err != nil { return err } - left = left - limit + left -= limit posterIDs = posterIDs[limit:] } @@ -146,13 +148,21 @@ func (issues IssueList) loadLabels(e Engine) error { var labelIssue LabelIssue err = rows.Scan(&labelIssue) if err != nil { - rows.Close() + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadLabels: Close: %v", err) + } return err } issueLabels[labelIssue.IssueLabel.IssueID] = append(issueLabels[labelIssue.IssueLabel.IssueID], labelIssue.Label) } - rows.Close() - left = left - limit + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadLabels: Close: %v", err) + } + left -= limit issueIDs = issueIDs[limit:] } @@ -191,7 +201,7 @@ func (issues IssueList) loadMilestones(e Engine) error { if err != nil { return err } - left = left - limit + left -= limit milestoneIDs = milestoneIDs[limit:] } @@ -231,15 +241,22 @@ func (issues IssueList) loadAssignees(e Engine) error { var assigneeIssue AssigneeIssue err = rows.Scan(&assigneeIssue) if err != nil { - rows.Close() + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadAssignees: Close: %v", err) + } return err } assignees[assigneeIssue.IssueAssignee.IssueID] = append(assignees[assigneeIssue.IssueAssignee.IssueID], assigneeIssue.Assignee) } - rows.Close() - - left = left - limit + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadAssignees: Close: %v", err) + } + left -= limit issueIDs = issueIDs[limit:] } @@ -283,14 +300,21 @@ func (issues IssueList) loadPullRequests(e Engine) error { var pr PullRequest err = rows.Scan(&pr) if err != nil { - rows.Close() + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadPullRequests: Close: %v", err) + } return err } pullRequestMaps[pr.IssueID] = &pr } - - rows.Close() - left = left - limit + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadPullRequests: Close: %v", err) + } + left -= limit issuesIDs = issuesIDs[limit:] } @@ -325,14 +349,21 @@ func (issues IssueList) loadAttachments(e Engine) (err error) { var attachment Attachment err = rows.Scan(&attachment) if err != nil { - rows.Close() + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadAttachments: Close: %v", err) + } return err } attachments[attachment.IssueID] = append(attachments[attachment.IssueID], &attachment) } - - rows.Close() - left = left - limit + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadAttachments: Close: %v", err) + } + left -= limit issuesIDs = issuesIDs[limit:] } @@ -368,13 +399,21 @@ func (issues IssueList) loadComments(e Engine, cond builder.Cond) (err error) { var comment Comment err = rows.Scan(&comment) if err != nil { - rows.Close() + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadComments: Close: %v", err) + } return err } comments[comment.IssueID] = append(comments[comment.IssueID], &comment) } - rows.Close() - left = left - limit + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadComments: Close: %v", err) + } + left -= limit issuesIDs = issuesIDs[limit:] } @@ -422,13 +461,21 @@ func (issues IssueList) loadTotalTrackedTimes(e Engine) (err error) { var totalTime totalTimesByIssue err = rows.Scan(&totalTime) if err != nil { - rows.Close() + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadTotalTrackedTimes: Close: %v", err) + } return err } trackedTimes[totalTime.IssueID] = totalTime.Time } - rows.Close() - left = left - limit + // When there are no rows left and we try to close it, xorm will complain with an error. + // Since that is not relevant for us, we can safely ignore it. + if err := rows.Close(); err != nil { + log.Error("IssueList.loadTotalTrackedTimes: Close: %v", err) + } + left -= limit ids = ids[limit:] } @@ -439,33 +486,33 @@ func (issues IssueList) loadTotalTrackedTimes(e Engine) (err error) { } // loadAttributes loads all attributes, expect for attachments and comments -func (issues IssueList) loadAttributes(e Engine) (err error) { - if _, err = issues.loadRepositories(e); err != nil { - return +func (issues IssueList) loadAttributes(e Engine) error { + if _, err := issues.loadRepositories(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadRepositories: %v", err) } - if err = issues.loadPosters(e); err != nil { - return + if err := issues.loadPosters(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadPosters: %v", err) } - if err = issues.loadLabels(e); err != nil { - return + if err := issues.loadLabels(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadLabels: %v", err) } - if err = issues.loadMilestones(e); err != nil { - return + if err := issues.loadMilestones(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadMilestones: %v", err) } - if err = issues.loadAssignees(e); err != nil { - return + if err := issues.loadAssignees(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadAssignees: %v", err) } - if err = issues.loadPullRequests(e); err != nil { - return + if err := issues.loadPullRequests(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadPullRequests: %v", err) } - if err = issues.loadTotalTrackedTimes(e); err != nil { - return + if err := issues.loadTotalTrackedTimes(e); err != nil { + return fmt.Errorf("issue.loadAttributes: loadTotalTrackedTimes: %v", err) } return nil diff --git a/models/log.go b/models/log.go index 4994545c5f429..38d6caf07c979 100644 --- a/models/log.go +++ b/models/log.go @@ -15,7 +15,6 @@ import ( // XORMLogBridge a logger bridge from Logger to xorm type XORMLogBridge struct { showSQL bool - level core.LogLevel logger *log.Logger } @@ -34,42 +33,42 @@ func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...inter // Debug show debug log func (l *XORMLogBridge) Debug(v ...interface{}) { - l.Log(2, log.DEBUG, fmt.Sprint(v...)) + _ = l.Log(2, log.DEBUG, fmt.Sprint(v...)) } // Debugf show debug log func (l *XORMLogBridge) Debugf(format string, v ...interface{}) { - l.Log(2, log.DEBUG, format, v...) + _ = l.Log(2, log.DEBUG, format, v...) } // Error show error log func (l *XORMLogBridge) Error(v ...interface{}) { - l.Log(2, log.ERROR, fmt.Sprint(v...)) + _ = l.Log(2, log.ERROR, fmt.Sprint(v...)) } // Errorf show error log func (l *XORMLogBridge) Errorf(format string, v ...interface{}) { - l.Log(2, log.ERROR, format, v...) + _ = l.Log(2, log.ERROR, format, v...) } // Info show information level log func (l *XORMLogBridge) Info(v ...interface{}) { - l.Log(2, log.INFO, fmt.Sprint(v...)) + _ = l.Log(2, log.INFO, fmt.Sprint(v...)) } // Infof show information level log func (l *XORMLogBridge) Infof(format string, v ...interface{}) { - l.Log(2, log.INFO, format, v...) + _ = l.Log(2, log.INFO, format, v...) } // Warn show warning log func (l *XORMLogBridge) Warn(v ...interface{}) { - l.Log(2, log.WARN, fmt.Sprint(v...)) + _ = l.Log(2, log.WARN, fmt.Sprint(v...)) } // Warnf show warnning log func (l *XORMLogBridge) Warnf(format string, v ...interface{}) { - l.Log(2, log.WARN, format, v...) + _ = l.Log(2, log.WARN, format, v...) } // Level get logger level diff --git a/models/login_source.go b/models/login_source.go index 9b8173b84dfb5..8eefec4ae5873 100644 --- a/models/login_source.go +++ b/models/login_source.go @@ -164,8 +164,7 @@ func Cell2Int64(val xorm.Cell) int64 { // BeforeSet is invoked from XORM before setting the value of a field of this object. func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { - switch colName { - case "type": + if colName == "type" { switch LoginType(Cell2Int64(val)) { case LoginLDAP, LoginDLDAP: source.Cfg = new(LDAPConfig) @@ -282,10 +281,12 @@ func CreateLoginSource(source *LoginSource) error { oAuth2Config := source.OAuth2() err = oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping) err = wrapOpenIDConnectInitializeError(err, source.Name, oAuth2Config) - if err != nil { // remove the LoginSource in case of errors while registering OAuth2 providers - x.Delete(source) + if _, err := x.Delete(source); err != nil { + log.Error("CreateLoginSource: Error while wrapOpenIDConnectInitializeError: %v", err) + } + return err } } return err @@ -325,10 +326,12 @@ func UpdateSource(source *LoginSource) error { oAuth2Config := source.OAuth2() err = oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping) err = wrapOpenIDConnectInitializeError(err, source.Name, oAuth2Config) - if err != nil { // restore original values since we cannot update the provider it self - x.ID(source.ID).AllCols().Update(originalLoginSource) + if _, err := x.ID(source.ID).AllCols().Update(originalLoginSource); err != nil { + log.Error("UpdateSource: Error while wrapOpenIDConnectInitializeError: %v", err) + } + return err } } return err @@ -385,7 +388,7 @@ func composeFullName(firstname, surname, username string) string { } var ( - alphaDashDotPattern = regexp.MustCompile("[^\\w-\\.]") + alphaDashDotPattern = regexp.MustCompile(`[^\w-\.]`) ) // LoginViaLDAP queries if login/password is valid against the LDAP directory pool, @@ -401,7 +404,7 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR if !autoRegister { if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(user, source, sr.SSHPublicKey) { - RewriteAllPublicKeys() + return user, RewriteAllPublicKeys() } return user, nil @@ -435,7 +438,7 @@ func LoginViaLDAP(user *User, login, password string, source *LoginSource, autoR err := CreateUser(user) if err == nil && isAttributeSSHPublicKeySet && addLdapSSHPublicKeys(user, source, sr.SSHPublicKey) { - RewriteAllPublicKeys() + err = RewriteAllPublicKeys() } return user, err diff --git a/models/mail.go b/models/mail.go index 6be0df95ba51c..2bb07607a4119 100644 --- a/models/mail.go +++ b/models/mail.go @@ -157,10 +157,13 @@ func composeTplData(subject, body, link string) map[string]interface{} { func composeIssueCommentMessage(issue *Issue, doer *User, content string, comment *Comment, tplName base.TplName, tos []string, info string) *mailer.Message { subject := issue.mailSubject() - issue.LoadRepo() + err := issue.LoadRepo() + if err != nil { + log.Error("LoadRepo: %v", err) + } body := string(markup.RenderByType(markdown.MarkupName, []byte(content), issue.Repo.HTMLURL(), issue.Repo.ComposeMetas())) - data := make(map[string]interface{}, 10) + var data = make(map[string]interface{}, 10) if comment != nil { data = composeTplData(subject, body, issue.HTMLURL()+"#"+comment.HashTag()) } else { diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index b95a74c3621db..e8fb42c492ea7 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -399,7 +399,7 @@ func trimCommitActionAppURLPrefix(x *xorm.Engine) error { return fmt.Errorf("marshal action content[%d]: %v", actID, err) } - if _, err = sess.Id(actID).Update(&Action{ + if _, err = sess.ID(actID).Update(&Action{ Content: string(p), }); err != nil { return fmt.Errorf("update action[%d]: %v", actID, err) @@ -503,7 +503,7 @@ func attachmentRefactor(x *xorm.Engine) error { // Update database first because this is where error happens the most often. for _, attach := range attachments { - if _, err = sess.Id(attach.ID).Update(attach); err != nil { + if _, err = sess.ID(attach.ID).Update(attach); err != nil { return err } @@ -581,7 +581,7 @@ func renamePullRequestFields(x *xorm.Engine) (err error) { if pull.Index == 0 { continue } - if _, err = sess.Id(pull.ID).Update(pull); err != nil { + if _, err = sess.ID(pull.ID).Update(pull); err != nil { return err } } @@ -661,7 +661,7 @@ func generateOrgRandsAndSalt(x *xorm.Engine) (err error) { if org.Salt, err = generate.GetRandomString(10); err != nil { return err } - if _, err = sess.Id(org.ID).Update(org); err != nil { + if _, err = sess.ID(org.ID).Update(org); err != nil { return err } } diff --git a/models/migrations/v27.go b/models/migrations/v27.go index bd115cf937275..e87c7ab68f582 100644 --- a/models/migrations/v27.go +++ b/models/migrations/v27.go @@ -58,13 +58,13 @@ func convertIntervalToDuration(x *xorm.Engine) (err error) { return fmt.Errorf("Query repositories: %v", err) } for _, mirror := range mirrors { - mirror.Interval = mirror.Interval * time.Hour + mirror.Interval *= time.Hour if mirror.Interval < setting.Mirror.MinInterval { log.Info("Mirror interval less than Mirror.MinInterval, setting default interval: repo id %v", mirror.RepoID) mirror.Interval = setting.Mirror.DefaultInterval } log.Debug("Mirror interval set to %v for repo id %v", mirror.Interval, mirror.RepoID) - _, err := sess.Id(mirror.ID).Cols("interval").Update(mirror) + _, err := sess.ID(mirror.ID).Cols("interval").Update(mirror) if err != nil { return fmt.Errorf("update mirror interval failed: %v", err) } diff --git a/models/migrations/v78.go b/models/migrations/v78.go index 7ca112dbd5005..310c479d01b74 100644 --- a/models/migrations/v78.go +++ b/models/migrations/v78.go @@ -48,6 +48,9 @@ func renameRepoIsBareToIsEmpty(x *xorm.Engine) error { if len(indexes) >= 1 { _, err = sess.Exec("DROP INDEX IDX_repository_is_bare ON repository") + if err != nil { + return fmt.Errorf("Drop index failed: %v", err) + } } } else { _, err = sess.Exec("DROP INDEX IDX_repository_is_bare ON repository") diff --git a/models/migrations/v85.go b/models/migrations/v85.go index 1fe85ac4087b8..d511628b8d544 100644 --- a/models/migrations/v85.go +++ b/models/migrations/v85.go @@ -58,6 +58,9 @@ func hashAppToken(x *xorm.Engine) error { if len(indexes) >= 1 { _, err = sess.Exec("DROP INDEX UQE_access_token_sha1 ON access_token") + if err != nil { + return err + } } } else { _, err = sess.Exec("DROP INDEX UQE_access_token_sha1 ON access_token") diff --git a/models/models.go b/models/models.go index c1d4c100d0027..5752a8edd6dcf 100644 --- a/models/models.go +++ b/models/models.go @@ -48,6 +48,7 @@ type Engine interface { Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *xorm.Session SQL(interface{}, ...interface{}) *xorm.Session Where(interface{}, ...interface{}) *xorm.Session + Asc(colNames ...string) *xorm.Session } var ( @@ -181,14 +182,14 @@ func parsePostgreSQLHostPort(info string) (string, string) { return host, port } -func getPostgreSQLConnectionString(DBHost, DBUser, DBPasswd, DBName, DBParam, DBSSLMode string) (connStr string) { - host, port := parsePostgreSQLHostPort(DBHost) +func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) { + host, port := parsePostgreSQLHostPort(dbHost) if host[0] == '/' { // looks like a unix socket connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s", - url.PathEscape(DBUser), url.PathEscape(DBPasswd), port, DBName, DBParam, DBSSLMode, host) + url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host) } else { connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s", - url.PathEscape(DBUser), url.PathEscape(DBPasswd), host, port, DBName, DBParam, DBSSLMode) + url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode) } return } diff --git a/models/notification.go b/models/notification.go index cda2916faeb1d..f83fe63e5ac5a 100644 --- a/models/notification.go +++ b/models/notification.go @@ -119,7 +119,10 @@ func createOrUpdateIssueNotifications(e Engine, issue *Issue, notificationAuthor } } - issue.loadRepo(e) + err = issue.loadRepo(e) + if err != nil { + return err + } for _, watch := range watches { issue.Repo.Units = nil diff --git a/models/oauth2.go b/models/oauth2.go index 10bce31924862..bf4446229a422 100644 --- a/models/oauth2.go +++ b/models/oauth2.go @@ -106,7 +106,10 @@ func InitOAuth2() error { for _, source := range loginSources { oAuth2Config := source.OAuth2() - oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping) + err := oauth2.RegisterProvider(source.Name, oAuth2Config.Provider, oAuth2Config.ClientID, oAuth2Config.ClientSecret, oAuth2Config.OpenIDConnectAutoDiscoveryURL, oAuth2Config.CustomURLMapping) + if err != nil { + return err + } } return nil } diff --git a/models/oauth2_application.go b/models/oauth2_application.go index 1e69dd6430464..63d2e7ce5eb4b 100644 --- a/models/oauth2_application.go +++ b/models/oauth2_application.go @@ -142,6 +142,9 @@ func GetOAuth2ApplicationByID(id int64) (app *OAuth2Application, err error) { func getOAuth2ApplicationByID(e Engine, id int64) (app *OAuth2Application, err error) { app = new(OAuth2Application) has, err := e.ID(id).Get(app) + if err != nil { + return nil, err + } if !has { return nil, ErrOAuthApplicationNotFound{ID: id} } @@ -295,10 +298,10 @@ func (code *OAuth2AuthorizationCode) invalidate(e Engine) error { // ValidateCodeChallenge validates the given verifier against the saved code challenge. This is part of the PKCE implementation. func (code *OAuth2AuthorizationCode) ValidateCodeChallenge(verifier string) bool { - return code.validateCodeChallenge(x, verifier) + return code.validateCodeChallenge(verifier) } -func (code *OAuth2AuthorizationCode) validateCodeChallenge(e Engine, verifier string) bool { +func (code *OAuth2AuthorizationCode) validateCodeChallenge(verifier string) bool { switch code.CodeChallengeMethod { case "S256": // base64url(SHA256(verifier)) see https://tools.ietf.org/html/rfc7636#section-4.6 diff --git a/models/org.go b/models/org.go index 6511072e2b7b0..65002eadff148 100644 --- a/models/org.go +++ b/models/org.go @@ -172,7 +172,9 @@ func CreateOrganization(org, owner *User) (err error) { } if _, err = sess.Insert(&units); err != nil { - sess.Rollback() + if err := sess.Rollback(); err != nil { + log.Error("CreateOrganization: sess.Rollback: %v", err) + } return err } @@ -376,10 +378,7 @@ func HasOrgVisible(org *User, user *User) bool { func hasOrgVisible(e Engine, org *User, user *User) bool { // Not SignedUser if user == nil { - if org.Visibility == structs.VisibleTypePublic { - return true - } - return false + return org.Visibility == structs.VisibleTypePublic } if user.IsAdmin { @@ -485,10 +484,14 @@ func AddOrgUser(orgID, uid int64) error { } if _, err := sess.Insert(ou); err != nil { - sess.Rollback() + if err := sess.Rollback(); err != nil { + log.Error("AddOrgUser: sess.Rollback: %v", err) + } return err } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil { - sess.Rollback() + if err := sess.Rollback(); err != nil { + log.Error("AddOrgUser: sess.Rollback: %v", err) + } return err } diff --git a/models/org_team.go b/models/org_team.go index 49d06896e59d7..dcf07437403d3 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -287,7 +287,8 @@ func NewTeam(t *Team) (err error) { has, err := x.ID(t.OrgID).Get(new(User)) if err != nil { return err - } else if !has { + } + if !has { return ErrOrgNotExist{t.OrgID, ""} } @@ -298,7 +299,8 @@ func NewTeam(t *Team) (err error) { Get(new(Team)) if err != nil { return err - } else if has { + } + if has { return ErrTeamAlreadyExist{t.OrgID, t.LowerName} } @@ -309,7 +311,10 @@ func NewTeam(t *Team) (err error) { } if _, err = sess.Insert(t); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("NewTeam sess.Rollback: %v", errRollback) + } return err } @@ -319,14 +324,20 @@ func NewTeam(t *Team) (err error) { unit.TeamID = t.ID } if _, err = sess.Insert(&t.Units); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("NewTeam sess.Rollback: %v", errRollback) + } return err } } // Update organization number of teams. if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams+1 WHERE id = ?", t.OrgID); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("NewTeam sess.Rollback: %v", errRollback) + } return err } return sess.Commit() @@ -412,7 +423,10 @@ func UpdateTeam(t *Team, authChanged bool) (err error) { } if _, err = sess.Insert(&t.Units); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("UpdateTeam sess.Rollback: %v", errRollback) + } return err } } @@ -841,7 +855,10 @@ func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) { } if _, err = sess.Insert(units); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("UpdateTeamUnits sess.Rollback: %v", errRollback) + } return err } diff --git a/models/org_test.go b/models/org_test.go index b484208be152d..a2ebf1f60bce8 100644 --- a/models/org_test.go +++ b/models/org_test.go @@ -242,10 +242,10 @@ func TestGetOrgByName(t *testing.T) { assert.EqualValues(t, 3, org.ID) assert.Equal(t, "user3", org.Name) - org, err = GetOrgByName("user2") // user2 is an individual + _, err = GetOrgByName("user2") // user2 is an individual assert.True(t, IsErrOrgNotExist(err)) - org, err = GetOrgByName("") // corner case + _, err = GetOrgByName("") // corner case assert.True(t, IsErrOrgNotExist(err)) } @@ -499,7 +499,7 @@ func TestAccessibleReposEnv_CountRepos(t *testing.T) { func TestAccessibleReposEnv_RepoIDs(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) org := AssertExistsAndLoadBean(t, &User{ID: 3}).(*User) - testSuccess := func(userID, page, pageSize int64, expectedRepoIDs []int64) { + testSuccess := func(userID, _, pageSize int64, expectedRepoIDs []int64) { env, err := org.AccessibleReposEnv(userID) assert.NoError(t, err) repoIDs, err := env.RepoIDs(1, 100) diff --git a/models/pull.go b/models/pull.go index 1f03dd9b0f5a9..7a168181e25b6 100644 --- a/models/pull.go +++ b/models/pull.go @@ -192,15 +192,19 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest { } } if baseBranch, err = pr.BaseRepo.GetBranch(pr.BaseBranch); err != nil { + log.Error("pr.BaseRepo.GetBranch[%d]: %v", pr.BaseBranch, err) return nil } if baseCommit, err = baseBranch.GetCommit(); err != nil { + log.Error("baseBranch.GetCommit[%d]: %v", pr.ID, err) return nil } if headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch); err != nil { + log.Error("pr.HeadRepo.GetBranch[%d]: %v", pr.HeadBranch, err) return nil } if headCommit, err = headBranch.GetCommit(); err != nil { + log.Error("headBranch.GetCommit[%d]: %v", pr.ID, err) return nil } apiBaseBranchInfo := &api.PRBranchInfo{ @@ -218,7 +222,10 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest { Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false), } - pr.Issue.loadRepo(e) + if err = pr.Issue.loadRepo(e); err != nil { + log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err) + return nil + } apiPullRequest := &api.PullRequest{ ID: pr.ID, @@ -420,7 +427,11 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle if err != nil { return err } - defer RemoveTemporaryPath(tmpBasePath) + defer func() { + if err := RemoveTemporaryPath(tmpBasePath); err != nil { + log.Error("Merge: RemoveTemporaryPath: %s", err) + } + }() headRepoPath := RepoPath(pr.HeadUserName, pr.HeadRepo.Name) @@ -1142,7 +1153,9 @@ func (pr *PullRequest) UpdatePatch() (err error) { return fmt.Errorf("AddRemote: %v", err) } defer func() { - headGitRepo.RemoveRemote(tmpRemote) + if err := headGitRepo.RemoveRemote(tmpRemote); err != nil { + log.Error("UpdatePatch: RemoveRemote: %s", err) + } }() pr.MergeBase, _, err = headGitRepo.GetMergeBase(tmpRemote, pr.BaseBranch, pr.HeadBranch) if err != nil { @@ -1180,7 +1193,11 @@ func (pr *PullRequest) PushToBaseRepo() (err error) { return fmt.Errorf("headGitRepo.AddRemote: %v", err) } // Make sure to remove the remote even if the push fails - defer headGitRepo.RemoveRemote(tmpRemoteName) + defer func() { + if err := headGitRepo.RemoveRemote(tmpRemoteName); err != nil { + log.Error("PushToBaseRepo: RemoveRemote: %s", err) + } + }() headFile := pr.GetGitRefName() diff --git a/models/pull_test.go b/models/pull_test.go index 1dad664077711..5a53474ac4fc7 100644 --- a/models/pull_test.go +++ b/models/pull_test.go @@ -94,7 +94,7 @@ func TestGetUnmergedPullRequest(t *testing.T) { assert.NoError(t, err) assert.Equal(t, int64(2), pr.ID) - pr, err = GetUnmergedPullRequest(1, 9223372036854775807, "branch1", "master") + _, err = GetUnmergedPullRequest(1, 9223372036854775807, "branch1", "master") assert.Error(t, err) assert.True(t, IsErrPullRequestNotExist(err)) } @@ -128,7 +128,7 @@ func TestGetPullRequestByIndex(t *testing.T) { assert.Equal(t, int64(1), pr.BaseRepoID) assert.Equal(t, int64(2), pr.Index) - pr, err = GetPullRequestByIndex(9223372036854775807, 9223372036854775807) + _, err = GetPullRequestByIndex(9223372036854775807, 9223372036854775807) assert.Error(t, err) assert.True(t, IsErrPullRequestNotExist(err)) } @@ -151,7 +151,7 @@ func TestGetPullRequestByIssueID(t *testing.T) { assert.NoError(t, err) assert.Equal(t, int64(2), pr.IssueID) - pr, err = GetPullRequestByIssueID(9223372036854775807) + _, err = GetPullRequestByIssueID(9223372036854775807) assert.Error(t, err) assert.True(t, IsErrPullRequestNotExist(err)) } diff --git a/models/release.go b/models/release.go index b7ec4461f274c..28a2891013582 100644 --- a/models/release.go +++ b/models/release.go @@ -50,12 +50,12 @@ func (r *Release) loadAttributes(e Engine) error { } } if r.Publisher == nil { - r.Publisher, err = GetUserByID(r.PublisherID) + r.Publisher, err = getUserByID(e, r.PublisherID) if err != nil { return err } } - return GetReleaseAttachments(r) + return getReleaseAttachments(e, r) } // LoadAttributes load repo and publisher attributes for a release @@ -316,6 +316,10 @@ func (s releaseMetaSearch) Less(i, j int) bool { // GetReleaseAttachments retrieves the attachments for releases func GetReleaseAttachments(rels ...*Release) (err error) { + return getReleaseAttachments(x, rels...) +} + +func getReleaseAttachments(e Engine, rels ...*Release) (err error) { if len(rels) == 0 { return } @@ -335,11 +339,10 @@ func GetReleaseAttachments(rels ...*Release) (err error) { sort.Sort(sortedRels) // Select attachments - err = x. + err = e. Asc("release_id"). In("release_id", sortedRels.ID). Find(&attachments, Attachment{}) - if err != nil { return err } @@ -354,7 +357,6 @@ func GetReleaseAttachments(rels ...*Release) (err error) { } return - } type releaseSorter struct { @@ -493,7 +495,7 @@ func SyncReleasesWithTags(repo *Repository, gitRepo *git.Repository) error { return fmt.Errorf("GetTagCommitID: %v", err) } if git.IsErrNotExist(err) || commitID != rel.Sha1 { - if err := pushUpdateDeleteTag(repo, gitRepo, rel.TagName); err != nil { + if err := pushUpdateDeleteTag(repo, rel.TagName); err != nil { return fmt.Errorf("pushUpdateDeleteTag: %v", err) } } else { diff --git a/models/repo.go b/models/repo.go index a855c84939cc4..a4a7521aa48f1 100644 --- a/models/repo.go +++ b/models/repo.go @@ -20,7 +20,6 @@ import ( "os" "path" "path/filepath" - "regexp" "sort" "strconv" "strings" @@ -744,10 +743,6 @@ func (repo *Repository) getUsersWithAccessMode(e Engine, mode AccessMode) (_ []* return users, nil } -var ( - descPattern = regexp.MustCompile(`https?://\S+`) -) - // DescriptionHTML does special handles to description and return HTML string. func (repo *Repository) DescriptionHTML() template.HTML { desc, err := markup.RenderDescriptionHTML([]byte(repo.Description), repo.HTMLURL(), repo.ComposeMetas()) @@ -1333,11 +1328,9 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err return fmt.Errorf("prepareWebhooks: %v", err) } go HookQueue.Add(repo.ID) - } else { + } else if err = repo.recalculateAccesses(e); err != nil { // Organization automatically called this in addRepository method. - if err = repo.recalculateAccesses(e); err != nil { - return fmt.Errorf("recalculateAccesses: %v", err) - } + return fmt.Errorf("recalculateAccesses: %v", err) } if setting.Service.AutoWatchNewRepos { @@ -1512,11 +1505,9 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error } else if err = t.addRepository(sess, repo); err != nil { return fmt.Errorf("add to owner team: %v", err) } - } else { + } else if err = repo.recalculateAccesses(sess); err != nil { // Organization called this in addRepository method. - if err = repo.recalculateAccesses(sess); err != nil { - return fmt.Errorf("recalculateAccesses: %v", err) - } + return fmt.Errorf("recalculateAccesses: %v", err) } // Update repository count. @@ -1864,7 +1855,10 @@ func DeleteRepository(doer *User, uid, repoID int64) error { repoPath := repo.repoPath(sess) removeAllWithNotice(sess, "Delete repository files", repoPath) - repo.deleteWiki(sess) + err = repo.deleteWiki(sess) + if err != nil { + return err + } // Remove attachment files. for i := range attachmentPaths { @@ -2522,7 +2516,7 @@ func (repo *Repository) GetUserFork(userID int64) (*Repository, error) { // CustomAvatarPath returns repository custom avatar file path. func (repo *Repository) CustomAvatarPath() string { // Avatar empty by default - if len(repo.Avatar) <= 0 { + if len(repo.Avatar) == 0 { return "" } return filepath.Join(setting.RepositoryAvatarUploadPath, repo.Avatar) @@ -2562,10 +2556,7 @@ func (repo *Repository) generateRandomAvatar(e Engine) error { // RemoveRandomAvatars removes the randomly generated avatars that were created for repositories func RemoveRandomAvatars() error { - var ( - err error - ) - err = x. + return x. Where("id > 0").BufferSize(setting.IterateBufferSize). Iterate(new(Repository), func(idx int, bean interface{}) error { @@ -2576,7 +2567,6 @@ func RemoveRandomAvatars() error { } return nil }) - return err } // RelAvatarLink returns a relative link to the repository's avatar. @@ -2587,7 +2577,7 @@ func (repo *Repository) RelAvatarLink() string { func (repo *Repository) relAvatarLink(e Engine) string { // If no avatar - path is empty avatarPath := repo.CustomAvatarPath() - if len(avatarPath) <= 0 || !com.IsFile(avatarPath) { + if len(avatarPath) == 0 || !com.IsFile(avatarPath) { switch mode := setting.RepositoryAvatarFallback; mode { case "image": return setting.RepositoryAvatarFallbackImage diff --git a/models/repo_activity.go b/models/repo_activity.go index fb1385a54b12e..04612ae1efca0 100644 --- a/models/repo_activity.go +++ b/models/repo_activity.go @@ -114,7 +114,7 @@ func GetActivityStatsTopAuthors(repo *Repository, timeFrom time.Time, count int) v = append(v, u) } - sort.Slice(v[:], func(i, j int) bool { + sort.Slice(v, func(i, j int) bool { return v[i].Commits < v[j].Commits }) diff --git a/models/repo_branch.go b/models/repo_branch.go index 08c881fc24c29..dee6ef3d7e267 100644 --- a/models/repo_branch.go +++ b/models/repo_branch.go @@ -75,7 +75,11 @@ func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName st if err != nil { return err } - defer RemoveTemporaryPath(basePath) + defer func() { + if err := RemoveTemporaryPath(basePath); err != nil { + log.Error("CreateNewBranch: RemoveTemporaryPath: %s", err) + } + }() if err := git.Clone(repo.RepoPath(), basePath, git.CloneRepoOptions{ Bare: true, @@ -117,7 +121,11 @@ func (repo *Repository) CreateNewBranchFromCommit(doer *User, commit, branchName if err != nil { return err } - defer RemoveTemporaryPath(basePath) + defer func() { + if err := RemoveTemporaryPath(basePath); err != nil { + log.Error("CreateNewBranchFromCommit: RemoveTemporaryPath: %s", err) + } + }() if err := git.Clone(repo.RepoPath(), basePath, git.CloneRepoOptions{ Bare: true, diff --git a/models/repo_collaboration.go b/models/repo_collaboration.go index 9d2935d581d83..0797f504305f7 100644 --- a/models/repo_collaboration.go +++ b/models/repo_collaboration.go @@ -142,7 +142,7 @@ func (repo *Repository) ChangeCollaborationAccessMode(uid int64, mode AccessMode } if _, err = sess. - Id(collaboration.ID). + ID(collaboration.ID). Cols("mode"). Update(collaboration); err != nil { return fmt.Errorf("update collaboration: %v", err) diff --git a/models/repo_list.go b/models/repo_list.go index 9686676eae2cc..5655404f7c71f 100644 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -148,19 +148,19 @@ func (s SearchOrderBy) String() string { // Strings for sorting result const ( SearchOrderByAlphabetically SearchOrderBy = "name ASC" - SearchOrderByAlphabeticallyReverse = "name DESC" - SearchOrderByLeastUpdated = "updated_unix ASC" - SearchOrderByRecentUpdated = "updated_unix DESC" - SearchOrderByOldest = "created_unix ASC" - SearchOrderByNewest = "created_unix DESC" - SearchOrderBySize = "size ASC" - SearchOrderBySizeReverse = "size DESC" - SearchOrderByID = "id ASC" - SearchOrderByIDReverse = "id DESC" - SearchOrderByStars = "num_stars ASC" - SearchOrderByStarsReverse = "num_stars DESC" - SearchOrderByForks = "num_forks ASC" - SearchOrderByForksReverse = "num_forks DESC" + SearchOrderByAlphabeticallyReverse SearchOrderBy = "name DESC" + SearchOrderByLeastUpdated SearchOrderBy = "updated_unix ASC" + SearchOrderByRecentUpdated SearchOrderBy = "updated_unix DESC" + SearchOrderByOldest SearchOrderBy = "created_unix ASC" + SearchOrderByNewest SearchOrderBy = "created_unix DESC" + SearchOrderBySize SearchOrderBy = "size ASC" + SearchOrderBySizeReverse SearchOrderBy = "size DESC" + SearchOrderByID SearchOrderBy = "id ASC" + SearchOrderByIDReverse SearchOrderBy = "id DESC" + SearchOrderByStars SearchOrderBy = "num_stars ASC" + SearchOrderByStarsReverse SearchOrderBy = "num_stars DESC" + SearchOrderByForks SearchOrderBy = "num_forks ASC" + SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" ) // SearchRepositoryByName takes keyword and part of repository name to search, diff --git a/models/repo_redirect.go b/models/repo_redirect.go index 813b3e6c9e554..8847a0889c424 100644 --- a/models/repo_redirect.go +++ b/models/repo_redirect.go @@ -4,7 +4,10 @@ package models -import "strings" +import ( + "code.gitea.io/gitea/modules/log" + "strings" +) // RepoRedirect represents that a repo name should be redirected to another type RepoRedirect struct { @@ -38,7 +41,10 @@ func NewRepoRedirect(ownerID, repoID int64, oldRepoName, newRepoName string) err } if err := deleteRepoRedirect(sess, ownerID, newRepoName); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("NewRepoRedirect sess.Rollback: %v", errRollback) + } return err } @@ -47,7 +53,10 @@ func NewRepoRedirect(ownerID, repoID int64, oldRepoName, newRepoName string) err LowerName: oldRepoName, RedirectRepoID: repoID, }); err != nil { - sess.Rollback() + errRollback := sess.Rollback() + if errRollback != nil { + log.Error("NewRepoRedirect sess.Rollback: %v", errRollback) + } return err } return sess.Commit() diff --git a/models/ssh_key.go b/models/ssh_key.go index fb5f9f399b757..1f2288b13ec42 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -142,7 +142,7 @@ func parseKeyString(content string) (string, error) { if continuationLine || strings.ContainsAny(line, ":-") { continuationLine = strings.HasSuffix(line, "\\") } else { - keyContent = keyContent + line + keyContent += line } } @@ -392,7 +392,7 @@ func addKey(e Engine, key *PublicKey) (err error) { } // AddPublicKey adds new public key to database and authorized_keys file. -func AddPublicKey(ownerID int64, name, content string, LoginSourceID int64) (*PublicKey, error) { +func AddPublicKey(ownerID int64, name, content string, loginSourceID int64) (*PublicKey, error) { log.Trace(content) fingerprint, err := calcFingerprint(content) @@ -427,7 +427,7 @@ func AddPublicKey(ownerID int64, name, content string, LoginSourceID int64) (*Pu Content: content, Mode: AccessModeWrite, Type: KeyTypeUser, - LoginSourceID: LoginSourceID, + LoginSourceID: loginSourceID, } if err = addKey(sess, key); err != nil { return nil, fmt.Errorf("addKey: %v", err) @@ -491,10 +491,10 @@ func ListPublicKeys(uid int64) ([]*PublicKey, error) { } // ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source. -func ListPublicLdapSSHKeys(uid int64, LoginSourceID int64) ([]*PublicKey, error) { +func ListPublicLdapSSHKeys(uid int64, loginSourceID int64) ([]*PublicKey, error) { keys := make([]*PublicKey, 0, 5) return keys, x. - Where("owner_id = ? AND login_source_id = ?", uid, LoginSourceID). + Where("owner_id = ? AND login_source_id = ?", uid, loginSourceID). Find(&keys) } diff --git a/models/status.go b/models/status.go index a3db47f45537b..384f5693dcf56 100644 --- a/models/status.go +++ b/models/status.go @@ -87,7 +87,7 @@ func (status *CommitStatus) loadRepo(e Engine) (err error) { // APIURL returns the absolute APIURL to this commit-status. func (status *CommitStatus) APIURL() string { - status.loadRepo(x) + _ = status.loadRepo(x) return fmt.Sprintf("%sapi/v1/%s/statuses/%s", setting.AppURL, status.Repo.FullName(), status.SHA) } @@ -95,7 +95,7 @@ func (status *CommitStatus) APIURL() string { // APIFormat assumes some fields assigned with values: // Required - Repo, Creator func (status *CommitStatus) APIFormat() *api.Status { - status.loadRepo(x) + _ = status.loadRepo(x) apiStatus := &api.Status{ Created: status.CreatedUnix.AsTime(), Updated: status.CreatedUnix.AsTime(), @@ -219,7 +219,9 @@ func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error { } has, err := sess.Desc("index").Limit(1).Get(lastCommitStatus) if err != nil { - sess.Rollback() + if err := sess.Rollback(); err != nil { + log.Error("newCommitStatus: sess.Rollback: %v", err) + } return fmt.Errorf("newCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err) } if has { @@ -231,7 +233,9 @@ func newCommitStatus(sess *xorm.Session, opts NewCommitStatusOptions) error { // Insert new CommitStatus if _, err = sess.Insert(opts.CommitStatus); err != nil { - sess.Rollback() + if err := sess.Rollback(); err != nil { + log.Error("newCommitStatus: sess.Rollback: %v", err) + } return fmt.Errorf("newCommitStatus[%s, %s]: %v", repoPath, opts.SHA, err) } diff --git a/models/token_test.go b/models/token_test.go index 9f2699a16862f..a74de8f81823f 100644 --- a/models/token_test.go +++ b/models/token_test.go @@ -36,11 +36,11 @@ func TestGetAccessTokenBySHA(t *testing.T) { assert.Equal(t, "2b3668e11cb82d3af8c6e4524fc7841297668f5008d1626f0ad3417e9fa39af84c268248b78c481daa7e5dc437784003494f", token.TokenHash) assert.Equal(t, "e4efbf36", token.TokenLastEight) - token, err = GetAccessTokenBySHA("notahash") + _, err = GetAccessTokenBySHA("notahash") assert.Error(t, err) assert.True(t, IsErrAccessTokenNotExist(err)) - token, err = GetAccessTokenBySHA("") + _, err = GetAccessTokenBySHA("") assert.Error(t, err) assert.True(t, IsErrAccessTokenEmpty(err)) } diff --git a/models/update.go b/models/update.go index 0883cb0e0116f..3eb0990d3dea9 100644 --- a/models/update.go +++ b/models/update.go @@ -84,7 +84,7 @@ func PushUpdate(branch string, opt PushUpdateOptions) error { return nil } -func pushUpdateDeleteTag(repo *Repository, gitRepo *git.Repository, tagName string) error { +func pushUpdateDeleteTag(repo *Repository, tagName string) error { rel, err := GetRelease(repo.ID, tagName) if err != nil { if IsErrReleaseNotExist(err) { @@ -223,7 +223,7 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) { // If is tag reference tagName := opts.RefFullName[len(git.TagPrefix):] if isDelRef { - err = pushUpdateDeleteTag(repo, gitRepo, tagName) + err = pushUpdateDeleteTag(repo, tagName) if err != nil { return nil, fmt.Errorf("pushUpdateDeleteTag: %v", err) } diff --git a/models/user.go b/models/user.go index e29cf5b32a6c2..2820d2edbc0c6 100644 --- a/models/user.go +++ b/models/user.go @@ -1072,7 +1072,10 @@ func deleteUser(e *xorm.Session, u *User) error { if _, err = e.Delete(&PublicKey{OwnerID: u.ID}); err != nil { return fmt.Errorf("deletePublicKeys: %v", err) } - rewriteAllPublicKeys(e) + err = rewriteAllPublicKeys(e) + if err != nil { + return err + } // ***** END: PublicKey ***** // ***** START: GPGPublicKey ***** @@ -1401,8 +1404,7 @@ func (opts *SearchUserOptions) toConds() builder.Cond { } else { exprCond = builder.Expr("org_user.org_id = \"user\".id") } - var accessCond = builder.NewCond() - accessCond = builder.Or( + accessCond := builder.Or( builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.OwnerID}, builder.Eq{"visibility": structs.VisibleTypePrivate}))), builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited)) cond = cond.And(accessCond) @@ -1512,9 +1514,9 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) { } // addLdapSSHPublicKeys add a users public keys. Returns true if there are changes. -func addLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool { +func addLdapSSHPublicKeys(usr *User, s *LoginSource, sshPublicKeys []string) bool { var sshKeysNeedUpdate bool - for _, sshKey := range SSHPublicKeys { + for _, sshKey := range sshPublicKeys { _, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sshKey)) if err == nil { sshKeyName := fmt.Sprintf("%s-%s", s.Name, sshKey[0:40]) @@ -1536,7 +1538,7 @@ func addLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) boo } // synchronizeLdapSSHPublicKeys updates a users public keys. Returns true if there are changes. -func synchronizeLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []string) bool { +func synchronizeLdapSSHPublicKeys(usr *User, s *LoginSource, sshPublicKeys []string) bool { var sshKeysNeedUpdate bool log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name) @@ -1554,7 +1556,7 @@ func synchronizeLdapSSHPublicKeys(usr *User, s *LoginSource, SSHPublicKeys []str // Get Public Keys from LDAP and skip duplicate keys var ldapKeys []string - for _, v := range SSHPublicKeys { + for _, v := range sshPublicKeys { sshKeySplit := strings.Split(v, " ") if len(sshKeySplit) > 1 { ldapKey := strings.Join(sshKeySplit[:2], " ") @@ -1634,9 +1636,13 @@ func SyncExternalUsers() { // Find all users with this login type var users []*User - x.Where("login_type = ?", LoginLDAP). + err = x.Where("login_type = ?", LoginLDAP). And("login_source = ?", s.ID). Find(&users) + if err != nil { + log.Error("SyncExternalUsers: %v", err) + return + } sr := s.LDAP().SearchEntries() for _, su := range sr { @@ -1694,7 +1700,7 @@ func SyncExternalUsers() { // Check if user data has changed if (len(s.LDAP().AdminFilter) > 0 && usr.IsAdmin != su.IsAdmin) || - strings.ToLower(usr.Email) != strings.ToLower(su.Mail) || + !strings.EqualFold(usr.Email, su.Mail) || usr.FullName != fullName || !usr.IsActive { @@ -1718,7 +1724,10 @@ func SyncExternalUsers() { // Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed if sshKeysNeedUpdate { - RewriteAllPublicKeys() + err = RewriteAllPublicKeys() + if err != nil { + log.Error("RewriteAllPublicKeys: %v", err) + } } // Deactivate users not present in LDAP diff --git a/models/user_mail.go b/models/user_mail.go index 39d1070c35e9c..d929ba5a5d892 100644 --- a/models/user_mail.go +++ b/models/user_mail.go @@ -134,7 +134,7 @@ func (email *EmailAddress) Activate() error { email.IsActivated = true if _, err := sess. - Id(email.ID). + ID(email.ID). Cols("is_activated"). Update(email); err != nil { return err diff --git a/models/user_openid_test.go b/models/user_openid_test.go index 711f92b9ffe65..18f84bef760b2 100644 --- a/models/user_openid_test.go +++ b/models/user_openid_test.go @@ -31,12 +31,12 @@ func TestGetUserOpenIDs(t *testing.T) { func TestGetUserByOpenID(t *testing.T) { assert.NoError(t, PrepareTestDatabase()) - user, err := GetUserByOpenID("https://unknown") + _, err := GetUserByOpenID("https://unknown") if assert.Error(t, err) { assert.True(t, IsErrUserNotExist(err)) } - user, err = GetUserByOpenID("https://user1.domain1.tld") + user, err := GetUserByOpenID("https://user1.domain1.tld") if assert.NoError(t, err) { assert.Equal(t, user.ID, int64(1)) } diff --git a/models/webhook.go b/models/webhook.go index 7a28e37958b96..e3e11e59633f4 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -700,7 +700,10 @@ func prepareWebhook(e Engine, w *Webhook, repo *Repository, event HookEventType, log.Error("prepareWebhooks.JSONPayload: %v", err) } sig := hmac.New(sha256.New, []byte(w.Secret)) - sig.Write(data) + _, err = sig.Write(data) + if err != nil { + log.Error("prepareWebhooks.sigWrite: %v", err) + } signature = hex.EncodeToString(sig.Sum(nil)) } @@ -930,8 +933,7 @@ func InitDeliverHooks() { return nil, err } - conn.SetDeadline(time.Now().Add(timeout)) - return conn, nil + return conn, conn.SetDeadline(time.Now().Add(timeout)) }, }, diff --git a/models/webhook_discord.go b/models/webhook_discord.go index 0029e94fca421..d7a2de0d1168e 100644 --- a/models/webhook_discord.go +++ b/models/webhook_discord.go @@ -490,7 +490,7 @@ func getDiscordReleasePayload(p *api.ReleasePayload, meta *DiscordMeta) (*Discor Embeds: []DiscordEmbed{ { Title: title, - Description: fmt.Sprintf("%s", p.Release.Note), + Description: p.Release.Note, URL: url, Color: color, Author: DiscordEmbedAuthor{ diff --git a/models/wiki.go b/models/wiki.go index bcf97c076573b..9ae3386333298 100644 --- a/models/wiki.go +++ b/models/wiki.go @@ -115,7 +115,11 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con if err != nil { return err } - defer RemoveTemporaryPath(basePath) + defer func() { + if err := RemoveTemporaryPath(basePath); err != nil { + log.Error("Merge: RemoveTemporaryPath: %s", err) + } + }() cloneOpts := git.CloneRepoOptions{ Bare: true, @@ -246,7 +250,11 @@ func (repo *Repository) DeleteWikiPage(doer *User, wikiName string) (err error) if err != nil { return err } - defer RemoveTemporaryPath(basePath) + defer func() { + if err := RemoveTemporaryPath(basePath); err != nil { + log.Error("Merge: RemoveTemporaryPath: %s", err) + } + }() if err := git.Clone(repo.WikiPath(), basePath, git.CloneRepoOptions{ Bare: true, diff --git a/modules/auth/auth.go b/modules/auth/auth.go index edb596c240496..2a2ee404928cb 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -214,10 +214,8 @@ func SignedInUser(ctx *macaron.Context, sess session.Store) (*models.User, bool) if err = models.UpdateAccessToken(token); err != nil { log.Error("UpdateAccessToken: %v", err) } - } else { - if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) { - log.Error("GetAccessTokenBySha: %v", err) - } + } else if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) { + log.Error("GetAccessTokenBySha: %v", err) } if u == nil { @@ -301,12 +299,6 @@ func GetInclude(field reflect.StructField) string { return getRuleBody(field, "Include(") } -// FIXME: struct contains a struct -func validateStruct(obj interface{}) binding.Errors { - - return nil -} - func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors { if errs.Len() == 0 { return errs diff --git a/modules/auth/oauth2/oauth2.go b/modules/auth/oauth2/oauth2.go index 5684f44a89b8f..a2d7116211cf7 100644 --- a/modules/auth/oauth2/oauth2.go +++ b/modules/auth/oauth2/oauth2.go @@ -220,8 +220,7 @@ func GetDefaultProfileURL(provider string) string { // GetDefaultEmailURL return the default email url for the given provider func GetDefaultEmailURL(provider string) string { - switch provider { - case "github": + if provider == "github" { return github.EmailURL } return "" diff --git a/modules/auth/openid/discovery_cache_test.go b/modules/auth/openid/discovery_cache_test.go index 2e37058cc3f5f..931e5c7945e33 100644 --- a/modules/auth/openid/discovery_cache_test.go +++ b/modules/auth/openid/discovery_cache_test.go @@ -39,7 +39,7 @@ func TestTimedDiscoveryCache(t *testing.T) { t.Errorf("Expected nil, got %v", di) } - // Sleep one second and try retrive again + // Sleep one second and try retrieve again time.Sleep(1 * time.Second) if di := dc.Get("foo"); di != nil { diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 8b9e5877d9565..0c8bd30abc8d3 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -253,7 +253,7 @@ func (f UpdateThemeForm) IsThemeExists() bool { var exists bool for _, v := range setting.UI.Themes { - if strings.ToLower(v) == strings.ToLower(f.Theme) { + if strings.EqualFold(v, f.Theme) { exists = true break } diff --git a/modules/base/tool.go b/modules/base/tool.go index dcf9155a07750..4893abff71ddf 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -44,21 +44,21 @@ var UTF8BOM = []byte{'\xef', '\xbb', '\xbf'} // EncodeMD5 encodes string to md5 hex value. func EncodeMD5(str string) string { m := md5.New() - m.Write([]byte(str)) + _, _ = m.Write([]byte(str)) return hex.EncodeToString(m.Sum(nil)) } // EncodeSha1 string to sha1 hex value. func EncodeSha1(str string) string { h := sha1.New() - h.Write([]byte(str)) + _, _ = h.Write([]byte(str)) return hex.EncodeToString(h.Sum(nil)) } // EncodeSha256 string to sha1 hex value. func EncodeSha256(str string) string { h := sha256.New() - h.Write([]byte(str)) + _, _ = h.Write([]byte(str)) return hex.EncodeToString(h.Sum(nil)) } @@ -193,7 +193,7 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string // create sha1 encode string sh := sha1.New() - sh.Write([]byte(data + setting.SecretKey + startStr + endStr + com.ToStr(minutes))) + _, _ = sh.Write([]byte(data + setting.SecretKey + startStr + endStr + com.ToStr(minutes))) encoded := hex.EncodeToString(sh.Sum(nil)) code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded) @@ -425,16 +425,6 @@ const ( EByte = PByte * 1024 ) -var bytesSizeTable = map[string]uint64{ - "b": Byte, - "kb": KByte, - "mb": MByte, - "gb": GByte, - "tb": TByte, - "pb": PByte, - "eb": EByte, -} - func logn(n, b float64) float64 { return math.Log(n) / math.Log(b) } @@ -582,27 +572,27 @@ func IsTextFile(data []byte) bool { if len(data) == 0 { return true } - return strings.Index(http.DetectContentType(data), "text/") != -1 + return strings.Contains(http.DetectContentType(data), "text/") } // IsImageFile detects if data is an image format func IsImageFile(data []byte) bool { - return strings.Index(http.DetectContentType(data), "image/") != -1 + return strings.Contains(http.DetectContentType(data), "image/") } // IsPDFFile detects if data is a pdf format func IsPDFFile(data []byte) bool { - return strings.Index(http.DetectContentType(data), "application/pdf") != -1 + return strings.Contains(http.DetectContentType(data), "application/pdf") } // IsVideoFile detects if data is an video format func IsVideoFile(data []byte) bool { - return strings.Index(http.DetectContentType(data), "video/") != -1 + return strings.Contains(http.DetectContentType(data), "video/") } // IsAudioFile detects if data is an video format func IsAudioFile(data []byte) bool { - return strings.Index(http.DetectContentType(data), "audio/") != -1 + return strings.Contains(http.DetectContentType(data), "audio/") } // EntryIcon returns the octicon class for displaying files/directories diff --git a/modules/base/tool_test.go b/modules/base/tool_test.go index ec9bc1eb52335..fa61e5dfb16d4 100644 --- a/modules/base/tool_test.go +++ b/modules/base/tool_test.go @@ -287,20 +287,19 @@ func TestHtmlTimeSince(t *testing.T) { } func TestFileSize(t *testing.T) { - var size int64 - size = 512 + var size int64 = 512 assert.Equal(t, "512B", FileSize(size)) - size = size * 1024 + size *= 1024 assert.Equal(t, "512KB", FileSize(size)) - size = size * 1024 + size *= 1024 assert.Equal(t, "512MB", FileSize(size)) - size = size * 1024 + size *= 1024 assert.Equal(t, "512GB", FileSize(size)) - size = size * 1024 + size *= 1024 assert.Equal(t, "512TB", FileSize(size)) - size = size * 1024 + size *= 1024 assert.Equal(t, "512PB", FileSize(size)) - size = size * 4 + size *= 4 assert.Equal(t, "2.0EB", FileSize(size)) } diff --git a/modules/cache/cache.go b/modules/cache/cache.go index a2d6c724c851a..a7412f109f108 100644 --- a/modules/cache/cache.go +++ b/modules/cache/cache.go @@ -43,7 +43,10 @@ func GetInt(key string, getFunc func() (int, error)) (int, error) { if value, err = getFunc(); err != nil { return value, err } - conn.Put(key, value, int64(setting.CacheService.TTL.Seconds())) + err = conn.Put(key, value, int64(setting.CacheService.TTL.Seconds())) + if err != nil { + return 0, err + } } switch value := conn.Get(key).(type) { case int: @@ -72,7 +75,10 @@ func GetInt64(key string, getFunc func() (int64, error)) (int64, error) { if value, err = getFunc(); err != nil { return value, err } - conn.Put(key, value, int64(setting.CacheService.TTL.Seconds())) + err = conn.Put(key, value, int64(setting.CacheService.TTL.Seconds())) + if err != nil { + return 0, err + } } switch value := conn.Get(key).(type) { case int64: @@ -93,5 +99,5 @@ func Remove(key string) { if conn == nil { return } - conn.Delete(key) + _ = conn.Delete(key) } diff --git a/modules/context/context.go b/modules/context/context.go index 1699d7aeccb7d..b7c77ac4605ee 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -130,7 +130,6 @@ func (ctx *Context) RedirectToFirst(location ...string) { } ctx.Redirect(setting.AppSubURL + "/") - return } // HTML calls Context.HTML and converts template name to string. @@ -266,7 +265,7 @@ func Contexter() macaron.Handler { } c.Header().Set("Content-Type", "text/html") c.WriteHeader(http.StatusOK) - c.Write([]byte(com.Expand(` + _, _ = c.Write([]byte(com.Expand(` diff --git a/modules/context/pagination.go b/modules/context/pagination.go index 4795f650fb850..390b4dbdd7073 100644 --- a/modules/context/pagination.go +++ b/modules/context/pagination.go @@ -39,7 +39,7 @@ func (p *Pagination) AddParam(ctx *Context, paramKey string, ctxKey string) { // GetParams returns the configured URL params func (p *Pagination) GetParams() template.URL { - return template.URL(strings.Join(p.urlParams[:], "&")) + return template.URL(strings.Join(p.urlParams, "&")) } // SetDefaultParams sets common pagination params that are often used diff --git a/modules/context/repo.go b/modules/context/repo.go index 0908340879cb0..096f3c0a5d216 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -455,15 +455,13 @@ func RepoAssignment() macaron.Handler { ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo ctx.Repo.PullRequest.Allowed = true ctx.Repo.PullRequest.HeadInfo = ctx.Repo.Owner.Name + ":" + ctx.Repo.BranchName - } else { + } else if repo.AllowsPulls() { // Or, this is repository accepts pull requests between branches. - if repo.AllowsPulls() { - ctx.Data["BaseRepo"] = repo - ctx.Repo.PullRequest.BaseRepo = repo - ctx.Repo.PullRequest.Allowed = true - ctx.Repo.PullRequest.SameRepo = true - ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName - } + ctx.Data["BaseRepo"] = repo + ctx.Repo.PullRequest.BaseRepo = repo + ctx.Repo.PullRequest.Allowed = true + ctx.Repo.PullRequest.SameRepo = true + ctx.Repo.PullRequest.HeadInfo = ctx.Repo.BranchName } } ctx.Data["PullRequestCtx"] = ctx.Repo.PullRequest diff --git a/modules/git/blob.go b/modules/git/blob.go index 171b4a1010d85..73ac89dfdf98e 100644 --- a/modules/git/blob.go +++ b/modules/git/blob.go @@ -50,12 +50,12 @@ func (b *Blob) GetBlobContentBase64() (string, error) { go func() { _, err := io.Copy(encoder, dataRc) - encoder.Close() + _ = encoder.Close() if err != nil { - pw.CloseWithError(err) + _ = pw.CloseWithError(err) } else { - pw.Close() + _ = pw.Close() } }() diff --git a/modules/git/commit.go b/modules/git/commit.go index 7b64a300ab1be..c86ece984883b 100644 --- a/modules/git/commit.go +++ b/modules/git/commit.go @@ -133,7 +133,7 @@ func (c *Commit) ParentCount() int { func isImageFile(data []byte) (string, bool) { contentType := http.DetectContentType(data) - if strings.Index(contentType, "image/") != -1 { + if strings.Contains(contentType, "image/") { return contentType, true } return contentType, false @@ -206,8 +206,7 @@ func CommitChanges(repoPath string, opts CommitChangesOptions) error { } func commitsCount(repoPath, revision, relpath string) (int64, error) { - var cmd *Command - cmd = NewCommand("rev-list", "--count") + cmd := NewCommand("rev-list", "--count") cmd.AddArguments(revision) if len(relpath) > 0 { cmd.AddArguments("--", relpath) @@ -263,7 +262,7 @@ type SearchCommitsOptions struct { All bool } -// NewSearchCommitsOptions contruct a SearchCommitsOption from a space-delimited search string +// NewSearchCommitsOptions construct a SearchCommitsOption from a space-delimited search string func NewSearchCommitsOptions(searchString string, forAllRefs bool) SearchCommitsOptions { var keywords, authors, committers []string var after, before string diff --git a/modules/git/commit_info.go b/modules/git/commit_info.go index da430a21cddbc..43723d169b7a5 100644 --- a/modules/git/commit_info.go +++ b/modules/git/commit_info.go @@ -87,16 +87,6 @@ func getCommitTree(c *object.Commit, treePath string) (*object.Tree, error) { return tree, nil } -func getFullPath(treePath, path string) string { - if treePath != "" { - if path != "" { - return treePath + "/" + path - } - return treePath - } - return path -} - func getFileHashes(c *object.Commit, treePath string, paths []string) (map[string]plumbing.Hash, error) { tree, err := getCommitTree(c, treePath) if err == object.ErrDirectoryNotFound { diff --git a/modules/git/repo.go b/modules/git/repo.go index 4be3164130795..f5d7ee63bb256 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -58,21 +58,21 @@ func (repo *Repository) parsePrettyFormatLogToList(logs []byte) (*list.List, err // IsRepoURLAccessible checks if given repository URL is accessible. func IsRepoURLAccessible(url string) bool { _, err := NewCommand("ls-remote", "-q", "-h", url, "HEAD").Run() - if err != nil { - return false - } - return true + return err == nil } // InitRepository initializes a new Git repository. func InitRepository(repoPath string, bare bool) error { - os.MkdirAll(repoPath, os.ModePerm) + err := os.MkdirAll(repoPath, os.ModePerm) + if err != nil { + return err + } cmd := NewCommand("init") if bare { cmd.AddArguments("--bare") } - _, err := cmd.RunInDir(repoPath) + _, err = cmd.RunInDir(repoPath) return err } diff --git a/modules/git/repo_branch.go b/modules/git/repo_branch.go index 116bdbee823c7..05eba1e30ed66 100644 --- a/modules/git/repo_branch.go +++ b/modules/git/repo_branch.go @@ -29,10 +29,7 @@ func IsBranchExist(repoPath, name string) bool { // IsBranchExist returns true if given branch exists in current repository. func (repo *Repository) IsBranchExist(name string) bool { _, err := repo.gogitRepo.Reference(plumbing.ReferenceName(BranchPrefix+name), true) - if err != nil { - return false - } - return true + return err == nil } // Branch represents a Git branch. @@ -77,7 +74,7 @@ func (repo *Repository) GetBranches() ([]string, error) { return nil, err } - branches.ForEach(func(branch *plumbing.Reference) error { + _ = branches.ForEach(func(branch *plumbing.Reference) error { branchNames = append(branchNames, strings.TrimPrefix(branch.Name().String(), BranchPrefix)) return nil }) diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 501ea88e4000b..8ea2a331458b4 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -31,10 +31,7 @@ func (repo *Repository) GetRefCommitID(name string) (string, error) { func (repo *Repository) IsCommitExist(name string) bool { hash := plumbing.NewHash(name) _, err := repo.gogitRepo.CommitObject(hash) - if err != nil { - return false - } - return true + return err == nil } // GetBranchCommitID returns last commit ID string of given branch. diff --git a/modules/git/repo_compare.go b/modules/git/repo_compare.go index 42f0b9ad0cd76..ddc81097208b6 100644 --- a/modules/git/repo_compare.go +++ b/modules/git/repo_compare.go @@ -13,6 +13,8 @@ import ( "strconv" "strings" "time" + + logger "code.gitea.io/gitea/modules/log" ) // CompareInfo represents needed information for comparing references. @@ -55,7 +57,11 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string) if err = repo.AddRemote(tmpRemote, basePath, true); err != nil { return nil, fmt.Errorf("AddRemote: %v", err) } - defer repo.RemoveRemote(tmpRemote) + defer func() { + if err := repo.RemoveRemote(tmpRemote); err != nil { + logger.Error("GetPullRequestInfo: RemoveRemote: %v", err) + } + }() } compareInfo := new(CompareInfo) diff --git a/modules/git/repo_tag.go b/modules/git/repo_tag.go index 08d66262c17d1..df49e9acd6dd5 100644 --- a/modules/git/repo_tag.go +++ b/modules/git/repo_tag.go @@ -24,10 +24,7 @@ func IsTagExist(repoPath, name string) bool { // IsTagExist returns true if given tag exists in the repository. func (repo *Repository) IsTagExist(name string) bool { _, err := repo.gogitRepo.Reference(plumbing.ReferenceName(TagPrefix+name), true) - if err != nil { - return false - } - return true + return err == nil } // CreateTag create one tag in the repository @@ -221,7 +218,7 @@ func (repo *Repository) GetTags() ([]string, error) { return nil, err } - tags.ForEach(func(tag *plumbing.Reference) error { + _ = tags.ForEach(func(tag *plumbing.Reference) error { tagNames = append(tagNames, strings.TrimPrefix(tag.Name().String(), TagPrefix)) return nil }) diff --git a/modules/git/utils.go b/modules/git/utils.go index 8f010321cf836..83cd21f34e77c 100644 --- a/modules/git/utils.go +++ b/modules/git/utils.go @@ -7,7 +7,6 @@ package git import ( "fmt" "os" - "path/filepath" "strings" "sync" ) @@ -75,13 +74,6 @@ func concatenateError(err error, stderr string) error { return fmt.Errorf("%v - %s", err, stderr) } -// If the object is stored in its own file (i.e not in a pack file), -// this function returns the full path to the object file. -// It does not test if the file exists. -func filepathFromSHA1(rootdir, sha1 string) string { - return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:]) -} - // RefEndName return the end name of a ref name func RefEndName(refStr string) string { if strings.HasPrefix(refStr, BranchPrefix) { diff --git a/modules/gzip/gzip.go b/modules/gzip/gzip.go index 4a4a797c7aac0..0d1007183027d 100644 --- a/modules/gzip/gzip.go +++ b/modules/gzip/gzip.go @@ -74,7 +74,6 @@ func (wp *WriterPool) Put(w *gzip.Writer) { } var writerPool WriterPool -var regex regexp.Regexp // Options represents the configuration for the gzip middleware type Options struct { @@ -116,7 +115,7 @@ func Middleware(options ...Options) macaron.Handler { if rangeHdr := ctx.Req.Header.Get(rangeHeader); rangeHdr != "" { match := regex.FindStringSubmatch(rangeHdr) - if match != nil && len(match) > 1 { + if len(match) > 1 { return } } @@ -270,9 +269,8 @@ func (proxy *ProxyResponseWriter) Close() error { if proxy.writer == nil { err := proxy.startPlain() - if err != nil { - err = fmt.Errorf("GzipMiddleware: write to regular responseWriter at close gets error: %q", err.Error()) + return fmt.Errorf("GzipMiddleware: write to regular responseWriter at close gets error: %q", err.Error()) } } diff --git a/modules/httplib/httplib.go b/modules/httplib/httplib.go index c96e04c35fee2..90bbe8f12af2b 100644 --- a/modules/httplib/httplib.go +++ b/modules/httplib/httplib.go @@ -263,7 +263,7 @@ func (r *Request) getResponse() (*http.Response, error) { } if r.req.Method == "GET" && len(paramBody) > 0 { - if strings.Index(r.url, "?") != -1 { + if strings.Contains(r.url, "?") { r.url += "&" + paramBody } else { r.url = r.url + "?" + paramBody @@ -290,10 +290,13 @@ func (r *Request) getResponse() (*http.Response, error) { } } for k, v := range r.params { - bodyWriter.WriteField(k, v) + err := bodyWriter.WriteField(k, v) + if err != nil { + log.Fatal(err) + } } - bodyWriter.Close() - pw.Close() + _ = bodyWriter.Close() + _ = pw.Close() }() r.Header("Content-Type", bodyWriter.FormDataContentType()) r.req.Body = ioutil.NopCloser(pr) @@ -323,18 +326,15 @@ func (r *Request) getResponse() (*http.Response, error) { Proxy: proxy, Dial: TimeoutDialer(r.setting.ConnectTimeout, r.setting.ReadWriteTimeout), } - } else { - // if r.transport is *http.Transport then set the settings. - if t, ok := trans.(*http.Transport); ok { - if t.TLSClientConfig == nil { - t.TLSClientConfig = r.setting.TLSClientConfig - } - if t.Proxy == nil { - t.Proxy = r.setting.Proxy - } - if t.Dial == nil { - t.Dial = TimeoutDialer(r.setting.ConnectTimeout, r.setting.ReadWriteTimeout) - } + } else if t, ok := trans.(*http.Transport); ok { + if t.TLSClientConfig == nil { + t.TLSClientConfig = r.setting.TLSClientConfig + } + if t.Proxy == nil { + t.Proxy = r.setting.Proxy + } + if t.Dial == nil { + t.Dial = TimeoutDialer(r.setting.ConnectTimeout, r.setting.ReadWriteTimeout) } } @@ -461,7 +461,6 @@ func TimeoutDialer(cTimeout time.Duration, rwTimeout time.Duration) func(net, ad if err != nil { return nil, err } - conn.SetDeadline(time.Now().Add(rwTimeout)) - return conn, nil + return conn, conn.SetDeadline(time.Now().Add(rwTimeout)) } } diff --git a/modules/indexer/indexer.go b/modules/indexer/indexer.go index 9e12a7f5013b1..29261c693b592 100644 --- a/modules/indexer/indexer.go +++ b/modules/indexer/indexer.go @@ -5,7 +5,6 @@ package indexer import ( - "fmt" "os" "strconv" @@ -24,15 +23,6 @@ func indexerID(id int64) string { return strconv.FormatInt(id, 36) } -// idOfIndexerID the integer id associated with an indexer id -func idOfIndexerID(indexerID string) (int64, error) { - id, err := strconv.ParseInt(indexerID, 36, 64) - if err != nil { - return 0, fmt.Errorf("Unexpected indexer ID %s: %v", indexerID, err) - } - return id, nil -} - // numericEqualityQuery a numeric equality query for the given value and field func numericEqualityQuery(value int64, field string) *query.NumericRangeQuery { f := float64(value) @@ -42,13 +32,6 @@ func numericEqualityQuery(value int64, field string) *query.NumericRangeQuery { return q } -func newMatchPhraseQuery(matchPhrase, field, analyzer string) *query.MatchPhraseQuery { - q := bleve.NewMatchPhraseQuery(matchPhrase) - q.FieldVal = field - q.Analyzer = analyzer - return q -} - const unicodeNormalizeName = "unicodeNormalize" func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error { diff --git a/modules/indexer/issues/indexer.go b/modules/indexer/issues/indexer.go index 75e6893b87d52..df8bfd6305912 100644 --- a/modules/indexer/issues/indexer.go +++ b/modules/indexer/issues/indexer.go @@ -101,7 +101,12 @@ func InitIssueIndexer(syncReindex bool) error { return fmt.Errorf("Unsupported indexer queue type: %v", setting.Indexer.IssueQueueType) } - go issueIndexerQueue.Run() + go func() { + err = issueIndexerQueue.Run() + if err != nil { + log.Error("issueIndexerQueue.Run: %v", err) + } + }() if populate { if syncReindex { @@ -161,7 +166,7 @@ func UpdateIssueIndexer(issue *models.Issue) { comments = append(comments, comment.Content) } } - issueIndexerQueue.Push(&IndexerData{ + _ = issueIndexerQueue.Push(&IndexerData{ ID: issue.ID, RepoID: issue.RepoID, Title: issue.Title, @@ -179,11 +184,11 @@ func DeleteRepoIssueIndexer(repo *models.Repository) { return } - if len(ids) <= 0 { + if len(ids) == 0 { return } - issueIndexerQueue.Push(&IndexerData{ + _ = issueIndexerQueue.Push(&IndexerData{ IDs: ids, IsDelete: true, }) diff --git a/modules/indexer/issues/queue_channel.go b/modules/indexer/issues/queue_channel.go index bd92f6b7b114c..b6458d3eb53db 100644 --- a/modules/indexer/issues/queue_channel.go +++ b/modules/indexer/issues/queue_channel.go @@ -34,20 +34,20 @@ func (c *ChannelQueue) Run() error { select { case data := <-c.queue: if data.IsDelete { - c.indexer.Delete(data.IDs...) + _ = c.indexer.Delete(data.IDs...) continue } datas = append(datas, data) if len(datas) >= c.batchNumber { - c.indexer.Index(datas) + _ = c.indexer.Index(datas) // TODO: save the point datas = make([]*IndexerData, 0, c.batchNumber) } case <-time.After(time.Millisecond * 100): i++ if i >= 3 && len(datas) > 0 { - c.indexer.Index(datas) + _ = c.indexer.Index(datas) // TODO: save the point datas = make([]*IndexerData, 0, c.batchNumber) } diff --git a/modules/indexer/issues/queue_disk.go b/modules/indexer/issues/queue_disk.go index cf9e6aee225a6..e5ac2a79812ae 100644 --- a/modules/indexer/issues/queue_disk.go +++ b/modules/indexer/issues/queue_disk.go @@ -44,7 +44,7 @@ func (l *LevelQueue) Run() error { for { i++ if len(datas) > l.batchNumber || (len(datas) > 0 && i > 3) { - l.indexer.Index(datas) + _ = l.indexer.Index(datas) datas = make([]*IndexerData, 0, l.batchNumber) i = 0 continue @@ -59,7 +59,7 @@ func (l *LevelQueue) Run() error { continue } - if len(bs) <= 0 { + if len(bs) == 0 { time.Sleep(time.Millisecond * 100) continue } diff --git a/modules/indexer/issues/queue_redis.go b/modules/indexer/issues/queue_redis.go index a9434c4f92610..aeccd7920ce8f 100644 --- a/modules/indexer/issues/queue_redis.go +++ b/modules/indexer/issues/queue_redis.go @@ -96,12 +96,12 @@ func (r *RedisQueue) Run() error { i++ if len(datas) > r.batchNumber || (len(datas) > 0 && i > 3) { - r.indexer.Index(datas) + _ = r.indexer.Index(datas) datas = make([]*IndexerData, 0, r.batchNumber) i = 0 } - if len(bs) <= 0 { + if len(bs) == 0 { time.Sleep(time.Millisecond * 100) continue } diff --git a/modules/lfs/locks.go b/modules/lfs/locks.go index b1ca2f094a25f..4516ba01aee53 100644 --- a/modules/lfs/locks.go +++ b/modules/lfs/locks.go @@ -17,7 +17,7 @@ import ( ) //checkIsValidRequest check if it a valid request in case of bad request it write the response to ctx. -func checkIsValidRequest(ctx *context.Context, post bool) bool { +func checkIsValidRequest(ctx *context.Context) bool { if !setting.LFS.StartServer { writeStatus(ctx, 404) return false @@ -35,13 +35,6 @@ func checkIsValidRequest(ctx *context.Context, post bool) bool { } ctx.User = user } - if post { - mediaParts := strings.Split(ctx.Req.Header.Get("Content-Type"), ";") - if mediaParts[0] != metaMediaType { - writeStatus(ctx, 400) - return false - } - } return true } @@ -71,7 +64,7 @@ func handleLockListOut(ctx *context.Context, repo *models.Repository, lock *mode // GetListLockHandler list locks func GetListLockHandler(ctx *context.Context) { - if !checkIsValidRequest(ctx, false) { + if !checkIsValidRequest(ctx) { return } ctx.Resp.Header().Set("Content-Type", metaMediaType) @@ -135,7 +128,7 @@ func GetListLockHandler(ctx *context.Context) { // PostLockHandler create lock func PostLockHandler(ctx *context.Context) { - if !checkIsValidRequest(ctx, false) { + if !checkIsValidRequest(ctx) { return } ctx.Resp.Header().Set("Content-Type", metaMediaType) @@ -198,7 +191,7 @@ func PostLockHandler(ctx *context.Context) { // VerifyLockHandler list locks for verification func VerifyLockHandler(ctx *context.Context) { - if !checkIsValidRequest(ctx, false) { + if !checkIsValidRequest(ctx) { return } ctx.Resp.Header().Set("Content-Type", metaMediaType) @@ -249,7 +242,7 @@ func VerifyLockHandler(ctx *context.Context) { // UnLockHandler delete locks func UnLockHandler(ctx *context.Context) { - if !checkIsValidRequest(ctx, false) { + if !checkIsValidRequest(ctx) { return } ctx.Resp.Header().Set("Content-Type", metaMediaType) diff --git a/modules/lfs/server.go b/modules/lfs/server.go index 7e20aa851593e..bf5355acfc3b1 100644 --- a/modules/lfs/server.go +++ b/modules/lfs/server.go @@ -152,7 +152,7 @@ func getContentHandler(ctx *context.Context) { if rangeHdr := ctx.Req.Header.Get("Range"); rangeHdr != "" { regex := regexp.MustCompile(`bytes=(\d+)\-.*`) match := regex.FindStringSubmatch(rangeHdr) - if match != nil && len(match) > 1 { + if len(match) > 1 { statusCode = 206 fromByte, _ = strconv.ParseInt(match[1], 10, 32) ctx.Resp.Header().Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", fromByte, meta.Size-1, meta.Size-fromByte)) @@ -178,8 +178,8 @@ func getContentHandler(ctx *context.Context) { } ctx.Resp.WriteHeader(statusCode) - io.Copy(ctx.Resp, content) - content.Close() + _, _ = io.Copy(ctx.Resp, content) + _ = content.Close() logRequest(ctx.Req, statusCode) } @@ -196,7 +196,7 @@ func getMetaHandler(ctx *context.Context) { if ctx.Req.Method == "GET" { enc := json.NewEncoder(ctx.Resp) - enc.Encode(Represent(rv, meta, true, false)) + _ = enc.Encode(Represent(rv, meta, true, false)) } logRequest(ctx.Req, 200) @@ -249,7 +249,7 @@ func PostHandler(ctx *context.Context) { ctx.Resp.WriteHeader(sentStatus) enc := json.NewEncoder(ctx.Resp) - enc.Encode(Represent(rv, meta, meta.Existing, true)) + _ = enc.Encode(Represent(rv, meta, meta.Existing, true)) logRequest(ctx.Req, sentStatus) } @@ -313,7 +313,7 @@ func BatchHandler(ctx *context.Context) { respobj := &BatchResponse{Objects: responseObjects} enc := json.NewEncoder(ctx.Resp) - enc.Encode(respobj) + _ = enc.Encode(respobj) logRequest(ctx.Req, 200) } diff --git a/modules/log/colors.go b/modules/log/colors.go index 0ec8ce4ba86da..c29741634f5e1 100644 --- a/modules/log/colors.go +++ b/modules/log/colors.go @@ -208,7 +208,7 @@ normalLoop: if i > lasti { written, err := c.w.Write(bytes[lasti:i]) - totalWritten = totalWritten + written + totalWritten += written if err != nil { return totalWritten, err } @@ -243,7 +243,7 @@ normalLoop: if bytes[j] == 'm' { if c.mode == allowColor { written, err := c.w.Write(bytes[i : j+1]) - totalWritten = totalWritten + written + totalWritten += written if err != nil { return totalWritten, err } @@ -278,7 +278,7 @@ func ColorSprintf(format string, args ...interface{}) string { } return fmt.Sprintf(format, v...) } - return fmt.Sprintf(format) + return format } // ColorFprintf will write to the provided writer similar to ColorSprintf @@ -290,7 +290,7 @@ func ColorFprintf(w io.Writer, format string, args ...interface{}) (int, error) } return fmt.Fprintf(w, format, v...) } - return fmt.Fprintf(w, format) + return fmt.Fprint(w, format) } // ColorFormatted structs provide their own colored string when formatted with ColorSprintf diff --git a/modules/log/conn.go b/modules/log/conn.go index bd76855168820..88166645265d9 100644 --- a/modules/log/conn.go +++ b/modules/log/conn.go @@ -67,7 +67,10 @@ func (i *connWriter) connect() error { } if tcpConn, ok := conn.(*net.TCPConn); ok { - tcpConn.SetKeepAlive(true) + err = tcpConn.SetKeepAlive(true) + if err != nil { + return err + } } i.innerWriter = conn diff --git a/modules/log/conn_test.go b/modules/log/conn_test.go index 380a115d9636c..cc3d758fa98f9 100644 --- a/modules/log/conn_test.go +++ b/modules/log/conn_test.go @@ -24,7 +24,6 @@ func listenReadAndClose(t *testing.T, l net.Listener, expected string) { assert.NoError(t, err) assert.Equal(t, expected, string(written)) - return } func TestConnLogger(t *testing.T) { diff --git a/modules/log/event.go b/modules/log/event.go index 2ec1f9587d54d..37efa3c2306aa 100644 --- a/modules/log/event.go +++ b/modules/log/event.go @@ -79,7 +79,7 @@ func (l *ChannelledLog) Start() { return } l.loggerProvider.Flush() - case _, _ = <-l.close: + case <-l.close: l.closeLogger() return } @@ -104,7 +104,6 @@ func (l *ChannelledLog) closeLogger() { l.loggerProvider.Flush() l.loggerProvider.Close() l.closed <- true - return } // Close this ChannelledLog @@ -228,7 +227,6 @@ func (m *MultiChannelledLog) closeLoggers() { } m.mutex.Unlock() m.closed <- true - return } // Start processing the MultiChannelledLog diff --git a/modules/log/file.go b/modules/log/file.go index cdda85d626ffa..877820b8bea4e 100644 --- a/modules/log/file.go +++ b/modules/log/file.go @@ -223,7 +223,7 @@ func compressOldLogFile(fname string, compressionLevel int) error { func (log *FileLogger) deleteOldLog() { dir := filepath.Dir(log.Filename) - filepath.Walk(dir, func(path string, info os.FileInfo, err error) (returnErr error) { + _ = filepath.Walk(dir, func(path string, info os.FileInfo, err error) (returnErr error) { defer func() { if r := recover(); r != nil { returnErr = fmt.Errorf("Unable to delete old log '%s', error: %+v", path, r) @@ -246,7 +246,7 @@ func (log *FileLogger) deleteOldLog() { // there are no buffering messages in file logger in memory. // flush file means sync file from disk. func (log *FileLogger) Flush() { - log.mw.fd.Sync() + _ = log.mw.fd.Sync() } // GetName returns the default name for this implementation diff --git a/modules/log/file_test.go b/modules/log/file_test.go index 648db6f393090..38279315ab363 100644 --- a/modules/log/file_test.go +++ b/modules/log/file_test.go @@ -103,7 +103,7 @@ func TestFileLogger(t *testing.T) { assert.Equal(t, expected, string(logData)) event.level = WARN - expected = expected + fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) + expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) fileLogger.LogEvent(&event) fileLogger.Flush() logData, err = ioutil.ReadFile(filename) @@ -130,7 +130,7 @@ func TestFileLogger(t *testing.T) { err = realFileLogger.DoRotate() assert.Error(t, err) - expected = expected + fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) + expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) fileLogger.LogEvent(&event) fileLogger.Flush() logData, err = ioutil.ReadFile(filename) @@ -138,7 +138,7 @@ func TestFileLogger(t *testing.T) { assert.Equal(t, expected, string(logData)) // Should fail to rotate - expected = expected + fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) + expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) fileLogger.LogEvent(&event) fileLogger.Flush() logData, err = ioutil.ReadFile(filename) @@ -188,7 +188,7 @@ func TestCompressFileLogger(t *testing.T) { assert.Equal(t, expected, string(logData)) event.level = WARN - expected = expected + fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) + expected += fmt.Sprintf("%s%s %s:%d:%s [%c] %s\n", prefix, dateString, event.filename, event.line, event.caller, strings.ToUpper(event.level.String())[0], event.msg) fileLogger.LogEvent(&event) fileLogger.Flush() logData, err = ioutil.ReadFile(filename) diff --git a/modules/log/flags.go b/modules/log/flags.go index 928d42b96546e..992fc62ddb6e8 100644 --- a/modules/log/flags.go +++ b/modules/log/flags.go @@ -57,7 +57,7 @@ func FlagsFromString(from string) int { for _, flag := range strings.Split(strings.ToLower(from), ",") { f, ok := flagFromString[strings.TrimSpace(flag)] if ok { - flags = flags | f + flags |= f } } return flags diff --git a/modules/log/log.go b/modules/log/log.go index 8698e9eed3ae3..0ca0f3adc5af1 100644 --- a/modules/log/log.go +++ b/modules/log/log.go @@ -218,7 +218,7 @@ func (l *LoggerAsWriter) Write(p []byte) (int, error) { func (l *LoggerAsWriter) Log(msg string) { for _, logger := range l.ourLoggers { // Set the skip to reference the call just above this - logger.Log(1, l.level, msg) + _ = logger.Log(1, l.level, msg) } } diff --git a/modules/log/smtp.go b/modules/log/smtp.go index f77d716d9491c..f912299a73628 100644 --- a/modules/log/smtp.go +++ b/modules/log/smtp.go @@ -11,10 +11,6 @@ import ( "strings" ) -const ( - subjectPhrase = "Diagnostic message from server" -) - type smtpWriter struct { owner *SMTPLogger } diff --git a/modules/log/writer.go b/modules/log/writer.go index 22ef0b90476bf..2503f04d76f7e 100644 --- a/modules/log/writer.go +++ b/modules/log/writer.go @@ -252,10 +252,7 @@ func (logger *WriterLogger) Match(event *Event) bool { mode: removeColor, }).Write([]byte(event.msg)) msg = baw - if logger.regexp.Match(msg) { - return true - } - return false + return logger.regexp.Match(msg) } // Close the base logger diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go index 411d6eafd8947..d19ae7b2f42ee 100644 --- a/modules/mailer/mailer.go +++ b/modules/mailer/mailer.go @@ -258,15 +258,12 @@ func (s *dummySender) Send(from string, to []string, msg io.WriterTo) error { } func processMailQueue() { - for { - select { - case msg := <-mailQueue: - log.Trace("New e-mail sending request %s: %s", msg.GetHeader("To"), msg.Info) - if err := gomail.Send(Sender, msg.Message); err != nil { - log.Error("Failed to send emails %s: %s - %v", msg.GetHeader("To"), msg.Info, err) - } else { - log.Trace("E-mails sent %s: %s", msg.GetHeader("To"), msg.Info) - } + for msg := range mailQueue { + log.Trace("New e-mail sending request %s: %s", msg.GetHeader("To"), msg.Info) + if err := gomail.Send(Sender, msg.Message); err != nil { + log.Error("Failed to send emails %s: %s - %v", msg.GetHeader("To"), msg.Info, err) + } else { + log.Trace("E-mails sent %s: %s", msg.GetHeader("To"), msg.Info) } } } diff --git a/modules/markup/html.go b/modules/markup/html.go index 91913b06792ac..dbfc8dbe85f71 100644 --- a/modules/markup/html.go +++ b/modules/markup/html.go @@ -108,24 +108,6 @@ func FindAllMentions(content string) []string { return ret } -// cutoutVerbosePrefix cutouts URL prefix including sub-path to -// return a clean unified string of request URL path. -func cutoutVerbosePrefix(prefix string) string { - if len(prefix) == 0 || prefix[0] != '/' { - return prefix - } - count := 0 - for i := 0; i < len(prefix); i++ { - if prefix[i] == '/' { - count++ - } - if count >= 3+setting.AppSubURLDepth { - return prefix[:i] - } - } - return prefix -} - // IsSameDomain checks if given url string has the same hostname as current Gitea instance func IsSameDomain(s string) bool { if strings.HasPrefix(s, "/") { @@ -146,7 +128,7 @@ type postProcessError struct { } func (p *postProcessError) Error() string { - return "PostProcess: " + p.context + ", " + p.Error() + return "PostProcess: " + p.context + ", " + p.err.Error() } type processor func(ctx *postProcessCtx, node *html.Node) @@ -304,20 +286,6 @@ func (ctx *postProcessCtx) visitNode(node *html.Node) { // ignore everything else } -func (ctx *postProcessCtx) visitNodeForShortLinks(node *html.Node) { - switch node.Type { - case html.TextNode: - shortLinkProcessorFull(ctx, node, true) - case html.ElementNode: - if node.Data == "code" || node.Data == "pre" || node.Data == "a" { - return - } - for n := node.FirstChild; n != nil; n = n.NextSibling { - ctx.visitNodeForShortLinks(n) - } - } -} - // textNode runs the passed node through various processors, in order to handle // all kinds of special links handled by the post-processing. func (ctx *postProcessCtx) textNode(node *html.Node) { diff --git a/modules/markup/html_internal_test.go b/modules/markup/html_internal_test.go index 135a8e103c573..10bc4973cd525 100644 --- a/modules/markup/html_internal_test.go +++ b/modules/markup/html_internal_test.go @@ -29,11 +29,6 @@ func numericIssueLink(baseURL string, index int) string { return link(util.URLJoin(baseURL, strconv.Itoa(index)), fmt.Sprintf("#%d", index)) } -// urlContentsLink an HTML link whose contents is the target URL -func urlContentsLink(href string) string { - return link(href, href) -} - // link an HTML link func link(href, contents string) string { return fmt.Sprintf("%s", href, contents) diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index a31591c2a708d..22089158f5b72 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -35,12 +35,9 @@ func NewNotifier() base.Notifier { } func (ns *notificationService) Run() { - for { - select { - case opts := <-ns.issueQueue: - if err := models.CreateOrUpdateIssueNotifications(opts.issue, opts.notificationAuthorID); err != nil { - log.Error("Was unable to create issue notification: %v", err) - } + for opts := range ns.issueQueue { + if err := models.CreateOrUpdateIssueNotifications(opts.issue, opts.notificationAuthorID); err != nil { + log.Error("Was unable to create issue notification: %v", err) } } } diff --git a/modules/pprof/pprof.go b/modules/pprof/pprof.go index b63904e713626..80ad67be3a81b 100644 --- a/modules/pprof/pprof.go +++ b/modules/pprof/pprof.go @@ -9,6 +9,8 @@ import ( "io/ioutil" "runtime" "runtime/pprof" + + "code.gitea.io/gitea/modules/log" ) // DumpMemProfileForUsername dumps a memory profile at pprofDataPath as memprofile__ @@ -30,9 +32,15 @@ func DumpCPUProfileForUsername(pprofDataPath, username string) (func(), error) { return nil, err } - pprof.StartCPUProfile(f) + err = pprof.StartCPUProfile(f) + if err != nil { + log.Fatal("StartCPUProfile: %v", err) + } return func() { pprof.StopCPUProfile() - f.Close() + err = f.Close() + if err != nil { + log.Fatal("StopCPUProfile Close: %v", err) + } }, nil } diff --git a/modules/repofiles/delete.go b/modules/repofiles/delete.go index 09a4dbb44c9b1..91910fa86043f 100644 --- a/modules/repofiles/delete.go +++ b/modules/repofiles/delete.go @@ -53,11 +53,9 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo BranchName: opts.NewBranch, } } - } else { - if protected, _ := repo.IsProtectedBranchForPush(opts.OldBranch, doer); protected { - return nil, models.ErrUserCannotCommit{ - UserName: doer.LowerName, - } + } else if protected, _ := repo.IsProtectedBranchForPush(opts.OldBranch, doer); protected { + return nil, models.ErrUserCannotCommit{ + UserName: doer.LowerName, } } @@ -74,10 +72,10 @@ func DeleteRepoFile(repo *models.Repository, doer *models.User, opts *DeleteRepo author, committer := GetAuthorAndCommitterUsers(opts.Committer, opts.Author, doer) t, err := NewTemporaryUploadRepository(repo) - defer t.Close() if err != nil { return nil, err } + defer t.Close() if err := t.Clone(opts.OldBranch); err != nil { return nil, err } diff --git a/modules/repofiles/file.go b/modules/repofiles/file.go index de3ee71dba9a8..70fd57bba0ea7 100644 --- a/modules/repofiles/file.go +++ b/modules/repofiles/file.go @@ -86,7 +86,7 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *models // If only one of the two are provided, we set both of them to it. // If neither are provided, both are the doer. if committer != nil && committer.Email != "" { - if doer != nil && strings.ToLower(doer.Email) == strings.ToLower(committer.Email) { + if doer != nil && strings.EqualFold(doer.Email, committer.Email) { committerUser = doer // the committer is the doer, so will use their user object if committer.Name != "" { committerUser.FullName = committer.Name @@ -99,7 +99,7 @@ func GetAuthorAndCommitterUsers(author, committer *IdentityOptions, doer *models } } if author != nil && author.Email != "" { - if doer != nil && strings.ToLower(doer.Email) == strings.ToLower(author.Email) { + if doer != nil && strings.EqualFold(doer.Email, author.Email) { authorUser = doer // the author is the doer, so will use their user object if authorUser.Name != "" { authorUser.FullName = author.Name diff --git a/modules/repofiles/tree.go b/modules/repofiles/tree.go index 4eb54a25981dc..318a5d152d839 100644 --- a/modules/repofiles/tree.go +++ b/modules/repofiles/tree.go @@ -16,6 +16,9 @@ import ( // GetTreeBySHA get the GitTreeResponse of a repository using a sha hash. func GetTreeBySHA(repo *models.Repository, sha string, page, perPage int, recursive bool) (*api.GitTreeResponse, error) { gitRepo, err := git.OpenRepository(repo.RepoPath()) + if err != nil { + return nil, err + } gitTree, err := gitRepo.GetTree(sha) if err != nil || gitTree == nil { return nil, models.ErrSHANotFound{ @@ -39,12 +42,12 @@ func GetTreeBySHA(repo *models.Repository, sha string, page, perPage int, recurs // 51 is len(sha1) + len("/git/blobs/"). 40 + 11. blobURL := make([]byte, apiURLLen+51) - copy(blobURL[:], apiURL) + copy(blobURL, apiURL) copy(blobURL[apiURLLen:], "/git/blobs/") // 51 is len(sha1) + len("/git/trees/"). 40 + 11. treeURL := make([]byte, apiURLLen+51) - copy(treeURL[:], apiURL) + copy(treeURL, apiURL) copy(treeURL[apiURLLen:], "/git/trees/") // 40 is the size of the sha1 hash in hexadecimal format. @@ -83,10 +86,10 @@ func GetTreeBySHA(repo *models.Repository, sha string, page, perPage int, recurs if entries[e].IsDir() { copy(treeURL[copyPos:], entries[e].ID.String()) - tree.Entries[i].URL = string(treeURL[:]) + tree.Entries[i].URL = string(treeURL) } else { copy(blobURL[copyPos:], entries[e].ID.String()) - tree.Entries[i].URL = string(blobURL[:]) + tree.Entries[i].URL = string(blobURL) } } return tree, nil diff --git a/modules/repofiles/update.go b/modules/repofiles/update.go index 569c89ac51d51..f011017a5e87a 100644 --- a/modules/repofiles/update.go +++ b/modules/repofiles/update.go @@ -99,6 +99,10 @@ func detectEncodingAndBOM(entry *git.TreeEntry, repo *models.Repository) (string } result, n, err := transform.String(charsetEncoding.NewDecoder(), string(buf)) + if err != nil { + // return default + return "UTF-8", false + } if n > 2 { return encoding, bytes.Equal([]byte(result)[0:3], base.UTF8BOM) @@ -135,10 +139,8 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up if err != nil && !git.IsErrBranchNotExist(err) { return nil, err } - } else { - if protected, _ := repo.IsProtectedBranchForPush(opts.OldBranch, doer); protected { - return nil, models.ErrUserCannotCommit{UserName: doer.LowerName} - } + } else if protected, _ := repo.IsProtectedBranchForPush(opts.OldBranch, doer); protected { + return nil, models.ErrUserCannotCommit{UserName: doer.LowerName} } // If FromTreePath is not set, set it to the opts.TreePath @@ -166,10 +168,10 @@ func CreateOrUpdateRepoFile(repo *models.Repository, doer *models.User, opts *Up author, committer := GetAuthorAndCommitterUsers(opts.Committer, opts.Author, doer) t, err := NewTemporaryUploadRepository(repo) - defer t.Close() if err != nil { - return nil, err + log.Error("%v", err) } + defer t.Close() if err := t.Clone(opts.OldBranch); err != nil { return nil, err } diff --git a/modules/repofiles/upload.go b/modules/repofiles/upload.go index 5f428c3139a43..2da101c64dad6 100644 --- a/modules/repofiles/upload.go +++ b/modules/repofiles/upload.go @@ -57,10 +57,10 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep } t, err := NewTemporaryUploadRepository(repo) - defer t.Close() if err != nil { return err } + defer t.Close() if err := t.Clone(opts.OldBranch); err != nil { return err } @@ -108,10 +108,8 @@ func UploadRepoFiles(repo *models.Repository, doer *models.User, opts *UploadRep } infos[i] = uploadInfo - } else { - if objectHash, err = t.HashObject(file); err != nil { - return err - } + } else if objectHash, err = t.HashObject(file); err != nil { + return err } // Add the object to the index diff --git a/modules/repofiles/verification.go b/modules/repofiles/verification.go index be56f9b8b86b0..9fc084daafed5 100644 --- a/modules/repofiles/verification.go +++ b/modules/repofiles/verification.go @@ -20,10 +20,8 @@ func GetPayloadCommitVerification(commit *git.Commit) *structs.PayloadCommitVeri } if verification.Reason != "" { verification.Reason = commitVerification.Reason - } else { - if verification.Verified { - verification.Reason = "unsigned" - } + } else if verification.Verified { + verification.Reason = "unsigned" } return verification } diff --git a/modules/session/virtual.go b/modules/session/virtual.go index b90f03417ae7a..b8ddd2f71bdd1 100644 --- a/modules/session/virtual.go +++ b/modules/session/virtual.go @@ -21,10 +21,8 @@ import ( // VirtualSessionProvider represents a shadowed session provider implementation. type VirtualSessionProvider struct { - lock sync.RWMutex - maxlifetime int64 - rootPath string - provider session.Provider + lock sync.RWMutex + provider session.Provider } // Init initializes the cookie session provider with given root path. diff --git a/modules/setting/log.go b/modules/setting/log.go index 9f4bbf9d87d4b..5e2d2d769d701 100644 --- a/modules/setting/log.go +++ b/modules/setting/log.go @@ -150,8 +150,6 @@ func generateNamedLogger(key string, options defaultLogOptions) *LogDescription sections := strings.Split(Cfg.Section("log").Key(strings.ToUpper(key)).MustString(""), ",") - //description.Configs = make([]string, len(description.Sections)) - for i := 0; i < len(sections); i++ { sections[i] = strings.TrimSpace(sections[i]) } @@ -167,7 +165,10 @@ func generateNamedLogger(key string, options defaultLogOptions) *LogDescription provider, config, levelName := generateLogConfig(sec, name, options) - log.NewNamedLogger(key, options.bufferLength, name, provider, config) + if err := log.NewNamedLogger(key, options.bufferLength, name, provider, config); err != nil { + // Maybe panic here? + log.Error("Could not create new named logger: %v", err.Error()) + } description.SubLogDescriptions = append(description.SubLogDescriptions, SubLogDescription{ Name: name, @@ -242,7 +243,10 @@ func newLogService() { } if !useConsole { - log.DelLogger("console") + err := log.DelLogger("console") + if err != nil { + log.Fatal("DelLogger: %v", err) + } } for _, name := range sections { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index ff53e9a3757f1..b550836bc1640 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -545,13 +545,14 @@ func NewContext() { AppName = Cfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea") Protocol = HTTP - if sec.Key("PROTOCOL").String() == "https" { + switch sec.Key("PROTOCOL").String() { + case "https": Protocol = HTTPS CertFile = sec.Key("CERT_FILE").String() KeyFile = sec.Key("KEY_FILE").String() - } else if sec.Key("PROTOCOL").String() == "fcgi" { + case "fcgi": Protocol = FCGI - } else if sec.Key("PROTOCOL").String() == "unix" { + case "unix": Protocol = UnixSocket UnixSocketPermissionRaw := sec.Key("UNIX_SOCKET_PERMISSION").MustString("666") UnixSocketPermissionParsed, err := strconv.ParseUint(UnixSocketPermissionRaw, 8, 32) diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go index 98ff50bfeca9a..c5251ef23aca1 100644 --- a/modules/ssh/ssh.go +++ b/modules/ssh/ssh.go @@ -37,7 +37,10 @@ func cleanCommand(cmd string) string { func handleServerConn(keyID string, chans <-chan ssh.NewChannel) { for newChan := range chans { if newChan.ChannelType() != "session" { - newChan.Reject(ssh.UnknownChannelType, "unknown channel type") + err := newChan.Reject(ssh.UnknownChannelType, "unknown channel type") + if err != nil { + log.Error("Error rejecting channel: %v", err) + } continue } @@ -48,7 +51,11 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) { } go func(in <-chan *ssh.Request) { - defer ch.Close() + defer func() { + if err = ch.Close(); err != nil { + log.Error("Close: %v", err) + } + }() for req := range in { payload := cleanCommand(string(req.Payload)) switch req.Type { @@ -87,17 +94,34 @@ func handleServerConn(keyID string, chans <-chan ssh.NewChannel) { return } - req.Reply(true, nil) - go io.Copy(input, ch) - io.Copy(ch, stdout) - io.Copy(ch.Stderr(), stderr) + err = req.Reply(true, nil) + if err != nil { + log.Error("SSH: Reply: %v", err) + } + go func() { + _, err = io.Copy(input, ch) + if err != nil { + log.Error("SSH: Copy: %v", err) + } + }() + _, err = io.Copy(ch, stdout) + if err != nil { + log.Error("SSH: Copy: %v", err) + } + _, err = io.Copy(ch.Stderr(), stderr) + if err != nil { + log.Error("SSH: Copy: %v", err) + } if err = cmd.Wait(); err != nil { log.Error("SSH: Wait: %v", err) return } - ch.SendRequest("exit-status", false, []byte{0, 0, 0, 0}) + _, err = ch.SendRequest("exit-status", false, []byte{0, 0, 0, 0}) + if err != nil { + log.Error("SSH: SendRequest: %v", err) + } return default: } @@ -203,7 +227,11 @@ func GenKeyPair(keyPath string) error { if err != nil { return err } - defer f.Close() + defer func() { + if err = f.Close(); err != nil { + log.Error("Close: %v", err) + } + }() if err := pem.Encode(f, privateKeyPEM); err != nil { return err @@ -220,7 +248,11 @@ func GenKeyPair(keyPath string) error { if err != nil { return err } - defer p.Close() + defer func() { + if err = p.Close(); err != nil { + log.Error("Close: %v", err) + } + }() _, err = p.Write(public) return err } diff --git a/modules/structs/user_search.go b/modules/structs/user_search.go deleted file mode 100644 index 1650cf736a1c6..0000000000000 --- a/modules/structs/user_search.go +++ /dev/null @@ -1,5 +0,0 @@ -package structs - -type searchUsersResponse struct { - Users []*User `json:"data"` -} diff --git a/modules/structs/utils.go b/modules/structs/utils.go index 1b9d689562813..aaeb653d03acd 100644 --- a/modules/structs/utils.go +++ b/modules/structs/utils.go @@ -4,12 +4,6 @@ package structs -import ( - "net/http" -) - -var jsonHeader = http.Header{"content-type": []string{"application/json"}} - // Bool return address of bool value func Bool(v bool) *bool { return &v diff --git a/modules/templates/dynamic.go b/modules/templates/dynamic.go index dbd75221d22c3..d7c04ccb09d8d 100644 --- a/modules/templates/dynamic.go +++ b/modules/templates/dynamic.go @@ -83,12 +83,15 @@ func Mailer() *template.Template { continue } - templates.New( + _, err = templates.New( strings.TrimSuffix( filePath, ".tmpl", ), ).Parse(string(content)) + if err != nil { + log.Warn("Failed to parse template %v", err) + } } } } @@ -113,12 +116,15 @@ func Mailer() *template.Template { continue } - templates.New( + _, err = templates.New( strings.TrimSuffix( filePath, ".tmpl", ), ).Parse(string(content)) + if err != nil { + log.Warn("Failed to parse template %v", err) + } } } } diff --git a/modules/templates/helper.go b/modules/templates/helper.go index ef4a68add0c37..c4551bb4be4da 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -343,7 +343,7 @@ func ReplaceLeft(s, oldS, newS string) string { // allocating space for the new string curLen := n*newLen + len(s[i:]) - replacement := make([]byte, curLen, curLen) + replacement := make([]byte, curLen) j := 0 for ; j < n*newLen; j += newLen { diff --git a/modules/user/user_test.go b/modules/user/user_test.go index ae7460281fc03..fadcbde7bf23e 100644 --- a/modules/user/user_test.go +++ b/modules/user/user_test.go @@ -13,7 +13,7 @@ func getWhoamiOutput() (string, error) { if err != nil { return "", err } - return strings.TrimSpace(string(output[:])), nil + return strings.TrimSpace(string(output)), nil } func TestCurrentUsername(t *testing.T) { diff --git a/modules/validation/binding_test.go b/modules/validation/binding_test.go index 7bc41ac3959bc..f55b09266dd26 100644 --- a/modules/validation/binding_test.go +++ b/modules/validation/binding_test.go @@ -26,12 +26,6 @@ type ( expectedErrors binding.Errors } - handlerFunc func(interface{}, ...interface{}) macaron.Handler - - modeler interface { - Model() string - } - TestForm struct { BranchName string `form:"BranchName" binding:"GitRefName"` URL string `form:"ValidUrl" binding:"ValidUrl"` diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 5107e18b7d98d..b4eac2c677ac4 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -261,10 +261,6 @@ func Config(ctx *context.Context) { } ctx.Data["EnvVars"] = envVars - - type logger struct { - Mode, Config string - } ctx.Data["Loggers"] = setting.LogDescriptions ctx.Data["RedirectMacaronLog"] = setting.RedirectMacaronLog ctx.Data["EnableAccessLog"] = setting.EnableAccessLog diff --git a/routers/api/v1/misc/markdown.go b/routers/api/v1/misc/markdown.go index 06e344a15b5b8..b00b00c499e11 100644 --- a/routers/api/v1/misc/markdown.go +++ b/routers/api/v1/misc/markdown.go @@ -5,6 +5,7 @@ package misc import ( + "net/http" "strings" api "code.gitea.io/gitea/modules/structs" @@ -42,7 +43,7 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { } if len(form.Text) == 0 { - ctx.Write([]byte("")) + _, _ = ctx.Write([]byte("")) return } @@ -63,12 +64,24 @@ func Markdown(ctx *context.APIContext, form api.MarkdownOption) { meta = ctx.Repo.Repository.ComposeMetas() } if form.Wiki { - ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta))) + _, err := ctx.Write([]byte(markdown.RenderWiki(md, urlPrefix, meta))) + if err != nil { + ctx.Error(http.StatusInternalServerError, "", err) + return + } } else { - ctx.Write(markdown.Render(md, urlPrefix, meta)) + _, err := ctx.Write(markdown.Render(md, urlPrefix, meta)) + if err != nil { + ctx.Error(http.StatusInternalServerError, "", err) + return + } } default: - ctx.Write(markdown.RenderRaw([]byte(form.Text), "", false)) + _, err := ctx.Write(markdown.RenderRaw([]byte(form.Text), "", false)) + if err != nil { + ctx.Error(http.StatusInternalServerError, "", err) + return + } } } @@ -98,5 +111,9 @@ func MarkdownRaw(ctx *context.APIContext) { ctx.Error(422, "", err) return } - ctx.Write(markdown.RenderRaw(body, "", false)) + _, err = ctx.Write(markdown.RenderRaw(body, "", false)) + if err != nil { + ctx.Error(http.StatusInternalServerError, "", err) + return + } } diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 0e1db144b1991..b14b0b02b838e 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -353,7 +353,11 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { return } - pr.LoadIssue() + err = pr.LoadIssue() + if err != nil { + ctx.Error(http.StatusInternalServerError, "LoadIssue", err) + return + } issue := pr.Issue issue.Repo = ctx.Repo.Repository @@ -547,7 +551,11 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) { return } - pr.LoadIssue() + err = pr.LoadIssue() + if err != nil { + ctx.Error(http.StatusInternalServerError, "LoadIssue", err) + return + } pr.Issue.Repo = ctx.Repo.Repository if ctx.IsSigned { diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index f8df3e9fa12fe..26cfff51ce76b 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -631,15 +631,6 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err return nil } -func unitTypeInTypes(unitType models.UnitType, unitTypes []models.UnitType) bool { - for _, tp := range unitTypes { - if unitType == tp { - return true - } - } - return false -} - // updateRepoUnits updates repo units: Issue settings, Wiki settings, PR settings func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { owner := ctx.Repo.Owner diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go index c2c55e9b927b7..7bf43c582215e 100644 --- a/routers/api/v1/user/gpg_key.go +++ b/routers/api/v1/user/gpg_key.go @@ -9,14 +9,9 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/routers/api/v1/convert" ) -func composePublicGPGKeysAPILink() string { - return setting.AppURL + "api/v1/user/gpg_keys/" -} - func listGPGKeys(ctx *context.APIContext, uid int64) { keys, err := models.ListGPGKeys(uid) if err != nil { diff --git a/routers/init.go b/routers/init.go index b3078b478aff0..e6b23cf8b82d8 100644 --- a/routers/init.go +++ b/routers/init.go @@ -41,7 +41,7 @@ func checkRunMode() { func NewServices() { setting.NewServices() mailer.NewContext() - cache.NewContext() + _ = cache.NewContext() } // In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology diff --git a/routers/org/teams.go b/routers/org/teams.go index 27db14e4b5535..f662bd92e2ccf 100644 --- a/routers/org/teams.go +++ b/routers/org/teams.go @@ -5,6 +5,7 @@ package org import ( + "net/http" "path" "strings" @@ -287,7 +288,11 @@ func EditTeamPost(ctx *context.Context, form auth.CreateTeamForm) { Type: tp, }) } - models.UpdateTeamUnits(t, units) + err := models.UpdateTeamUnits(t, units) + if err != nil { + ctx.Error(http.StatusInternalServerError, "LoadIssue", err.Error()) + return + } } if ctx.HasError() { diff --git a/routers/private/hook.go b/routers/private/hook.go index a5985f161e719..3da5e38edb50b 100644 --- a/routers/private/hook.go +++ b/routers/private/hook.go @@ -214,5 +214,4 @@ func HookPostReceive(ctx *macaron.Context) { ctx.JSON(http.StatusOK, map[string]interface{}{ "message": false, }) - return } diff --git a/routers/private/serv.go b/routers/private/serv.go index 68e4361e56d84..90579a3dcce16 100644 --- a/routers/private/serv.go +++ b/routers/private/serv.go @@ -62,7 +62,6 @@ func ServNoCommand(ctx *macaron.Context) { results.Owner = user } ctx.JSON(http.StatusOK, &results) - return } // ServCommand returns information about the provided keyid @@ -282,5 +281,4 @@ func ServCommand(ctx *macaron.Context) { ctx.JSON(http.StatusOK, results) // We will update the keys in a different call. - return } diff --git a/routers/repo/blame.go b/routers/repo/blame.go index 964fdc8746a22..2b2f45f0bb9f1 100644 --- a/routers/repo/blame.go +++ b/routers/repo/blame.go @@ -192,7 +192,7 @@ func RefBlame(ctx *context.Context) { func renderBlame(ctx *context.Context, blameParts []models.BlamePart, commitNames map[string]models.UserCommit) { repoLink := ctx.Repo.RepoLink - var lines = make([]string, 0, 0) + var lines = make([]string, 0) var commitInfo bytes.Buffer var lineNumbers bytes.Buffer diff --git a/routers/repo/commit.go b/routers/repo/commit.go index dde6d8f321550..4dbedea2a08d2 100644 --- a/routers/repo/commit.go +++ b/routers/repo/commit.go @@ -261,6 +261,9 @@ func Diff(ctx *context.Context) { } ctx.Data["RawPath"] = setting.AppSubURL + "/" + path.Join(userName, repoName, "raw", "commit", commitID) ctx.Data["BranchName"], err = commit.GetBranchName() + if err != nil { + ctx.ServerError("commit.GetBranchName", err) + } ctx.HTML(200, tplCommitPage) } diff --git a/routers/repo/download.go b/routers/repo/download.go index 41c4a181025d2..2da8b109ca957 100644 --- a/routers/repo/download.go +++ b/routers/repo/download.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/lfs" + "code.gitea.io/gitea/modules/log" ) // ServeData download file from io.Reader @@ -39,8 +40,11 @@ func ServeData(ctx *context.Context, name string, reader io.Reader) error { ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name)) } - ctx.Resp.Write(buf) - _, err := io.Copy(ctx.Resp, reader) + _, err := ctx.Resp.Write(buf) + if err != nil { + return err + } + _, err = io.Copy(ctx.Resp, reader) return err } @@ -50,7 +54,11 @@ func ServeBlob(ctx *context.Context, blob *git.Blob) error { if err != nil { return err } - defer dataRc.Close() + defer func() { + if err = dataRc.Close(); err != nil { + log.Error("ServeBlob: Close: %v", err) + } + }() return ServeData(ctx, ctx.Repo.TreePath, dataRc) } @@ -61,7 +69,11 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error { if err != nil { return err } - defer dataRc.Close() + defer func() { + if err = dataRc.Close(); err != nil { + log.Error("ServeBlobOrLFS: Close: %v", err) + } + }() if meta, _ := lfs.ReadPointerFile(dataRc); meta != nil { meta, _ = ctx.Repo.Repository.GetLFSMetaObjectByOid(meta.Oid) diff --git a/routers/repo/editor.go b/routers/repo/editor.go index 46f12d66d280d..062ecfebf777b 100644 --- a/routers/repo/editor.go +++ b/routers/repo/editor.go @@ -118,9 +118,7 @@ func editFile(ctx *context.Context, isNewFile bool) { d, _ := ioutil.ReadAll(dataRc) buf = append(buf, d...) if content, err := templates.ToUTF8WithErr(buf); err != nil { - if err != nil { - log.Error("ToUTF8WithErr: %v", err) - } + log.Error("ToUTF8WithErr: %v", err) ctx.Data["FileContent"] = string(buf) } else { ctx.Data["FileContent"] = content @@ -235,16 +233,12 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo switch fileErr.Type { case git.EntryModeSymlink: ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form) - break case git.EntryModeTree: ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplEditFile, &form) - break case git.EntryModeBlob: ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplEditFile, &form) - break default: ctx.Error(500, err.Error()) - break } } else { ctx.Error(500, err.Error()) @@ -403,16 +397,12 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) { switch fileErr.Type { case git.EntryModeSymlink: ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form) - break case git.EntryModeTree: ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplEditFile, &form) - break case git.EntryModeBlob: ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplEditFile, &form) - break default: ctx.ServerError("DeleteRepoFile", err) - break } } else { ctx.ServerError("DeleteRepoFile", err) diff --git a/routers/repo/http.go b/routers/repo/http.go index 214e2f3411330..30722094489f0 100644 --- a/routers/repo/http.go +++ b/routers/repo/http.go @@ -206,10 +206,8 @@ func HTTP(ctx *context.Context) { if err = models.UpdateAccessToken(token); err != nil { ctx.ServerError("UpdateAccessToken", err) } - } else { - if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) { - log.Error("GetAccessTokenBySha: %v", err) - } + } else if !models.IsErrAccessTokenNotExist(err) && !models.IsErrAccessTokenEmpty(err) { + log.Error("GetAccessTokenBySha: %v", err) } if authUser == nil { @@ -332,17 +330,17 @@ type route struct { } var routes = []route{ - {regexp.MustCompile("(.*?)/git-upload-pack$"), "POST", serviceUploadPack}, - {regexp.MustCompile("(.*?)/git-receive-pack$"), "POST", serviceReceivePack}, - {regexp.MustCompile("(.*?)/info/refs$"), "GET", getInfoRefs}, - {regexp.MustCompile("(.*?)/HEAD$"), "GET", getTextFile}, - {regexp.MustCompile("(.*?)/objects/info/alternates$"), "GET", getTextFile}, - {regexp.MustCompile("(.*?)/objects/info/http-alternates$"), "GET", getTextFile}, - {regexp.MustCompile("(.*?)/objects/info/packs$"), "GET", getInfoPacks}, - {regexp.MustCompile("(.*?)/objects/info/[^/]*$"), "GET", getTextFile}, - {regexp.MustCompile("(.*?)/objects/[0-9a-f]{2}/[0-9a-f]{38}$"), "GET", getLooseObject}, - {regexp.MustCompile("(.*?)/objects/pack/pack-[0-9a-f]{40}\\.pack$"), "GET", getPackFile}, - {regexp.MustCompile("(.*?)/objects/pack/pack-[0-9a-f]{40}\\.idx$"), "GET", getIdxFile}, + {regexp.MustCompile(`(.*?)/git-upload-pack$`), "POST", serviceUploadPack}, + {regexp.MustCompile(`(.*?)/git-receive-pack$`), "POST", serviceReceivePack}, + {regexp.MustCompile(`(.*?)/info/refs$`), "GET", getInfoRefs}, + {regexp.MustCompile(`(.*?)/HEAD$`), "GET", getTextFile}, + {regexp.MustCompile(`(.*?)/objects/info/alternates$`), "GET", getTextFile}, + {regexp.MustCompile(`(.*?)/objects/info/http-alternates$`), "GET", getTextFile}, + {regexp.MustCompile(`(.*?)/objects/info/packs$`), "GET", getInfoPacks}, + {regexp.MustCompile(`(.*?)/objects/info/[^/]*$`), "GET", getTextFile}, + {regexp.MustCompile(`(.*?)/objects/[0-9a-f]{2}/[0-9a-f]{38}$`), "GET", getLooseObject}, + {regexp.MustCompile(`(.*?)/objects/pack/pack-[0-9a-f]{40}\.pack$`), "GET", getPackFile}, + {regexp.MustCompile(`(.*?)/objects/pack/pack-[0-9a-f]{40}\.idx$`), "GET", getIdxFile}, } // FIXME: use process module @@ -393,7 +391,12 @@ func hasAccess(service string, h serviceHandler, checkContentType bool) bool { } func serviceRPC(h serviceHandler, service string) { - defer h.r.Body.Close() + defer func() { + if err := h.r.Body.Close(); err != nil { + log.Error("serviceRPC: Close: %v", err) + } + + }() if !hasAccess(service, h, true) { h.w.WriteHeader(http.StatusUnauthorized) @@ -469,9 +472,9 @@ func getInfoRefs(h serviceHandler) { h.w.Header().Set("Content-Type", fmt.Sprintf("application/x-git-%s-advertisement", service)) h.w.WriteHeader(http.StatusOK) - h.w.Write(packetWrite("# service=git-" + service + "\n")) - h.w.Write([]byte("0000")) - h.w.Write(refs) + _, _ = h.w.Write(packetWrite("# service=git-" + service + "\n")) + _, _ = h.w.Write([]byte("0000")) + _, _ = h.w.Write(refs) } else { updateServerInfo(h.dir) h.sendFile("text/plain; charset=utf-8") @@ -524,16 +527,25 @@ func HTTPBackend(ctx *context.Context, cfg *serviceConfig) http.HandlerFunc { if m := route.reg.FindStringSubmatch(r.URL.Path); m != nil { if setting.Repository.DisableHTTPGit { w.WriteHeader(http.StatusForbidden) - w.Write([]byte("Interacting with repositories by HTTP protocol is not allowed")) + _, err := w.Write([]byte("Interacting with repositories by HTTP protocol is not allowed")) + if err != nil { + log.Error(err.Error()) + } return } if route.method != r.Method { if r.Proto == "HTTP/1.1" { w.WriteHeader(http.StatusMethodNotAllowed) - w.Write([]byte("Method Not Allowed")) + _, err := w.Write([]byte("Method Not Allowed")) + if err != nil { + log.Error(err.Error()) + } } else { w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Bad Request")) + _, err := w.Write([]byte("Bad Request")) + if err != nil { + log.Error(err.Error()) + } } return } @@ -552,6 +564,5 @@ func HTTPBackend(ctx *context.Context, cfg *serviceConfig) http.HandlerFunc { } ctx.NotFound("HTTPBackend", nil) - return } } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index cd384da0d669f..3904d29532fde 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -945,7 +945,15 @@ func ViewIssue(ctx *context.Context) { // Get Dependencies ctx.Data["BlockedByDependencies"], err = issue.BlockedByDependencies() + if err != nil { + ctx.ServerError("BlockedByDependencies", err) + return + } ctx.Data["BlockingDependencies"], err = issue.BlockingDependencies() + if err != nil { + ctx.ServerError("BlockingDependencies", err) + return + } ctx.Data["Participants"] = participants ctx.Data["NumParticipants"] = len(participants) @@ -1226,7 +1234,8 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) { if form.Status == "reopen" && issue.IsPull { pull := issue.PullRequest - pr, err := models.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch) + var err error + pr, err = models.GetUnmergedPullRequest(pull.HeadRepoID, pull.BaseRepoID, pull.HeadBranch, pull.BaseBranch) if err != nil { if !models.IsErrPullRequestNotExist(err) { ctx.ServerError("GetUnmergedPullRequest", err) diff --git a/routers/repo/issue_label.go b/routers/repo/issue_label.go index 556a24c33ea75..cae6535c799bd 100644 --- a/routers/repo/issue_label.go +++ b/routers/repo/issue_label.go @@ -129,7 +129,6 @@ func DeleteLabel(ctx *context.Context) { ctx.JSON(200, map[string]interface{}{ "redirect": ctx.Repo.RepoLink + "/labels", }) - return } // UpdateIssueLabel change issue's labels diff --git a/routers/repo/milestone.go b/routers/repo/milestone.go index 644f7e043ba54..3ad638e60af46 100644 --- a/routers/repo/milestone.go +++ b/routers/repo/milestone.go @@ -19,7 +19,6 @@ import ( const ( tplMilestone base.TplName = "repo/issue/milestones" tplMilestoneNew base.TplName = "repo/issue/milestone_new" - tplMilestoneEdit base.TplName = "repo/issue/milestone_edit" tplMilestoneIssues base.TplName = "repo/issue/milestone_issues" ) @@ -57,7 +56,7 @@ func Milestones(ctx *context.Context) { return } if ctx.Repo.Repository.IsTimetrackerEnabled() { - if miles.LoadTotalTrackedTimes(); err != nil { + if err := miles.LoadTotalTrackedTimes(); err != nil { ctx.ServerError("LoadTotalTrackedTimes", err) return } diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 71c684356db2a..5be8aa57c1f84 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -793,10 +793,10 @@ func CleanUpPullRequest(ctx *context.Context) { // Forked repository has already been deleted ctx.NotFound("CleanUpPullRequest", nil) return - } else if pr.GetBaseRepo(); err != nil { + } else if err = pr.GetBaseRepo(); err != nil { ctx.ServerError("GetBaseRepo", err) return - } else if pr.HeadRepo.GetOwner(); err != nil { + } else if err = pr.HeadRepo.GetOwner(); err != nil { ctx.ServerError("HeadRepo.GetOwner", err) return } diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 767cdacde0195..757295069e90c 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -419,7 +419,10 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { return } - repo.DeleteWiki() + err := repo.DeleteWiki() + if err != nil { + log.Error("Delete Wiki: %v", err.Error()) + } log.Trace("Repository wiki deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name) ctx.Flash.Success(ctx.Tr("repo.settings.wiki_deletion_success")) diff --git a/routers/repo/view.go b/routers/repo/view.go index 3483a53a0d31f..edaf24017ce6d 100644 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -294,9 +294,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st // Building code view blocks with line number on server side. var fileContent string if content, err := templates.ToUTF8WithErr(buf); err != nil { - if err != nil { - log.Error("ToUTF8WithErr: %v", err) - } + log.Error("ToUTF8WithErr: %v", err) fileContent = string(buf) } else { fileContent = content diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go index 8daf721b50e1c..20a3a45c18ae6 100644 --- a/routers/repo/webhook.go +++ b/routers/repo/webhook.go @@ -197,12 +197,20 @@ func WebHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { } // GogsHooksNewPost response for creating webhook -func GogsHooksNewPost(ctx *context.Context, form auth.NewGogshookForm) { +func GogsHooksNewPost(ctx *context.Context, form auth.NewWebhookForm) { + newGenericWebhookPost(ctx, form, models.GOGS) +} + +func newGenericWebhookPost(ctx *context.Context, form auth.NewWebhookForm, kind models.HookTaskType) { ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook") ctx.Data["PageIsSettingsHooks"] = true ctx.Data["PageIsSettingsHooksNew"] = true ctx.Data["Webhook"] = models.Webhook{HookEvent: &models.HookEvent{}} - ctx.Data["HookType"] = "gogs" + + ctx.Data["HookType"] = "gitea" + if kind == models.GOGS { + ctx.Data["HookType"] = "gogs" + } orCtx, err := getOrgRepoCtx(ctx) if err != nil { @@ -228,7 +236,7 @@ func GogsHooksNewPost(ctx *context.Context, form auth.NewGogshookForm) { Secret: form.Secret, HookEvent: ParseHookEvent(form.WebhookForm), IsActive: form.Active, - HookTaskType: models.GOGS, + HookTaskType: kind, OrgID: orCtx.OrgID, } if err := w.UpdateEvent(); err != nil { diff --git a/routers/routes/routes.go b/routers/routes/routes.go index f7ccfc43d24b5..744088a9d7b1e 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -47,19 +47,6 @@ import ( macaron "gopkg.in/macaron.v1" ) -/*func giteaLogger(l *log.LoggerAsWriter) macaron.Handler { - return func(ctx *macaron.Context) { - start := time.Now() - - l.Log(fmt.Sprintf("[Macaron] Started %s %s for %s", ctx.Req.Method, ctx.Req.RequestURI, ctx.RemoteAddr())) - - ctx.Next() - - rw := ctx.Resp.(macaron.ResponseWriter) - l.Log(fmt.Sprintf("[Macaron] Completed %s %s %v %s in %v", ctx.Req.Method, ctx.Req.RequestURI, rw.Status(), http.StatusText(rw.Status()), time.Since(start))) - } -}*/ - type routerLoggerOptions struct { Ctx *macaron.Context Identity *string @@ -83,14 +70,20 @@ func setupAccessLogger(m *macaron.Macaron) { rw := ctx.Resp.(macaron.ResponseWriter) buf := bytes.NewBuffer([]byte{}) - logTemplate.Execute(buf, routerLoggerOptions{ + err := logTemplate.Execute(buf, routerLoggerOptions{ Ctx: ctx, Identity: &identity, Start: &start, ResponseWriter: &rw, }) + if err != nil { + log.Error("Could not set up macaron access logger: %v", err.Error()) + } - logger.SendLog(log.INFO, "", "", 0, buf.String(), "") + err = logger.SendLog(log.INFO, "", "", 0, buf.String(), "") + if err != nil { + log.Error("Could not set up macaron access logger: %v", err.Error()) + } }) } @@ -99,13 +92,13 @@ func RouterHandler(level log.Level) func(ctx *macaron.Context) { return func(ctx *macaron.Context) { start := time.Now() - log.GetLogger("router").Log(0, level, "Started %s %s for %s", log.ColoredMethod(ctx.Req.Method), ctx.Req.RequestURI, ctx.RemoteAddr()) + _ = log.GetLogger("router").Log(0, level, "Started %s %s for %s", log.ColoredMethod(ctx.Req.Method), ctx.Req.RequestURI, ctx.RemoteAddr()) rw := ctx.Resp.(macaron.ResponseWriter) ctx.Next() status := rw.Status() - log.GetLogger("router").Log(0, level, "Completed %s %s %v %s in %v", log.ColoredMethod(ctx.Req.Method), ctx.Req.RequestURI, log.ColoredStatus(status), log.ColoredStatus(status, http.StatusText(rw.Status())), log.ColoredTime(time.Since(start))) + _ = log.GetLogger("router").Log(0, level, "Completed %s %s %v %s in %v", log.ColoredMethod(ctx.Req.Method), ctx.Req.RequestURI, log.ColoredStatus(status), log.ColoredStatus(status, http.StatusText(rw.Status())), log.ColoredTime(time.Since(start))) } } @@ -443,14 +436,14 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/delete", admin.DeleteDefaultWebhook) m.Get("/:type/new", repo.WebhooksNew) m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) - m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) + m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) m.Post("/dingtalk/new", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost) m.Post("/msteams/new", bindIgnErr(auth.NewMSTeamsHookForm{}), repo.MSTeamsHooksNewPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/gitea/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) - m.Post("/gogs/:id", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksEditPost) + m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.GogsHooksEditPost) m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) m.Post("/discord/:id", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksEditPost) m.Post("/dingtalk/:id", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksEditPost) @@ -582,7 +575,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/delete", org.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) - m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) + m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) m.Post("/dingtalk/new", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost) @@ -640,7 +633,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/delete", repo.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) m.Post("/gitea/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) - m.Post("/gogs/new", bindIgnErr(auth.NewGogshookForm{}), repo.GogsHooksNewPost) + m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.GogsHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Post("/discord/new", bindIgnErr(auth.NewDiscordHookForm{}), repo.DiscordHooksNewPost) m.Post("/dingtalk/new", bindIgnErr(auth.NewDingtalkHookForm{}), repo.DingtalkHooksNewPost) diff --git a/routers/user/auth.go b/routers/user/auth.go index b8f697b3ca4cd..0731e34675613 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -77,8 +77,14 @@ func AutoSignIn(ctx *context.Context) (bool, error) { } isSucceed = true - ctx.Session.Set("uid", u.ID) - ctx.Session.Set("uname", u.Name) + err = ctx.Session.Set("uid", u.ID) + if err != nil { + return false, err + } + err = ctx.Session.Set("uname", u.Name) + if err != nil { + return false, err + } ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) return true, nil } @@ -191,8 +197,16 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) { } // User needs to use 2FA, save data and redirect to 2FA page. - ctx.Session.Set("twofaUid", u.ID) - ctx.Session.Set("twofaRemember", form.Remember) + err = ctx.Session.Set("twofaUid", u.ID) + if err != nil { + ctx.ServerError("UserSignIn", err) + return + } + err = ctx.Session.Set("twofaRemember", form.Remember) + if err != nil { + ctx.ServerError("UserSignIn", err) + return + } regs, err := models.GetU2FRegistrationsByUID(u.ID) if err == nil && len(regs) > 0 { @@ -383,6 +397,10 @@ func U2FChallenge(ctx *context.Context) { return } challenge, err := u2f.NewChallenge(setting.U2F.AppID, setting.U2F.TrustedFacets) + if err != nil { + ctx.ServerError("u2f.NewChallenge", err) + return + } if err = ctx.Session.Set("u2fChallenge", challenge); err != nil { ctx.ServerError("UserSignIn", err) return @@ -462,16 +480,22 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR setting.CookieRememberName, u.Name, days, setting.AppSubURL, "", setting.SessionConfig.Secure, true) } - ctx.Session.Delete("openid_verified_uri") - ctx.Session.Delete("openid_signin_remember") - ctx.Session.Delete("openid_determined_email") - ctx.Session.Delete("openid_determined_username") - ctx.Session.Delete("twofaUid") - ctx.Session.Delete("twofaRemember") - ctx.Session.Delete("u2fChallenge") - ctx.Session.Delete("linkAccount") - ctx.Session.Set("uid", u.ID) - ctx.Session.Set("uname", u.Name) + _ = ctx.Session.Delete("openid_verified_uri") + _ = ctx.Session.Delete("openid_signin_remember") + _ = ctx.Session.Delete("openid_determined_email") + _ = ctx.Session.Delete("openid_determined_username") + _ = ctx.Session.Delete("twofaUid") + _ = ctx.Session.Delete("twofaRemember") + _ = ctx.Session.Delete("u2fChallenge") + _ = ctx.Session.Delete("linkAccount") + err := ctx.Session.Set("uid", u.ID) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } + err = ctx.Session.Set("uname", u.Name) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } // Language setting of the user overwrites the one previously set // If the user does not have a locale set, we save the current one. @@ -563,7 +587,10 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context if u == nil { // no existing user is found, request attach or new account - ctx.Session.Set("linkAccountGothUser", gothUser) + err = ctx.Session.Set("linkAccountGothUser", gothUser) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } ctx.Redirect(setting.AppSubURL + "/user/link_account") return } @@ -573,8 +600,14 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context _, err = models.GetTwoFactorByUID(u.ID) if err != nil { if models.IsErrTwoFactorNotEnrolled(err) { - ctx.Session.Set("uid", u.ID) - ctx.Session.Set("uname", u.Name) + err = ctx.Session.Set("uid", u.ID) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } + err = ctx.Session.Set("uname", u.Name) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } // Clear whatever CSRF has right now, force to generate a new one ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) @@ -600,8 +633,14 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context } // User needs to use 2FA, save data and redirect to 2FA page. - ctx.Session.Set("twofaUid", u.ID) - ctx.Session.Set("twofaRemember", false) + err = ctx.Session.Set("twofaUid", u.ID) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } + err = ctx.Session.Set("twofaRemember", false) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } // If U2F is enrolled -> Redirect to U2F instead regs, err := models.GetU2FRegistrationsByUID(u.ID) @@ -760,9 +799,18 @@ func LinkAccountPostSignIn(ctx *context.Context, signInForm auth.SignInForm) { } // User needs to use 2FA, save data and redirect to 2FA page. - ctx.Session.Set("twofaUid", u.ID) - ctx.Session.Set("twofaRemember", signInForm.Remember) - ctx.Session.Set("linkAccount", true) + err = ctx.Session.Set("twofaUid", u.ID) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } + err = ctx.Session.Set("twofaRemember", signInForm.Remember) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } + err = ctx.Session.Set("linkAccount", true) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } // If U2F is enrolled -> Redirect to U2F instead regs, err := models.GetU2FRegistrationsByUID(u.ID) @@ -897,11 +945,11 @@ func LinkAccountPostRegister(ctx *context.Context, cpt *captcha.Captcha, form au } func handleSignOut(ctx *context.Context) { - ctx.Session.Delete("uid") - ctx.Session.Delete("uname") - ctx.Session.Delete("socialId") - ctx.Session.Delete("socialName") - ctx.Session.Delete("socialEmail") + _ = ctx.Session.Delete("uid") + _ = ctx.Session.Delete("uname") + _ = ctx.Session.Delete("socialId") + _ = ctx.Session.Delete("socialName") + _ = ctx.Session.Delete("socialEmail") ctx.SetCookie(setting.CookieUserName, "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) ctx.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) ctx.SetCookie(setting.CSRFCookieName, "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) @@ -1086,8 +1134,14 @@ func Activate(ctx *context.Context) { log.Trace("User activated: %s", user.Name) - ctx.Session.Set("uid", user.ID) - ctx.Session.Set("uname", user.Name) + err = ctx.Session.Set("uid", user.ID) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } + err = ctx.Session.Set("uname", user.Name) + if err != nil { + log.Error(fmt.Sprintf("Error setting session: %v", err)) + } ctx.Flash.Success(ctx.Tr("auth.account_activated")) ctx.Redirect(setting.AppSubURL + "/") return @@ -1113,7 +1167,6 @@ func ActivateEmail(ctx *context.Context) { } ctx.Redirect(setting.AppSubURL + "/user/settings/email") - return } // ForgotPasswd render the forget pasword page diff --git a/routers/user/auth_openid.go b/routers/user/auth_openid.go index 1351ca040b7fa..f98c07acd79f8 100644 --- a/routers/user/auth_openid.go +++ b/routers/user/auth_openid.go @@ -126,7 +126,10 @@ func SignInOpenIDPost(ctx *context.Context, form auth.SignInOpenIDForm) { url += "&openid.sreg.optional=nickname%2Cemail" log.Trace("Form-passed openid-remember: %t", form.Remember) - ctx.Session.Set("openid_signin_remember", form.Remember) + err = ctx.Session.Set("openid_signin_remember", form.Remember) + if err != nil { + log.Error("SignInOpenIDPost: Could not set session: %v", err.Error()) + } ctx.Redirect(url) } @@ -152,7 +155,7 @@ func signInOpenIDVerify(ctx *context.Context) { /* Now we should seek for the user and log him in, or prompt * to register if not found */ - u, _ := models.GetUserByOpenID(id) + u, err := models.GetUserByOpenID(id) if err != nil { if !models.IsErrUserNotExist(err) { ctx.RenderWithErr(err.Error(), tplSignInOpenID, &auth.SignInOpenIDForm{ @@ -160,6 +163,7 @@ func signInOpenIDVerify(ctx *context.Context) { }) return } + log.Error("signInOpenIDVerify: %v", err) } if u != nil { log.Trace("User exists, logging in") @@ -191,7 +195,7 @@ func signInOpenIDVerify(ctx *context.Context) { log.Trace("User has email=" + email + " and nickname=" + nickname) if email != "" { - u, _ = models.GetUserByEmail(email) + u, err = models.GetUserByEmail(email) if err != nil { if !models.IsErrUserNotExist(err) { ctx.RenderWithErr(err.Error(), tplSignInOpenID, &auth.SignInOpenIDForm{ @@ -199,6 +203,7 @@ func signInOpenIDVerify(ctx *context.Context) { }) return } + log.Error("signInOpenIDVerify: %v", err) } if u != nil { log.Trace("Local user " + u.LowerName + " has OpenID provided email " + email) @@ -220,15 +225,24 @@ func signInOpenIDVerify(ctx *context.Context) { } } - ctx.Session.Set("openid_verified_uri", id) + err = ctx.Session.Set("openid_verified_uri", id) + if err != nil { + log.Error("signInOpenIDVerify: Could not set session: %v", err.Error()) + } - ctx.Session.Set("openid_determined_email", email) + err = ctx.Session.Set("openid_determined_email", email) + if err != nil { + log.Error("signInOpenIDVerify: Could not set session: %v", err.Error()) + } if u != nil { nickname = u.LowerName } - ctx.Session.Set("openid_determined_username", nickname) + err = ctx.Session.Set("openid_determined_username", nickname) + if err != nil { + log.Error("signInOpenIDVerify: Could not set session: %v", err.Error()) + } if u != nil || !setting.Service.EnableOpenIDSignUp { ctx.Redirect(setting.AppSubURL + "/user/openid/connect") @@ -350,7 +364,11 @@ func RegisterOpenIDPost(ctx *context.Context, cpt *captcha.Captcha, form auth.Si } if setting.Service.EnableCaptcha && setting.Service.CaptchaType == setting.ReCaptcha { - ctx.Req.ParseForm() + err := ctx.Req.ParseForm() + if err != nil { + ctx.ServerError("", err) + return + } valid, _ := recaptcha.Verify(form.GRecaptchaResponse) if !valid { ctx.Data["Err_Captcha"] = true diff --git a/routers/user/oauth.go b/routers/user/oauth.go index b85ea8125e333..aaad26201bb79 100644 --- a/routers/user/oauth.go +++ b/routers/user/oauth.go @@ -7,12 +7,10 @@ package user import ( "encoding/base64" "fmt" + "github.com/go-macaron/binding" "net/url" "strings" - "github.com/dgrijalva/jwt-go" - "github.com/go-macaron/binding" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" @@ -20,6 +18,8 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/util" + + "github.com/dgrijalva/jwt-go" ) const ( @@ -164,6 +164,14 @@ func newAccessTokenResponse(grant *models.OAuth2Grant) (*AccessTokenResponse, *A func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { errs := binding.Errors{} errs = form.Validate(ctx.Context, errs) + if len(errs) > 0 { + errstring := "" + for _, e := range errs { + errstring += e.Error() + "\n" + } + ctx.ServerError("AuthorizeOAuth: Validate: ", fmt.Errorf("errors occured during validation: %s", errstring)) + return + } app, err := models.GetOAuth2ApplicationByClientID(form.ClientID) if err != nil { @@ -221,7 +229,6 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { }, form.RedirectURI) return } - break case "": break default: @@ -262,9 +269,24 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { ctx.Data["ApplicationUserLink"] = "@" + app.User.Name + "" ctx.Data["ApplicationRedirectDomainHTML"] = "" + form.RedirectURI + "" // TODO document SESSION <=> FORM - ctx.Session.Set("client_id", app.ClientID) - ctx.Session.Set("redirect_uri", form.RedirectURI) - ctx.Session.Set("state", form.State) + err = ctx.Session.Set("client_id", app.ClientID) + if err != nil { + handleServerError(ctx, form.State, form.RedirectURI) + log.Error(err.Error()) + return + } + err = ctx.Session.Set("redirect_uri", form.RedirectURI) + if err != nil { + handleServerError(ctx, form.State, form.RedirectURI) + log.Error(err.Error()) + return + } + err = ctx.Session.Set("state", form.State) + if err != nil { + handleServerError(ctx, form.State, form.RedirectURI) + log.Error(err.Error()) + return + } ctx.HTML(200, tplGrantAccess) } diff --git a/routers/user/profile.go b/routers/user/profile.go index bda29522d9ccb..7df92d44f5925 100644 --- a/routers/user/profile.go +++ b/routers/user/profile.go @@ -20,7 +20,6 @@ import ( const ( tplFollowers base.TplName = "user/meta/followers" - tplStars base.TplName = "user/meta/stars" ) // GetUserByName get user by name diff --git a/routers/user/setting/profile.go b/routers/user/setting/profile.go index ac5c4c97fb27a..163bc869b4a16 100644 --- a/routers/user/setting/profile.go +++ b/routers/user/setting/profile.go @@ -141,13 +141,11 @@ func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *mo if err = ctxUser.UploadAvatar(data); err != nil { return fmt.Errorf("UploadAvatar: %v", err) } - } else { + } else if ctxUser.UseCustomAvatar && !com.IsFile(ctxUser.CustomAvatarPath()) { // No avatar is uploaded but setting has been changed to enable, // generate a random one when needed. - if ctxUser.UseCustomAvatar && !com.IsFile(ctxUser.CustomAvatarPath()) { - if err := ctxUser.GenerateRandomAvatar(); err != nil { - log.Error("GenerateRandomAvatar[%d]: %v", ctxUser.ID, err) - } + if err := ctxUser.GenerateRandomAvatar(); err != nil { + log.Error("GenerateRandomAvatar[%d]: %v", ctxUser.ID, err) } } diff --git a/routers/user/setting/security_twofa.go b/routers/user/setting/security_twofa.go index fca1151a04fc9..6e3516dbba081 100644 --- a/routers/user/setting/security_twofa.go +++ b/routers/user/setting/security_twofa.go @@ -73,6 +73,10 @@ func twofaGenerateSecretAndQr(ctx *context.Context) bool { uri := ctx.Session.Get("twofaUri") if uri != nil { otpKey, err = otp.NewKeyFromURL(uri.(string)) + if err != nil { + ctx.ServerError("SettingsTwoFactor: NewKeyFromURL: ", err) + return false + } } // Filter unsafe character ':' in issuer issuer := strings.Replace(setting.AppName+" ("+setting.Domain+")", ":", "", -1) @@ -103,8 +107,16 @@ func twofaGenerateSecretAndQr(ctx *context.Context) bool { } ctx.Data["QrUri"] = template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(imgBytes.Bytes())) - ctx.Session.Set("twofaSecret", otpKey.Secret()) - ctx.Session.Set("twofaUri", otpKey.String()) + err = ctx.Session.Set("twofaSecret", otpKey.Secret()) + if err != nil { + ctx.ServerError("SettingsTwoFactor", err) + return false + } + err = ctx.Session.Set("twofaUri", otpKey.String()) + if err != nil { + ctx.ServerError("SettingsTwoFactor", err) + return false + } return true } @@ -184,8 +196,16 @@ func EnrollTwoFactorPost(ctx *context.Context, form auth.TwoFactorAuthForm) { return } - ctx.Session.Delete("twofaSecret") - ctx.Session.Delete("twofaUri") + err = ctx.Session.Delete("twofaSecret") + if err != nil { + ctx.ServerError("SettingsTwoFactor", err) + return + } + err = ctx.Session.Delete("twofaUri") + if err != nil { + ctx.ServerError("SettingsTwoFactor", err) + return + } ctx.Flash.Success(ctx.Tr("settings.twofa_enrolled", token)) ctx.Redirect(setting.AppSubURL + "/user/settings/security") } diff --git a/routers/user/setting/security_u2f.go b/routers/user/setting/security_u2f.go index c1d6eab9672e9..b733467b846af 100644 --- a/routers/user/setting/security_u2f.go +++ b/routers/user/setting/security_u2f.go @@ -42,7 +42,11 @@ func U2FRegister(ctx *context.Context, form auth.U2FRegistrationForm) { return } } - ctx.Session.Set("u2fName", form.Name) + err = ctx.Session.Set("u2fName", form.Name) + if err != nil { + ctx.ServerError("", err) + return + } ctx.JSON(200, u2f.NewWebRegisterRequest(challenge, regs.ToRegistrations())) } @@ -95,5 +99,4 @@ func U2FDelete(ctx *context.Context, form auth.U2FDeleteForm) { ctx.JSON(200, map[string]interface{}{ "redirect": setting.AppSubURL + "/user/settings/security", }) - return } diff --git a/templates/user/meta/stars.tmpl b/templates/user/meta/stars.tmpl deleted file mode 100644 index e69de29bb2d1d..0000000000000 From 744fd6a1c87f2ad39dbe282133fae1190df6e538 Mon Sep 17 00:00:00 2001 From: John Olheiser <42128690+jolheiser@users.noreply.github.com> Date: Wed, 12 Jun 2019 15:20:43 -0500 Subject: [PATCH 28/30] Add error for fork already existing (#7185) --- models/error.go | 17 +++++++++++++++++ models/repo.go | 7 ++++--- models/repo_test.go | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/models/error.go b/models/error.go index fe0f05d36b27c..11ca6e6863f77 100644 --- a/models/error.go +++ b/models/error.go @@ -674,6 +674,23 @@ func (err ErrRepoAlreadyExist) Error() string { return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name) } +// ErrForkAlreadyExist represents a "ForkAlreadyExist" kind of error. +type ErrForkAlreadyExist struct { + Uname string + RepoName string + ForkName string +} + +// IsErrForkAlreadyExist checks if an error is an ErrForkAlreadyExist. +func IsErrForkAlreadyExist(err error) bool { + _, ok := err.(ErrForkAlreadyExist) + return ok +} + +func (err ErrForkAlreadyExist) Error() string { + return fmt.Sprintf("repository is already forked by user [uname: %s, repo path: %s, fork path: %s]", err.Uname, err.RepoName, err.ForkName) +} + // ErrRepoRedirectNotExist represents a "RepoRedirectNotExist" kind of error. type ErrRepoRedirectNotExist struct { OwnerID int64 diff --git a/models/repo.go b/models/repo.go index a4a7521aa48f1..8819debd4bcd0 100644 --- a/models/repo.go +++ b/models/repo.go @@ -2395,9 +2395,10 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R return nil, err } if forkedRepo != nil { - return nil, ErrRepoAlreadyExist{ - Uname: u.Name, - Name: forkedRepo.Name, + return nil, ErrForkAlreadyExist{ + Uname: u.Name, + RepoName: oldRepo.FullName(), + ForkName: forkedRepo.FullName(), } } diff --git a/models/repo_test.go b/models/repo_test.go index 8411536d70e23..02cb5ab993530 100644 --- a/models/repo_test.go +++ b/models/repo_test.go @@ -131,7 +131,7 @@ func TestForkRepository(t *testing.T) { fork, err := ForkRepository(user, user, repo, "test", "test") assert.Nil(t, fork) assert.Error(t, err) - assert.True(t, IsErrRepoAlreadyExist(err)) + assert.True(t, IsErrForkAlreadyExist(err)) } func TestRepoAPIURL(t *testing.T) { From 8f0182c3229dfbb8d731557e5006e39bd616b4e9 Mon Sep 17 00:00:00 2001 From: John Olheiser <42128690+jolheiser@users.noreply.github.com> Date: Wed, 12 Jun 2019 16:07:24 -0500 Subject: [PATCH 29/30] API error cleanup (#7186) --- integrations/api_repo_file_content_test.go | 3 +-- integrations/api_repo_file_create_test.go | 3 +-- integrations/api_repo_file_delete_test.go | 4 ++-- integrations/api_repo_file_update_test.go | 3 +-- modules/base/base.go | 3 --- modules/context/api.go | 13 ++----------- modules/setting/setting.go | 12 +++++++++--- 7 files changed, 16 insertions(+), 25 deletions(-) diff --git a/integrations/api_repo_file_content_test.go b/integrations/api_repo_file_content_test.go index 896d811083fb8..7a6025d423eb1 100644 --- a/integrations/api_repo_file_content_test.go +++ b/integrations/api_repo_file_content_test.go @@ -11,7 +11,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" @@ -98,7 +97,7 @@ func testAPIGetFileContents(t *testing.T, u *url.URL) { resp = session.MakeRequest(t, req, http.StatusInternalServerError) expectedAPIError := context.APIError{ Message: "object does not exist [id: " + branch + ", rel_path: ]", - URL: base.DocURL, + URL: setting.API.SwaggerURL, } var apiError context.APIError DecodeJSON(t, resp, &apiError) diff --git a/integrations/api_repo_file_create_test.go b/integrations/api_repo_file_create_test.go index 3bb2ecb812860..973ed9dfa595a 100644 --- a/integrations/api_repo_file_create_test.go +++ b/integrations/api_repo_file_create_test.go @@ -13,7 +13,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" @@ -160,7 +159,7 @@ func TestAPICreateFile(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusInternalServerError) expectedAPIError := context.APIError{ Message: "repository file already exists [path: " + treePath + "]", - URL: base.DocURL, + URL: setting.API.SwaggerURL, } var apiError context.APIError DecodeJSON(t, resp, &apiError) diff --git a/integrations/api_repo_file_delete_test.go b/integrations/api_repo_file_delete_test.go index e9029a669b977..2f5f9028a81a0 100644 --- a/integrations/api_repo_file_delete_test.go +++ b/integrations/api_repo_file_delete_test.go @@ -11,8 +11,8 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "github.com/stretchr/testify/assert" @@ -102,7 +102,7 @@ func TestAPIDeleteFile(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusInternalServerError) expectedAPIError := context.APIError{ Message: "sha does not match [given: " + deleteFileOptions.SHA + ", expected: " + correctSHA + "]", - URL: base.DocURL, + URL: setting.API.SwaggerURL, } var apiError context.APIError DecodeJSON(t, resp, &apiError) diff --git a/integrations/api_repo_file_update_test.go b/integrations/api_repo_file_update_test.go index eab7090df68f5..90fecf59d01a3 100644 --- a/integrations/api_repo_file_update_test.go +++ b/integrations/api_repo_file_update_test.go @@ -13,7 +13,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" @@ -173,7 +172,7 @@ func TestAPIUpdateFile(t *testing.T) { resp = session.MakeRequest(t, req, http.StatusInternalServerError) expectedAPIError := context.APIError{ Message: "sha does not match [given: " + updateFileOptions.SHA + ", expected: " + correctSHA + "]", - URL: base.DocURL, + URL: setting.API.SwaggerURL, } var apiError context.APIError DecodeJSON(t, resp, &apiError) diff --git a/modules/base/base.go b/modules/base/base.go index 0ba72c328e268..026f68f646ce3 100644 --- a/modules/base/base.go +++ b/modules/base/base.go @@ -4,9 +4,6 @@ package base -// DocURL api doc url -const DocURL = "https://godoc.org/github.com/go-gitea/go-sdk/gitea" - type ( // TplName template relative path type TplName string diff --git a/modules/context/api.go b/modules/context/api.go index 61f651475937b..9be3fb512cf3c 100644 --- a/modules/context/api.go +++ b/modules/context/api.go @@ -7,14 +7,11 @@ package context import ( "fmt" - "net/url" - "path" "strings" "github.com/go-macaron/csrf" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -76,7 +73,7 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) { ctx.JSON(status, APIError{ Message: message, - URL: base.DocURL, + URL: setting.API.SwaggerURL, }) } @@ -180,15 +177,9 @@ func (ctx *APIContext) NotFound(objs ...interface{}) { } } - u, err := url.Parse(setting.AppURL) - if err != nil { - ctx.Error(500, "Invalid AppURL", err) - return - } - u.Path = path.Join(u.Path, "api", "swagger") ctx.JSON(404, map[string]interface{}{ "message": message, - "documentation_url": u.String(), + "documentation_url": setting.API.SwaggerURL, "errors": errors, }) } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index b550836bc1640..5471a0b61d778 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -297,12 +297,14 @@ var ( // API settings API = struct { EnableSwagger bool + SwaggerURL string MaxResponseItems int DefaultPagingNum int DefaultGitTreesPerPage int DefaultMaxBlobSize int64 }{ EnableSwagger: true, + SwaggerURL: "", MaxResponseItems: 50, DefaultPagingNum: 30, DefaultGitTreesPerPage: 1000, @@ -581,17 +583,17 @@ func NewContext() { AppURL = strings.TrimRight(AppURL, "/") + "/" // Check if has app suburl. - url, err := url.Parse(AppURL) + appURL, err := url.Parse(AppURL) if err != nil { log.Fatal("Invalid ROOT_URL '%s': %s", AppURL, err) } // Suburl should start with '/' and end without '/', such as '/{subpath}'. // This value is empty if site does not have sub-url. - AppSubURL = strings.TrimSuffix(url.Path, "/") + AppSubURL = strings.TrimSuffix(appURL.Path, "/") AppSubURLDepth = strings.Count(AppSubURL, "/") // Check if Domain differs from AppURL domain than update it to AppURL's domain // TODO: Can be replaced with url.Hostname() when minimal GoLang version is 1.8 - urlHostname := strings.SplitN(url.Host, ":", 2)[0] + urlHostname := strings.SplitN(appURL.Host, ":", 2)[0] if urlHostname != Domain && net.ParseIP(urlHostname) == nil { Domain = urlHostname } @@ -900,6 +902,10 @@ func NewContext() { log.Fatal("Failed to map Metrics settings: %v", err) } + u := *appURL + u.Path = path.Join(u.Path, "api", "swagger") + API.SwaggerURL = u.String() + newCron() newGit() From 2f39fc7bb6a17b4637b723026a2e18dafd1a0adb Mon Sep 17 00:00:00 2001 From: Cherrg Date: Thu, 13 Jun 2019 06:23:45 +0200 Subject: [PATCH 30/30] fix drone build bug (#7192) --- Makefile | 1 + public/less/_repository.less | 2 ++ routers/user/oauth.go | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d7f27a8a94bc4..56fa863c8e790 100644 --- a/Makefile +++ b/Makefile @@ -469,6 +469,7 @@ pr: .PHONY: golangci-lint golangci-lint: @hash golangci-lint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ + export BINARY="golangci-lint"; \ curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.16.0; \ fi golangci-lint run diff --git a/public/less/_repository.less b/public/less/_repository.less index fcc153e31e8e9..71062bfa0eefd 100644 --- a/public/less/_repository.less +++ b/public/less/_repository.less @@ -1112,6 +1112,7 @@ .show-form-container { text-align: left; } + .choose.branch { .octicon { padding-right: 10px; @@ -2226,6 +2227,7 @@ tbody.commit-list { &.top { text-align: left; } + .commit-body { margin: 0; } diff --git a/routers/user/oauth.go b/routers/user/oauth.go index aaad26201bb79..924bac8ef6c49 100644 --- a/routers/user/oauth.go +++ b/routers/user/oauth.go @@ -169,7 +169,7 @@ func AuthorizeOAuth(ctx *context.Context, form auth.AuthorizationForm) { for _, e := range errs { errstring += e.Error() + "\n" } - ctx.ServerError("AuthorizeOAuth: Validate: ", fmt.Errorf("errors occured during validation: %s", errstring)) + ctx.ServerError("AuthorizeOAuth: Validate: ", fmt.Errorf("errors occurred during validation: %s", errstring)) return }