From 80baac19f25b1527dda8c27e4db70bc3a377faf4 Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Sat, 9 Dec 2023 00:24:26 +0000 Subject: [PATCH 1/6] [skip ci] Updated translations via Crowdin --- options/locale/locale_fr-FR.ini | 12 +++--- options/locale/locale_lv-LV.ini | 67 ++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 017444cbd091a..d2b90890dfa94 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -655,7 +655,7 @@ cancel=Annuler language=Langue ui=Thème hidden_comment_types=Catégories de commentaires masqués -hidden_comment_types_description=Les catégories cochées masquent les commentaires respectifs des tickets. Par exemple, « Label » cache les commentaires du genre « Cerise a attribué le label Bug il y a 2 heures. » +hidden_comment_types_description=Cochez les catégories suivantes pour masquer les commentaires correspondants des fils d'activité. Par exemple, « Label » cache les commentaires du genre « Cerise a attribué le label Bug il y a 2 heures. » hidden_comment_types.ref_tooltip=Commentaires où ce ticket a été référencé sur un autre ticket, révision, etc. hidden_comment_types.issue_ref_tooltip=Commentaires où l’utilisateur change la branche/étiquette associée au ticket comment_type_group_reference=Référence @@ -3227,7 +3227,7 @@ comment_pull=`a commenté la demande d’ajout %[3]s#%[2]s` merge_pull_request=`a fusionné la demande d’ajout %[3]s#%[2]s` auto_merge_pull_request=`a fusionné automatiquement la demande d’ajout %[3]s#%[2]s` transfer_repo=a transféré le dépôt %s vers %s -push_tag=a poussé l’étiquette %[3]s vers %[4]s +push_tag=a poussé l’étiquette %[3]s de %[4]s delete_tag=a supprimé l’étiquette %[2]s de %[3]s delete_branch=a supprimée la branche %[2]s de %[3]s compare_branch=Comparer @@ -3236,12 +3236,12 @@ compare_commits_general=Comparer les révisions mirror_sync_push=a synchronisé les révisions de %[3]s d’un miroir vers %[4]s. mirror_sync_create=a synchronisé la nouvelle référence %[3]s d’un miroir vers %[4]s. mirror_sync_delete=a synchronisé puis supprimé la nouvelle référence %[2]s vers %[3]s depuis le miroir -approve_pull_request=`a approuvé %[3]s#%[2]s.` +approve_pull_request=`a approuvé %[3]s#%[2]s` reject_pull_request=`a suggérés des changements pour %[3]s#%[2]s` -publish_release=`a publié "%[4]s" à %[3]s` -review_dismissed=`a révoqué l’évaluation de %[4]s sur %[3]s#%[2]s.` +publish_release=`a publié "%[4]s" dans %[3]s` +review_dismissed=`a révoqué l’évaluation de %[4]s dans %[3]s#%[2]s` review_dismissed_reason=Raison : -create_branch=a créé la branche %[3]s dans %[4]s. +create_branch=a créé la branche %[3]s dans %[4]s starred_repo=aime %[2]s watched_repo=observe %[2]s diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 1af1cc368564c..d0d4a39886011 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -3,7 +3,8 @@ dashboard=Infopanelis explore=Izpētīt help=Palīdzība logo=Logo -sign_in=Pierakstīties +sign_in=Pieteikties +sign_in_with_provider=Pieteikties ar %s sign_in_or=vai sign_out=Izrakstīties sign_up=Reģistrēties @@ -18,7 +19,7 @@ notifications=Paziņojumi active_stopwatch=Aktīvā laika uzskaite create_new=Izveidot… user_profile_and_more=Profils un iestatījumi… -signed_in_as=Pierakstījies kā +signed_in_as=Pieteicies kā enable_javascript=Šai lapas darbībai ir nepieciešams JavaScript. toc=Satura rādītājs licenses=Licences @@ -252,14 +253,14 @@ federated_avatar_lookup_popup=Iespējot apvienoto profila bilžu meklētāju, la disable_registration=Atspējot lietotāju reģistrāciju disable_registration_popup=Atspējot iespēju reģistrēties. Tikai administratori varēs izveidot jaunus kontus. allow_only_external_registration_popup=Atļaut reģistrēties tikai ar ārējiem servisiem -openid_signin=Iespējot OpenID autorizāciju -openid_signin_popup=Iespējot lietotāju autorizāciju ar OpenID. +openid_signin=Iespējot pieteikšanos ar OpenID +openid_signin_popup=Iespējot lietotāju pieteikšanos ar OpenID. openid_signup=Iespējot reģistrāciju, izmantojot OpenID openid_signup_popup=Iespējot lietotāju reģistrāciju pirms tam autorizējoties ar OpenID. enable_captcha=Pieprasīt drošības kodu lietotāju reģistrācijā enable_captcha_popup=Lietotājam reģistrējoties, pieprasīt ievadīt drošības kodu. -require_sign_in_view=Iespējot nepieciešamību autorizēties, lai aplūkotu lapas -require_sign_in_view_popup=Tikai autorizēti lietotāji var aplūkot lapas. Apmeklētāji redzēs tikai autorizācijas un reģistrācijas lapu. +require_sign_in_view=Pieprasīt pieteikšanos, lai aplūkotu lapas +require_sign_in_view_popup=Ierobežot piekļuvi lapām tikai lietotājiem, kuri ir pieteikušies. Apmeklētāji redzēs tikai pieteikšanās un reģistrēšanās lapu. admin_setting_desc=Nav nepieciešams izveidot administratora kontu uzreiz, pirmais reģistrētais lietotājs saņems administratora tiesības automātiski. admin_title=Administratora konta iestatījumi admin_name=Administratora lietotājvārds @@ -345,7 +346,7 @@ relevant_repositories=Tikai būtiskie repozitoriji tiek rādīti, p [auth] create_new_account=Reģistrēt kontu -register_helper_msg=Jau ir konts? Pieraksties tagad! +register_helper_msg=Jau ir konts? Piesakieties tagad! social_register_helper_msg=Jau ir konts? Piesaisti to! disable_register_prompt=Reģistrācija ir atspējota. Lūdzu, sazinieties ar vietnes administratoru. disable_register_mail=Reģistrācijas e-pasta apstiprināšana ir atspējota. @@ -360,7 +361,8 @@ allow_password_change=Pieprasīt lietotājam mainīt paroli (ieteicams) reset_password_mail_sent_prompt=Apstiprināšanas e-pasts tika nosūtīts uz %s. Pārbaudiet savu e-pasta kontu tuvāko %s laikā, lai pabeigtu paroles atjaunošanas procesu. active_your_account=Aktivizēt savu kontu account_activated=Konts ir aktivizēts -prohibit_login=Aizliegt pieteikšanos +prohibit_login=Pieteikšanās liegta +prohibit_login_desc=Jūsu konts ir bloķēts, sazinieties ar sistēmas administratoru. resent_limit_prompt=Jūs pieprasījāt aktivizācijas e-pastu pārāk bieži. Lūdzu, uzgaidiet 3 minūtes un mēģiniet vēlreiz. has_unconfirmed_mail=Sveiki %s, Jums ir neapstiprināta e-pasta adrese (%s). Ja neesat saņēmis apstiprināšanas e-pastu vai Jums ir nepieciešams nosūtīt jaunu, lūdzu, nospiediet pogu, kas atrodas zemāk. resend_mail=Nospiediet šeit, lai vēlreiz nosūtītu aktivizācijas e-pastu @@ -370,25 +372,26 @@ reset_password=Paroles atjaunošana invalid_code=Jūsu apstiprināšanas kodam ir beidzies derīguma termiņš vai arī tas ir nepareizs. invalid_password=Jūsu parole neatbilst parolei, kas tika ievadīta veidojot so kontu. reset_password_helper=Atjaunot paroli +reset_password_wrong_user=Jūs esat pieteicies kā %s, bet konta atkopšanas saite ir paredzēta lietotājam %s password_too_short=Paroles garums nedrīkst būt mazāks par %d simboliem. non_local_account=Ārējie konti nevar mainīt paroli, izmantojot, Gitea saskarni. verify=Pārbaudīt scratch_code=Vienreizējais kods use_scratch_code=Izmantot vienreizējo kodu twofa_scratch_used=Vienreizējais kods tika izmantots. Notika pārvirzīšana uz divfaktoru iestatījumu lapu, lai varētu pārsaistīt jaunu ierīci vai uzģenerēt jaunu vienreizējo kodu. -twofa_passcode_incorrect=Jūsu kods nav pareizs. Ja esat pazaudējis ierīci, izmantojiet vienreizējo kodu, lai autorizētos. +twofa_passcode_incorrect=Piekļuves kods nav pareizs. Ja esat pazaudējis ierīci, izmantojiet vienreizējo kodu, lai pieteiktos. twofa_scratch_token_incorrect=Ievadīts nepareizs vienreizējais kods. -login_userpass=Pierakstīties +login_userpass=Pieteikties login_openid=OpenID oauth_signup_tab=Reģistrēt jaunu kontu oauth_signup_title=Pabeigt konta veidošanu oauth_signup_submit=Pabeigt reģistrāciju -oauth_signin_tab=Savienot ar esošu kontu -oauth_signin_title=Pierakstīties, lai autorizētu saistīto kontu +oauth_signin_tab=Sasaistīt ar esošu kontu +oauth_signin_title=Pieteikties, lai autorizētu saistīto kontu oauth_signin_submit=Sasaistīt kontu -oauth.signin.error=Radās kļūda apstrādājot autorizācijas pieprasījumu. Ja šī kļūda atkārtojas, sazinieties ar lapas administratoru. +oauth.signin.error=Radās kļūda apstrādājot pieteikšanās pieprasījumu. Ja šī kļūda atkārtojas, sazinieties ar lapas administratoru. oauth.signin.error.access_denied=Autorizācijas pieprasījums tika noraidīts. -oauth.signin.error.temporarily_unavailable=Autorizācija neizdevās, jo autentifikācijas serveris ir īslaicīgi nepieejams. Mēģiniet autorizēties vēlāk. +oauth.signin.error.temporarily_unavailable=Pieteikšanās neizdevās, jo autentifikācijas serveris ir īslaicīgi nepieejams. Mēģiniet autorizēties vēlāk. openid_connect_submit=Pievienoties openid_connect_title=Pievienoties jau esošam kontam openid_connect_desc=Izvēlētais OpenID konts sistēmā netika atpazīts, bet Jūs to varat piesaistīt esošam kontam. @@ -662,7 +665,7 @@ change_password=Mainīt paroli old_password=Pašreizējā parole new_password=Jauna parole password_incorrect=Ievadīta nepareiza pašreizējā parole. -change_password_success=Parole tika veiksmīgi nomainīta. Tagad varat autorizēties ar jauno paroli. +change_password_success=Parole tika veiksmīgi nomainīta. Tagad varat pieteikties ar jauno paroli. password_change_disabled=Ārējie konti nevar mainīt paroli, izmantojot, Gitea saskarni. emails=E-pasta adreses @@ -683,7 +686,7 @@ email_deletion_success=E-pasta adrese ir veiksmīgi izdzēsta. theme_update_success=Jūsu motīvs tika nomainīts. theme_update_error=Izvēlētais motīvs neeksistē. openid_deletion=Dzēst OpenID adresi -openid_deletion_desc=Dzēšot šo OpenID adresi no Jūsu konta, ar to vairs nebūs iespējams autorizēties. Vai turpināt? +openid_deletion_desc=Dzēšot šo OpenID adresi no Jūsu konta, ar to vairs nebūs iespējams pieteikties. Vai turpināt? openid_deletion_success=OpenID adrese tika noņemta. add_new_email=Pievienot jaunu e-pasta adresi add_new_openid=Pievienot jaunu OpenID vietrādi @@ -772,6 +775,7 @@ ssh_disabled=SSH atspējots ssh_signonly=SSH ir atspējots, līdz ar to šīs atslēgas tiks izmantotas tikai revīziju parakstu pārbaudei. ssh_externally_managed=Šim lietotājam SSH atslēga tiek pāvaldīta attālināti manage_social=Pārvaldīt piesaistītos sociālos kontus +social_desc=Šie sociālo tīklu konti var tikt izmantoti, lai pieteiktos. Pārliecinieties, ka visi ir atpazīstami. unbind=Atsaistīt manage_access_token=Pārvaldīt piekļuves pilnvaras @@ -828,7 +832,7 @@ twofa_scratch_token_regenerate=Ģenerēt jaunu vienreizējo kodu twofa_enroll=Ieslēgt divfaktoru autentifikāciju twofa_disable_note=Nepieciešamības gadījumā divfaktoru autentifikāciju ir iespējams atslēgt. twofa_disable_desc=Atslēdzot divfaktoru autentifikāciju, konts vairs nebūs tik drošs. Vai turpināt? -regenerate_scratch_token_desc=Ja esat aizmirsis vienreizējo kodu vai jau esat to izmantojis, lai autorizētos, atjaunojiet to šeit. +regenerate_scratch_token_desc=Ja esat aizmirsis vienreizējo kodu vai esat to jau izmantojis, lai pieteiktos, atjaunojiet to šeit. twofa_disabled=Divfaktoru autentifikācija tika atslēgta. scan_this_image=Noskenējiet šo attēlu ar autentifikācijas lietojumprogrammu: or_enter_secret=Vai ievadiet šo noslēpumu: %s @@ -841,7 +845,7 @@ webauthn_desc=Drošības atslēgas ir fiziskas ierīces, kas satur kriptogrāfis webauthn_register_key=Pievienot drošības atslēgu webauthn_nickname=Segvārds webauthn_delete_key=Noņemt drošības atslēgu -webauthn_delete_key_desc=Noņemot drošības atslēgu ar to vairs nebūs iespējams autorizēties. Turpināt? +webauthn_delete_key_desc=Noņemot drošības atslēgu ar to vairs nebūs iespējams pieteikties. Vai turpināt? manage_account_links=Pārvaldīt saistītos kontus manage_account_links_desc=Šādi ārējie konti ir piesaistīti Jūsu Gitea kontam. @@ -1045,9 +1049,9 @@ mirror_from=spogulis no forked_from=atdalīts no generated_from=ģenerēts no fork_from_self=Nav iespējams atdalīt repozitoriju, kuram esat īpašnieks. -fork_guest_user=Autorizējieties, lai atdalītu repozitoriju. -watch_guest_user=Autorizejieties, lai sekotu šim repozitorijam. -star_guest_user=Autorizejieties, lai atzīmētu ar zvaigznīti šo repozitoriju. +fork_guest_user=Piesakieties, lai atdalītu repozitoriju. +watch_guest_user=Piesakieties, lai sekotu šim repozitorijam. +star_guest_user=Piesakieties, lai atzīmētu šo repozitoriju ar zvaigznīti. unwatch=Nevērot watch=Vērot unstar=Noņemt zvaigznīti @@ -1293,7 +1297,7 @@ issues.new.clear_assignees=Noņemt atbildīgo issues.new.no_assignees=Nav atbildīgo issues.new.no_reviewers=Nav recenzentu issues.choose.get_started=Sākt darbu -issues.choose.open_external_link=Aktīvie +issues.choose.open_external_link=Atvērt issues.choose.blank=Noklusējuma issues.choose.blank_about=Izveidot problēmu ar noklusējuma sagatavi. issues.choose.ignore_invalid_templates=Kļūdainās sagataves tika izlaistas @@ -1422,7 +1426,7 @@ issues.remove_request_review=Noņemt recenzijas pieprasījumu issues.remove_request_review_block=Nevar noņemt recenzījas pieprasījumu issues.dismiss_review=Atmest recenziju issues.dismiss_review_warning=Vai patiešām vēlaties atmest šo recenziju? -issues.sign_in_require_desc=Pierakstieties, lai pievienotos šai sarunai. +issues.sign_in_require_desc=Nepieciešams pieteikties, lai pievienotos šai sarunai. issues.edit=Labot issues.cancel=Atcelt issues.save=Saglabāt @@ -1735,6 +1739,8 @@ milestones.filter_sort.most_complete=Visvairāk pabeigtais milestones.filter_sort.most_issues=Visvairāk problēmu milestones.filter_sort.least_issues=Vismazāk problēmu +signing.wont_sign.error=Notika kļūda pārbaudot vai revīzija var tikt parakstīta. +signing.wont_sign.not_signed_in=Jūs neesat pieteicies. ext_wiki=Piekļuve ārējai vikivietnei ext_wiki.desc=Ārējā vikivietne norāda uz ārējo vikivietnes adresi. @@ -1865,6 +1871,7 @@ settings.mirror_settings.docs.no_new_mirrors=Šis repozitorijs spoguļo izmaiņa settings.mirror_settings.docs.can_still_use=Lai arī nav iespējams mainīt esošos vai izveidot jaunus spoguļa repozitorijus, esošie turpinās strādāt. settings.mirror_settings.docs.pull_mirror_instructions=Lai ietatītu atvilkšanas spoguli, sekojiet instrukcijām: settings.mirror_settings.docs.doc_link_title=Kā spoguļot repozitorijus? +settings.mirror_settings.docs.doc_link_pull_section=dokumentācijas nodaļā "Pulling from a remote repository". settings.mirror_settings.docs.pulling_remote_title=Atvilkt no attāla repozitorija settings.mirror_settings.mirrored_repository=Spoguļotais repozitorijs settings.mirror_settings.direction=Virziens @@ -2632,8 +2639,8 @@ users.restricted=Ierobežots users.2fa=2FA users.repos=Repozitoriji users.created=Izveidots -users.last_login=Pēdējā autorizācija -users.never_login=Nekad nav autorizējies +users.last_login=Pēdējā pieteikšanās +users.never_login=Pieteikšanās nekad nav veikta users.send_register_notify=Nosūtīt lietotājam reģistrācijas paziņojumu users.new_success=Lietotāja konts "%s" tika izveidots. users.edit=Labot @@ -2646,7 +2653,7 @@ users.edit_account=Labot lietotāja kontu users.max_repo_creation=Maksimālais repozitoriju skaits users.max_repo_creation_desc=(Ievadiet -1 lai izmantotu noklusēto globālo ierobežojumu) users.is_activated=Lietotāja konts ir aktivizēts -users.prohibit_login=Atspējota pieslēgšanās +users.prohibit_login=Atspējota pieteikšanās users.is_admin=Administratora tiesības users.is_restricted=Ir ierobežots users.allow_git_hook=Atļaut veidot git āķus @@ -2825,7 +2832,7 @@ auths.tip.github=Reģistrējiet jaunu aplikāciju adresē https://github.com/set auths.tip.gitlab=Reģistrējiet jaunu aplikāciju adresē https://gitlab.com/profile/applications auths.tip.google_plus=Iegūstiet OAuth2 klienta pilnvaru no Google API konsoles adresē https://console.developers.google.com/ auths.tip.openid_connect=Izmantojiet OpenID pieslēgšanās atklāšanas URL (/.well-known/openid-configuration), lai norādītu galapunktus -auths.tip.twitter=Dodieties uz adresi https://dev.twitter.com/apps, izveidojiet aplikāciju un pārliecinieties, ka ir atzīmēts “Allow this application to be used to Sign in with Twitter” +auths.tip.twitter=Dodieties uz adresi https://dev.twitter.com/apps, izveidojiet lietotni un pārliecinieties, ka ir atzīmēts “Allow this application to be used to Sign in with Twitter” auths.tip.discord=Reģistrējiet jaunu aplikāciju adresē https://discordapp.com/developers/applications/me auths.tip.yandex=`Izveidojiet jaunu lietotni adresē https://oauth.yandex.com/client/new. Izvēlieties sekojošas tiesības "Yandex.Passport API" sadaļā: "Access to email address", "Access to user avatar" un "Access to username, first name and surname, gender"` auths.tip.mastodon=Norādiet pielāgotu mastodon instances URL, ar kuru vēlaties autorizēties (vai izmantojiet noklusēto) @@ -2836,7 +2843,7 @@ auths.update_success=Autentifikācijas avots tika atjaunots. auths.update=Atjaunot autentifikācijas avotu auths.delete=Dzēst autentifikācijas avotu auths.delete_auth_title=Dzēst autentifikācijas avotu -auths.delete_auth_desc=Izdzēšot autentifikācijas avotu, tā lietotājiem nebūs iespējams autorizēties. Vai turpināt? +auths.delete_auth_desc=Izdzēšot autentifikācijas avotu, tā lietotājiem nebūs iespējams pieteikties. Vai turpināt? auths.still_in_used=Šo autentificēšanās avotu joprojām izmanto viens vai vairāki lietotāji, tos nepieciešams izdzēst vai pārvietot uz citu autentificēšanās avotu. auths.deletion_success=Autentifikācijas avots tika atjaunots. auths.login_source_exist=Autentifikācijas avots ar nosaukumu "%s" jau eksistē. @@ -2894,9 +2901,9 @@ config.disable_register=Atspējot lietotāju reģistrāciju config.allow_only_internal_registration=Atļaut reģistrāciju tikai no Gitea config.allow_only_external_registration=Atļaut reģistrēties tikai ar ārējiem servisiem config.enable_openid_signup=Iespējot reģistrāciju, izmantojot OpenID -config.enable_openid_signin=Iespējot OpenID autorizāciju +config.enable_openid_signin=Iespējot pieteikšanos ar OpenID config.show_registration_button=Rādīt reģistrēšanās pogu -config.require_sign_in_view=Iespējot nepieciešamību autorizēties, lai aplūkotu lapas +config.require_sign_in_view=Pieprasīt pieteikšanos, lai aplūkotu lapas config.mail_notify=Iespējot e-pasta paziņojumus config.disable_key_size_check=Atspējot atslēgas minimālā garuma pārbaudi config.enable_captcha=Iespējot drošības kodu From 27c05069a6a120d7a991d802548e8b74792af3e4 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 9 Dec 2023 19:38:46 +0800 Subject: [PATCH 2/6] Remove stale since giteabot has similiar feature (#28401) Replace #27447 --- .github/stale.yml | 54 ----------------------------------------------- 1 file changed, 54 deletions(-) delete mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index ebe95acf533a3..0000000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,54 +0,0 @@ -# Configuration for probot-stale - https://github.com/probot/stale - -# Number of days of inactivity before an Issue or Pull Request becomes stale -daysUntilStale: 60 - -# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. -# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. -daysUntilClose: 14 - -# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable -exemptLabels: - - status/blocked - - kind/security - - lgtm/done - - reviewed/confirmed - - priority/critical - - kind/proposal - -# Set to true to ignore issues in a project (defaults to false) -exemptProjects: false - -# Set to true to ignore issues in a milestone (defaults to false) -exemptMilestones: false - -# Label to use when marking as stale -staleLabel: stale - -# Comment to post when marking as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had recent activity. - I am here to help clear issues left open even if solved or waiting for more insight. - This issue will be closed if no further activity occurs during the next 2 weeks. - If the issue is still valid just add a comment to keep it alive. - Thank you for your contributions. - -# Comment to post when closing a stale Issue or Pull Request. -closeComment: > - This issue has been automatically closed because of inactivity. - You can re-open it if needed. - -# Limit the number of actions per hour, from 1-30. Default is 30 -limitPerRun: 1 - -# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': -pulls: - daysUntilStale: 60 - daysUntilClose: 60 - markComment: > - This pull request has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs during the next 2 months. Thank you - for your contributions. - closeComment: > - This pull request has been automatically closed because of inactivity. - You can re-open it if needed. From aeb383025f90abcda7a9562684376b1996dcf3a5 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 9 Dec 2023 21:30:56 +0800 Subject: [PATCH 3/6] Also sync DB branches on push if necessary (#28361) Fix #28056 This PR will check whether the repo has zero branch when pushing a branch. If that, it means this repository hasn't been synced. The reason caused that is after user upgrade from v1.20 -> v1.21, he just push branches without visit the repository user interface. Because all repositories routers will check whether a branches sync is necessary but push has not such check. For every repository, it has two states, synced or not synced. If there is zero branch for a repository, then it will be assumed as non-sync state. Otherwise, it's synced state. So if we think it's synced, we just need to update branch/insert new branch. Otherwise do a full sync. So that, for every push, there will be almost no extra load added. It's high performance than yours. For the implementation, we in fact will try to update the branch first, if updated success with affect records > 0, then all are done. Because that means the branch has been in the database. If no record is affected, that means the branch does not exist in database. So there are two possibilities. One is this is a new branch, then we just need to insert the record. Another is the branches haven't been synced, then we need to sync all the branches into database. --- models/git/branch.go | 33 +++--- models/git/branch_list.go | 8 +- models/git/branch_test.go | 2 +- routers/api/v1/repo/branch.go | 5 +- routers/web/repo/branch.go | 4 +- services/repository/branch.go | 100 ++++++++++++------ services/repository/push.go | 2 +- .../api_repo_get_contents_list_test.go | 9 +- .../integration/api_repo_get_contents_test.go | 9 +- 9 files changed, 99 insertions(+), 73 deletions(-) diff --git a/models/git/branch.go b/models/git/branch.go index 6d50fb9fb6a18..ffd1d7ed164a0 100644 --- a/models/git/branch.go +++ b/models/git/branch.go @@ -205,10 +205,9 @@ func DeleteBranches(ctx context.Context, repoID, doerID int64, branchIDs []int64 }) } -// UpdateBranch updates the branch information in the database. If the branch exist, it will update latest commit of this branch information -// If it doest not exist, insert a new record into database -func UpdateBranch(ctx context.Context, repoID, pusherID int64, branchName string, commit *git.Commit) error { - cnt, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repoID, branchName). +// UpdateBranch updates the branch information in the database. +func UpdateBranch(ctx context.Context, repoID, pusherID int64, branchName string, commit *git.Commit) (int64, error) { + return db.GetEngine(ctx).Where("repo_id=? AND name=?", repoID, branchName). Cols("commit_id, commit_message, pusher_id, commit_time, is_deleted, updated_unix"). Update(&Branch{ CommitID: commit.ID.String(), @@ -217,21 +216,6 @@ func UpdateBranch(ctx context.Context, repoID, pusherID int64, branchName string CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), IsDeleted: false, }) - if err != nil { - return err - } - if cnt > 0 { - return nil - } - - return db.Insert(ctx, &Branch{ - RepoID: repoID, - Name: branchName, - CommitID: commit.ID.String(), - CommitMessage: commit.Summary(), - PusherID: pusherID, - CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), - }) } // AddDeletedBranch adds a deleted branch to the database @@ -308,6 +292,17 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str sess := db.GetEngine(ctx) + var branch Branch + exist, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repo.ID, from).Get(&branch) + if err != nil { + return err + } else if !exist || branch.IsDeleted { + return ErrBranchNotExist{ + RepoID: repo.ID, + BranchName: from, + } + } + // 1. update branch in database if n, err := sess.Where("repo_id=? AND name=?", repo.ID, from).Update(&Branch{ Name: to, diff --git a/models/git/branch_list.go b/models/git/branch_list.go index b5c1301a1dc00..2efe495264abe 100644 --- a/models/git/branch_list.go +++ b/models/git/branch_list.go @@ -73,7 +73,7 @@ type FindBranchOptions struct { Keyword string } -func (opts *FindBranchOptions) Cond() builder.Cond { +func (opts FindBranchOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) @@ -92,7 +92,7 @@ func (opts *FindBranchOptions) Cond() builder.Cond { } func CountBranches(ctx context.Context, opts FindBranchOptions) (int64, error) { - return db.GetEngine(ctx).Where(opts.Cond()).Count(&Branch{}) + return db.GetEngine(ctx).Where(opts.ToConds()).Count(&Branch{}) } func orderByBranches(sess *xorm.Session, opts FindBranchOptions) *xorm.Session { @@ -108,7 +108,7 @@ func orderByBranches(sess *xorm.Session, opts FindBranchOptions) *xorm.Session { } func FindBranches(ctx context.Context, opts FindBranchOptions) (BranchList, error) { - sess := db.GetEngine(ctx).Where(opts.Cond()) + sess := db.GetEngine(ctx).Where(opts.ToConds()) if opts.PageSize > 0 && !opts.IsListAll() { sess = db.SetSessionPagination(sess, &opts.ListOptions) } @@ -119,7 +119,7 @@ func FindBranches(ctx context.Context, opts FindBranchOptions) (BranchList, erro } func FindBranchNames(ctx context.Context, opts FindBranchOptions) ([]string, error) { - sess := db.GetEngine(ctx).Select("name").Where(opts.Cond()) + sess := db.GetEngine(ctx).Select("name").Where(opts.ToConds()) if opts.PageSize > 0 && !opts.IsListAll() { sess = db.SetSessionPagination(sess, &opts.ListOptions) } diff --git a/models/git/branch_test.go b/models/git/branch_test.go index ba6902692792e..07b243e5e6e92 100644 --- a/models/git/branch_test.go +++ b/models/git/branch_test.go @@ -37,7 +37,7 @@ func TestAddDeletedBranch(t *testing.T) { }, } - err := git_model.UpdateBranch(db.DefaultContext, repo.ID, secondBranch.PusherID, secondBranch.Name, commit) + _, err := git_model.UpdateBranch(db.DefaultContext, repo.ID, secondBranch.PusherID, secondBranch.Name, commit) assert.NoError(t, err) } diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index f2386a607e657..677105bdb506c 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -251,12 +251,11 @@ func CreateBranch(ctx *context.APIContext) { } } - err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, oldCommit.ID.String(), opt.BranchName) + err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, oldCommit.ID.String(), opt.BranchName) if err != nil { if git_model.IsErrBranchNotExist(err) { ctx.Error(http.StatusNotFound, "", "The old branch does not exist") - } - if models.IsErrTagAlreadyExists(err) { + } else if models.IsErrTagAlreadyExists(err) { ctx.Error(http.StatusConflict, "", "The branch with the same tag already exists.") } else if git_model.IsErrBranchAlreadyExists(err) || git.IsErrPushOutOfDate(err) { ctx.Error(http.StatusConflict, "", "The branch already exists.") diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index bc72d5f2eca17..a0bc1dadade8b 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -191,9 +191,9 @@ func CreateBranch(ctx *context.Context) { } err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, target, form.NewBranchName, "") } else if ctx.Repo.IsViewBranch { - err = repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName) + err = repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.Repo.BranchName, form.NewBranchName) } else { - err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName) + err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, ctx.Repo.CommitID, form.NewBranchName) } if err != nil { if models.IsErrProtectedTagName(err) { diff --git a/services/repository/branch.go b/services/repository/branch.go index 735fa1a756816..6dc286675f3d6 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/queue" repo_module "code.gitea.io/gitea/modules/repository" + "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" notify_service "code.gitea.io/gitea/services/notify" files_service "code.gitea.io/gitea/services/repository/files" @@ -28,35 +29,13 @@ import ( ) // CreateNewBranch creates a new repository branch -func CreateNewBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldBranchName, branchName string) (err error) { - err = repo.MustNotBeArchived() +func CreateNewBranch(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, oldBranchName, branchName string) (err error) { + branch, err := git_model.GetBranch(ctx, repo.ID, oldBranchName) if err != nil { return err } - // Check if branch name can be used - if err := checkBranchName(ctx, repo, branchName); err != nil { - return err - } - - if !git.IsBranchExist(ctx, repo.RepoPath(), oldBranchName) { - return git_model.ErrBranchNotExist{ - BranchName: oldBranchName, - } - } - - if err := git.Push(ctx, repo.RepoPath(), git.PushOptions{ - Remote: repo.RepoPath(), - Branch: fmt.Sprintf("%s%s:%s%s", git.BranchPrefix, oldBranchName, git.BranchPrefix, branchName), - Env: repo_module.PushingEnvironment(doer, repo), - }); err != nil { - if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) { - return err - } - return fmt.Errorf("push: %w", err) - } - - return nil + return CreateNewBranchFromCommit(ctx, doer, repo, gitRepo, branch.CommitID, branchName) } // Branch contains the branch information @@ -249,8 +228,49 @@ func checkBranchName(ctx context.Context, repo *repo_model.Repository, name stri return err } +// syncBranchToDB sync the branch information in the database. It will try to update the branch first, +// if updated success with affect records > 0, then all are done. Because that means the branch has been in the database. +// If no record is affected, that means the branch does not exist in database. So there are two possibilities. +// One is this is a new branch, then we just need to insert the record. Another is the branches haven't been synced, +// then we need to sync all the branches into database. +func syncBranchToDB(ctx context.Context, repoID, pusherID int64, branchName string, commit *git.Commit) error { + cnt, err := git_model.UpdateBranch(ctx, repoID, pusherID, branchName, commit) + if err != nil { + return fmt.Errorf("git_model.UpdateBranch %d:%s failed: %v", repoID, branchName, err) + } + if cnt > 0 { // This means branch does exist, so it's a normal update. It also means the branch has been synced. + return nil + } + + // if user haven't visit UI but directly push to a branch after upgrading from 1.20 -> 1.21, + // we cannot simply insert the branch but need to check we have branches or not + hasBranch, err := db.Exist[git_model.Branch](ctx, git_model.FindBranchOptions{ + RepoID: repoID, + IsDeletedBranch: util.OptionalBoolFalse, + }.ToConds()) + if err != nil { + return err + } + if !hasBranch { + if _, err = repo_module.SyncRepoBranches(ctx, repoID, pusherID); err != nil { + return fmt.Errorf("repo_module.SyncRepoBranches %d:%s failed: %v", repoID, branchName, err) + } + return nil + } + + // if database have branches but not this branch, it means this is a new branch + return db.Insert(ctx, &git_model.Branch{ + RepoID: repoID, + Name: branchName, + CommitID: commit.ID.String(), + CommitMessage: commit.Summary(), + PusherID: pusherID, + CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()), + }) +} + // CreateNewBranchFromCommit creates a new repository branch -func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commit, branchName string) (err error) { +func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, gitRepo *git.Repository, commitID, branchName string) (err error) { err = repo.MustNotBeArchived() if err != nil { return err @@ -261,18 +281,28 @@ func CreateNewBranchFromCommit(ctx context.Context, doer *user_model.User, repo return err } - if err := git.Push(ctx, repo.RepoPath(), git.PushOptions{ - Remote: repo.RepoPath(), - Branch: fmt.Sprintf("%s:%s%s", commit, git.BranchPrefix, branchName), - Env: repo_module.PushingEnvironment(doer, repo), - }); err != nil { - if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) { + return db.WithTx(ctx, func(ctx context.Context) error { + commit, err := gitRepo.GetCommit(commitID) + if err != nil { + return err + } + // database operation should be done before git operation so that we can rollback if git operation failed + if err := syncBranchToDB(ctx, repo.ID, doer.ID, branchName, commit); err != nil { return err } - return fmt.Errorf("push: %w", err) - } - return nil + if err := git.Push(ctx, repo.RepoPath(), git.PushOptions{ + Remote: repo.RepoPath(), + Branch: fmt.Sprintf("%s:%s%s", commitID, git.BranchPrefix, branchName), + Env: repo_module.PushingEnvironment(doer, repo), + }); err != nil { + if git.IsErrPushOutOfDate(err) || git.IsErrPushRejected(err) { + return err + } + return fmt.Errorf("push: %w", err) + } + return nil + }) } // RenameBranch rename a branch diff --git a/services/repository/push.go b/services/repository/push.go index 391c8ad4ca7f1..b5388834c0bd1 100644 --- a/services/repository/push.go +++ b/services/repository/push.go @@ -259,7 +259,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error { commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum] } - if err = git_model.UpdateBranch(ctx, repo.ID, opts.PusherID, branch, newCommit); err != nil { + if err = syncBranchToDB(ctx, repo.ID, opts.PusherID, branch, newCommit); err != nil { return fmt.Errorf("git_model.UpdateBranch %s:%s failed: %v", repo.FullName(), branch, err) } diff --git a/tests/integration/api_repo_get_contents_list_test.go b/tests/integration/api_repo_get_contents_list_test.go index f3a5159115c18..7874eddfd4d19 100644 --- a/tests/integration/api_repo_get_contents_list_test.go +++ b/tests/integration/api_repo_get_contents_list_test.go @@ -70,15 +70,16 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) { session = loginUser(t, user4.Name) token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) - // Make a new branch in repo1 - newBranch := "test_branch" - err := repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, repo1.DefaultBranch, newBranch) - assert.NoError(t, err) // Get the commit ID of the default branch gitRepo, err := git.OpenRepository(git.DefaultContext, repo1.RepoPath()) assert.NoError(t, err) defer gitRepo.Close() + // Make a new branch in repo1 + newBranch := "test_branch" + err = repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, gitRepo, repo1.DefaultBranch, newBranch) + assert.NoError(t, err) + commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch) // Make a new tag in repo1 newTag := "test_tag" diff --git a/tests/integration/api_repo_get_contents_test.go b/tests/integration/api_repo_get_contents_test.go index 709bbe082a5a4..1d708a4cdb438 100644 --- a/tests/integration/api_repo_get_contents_test.go +++ b/tests/integration/api_repo_get_contents_test.go @@ -72,15 +72,16 @@ func testAPIGetContents(t *testing.T, u *url.URL) { session = loginUser(t, user4.Name) token4 := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository) - // Make a new branch in repo1 - newBranch := "test_branch" - err := repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, repo1.DefaultBranch, newBranch) - assert.NoError(t, err) // Get the commit ID of the default branch gitRepo, err := git.OpenRepository(git.DefaultContext, repo1.RepoPath()) assert.NoError(t, err) defer gitRepo.Close() + // Make a new branch in repo1 + newBranch := "test_branch" + err = repo_service.CreateNewBranch(git.DefaultContext, user2, repo1, gitRepo, repo1.DefaultBranch, newBranch) + assert.NoError(t, err) + commitID, err := gitRepo.GetBranchCommitID(repo1.DefaultBranch) assert.NoError(t, err) // Make a new tag in repo1 From 9a99c17a1412fce29944bd9a87d7dc6d40423c77 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 11 Dec 2023 03:37:10 +0800 Subject: [PATCH 4/6] Fix missing check (#28406) --- routers/web/repo/issue_content_history.go | 22 ++++++++++++++++++---- routers/web/repo/issue_pin.go | 6 ++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go index 473ab260f3ea0..0f376db145063 100644 --- a/routers/web/repo/issue_content_history.go +++ b/routers/web/repo/issue_content_history.go @@ -193,15 +193,29 @@ func SoftDeleteContentHistory(ctx *context.Context) { var comment *issues_model.Comment var history *issues_model.ContentHistory var err error + + if history, err = issues_model.GetIssueContentHistoryByID(ctx, historyID); err != nil { + log.Error("can not get issue content history %v. err=%v", historyID, err) + return + } + if history.IssueID != issue.ID { + ctx.NotFound("CompareRepoID", issues_model.ErrCommentNotExist{}) + return + } if commentID != 0 { + if history.CommentID != commentID { + ctx.NotFound("CompareCommentID", issues_model.ErrCommentNotExist{}) + return + } + if comment, err = issues_model.GetCommentByID(ctx, commentID); err != nil { log.Error("can not get comment for issue content history %v. err=%v", historyID, err) return } - } - if history, err = issues_model.GetIssueContentHistoryByID(ctx, historyID); err != nil { - log.Error("can not get issue content history %v. err=%v", historyID, err) - return + if comment.IssueID != issue.ID { + ctx.NotFound("CompareIssueID", issues_model.ErrCommentNotExist{}) + return + } } canSoftDelete := canSoftDeleteContentHistory(ctx, issue, comment, history) diff --git a/routers/web/repo/issue_pin.go b/routers/web/repo/issue_pin.go index f853f72335e66..9f334129f943e 100644 --- a/routers/web/repo/issue_pin.go +++ b/routers/web/repo/issue_pin.go @@ -90,6 +90,12 @@ func IssuePinMove(ctx *context.Context) { return } + if issue.RepoID != ctx.Repo.Repository.ID { + ctx.Status(http.StatusNotFound) + log.Error("Issue does not belong to this repository") + return + } + err = issue.MovePin(ctx, form.Position) if err != nil { ctx.Status(http.StatusInternalServerError) From fab73e4a3a598aa9433522f27edf2d8efea3d0e0 Mon Sep 17 00:00:00 2001 From: Earl Warren <109468362+earl-warren@users.noreply.github.com> Date: Sun, 10 Dec 2023 21:15:06 +0100 Subject: [PATCH 5/6] Actually recover from a panic in cron task (#28409) - Currently there's code to recover gracefully from panics that happen within the execution of cron tasks. However this recover code wasn't being run, because `RunWithShutdownContext` also contains code to recover from any panic and then gracefully shutdown Forgejo. Because `RunWithShutdownContext` registers that code as last, that would get run first which in this case is not behavior that we want. - Move the recover code to inside the function, so that is run first before `RunWithShutdownContext`'s recover code (which is now a noop). Fixes: https://codeberg.org/forgejo/forgejo/issues/1910 Co-authored-by: Gusted --- services/cron/tasks.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/services/cron/tasks.go b/services/cron/tasks.go index d2c3d1d812c42..f0956a97d88c7 100644 --- a/services/cron/tasks.go +++ b/services/cron/tasks.go @@ -84,13 +84,15 @@ func (t *Task) RunWithUser(doer *user_model.User, config Config) { t.lock.Unlock() defer func() { taskStatusTable.Stop(t.Name) - if err := recover(); err != nil { - // Recover a panic within the - combinedErr := fmt.Errorf("%s\n%s", err, log.Stack(2)) - log.Error("PANIC whilst running task: %s Value: %v", t.Name, combinedErr) - } }() graceful.GetManager().RunWithShutdownContext(func(baseCtx context.Context) { + defer func() { + if err := recover(); err != nil { + // Recover a panic within the execution of the task. + combinedErr := fmt.Errorf("%s\n%s", err, log.Stack(2)) + log.Error("PANIC whilst running task: %s Value: %v", t.Name, combinedErr) + } + }() // Store the time of this run, before the function is executed, so it // matches the behavior of what the cron library does. t.lock.Lock() From 5b2bbf1a1f2527b75d8a64bc36ea735cd19c0efa Mon Sep 17 00:00:00 2001 From: GiteaBot Date: Mon, 11 Dec 2023 00:25:45 +0000 Subject: [PATCH 6/6] [skip ci] Updated licenses and gitignores --- options/license/xkeyboard-config-Zinoviev | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 options/license/xkeyboard-config-Zinoviev diff --git a/options/license/xkeyboard-config-Zinoviev b/options/license/xkeyboard-config-Zinoviev new file mode 100644 index 0000000000000..509fc255e27f2 --- /dev/null +++ b/options/license/xkeyboard-config-Zinoviev @@ -0,0 +1,15 @@ +Copyright (C) 1999, 2000 by Anton Zinoviev + +This software may be used, modified, copied, distributed, and sold, +in both source and binary form provided that the above copyright +and these terms are retained. Under no circumstances is the author +responsible for the proper functioning of this software, nor does +the author assume any responsibility for damages incurred with its +use. + +Permission is granted to anyone to use, distribute and modify +this file in any way, provided that the above copyright notice +is left intact and the author of the modification summarizes +the changes in this header. + +This file is distributed without any expressed or implied warranty.