Compare commits

..

No commits in common. "1195d66c15ad6ead1f464b5d7ae30308e1278780" and "7735da1c66c5a1511a2eac04b2a7f5c60b214c83" have entirely different histories.

63 changed files with 400 additions and 623 deletions

View File

@ -64,6 +64,11 @@ func (branches BranchList) LoadPusher(ctx context.Context) error {
return nil
}
const (
BranchOrderByNameAsc = "name ASC"
BranchOrderByCommitTimeDesc = "commit_time DESC"
)
type FindBranchOptions struct {
db.ListOptions
RepoID int64
@ -97,8 +102,7 @@ func orderByBranches(sess *xorm.Session, opts FindBranchOptions) *xorm.Session {
}
if opts.OrderBy == "" {
// the commit_time might be the same, so add the "name" to make sure the order is stable
opts.OrderBy = "commit_time DESC, name ASC"
opts.OrderBy = BranchOrderByCommitTimeDesc
}
return sess.OrderBy(opts.OrderBy)
}

View File

@ -33,19 +33,6 @@ func TestRepository_GetCollaborators(t *testing.T) {
test(2)
test(3)
test(4)
// Test db.ListOptions
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22})
collaborators1, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{PageSize: 1, Page: 1})
assert.NoError(t, err)
assert.Len(t, collaborators1, 1)
collaborators2, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{PageSize: 1, Page: 2})
assert.NoError(t, err)
assert.Len(t, collaborators2, 1)
assert.NotEqualValues(t, collaborators1[0].ID, collaborators2[0].ID)
}
func TestRepository_IsCollaborator(t *testing.T) {
@ -79,80 +66,5 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin))
// Disvard invalid input.
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessMode(unittest.NonexistentID)))
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
}
func TestRepository_CountCollaborators(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
count, err := repo_model.CountCollaborators(repo1.ID)
assert.NoError(t, err)
assert.EqualValues(t, 2, count)
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22})
count, err = repo_model.CountCollaborators(repo2.ID)
assert.NoError(t, err)
assert.EqualValues(t, 2, count)
// Non-existent repository.
count, err = repo_model.CountCollaborators(unittest.NonexistentID)
assert.NoError(t, err)
assert.EqualValues(t, 0, count)
}
func TestRepository_IsOwnerMemberCollaborator(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
// Organisation owner.
actual, err := repo_model.IsOwnerMemberCollaborator(repo1, 2)
assert.NoError(t, err)
assert.True(t, actual)
// Team member.
actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 4)
assert.NoError(t, err)
assert.True(t, actual)
// Normal user.
actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 1)
assert.NoError(t, err)
assert.False(t, actual)
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
// Collaborator.
actual, err = repo_model.IsOwnerMemberCollaborator(repo2, 4)
assert.NoError(t, err)
assert.True(t, actual)
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15})
// Repository owner.
actual, err = repo_model.IsOwnerMemberCollaborator(repo3, 2)
assert.NoError(t, err)
assert.True(t, actual)
}
func TestRepo_GetCollaboration(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
// Existing collaboration.
collab, err := repo_model.GetCollaboration(db.DefaultContext, repo.ID, 4)
assert.NoError(t, err)
assert.NotNil(t, collab)
assert.EqualValues(t, 4, collab.UserID)
assert.EqualValues(t, 4, collab.RepoID)
// Non-existing collaboration.
collab, err = repo_model.GetCollaboration(db.DefaultContext, repo.ID, 1)
assert.NoError(t, err)
assert.Nil(t, collab)
}

View File

@ -64,10 +64,6 @@ func NewUserRedirect(ctx context.Context, ID int64, oldUserName, newUserName str
oldUserName = strings.ToLower(oldUserName)
newUserName = strings.ToLower(newUserName)
if err := DeleteUserRedirect(ctx, oldUserName); err != nil {
return err
}
if err := DeleteUserRedirect(ctx, newUserName); err != nil {
return err
}

View File

@ -5,11 +5,9 @@ package packages
import (
"io"
"net/url"
"path"
"strings"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
)
@ -33,14 +31,6 @@ func (s *ContentStore) Get(key BlobHash256Key) (storage.Object, error) {
return s.store.Open(KeyToRelativePath(key))
}
func (s *ContentStore) ShouldServeDirect() bool {
return setting.Packages.Storage.MinioConfig.ServeDirect
}
func (s *ContentStore) GetServeDirectURL(key BlobHash256Key, filename string) (*url.URL, error) {
return s.store.URL(KeyToRelativePath(key), filename)
}
// FIXME: Workaround to be removed in v1.20
// https://github.com/go-gitea/gitea/issues/19586
func (s *ContentStore) Has(key BlobHash256Key) error {

View File

@ -383,7 +383,7 @@ hi_user_x=Ahoj <b>%s</b>,
activate_account=Prosíme, aktivujte si váš účet
activate_account.title=%s, prosím aktivujte si váš účet
activate_account.text_1=Ahoj <b>%[1]s</b>, děkujeme za registraci na %[2]s!
activate_account.text_1=Ahoj <b>%[1]s</b>, děkujeme za registraci na %[2]!
activate_account.text_2=Pro aktivaci vašeho účtu do <b>%s</b> klikněte na následující odkaz:
activate_email=Ověřte vaši e-mailovou adresu
@ -402,8 +402,8 @@ reset_password.text=Klikněte prosím na následující odkaz pro obnovení vaš
register_success=Registrace byla úspěšná
issue_assigned.pull=@%[1]s vás přiřadil/a k požadavku na natažení %[2]s repozitáři %[3]s.
issue_assigned.issue=@%[1]s vás přiřadil/a k úkolu %[2]s repozitáři %[3]s.
issue_assigned.pull=@%[1]s vás přiřadil/a k požadavku na natažení %[2]v repozitáři %[3]s.
issue_assigned.issue=@%[1]s vás přiřadil/a k úkolu %[2]v repozitáři %[3]s.
issue.x_mentioned_you=<b>@%s</b> vás zmínil/a:
issue.action.force_push=<b>%[1]s</b> vynutil/a nahrání <b>%[2]s</b> z %[3]s do %[4]s.
@ -2310,7 +2310,7 @@ members.member_role=Role člena:
members.owner=Vlastník
members.member=Člen
members.remove=Smazat
members.remove.detail=Odstranit %[1]s z %[2]s?
members.remove.detail=Odstranit %[1]s z %[2]?
members.leave=Opustit
members.leave.detail=Opustit %s?
members.invite_desc=Přidat nového člena do %s:

View File

@ -19,7 +19,6 @@ active_stopwatch=Aktive Zeiterfassung
create_new=Erstellen…
user_profile_and_more=Profil und Einstellungen…
signed_in_as=Angemeldet als
enable_javascript=Diese Website benötigt JavaScript.
toc=Inhaltsverzeichnis
licenses=Lizenzen
return_to_gitea=Zurück zu Gitea
@ -93,7 +92,6 @@ copy_url=URL kopieren
copy_branch=Branchenname kopieren
copy_success=Kopiert!
copy_error=Kopieren fehlgeschlagen
copy_type_unsupported=Dieser Dateityp kann nicht kopiert werden
write=Verfassen
preview=Vorschau
@ -106,42 +104,22 @@ error=Fehler
error404=Die Seite, die du gerade versuchst aufzurufen, <strong>existiert entweder nicht</strong> oder <strong>du bist nicht berechtigt</strong>, diese anzusehen.
never=Niemals
unknown=Unbekannt
rss_feed=RSS Feed
artifacts=Artefakte
concept_system_global=Global
concept_code_repository=Repository
concept_user_organization=Organisation
show_log_seconds=Sekunden anzeigen
[aria]
footer.software=Über die Software
footer.links=Links
[heatmap]
less=Weniger
more=Mehr
[editor]
buttons.heading.tooltip=Titel hinzufügen
buttons.quote.tooltip=Text zitieren
buttons.code.tooltip=Code hinzufügen
buttons.link.tooltip=Link hinzufügen
buttons.list.ordered.tooltip=Nummerierte Liste hinzufügen
buttons.list.task.tooltip=Aufgabenliste hinzufügen
buttons.mention.tooltip=Benutzer oder Team erwähnen
buttons.ref.tooltip=Issue oder Pull-Request referenzieren
buttons.enable_monospace_font=Monospace-Schrift aktivieren
buttons.disable_monospace_font=Monospace-Schrift deaktivieren
[filter]
string.asc=AZ
string.desc=ZA
[error]
occurred=Ein Fehler ist aufgetreten
@ -250,7 +228,6 @@ install_btn_confirm=Gitea installieren
test_git_failed=Fehler beim Test des „git“-Befehls: %v
sqlite3_not_available=Diese Gitea-Version unterstützt SQLite3 nicht. Bitte lade die offizielle binäre Version von %s herunter (nicht die „gobuild“-Version).
invalid_db_setting=Datenbankeinstellungen sind ungültig: %v
invalid_db_table=Die Datenbanktabelle "%s" ist ungültig: %v
invalid_repo_path=Repository-Verzeichnis ist ungültig: %v
invalid_app_data_path=Der App-Daten-Pfad ist ungültig: %v
run_user_not_match=Der „Ausführen als“-Benutzername ist nicht der aktuelle Benutzername: %s -> %s
@ -268,7 +245,6 @@ default_enable_timetracking_popup=Zeiterfassung standardmäßig für neue Reposi
no_reply_address=Versteckte E-Mail-Domain
no_reply_address_helper=Domain-Name für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername „Joe“ in Git als „joe@noreply.example.org“ protokolliert, wenn die versteckte E-Mail-Domain „noreply.example.org“ festgelegt ist.
password_algorithm=Passwort Hashing Algorithmus
invalid_password_algorithm=Ungültiger Passwort-Hash-Algorithmus
[home]
uname_holder=E-Mail-Adresse oder Benutzername
@ -303,7 +279,6 @@ users=Benutzer
organizations=Organisationen
search=Suche
code=Code
search.type.tooltip=Suchmodus
search.fuzzy=Ähnlich
search.match=Genau
code_search_unavailable=Derzeit ist die Code-Suche nicht verfügbar. Bitte wende dich an den Website-Administrator.
@ -570,7 +545,6 @@ location=Standort
update_theme=Theme ändern
update_profile=Profil aktualisieren
update_language=Sprache aktualisieren
update_language_not_found=Sprache "%s" ist nicht verfügbar.
update_language_success=Sprache wurde aktualisiert.
update_profile_success=Dein Profil wurde aktualisiert.
change_username=Dein Benutzername wurde geändert.
@ -681,7 +655,6 @@ gpg_token_help=Du kannst eine Signatur wie folgt generieren:
gpg_token_code=echo "%s" | gpg -a --default-key %s --detach-sig
gpg_token_signature=GPG Textsignatur (armored signature)
key_signature_gpg_placeholder=Beginnt mit '-----BEGIN PGP SIGNATURE-----'
verify_gpg_key_success=GPG-Schlüssel "%s" wurde verifiziert.
ssh_key_verified=Verifizierter Schlüssel
ssh_key_verified_long=Der Schlüssel wurde mit einem Token verifiziert. Er kann verwendet werden, um Commits zu verifizieren, die mit irgendeiner für diesen Nutzer aktivierten E-Mail-Adresse und irgendeiner Identität dieses Schlüssels übereinstimmen.
ssh_key_verify=Verifizieren
@ -1002,7 +975,6 @@ download_archive=Repository herunterladen
no_desc=Keine Beschreibung
quick_guide=Kurzanleitung
clone_this_repo=Dieses Repository klonen
cite_this_repo=Dieses Repository zitieren
create_new_repo_command=Erstelle ein neues Repository von der Kommandozeile aus
push_exist_repo=Bestehendes Repository via Kommandozeile pushen
empty_message=Dieses Repository hat keinen Inhalt.
@ -1021,7 +993,6 @@ issues=Issues
pulls=Pull-Requests
project_board=Projekte
packages=Pakete
actions=Actions
labels=Label
org_labels_desc=Labels der Organisationsebene, die mit <strong>allen Repositories</strong> in dieser Organisation verwendet werden können
org_labels_desc_manage=verwalten
@ -1041,7 +1012,6 @@ file_view_rendered=Ansicht rendern
file_view_raw=Originalformat anzeigen
file_permalink=Permalink
file_too_large=Die Datei ist zu groß zum Anzeigen.
invisible_runes_header=`Diese Datei enthält unsichtbare Unicode-Zeichen!`
ambiguous_character=`%[1]c [U+%04[1]X] kann mit %[2]c [U+%04[2]X] verwechselt werden`
escape_control_characters=Escapen
@ -1062,7 +1032,6 @@ download_file=Datei herunterladen
normal_view=Normale Ansicht
line=zeile
lines=Zeilen
from_comment=(Kommentar)
editor.add_file=Datei hinzufügen
editor.new_file=Neue Datei
@ -1077,7 +1046,6 @@ editor.must_be_on_a_branch=Du musst dich in einem Branch befinden, um Änderunge
editor.fork_before_edit=Du musst dieses Repository forken, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
editor.delete_this_file=Datei löschen
editor.must_have_write_access=Du benötigst Schreibzugriff, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen.
editor.file_delete_success=Datei "%s" wurde gelöscht.
editor.name_your_file=Dateinamen eingeben…
editor.filename_help=Füge einen Ordner hinzu, indem du seinen Namen und anschließend '/' eingibst. Entferne einen Ordner indem du die Zurücktaste am Anfang des Feldes drückst.
editor.or=oder
@ -1713,7 +1681,6 @@ activity.git_stats_deletion_n=%d Löschungen
search=Suchen
search.search_repo=Repository durchsuchen
search.type.tooltip=Suchmodus
search.fuzzy=Ähnlich
search.match=Genau
search.results=Suchergebnisse für „%s“ in <a href="%s"> %s</a>
@ -2191,8 +2158,6 @@ branch.delete_html=Branch löschen
branch.delete_desc=Das Löschen eines Branches ist permanent. Es <strong>KANN NICHT</strong> rückgängig gemacht werden. Fortfahren?
branch.create_branch=Erstelle Branch <strong>%s</strong>
branch.deleted_by=Von %s gelöscht
branch.restore=Branch "%s" wiederherstellen
branch.download=Branch "%s" herunterladen
branch.included_desc=Dieser Branch ist im Standard-Branch enthalten
branch.included=Enthalten
branch.create_new_branch=Branch aus Branch erstellen:
@ -2200,15 +2165,12 @@ branch.confirm_create_branch=Branch erstellen
branch.confirm_rename_branch=Branch umbennen
branch.create_branch_operation=Branch erstellen
branch.new_branch=Neue Branch erstellen
branch.new_branch_from=Neuen Branch von "%s" erstellen
branch.renamed=Branch %s wurde in %s umbenannt.
tag.create_tag=Tag <strong>%s</strong> erstellen
tag.create_tag_operation=Tag erstellen
tag.confirm_create_tag=Tag erstellen
tag.create_tag_from=Neuen Tag von "%s" erstellen
tag.create_success=Tag "%s" wurde erstellt.
topic.manage_topics=Themen verwalten
topic.done=Fertig
@ -2445,7 +2407,6 @@ users.created=Registriert am
users.last_login=Letzte Anmeldung
users.never_login=Hat sich noch nie eingeloggt
users.send_register_notify=Benutzer-Registrierungsbenachrichtigung senden
users.new_success=Der Account "%s" wurde erstellt.
users.edit=Bearbeiten
users.auth_source=Authentifizierungsquelle
users.local=Lokal
@ -2809,7 +2770,7 @@ monitor.queue.review=Konfiguration überprüfen
monitor.queue.review_add=Worker hinzufügen/prüfen
monitor.queue.settings.title=Pool-Einstellungen
monitor.queue.settings.maxnumberworkers=Maximale Anzahl an Workern
monitor.queue.settings.maxnumberworkers.placeholder=Derzeit %[1]s
monitor.queue.settings.maxnumberworkers.placeholder=Derzeit %[1]v
monitor.queue.settings.maxnumberworkers.error=Die Anzahl der Worker muss eine Zahl sein
monitor.queue.settings.submit=Einstellungen aktualisieren
monitor.queue.settings.changed=Einstellungen aktualisiert
@ -3018,7 +2979,6 @@ settings.delete.description=Das Löschen eines Pakets ist dauerhaft und kann nic
settings.delete.notice=Du bist dabei, %s (%s) zu löschen. Dieser Vorgang ist unwiderruflich. Bist du sicher?
settings.delete.success=Das Paket wurde gelöscht.
settings.delete.error=Löschen des Pakets fehlgeschlagen.
owner.settings.cargo.initialize=Index initialisieren
owner.settings.cleanuprules.enabled=Aktiviert
[secrets]
@ -3026,10 +2986,8 @@ value=Wert
name=Name
[actions]
actions=Actions
status.unknown=Unbekannt
runners.id=ID
runners.name=Name
@ -3039,16 +2997,10 @@ runners.labels=Labels
runners.task_list.run=Ausführen
runners.task_list.repository=Repository
runners.task_list.commit=Commit
runners.status.unspecified=Unbekannt
runners.status.idle=Inaktiv
runners.status.active=Aktiv
runners.status.offline=Offline
runners.version=Version
runs.all_workflows=Alle Workflows
runs.commit=Commit
runs.pushed_by=Gepushed von
runs.no_matching_runner_helper=Kein passender Runner: %s
[projects]

View File

@ -408,7 +408,7 @@ hi_user_x=Γειά σου <b>%s</b>,
activate_account=Παρακαλώ ενεργοποιήστε το λογαριασμό σας
activate_account.title=%s, παρακαλώ ενεργοποιήστε το λογαριασμό σας
activate_account.text_1=Γεια σας <b>%[1]s</b>, ευχαριστούμε για την εγγραφή στο %[2]s!
activate_account.text_1=Γεια σας <b>%[1]s</b>, ευχαριστούμε για την εγγραφή στο %[2]!
activate_account.text_2=Παρακαλούμε κάντε κλικ στον παρακάτω σύνδεσμο για να ενεργοποιήσετε το λογαριασμό σας μέσα σε <b>%s</b>:
activate_email=Επιβεβαιώστε τη διεύθυνση email σας
@ -462,7 +462,7 @@ repo.collaborator.added.subject=%s σας πρόσθεσε στο %s
repo.collaborator.added.text=Έχετε προστεθεί ως συνεργάτης του αποθετηρίου:
team_invite.subject=%[1]s σας προσκάλεσε να συμμετέχετε στον οργανισμό %[2]s
team_invite.text_1=%[1]s σας προσκάλεσε να συμμετέχετε στην ομάδα %[2]s στον οργανισμός %[3]s.
team_invite.text_1=%[1]s σας προσκάλεσε να συμμετέχετε στην ομάδα %[2]s στον οργανισμός %[3].
team_invite.text_2=Παρακαλώ κάντε κλικ στον παρακάτω σύνδεσμο για να συμμετάσχετε στην ομάδα:
team_invite.text_3=Σημείωση: Αυτή η πρόσκληση προοριζόταν για %[1]s. Αν δεν περιμένατε αυτή την πρόσκληση, μπορείτε να αγνοήσετε αυτό το email.

View File

@ -2650,7 +2650,7 @@ dashboard.task.finished=Task: %[1]s started by %[2]s has finished
dashboard.task.unknown=Unknown task: %[1]s
dashboard.cron.started=Started Cron: %[1]s
dashboard.cron.process=Cron: %[1]s
dashboard.cron.cancelled=Cron: %[1]s cancelled: %[3]s
dashboard.cron.cancelled=Cron: %s cancelled: %[3]s
dashboard.cron.error=Error in Cron: %s: %[3]s
dashboard.cron.finished=Cron: %[1]s has finished
dashboard.delete_inactive_accounts = Delete all unactivated accounts

View File

@ -357,7 +357,7 @@ reset_password.text=لطفاً روی پیوند زیر کلیک کنید تا
register_success=ثبت‌نام با موفقیت انجام شد
issue_assigned.pull=@%[1]s به شما برای درخواست pull %[2]s در ریپازیتوری %[3]s محول شده.
issue_assigned.pull=@%[1] به شما برای درخواست pull %[2] در ریپازیتوری %[3] محول شده.
issue_assigned.issue=@%[1]s به شما واگذار شده است برای صدور %[2]s در انبار %[3]s.
issue.x_mentioned_you=<b>@%s</b> به شما اشاره کرد:

View File

@ -803,7 +803,7 @@ issues.action_milestone=Tímamót
issues.action_milestone_no_select=Ekkert tímamót
issues.action_assignee=Úthlutað að
issues.opened_by=opnað %[1]s af <a href="%[2]s">%[3]s</a>
issues.opened_by_fake=opnað %[1]s af %[2]s
issues.opened_by_fake=opnað %[1] af %[2]s
issues.previous=Fyrri
issues.next=Áfram
issues.open_title=Opið

View File

@ -438,7 +438,7 @@ repo.collaborator.added.subject=%s pievienoja Jūs repozitorijam %s
repo.collaborator.added.text=Jūs tikāt pievienots kā līdzstrādnieks repozitorijam:
team_invite.subject=%[1]s uzaicināja Jūs pievienoties organizācijai %[2]s
team_invite.text_1=%[1]s uzaicināja Jūs pievienoties komandai %[2]s organizācijā %[3]s.
team_invite.text_1=%[1]s uzaicināja Jūs pievienoties komandai %[2] organizācijā %[3]s.
team_invite.text_2=Uzspiediet uz šīs saites, lai pievienoties komandai:
team_invite.text_3=Piezīme: Šis uzaicinājums ir paredzēts %[1]s. Ja uzskatāt, ka tas nav domāts Jums, varat ignorēt šo e-pastu.

View File

@ -384,7 +384,7 @@ reset_password.text=Klik op de volgende link om je account te herstellen binnen
register_success=Registratie succesvol
issue_assigned.pull=@%[1]s heeft u toegewezen aan de pull request %[2]s in repository %[3]s.
issue_assigned.issue=@%[1]s heeft u toegewezen aan issue %[2]s in repository %[3]s.
issue_assigned.issue=@%[1]heeft u toegewezen aan issue %[2]s in repository %[3]s.
issue.x_mentioned_you=<b>@%s</b> heeft u vermeld:
issue.action.force_push=<b>%[1]s</b> heeft een force-push uitgevoerd <b>%[2]s</b> van %[3]s naar %[4]s.
@ -392,7 +392,7 @@ issue.action.push_1=<b>@%[1]s</b> heeft %[3]d commits gepusht naar %[2]s
issue.action.push_n=<b>@%[1]s</b> heeft %[3]d commits gepusht naar %[2]s
issue.action.close=<b>@%[1]s</b> sloot #%[2]d.
issue.action.reopen=<b>@%[1]s</b> heropend #%[2]d.
issue.action.merge=<b>@%[1]s</b> heeft een merge uitgevoerd van #%[2]d naar %[3]s.
issue.action.merge=<b>@%[1]</b> heeft een merge uitgevoerd van #%[2]d naar %[3]s.
issue.action.approve=<b>@%[1]s</b> heeft deze pull request goedgekeurd.
issue.action.reject=<b>@%[1]s</b> vraagt om wijzigingen op deze pull request.
issue.action.review=<b>@%[1]s</b> heeft gereageerd op deze pull request.

View File

@ -2494,7 +2494,7 @@ monitor.queue.review=Przejrzyj konfigurację
monitor.queue.review_add=Przejrzyj/Dodaj procesy pracujące
monitor.queue.settings.title=Ustawienia Puli
monitor.queue.settings.maxnumberworkers=Maksymalna liczba procesów pracujących
monitor.queue.settings.maxnumberworkers.placeholder=Obecnie %[1]d
monitor.queue.settings.maxnumberworkers.placeholder=Obecnie %[1]v
monitor.queue.settings.maxnumberworkers.error=Maksymalna liczba procesów pracujących musi być liczbą
monitor.queue.settings.submit=Aktualizuj ustawienia
monitor.queue.settings.changed=Zaktualizowano ustawienia

View File

@ -437,7 +437,7 @@ reset_password.text=Por favor clique no link a seguir para recuperar sua conta e
register_success=Cadastro bem-sucedido
issue_assigned.pull=@%[1]s atribuiu a você o pull request %[2]s no repositório %[3]s.
issue_assigned.pull=@%[1]atribuiu a você o pull request %[2]s no repositório %[3]s.
issue_assigned.issue=@%[1]s atribuiu a você a issue %[2]s no repositório %[3]s.
issue.x_mentioned_you=<b>@%s</b> mencionou você:
@ -1535,7 +1535,7 @@ issues.due_date_form_remove=Remover
issues.due_date_not_writer=Você deve ter permissão de escrita no repositório para atualizar a data limite de uma issue.
issues.due_date_not_set=Data limite não informada.
issues.due_date_added=adicionou a data limite %s %s
issues.due_date_modified=modificou a data limite de %[2]s para %[1]s %[3]s
issues.due_date_modified=modificou a data limite de %[2]para %[1]s %[3]s
issues.due_date_remove=removeu a data limite %s %s
issues.due_date_overdue=Em atraso
issues.due_date_invalid=A data limite é inválida ou está fora do intervalo. Por favor, use o formato 'dd/mm/aaaa'.
@ -2557,7 +2557,7 @@ dashboard.clean_unbind_oauth_success=Todas as conexões de OAuth não vinculadas
dashboard.task.started=Tarefa Iniciada: %[1]s
dashboard.task.process=Tarefa: %[1]s
dashboard.task.cancelled=Tarefa: %[1]s cancelada: %[3]s
dashboard.task.error=Erro na Tarefa: %[1]s: %[3]s
dashboard.task.error=Erro na Tarefa: %[1]: %[3]s
dashboard.task.finished=Tarefa: %[1]s iniciada por %[2]s foi finalizada
dashboard.task.unknown=Tarefa desconhecida: %[1]s
dashboard.cron.started=Cron Iniciado: %[1]s

View File

@ -472,7 +472,7 @@ repo.transfer.body=Для того чтобы принять или отклон
repo.collaborator.added.subject=%s добавил(а) вас в %s
repo.collaborator.added.text=Вы были добавлены в качестве соавтора репозитория:
team_invite.subject=%[1]s приглашает вас присоединиться к организации %[2]s
team_invite.subject=%[1] приглашает вас присоединиться к организации %[2]
team_invite.text_1=%[1]s приглашает вас присоединиться к команде %[2]s в организации %[3]s.
team_invite.text_2=Перейдите по ссылке, чтобы присоединиться к команде:
team_invite.text_3=Примечание: Это приглашение было направлено для %[1]s. Если вы не ожидали этого приглашения, можете проигнорировать это письмо.

View File

@ -353,17 +353,17 @@ issue.action.push_1=<b>@%[1]s</b> pushed%[3]d%[2]s කිරීමට කැප
issue.action.push_n=<b>@%[1]s</b> pushed%[3]d%[2]s දක්වා කැපේ
issue.action.close=<b>@%[1]s</b> වසා #%[2]d.
issue.action.reopen=<b>@%[1]s</b> නැවත විවෘත කරන ලද #%[2]d.
issue.action.merge=<b>@%[1]s ගේ</b> ඒකාබද්ධ #%[2]d ඈ into%[3]s.
issue.action.merge=<b>@%[1]ගේ</b> ඒකාබද්ධ #%[2]ඈ into%[3]s.
issue.action.approve=<b>@%[1]s</b> මෙම අදින්න ඉල්ලීම අනුමත.
issue.action.reject=<b>@%[1]s</b> මෙම අදින්න ඉල්ලීම මත වෙනස්කම් ඉල්ලා.
issue.action.review=<b>@%[1]s</b> මෙම අදින්න ඉල්ලීම පිළිබඳව අදහස් දැක්වීය.
issue.action.review_dismissed=<b>@%[1]s</b> මෙම අදින්න ඉල්ලීම සඳහා%[2]s සිට පසුගිය සමාලෝචනය බැහැර.
issue.action.ready_for_review=<b>@%[1]s</b> සමාලෝචනය සඳහා සූදානම් මෙම අදින්න ඉල්ලීම සලකුණු.
issue.action.new=<b>@%[1]s ගේ</b> නිර්මාණය #%[2]d ඈ.
issue.action.new=<b>@%[1]ගේ</b> නිර්මාණය #%[2]ඈ.
issue.in_tree_path=%sදී:
release.new.subject=%s %s නිදහස්
release.new.text=<b>@%[1]s හි</b> නිකුතුව%[2]s හි %[3]s හි
release.new.text=<b>@%[1]හි</b> නිකුතුව%[2]හි[3]හි
release.title=සිරැසිය: %s
release.note=සටහන:
release.downloads=බාගැනීම්:
@ -844,7 +844,7 @@ migrate.permission_denied_blocked=ඔබට අවසර නොලත් ධා
migrate.invalid_lfs_endpoint=මෙම LFS අවසන් ලක්ෂ්යය වලංගු නොවේ.
migrate.failed=සංක්රමණය අසාර්ථකයි: %v
migrate.migrate_items_options=අමතර අයිතම සංක්රමණය කිරීම සඳහා ප්රවේශ ටෝකනය අවශ්ය වේ
migrated_from=<a href="%[1]s">%[2]s සිට</a>දක්වා සංක්රමණය වී ඇත
migrated_from=<a href="%[1]s">%[2]සිට</a>දක්වා සංක්රමණය වී ඇත
migrated_from_fake=සංක්රමණය වූ ගෙම්%[1]s
migrate.migrate=%sසිට සංක්රමණය
migrate.migrating=<b>%s</b> සිට සංක්රමණය වීම...
@ -1071,7 +1071,7 @@ issues.remove_ref_at=`ඉවත් කරන ලද යොමු <b>%s</b> %s`
issues.add_ref_at=`එකතු කරන ලද යොමු <b>%s</b> %s`
issues.delete_branch_at=`මකාදැමූ ශාඛාව <b>%s</b> %s`
issues.filter_label=ලේබලය
issues.filter_label_exclude=ලේබල බැහැර කිරීමට <code>alt</code> + <code>click/enter</code> භාවිත කරන්න
issues.filter_label_exclude=Labels` ඉවත් කිරීමට <code>alt</code> + <code>ක්ලික් කරන්න/ඇතුළු කරන්න</code>
issues.filter_label_no_select=සියලු ලේබල
issues.filter_label_select_no_label=ලේබලයක් නැත
issues.filter_milestone=සන්ධිස්ථානය
@ -1127,7 +1127,7 @@ issues.reopen_comment_issue=අදහස් දක්වා විවෘත ක
issues.create_comment=අදහස
issues.closed_at=`මෙම ගැටළුව වසා <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`මෙම ගැටළුව නැවත විවෘත කරන ලදි <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_issue_from=<a href="%[3]s">මෙම නිකුතුව %[4]s හි</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>
issues.ref_issue_from=<a href="%[3]s">මෙම නිකුතුව%[4]හි</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>
issues.ref_pull_from=<a href="%[3]s">මෙම අදින්න ඉල්ලීම%[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>
issues.ref_closing_from=<a href="%[3]s">මෙම ගැටළුව වසා දමනු ඇත%[4]s මෙම ගැටළුව</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>
issues.ref_reopening_from=<a href="%[3]s">මෙම ගැටළුව නැවත විවෘත කරනු ඇත%[4]s මෙම ගැටළුව</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>
@ -1214,7 +1214,7 @@ issues.error_modifying_due_date=නියමිත දිනය වෙනස්
issues.error_removing_due_date=නියමිත දිනය ඉවත් කිරීමට අපොහොසත් විය.
issues.push_commit_1=එකතු %d කැප %s
issues.push_commits_n=එකතු %d විවරයන් %s
issues.force_push_codes=`බලය-pushed%[1]s සිට <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> <a class="ui sha" href="%[5]s"><code>%[4]s ගේ</code></a> %[6]s`
issues.force_push_codes=`බලය-pushed%[1]s සිට <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> <a class="ui sha" href="%[5]s"><code>%[4]ගේ</code></a> %[6]s`
issues.force_push_compare=සසඳන්න
issues.due_date_form=Yyy-mm-dd
issues.due_date_form_add=නියමිත දිනය එකතු කරන්න
@ -2039,7 +2039,7 @@ members.member_role=සාමාජික කාර්යභාරය:
members.owner=හිමිකරු
members.member=සාමාජික
members.remove=ඉවත් කරන්න
members.remove.detail=%[1]s ගේ සිට%[2]s ගේ ඉවත්?
members.remove.detail=%[1]ගේ සිට%[2]ගේ ඉවත්?
members.leave=හැරයන්න
members.leave.detail=%s හැරයනවාද?
members.invite_desc=%sවෙත නව සාමාජිකයෙකු එක් කරන්න:
@ -2111,7 +2111,7 @@ dashboard.clean_unbind_oauth=පිරිසිදු නොබැඳි OAUTH
dashboard.clean_unbind_oauth_success=සියලුම නොබැඳි OAUTH සම්බන්ධතා මකා දමා ඇත.
dashboard.task.started=ආරම්භ කාර්යය:%[1]s
dashboard.task.process=කාර්යය:%[1]s
dashboard.task.cancelled=කාර්යය: %[1]s ගේ අවලංගු: %[3]s ගේ
dashboard.task.cancelled=කාර්යය:%[1]ගේ අවලංගු:%[3]ගේ
dashboard.task.error=කාර්යයයේ දෝෂය:%[1]s:%[3]s
dashboard.task.finished=කාර්යය:%[1]s[2]s විසින් ආරම්භ කර ඇත
dashboard.task.unknown=නොදන්නා කාර්යය:%[1]s
@ -2551,16 +2551,16 @@ comment_issue=`නිකුතුව පිළිබඳ අදහස් <a href=
comment_pull=`අදින්න ඉල්ලීම මත අදහස් <a href="%[1]s">%[3]s #%[2]s</a>`
merge_pull_request=`ඒකාබද්ධ අදින්න ඉල්ලීම <a href="%[1]s">%[3]s #%[2]s</a>`
transfer_repo=මාරු කරන ලද ගබඩාව <code>%s</code> සිට <a href="%s">%s</a>
push_tag=තල්ලු ටැගය <a href="%[2]s">%[3]s ගේ</a> <a href="%[1]s">%[4]s ගේ</a>
delete_tag=මකාදැමුවා ටැගය%[2]s සිට <a href="%[1]s">%[3]s</a>
delete_branch=මකාදැමූ ශාඛාව %[2]s සිට <a href="%[1]s">%[3]s</a>
push_tag=තල්ලු ටැගය <a href="%[2]s">%[3]ගේ</a> <a href="%[1]s">%[4]ගේ</a>
delete_tag=මකාදැමුවා ටැගය%[2]සිට <a href="%[1]s">%[3]s</a>
delete_branch=මකාදැමූ ශාඛාව%[2]සිට <a href="%[1]s">%[3]s</a>
compare_branch=සසඳන්න
compare_commits=%d විවරයන් සසඳා බලන්න
compare_commits_general=විවරයන් සසඳා බලන්න
mirror_sync_push=සමමුහුර්ත <a href="%[2]s">%[3]s</a> ට <a href="%[1]s">%[4]s</a> කැඩපත සිට
mirror_sync_create=සමමුහුර්ත නව යොමු <a href="%[2]s">%[3]s</a> සිට <a href="%[1]s">%[4]s</a> කැඩපත සිට
mirror_sync_delete=සමමුහුර්ත සහ මකාදැමූ යොමු <code>%[2]s</code> හි <a href="%[1]s">%[3]s</a> කැඩපතෙන්
approve_pull_request=`අනුමත <a href="%[1]s">%[3]s #%[2]s ගේ</a>`
approve_pull_request=`අනුමත <a href="%[1]s">%[3]s #%[2]ගේ</a>`
reject_pull_request=<a href="%[1]s">%[3]s #%[2]s</a>සඳහා යෝජිත වෙනස්කම්
publish_release=`නිදහස් <a href="%[2]s"> "%[4]s" </a> හි <a href="%[1]s">%[3]s</a>`
review_dismissed_reason=හේතුව:

View File

@ -382,7 +382,7 @@ reset_password.text=Pre obnovenie vašeho účtu kliknite, prosím, na nasledovn
register_success=Registrácia prebehla úspešne
issue_assigned.pull=@%[1]s vám pridelil pull request %[2]s repozitári %[3]s.
issue_assigned.pull=@%[1]s vám pridelil pull request %[2] v repozitári %[3]s.
issue_assigned.issue=@%[1]s vám pridelil úkol %[2]s v repozitári %[3]s.
issue.x_mentioned_you=<b>@%s</b> vás zmienil:
@ -397,7 +397,7 @@ issue.action.reject=<b>@%[1]s</b> požadoval zmeny v tomto pull requeste.
issue.action.review=<b>@%[1]s</b> okomentoval tento pull request.
issue.action.review_dismissed=<b>@%[1]s</b> zamietol poslednú recenziu od %[2]s pre tento pull request.
issue.action.ready_for_review=<b>@%[1]s</b> označil tento pull request ako pripravený na revíziu.
issue.action.new=<b>@%[1]s</b> vytvoril/a #%[2]d.
issue.action.new=<b>@%[1]</b> vytvoril/a #%[2]d.
issue.in_tree_path=V %s:
release.new.subject=%s v %s vydané

View File

@ -461,10 +461,10 @@ repo.transfer.body=Kabul veya reddetmek için %s ziyaret edin veya görmezden ge
repo.collaborator.added.subject=%s sizi %s ekledi
repo.collaborator.added.text=Bu depo için katkıcı olarak eklendiniz:
team_invite.subject=%[1]s sizi %[2]s organizasyonuna katılmaya davet etti
team_invite.text_1=%[1]s sizi %[3]s organizasyonundaki %[2]s takımına katılmaya davet etti.
team_invite.subject=%[1] sizi %[2] organizasyonuna katılmaya davet etti
team_invite.text_1=%[1] sizi %[3] organizasyonundaki %[2] takımına katılmaya davet etti.
team_invite.text_2=Takıma katılmak lütfen aşağıdaki bağlantıya tıklayın:
team_invite.text_3=Not: Bu davet %[1]s içindi. Bu daveti beklemiyorsanız, e-postayı yok sayabilirsiniz.
team_invite.text_3=Not: Bu davet %[1] içindi. Bu daveti beklemiyorsanız, e-postayı yok sayabilirsiniz.
[modal]
yes=Evet

View File

@ -1182,10 +1182,10 @@ issues.create_comment=Коментар
issues.closed_at=`закрив цю задачу <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.reopened_at=`повторно відкрив цю задачу <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.commit_ref_at=`згадано цю задачу в коміті <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_issue_from=`<a href="%[3]s">посилання на цю задачу %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_issue_from=`<a href="%[3]s">посилання на цю задачу %[4]</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_pull_from=`<a href="%[3]s">послався на цей запит злиття %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_closing_from=`<a href="%[3]s">згадав запит на злиття %[4]s, які закриють цю задачу</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_reopening_from=`<a href="%[3]s">згадав запит на злиття %[4]s, які повторно відкриють цю задачу</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_closing_from=`<a href="%[3]s">згадав запит на злиття %[4]с, які закриють цю задачу</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_reopening_from=`<a href="%[3]s">згадав запит на злиття %[4]с, які повторно відкриють цю задачу</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_closed_from=`<a href="%[3]s">закрив цю задачу %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_reopened_from=`<a href="%[3]s">повторно відкрито цю задачу %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
issues.ref_from=`із %[1]s`
@ -1269,7 +1269,7 @@ issues.error_modifying_due_date=Не вдалося змінити дату за
issues.error_removing_due_date=Не вдалося видалити дату завершення.
issues.push_commit_1=додав %d коміт %s
issues.push_commits_n=додав %d коміти(-ів) %s
issues.force_push_codes=`примусово залито %[1]s з <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> до <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
issues.force_push_codes=`примусово залито %[1]s з <a class="ui sha" href="%[3]s"><code>%[2]</code></a> до <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s`
issues.force_push_compare=Порівняти
issues.due_date_form=рррр-мм-дд
issues.due_date_form_add=Додати дату завершення
@ -2613,7 +2613,7 @@ comment_issue=`прокоментував задачу <a href="%[1]s">%[3]s#%[2
comment_pull=`прокоментував запит злиття <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`прийняв запит злиття <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=перенесено репозиторій <code>%s</code> у <a href="%s">%s</a>
push_tag=створив мітку <a href="%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
push_tag=створив мітку <a href="%[2]s">%[3]</a> в <a href="%[1]s">%[4]s</a>
delete_tag=видалено мітку %[2]s з <a href="%[1]s">%[3]s</a>
delete_branch=видалено гілку %[2]s з <a href="%[1]s">%[3]s</a>
compare_branch=Порівняти
@ -2622,14 +2622,14 @@ compare_commits_general=Порівняти коміти
mirror_sync_push=синхронізував коміти в <a href="%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a> із дзеркала
mirror_sync_create=синхронізував нове посилання <a href="%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a> із дзеркала
mirror_sync_delete=синхронізовано й видалено посилання <code>%[2]s</code> на <a href="%[1]s">%[3]s</a> із дзеркала
approve_pull_request=`схвалив <a href="%[1]s">%[3]s#%[2]s</a>`
approve_pull_request=`схвалив <a href="%[1]s">%[3]s#%[2]</a>`
reject_pull_request=`запропонував зміни до <a href="%[1]s">%[3]s#%[2]s</a>`
publish_release=`опублікував випуск <a href="%[2]s"> "%[4]s" </a> з <a href="%[1]s">%[3]s</a>`
review_dismissed=`відхилив відгук від <b>%[4]s</b> для <a href="%[1]s">%[3]s#%[2]s</a>`
review_dismissed=`відхилив відгук від <b>%[4]</b> для <a href="%[1]s">%[3]s#%[2]s</a>`
review_dismissed_reason=Причина:
create_branch=створив гілку <a href="%[2]s">%[3]s</a> в <a href="%[1]s">%[4]s</a>
starred_repo=додав <a href="%[1]s">%[2]s</a> у обране
watched_repo=почав слідкувати за <a href="%[1]s">%[2]s</a>
watched_repo=почав слідкувати за <a href="%[1]s">%[2]</a>
[tool]
now=зараз

View File

@ -68,7 +68,7 @@ func GetRepositoryFile(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
s, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pv,
&packages_service.PackageFileInfo{
@ -84,8 +84,12 @@ func GetRepositoryFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
func UploadPackageFile(ctx *context.Context) {
@ -196,7 +200,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
@ -205,8 +209,12 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
func DeletePackageFile(ctx *context.Context) {

View File

@ -165,7 +165,7 @@ func ListOwners(ctx *context.Context) {
// DownloadPackageFile serves the content of a package
func DownloadPackageFile(ctx *context.Context) {
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -185,8 +185,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// https://doc.rust-lang.org/cargo/reference/registries.html#publish

View File

@ -341,13 +341,17 @@ func DownloadPackage(ctx *context.Context) {
pf := pd.Files[0].File
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// https://github.com/chef/chef/blob/main/knife/lib/chef/knife/supermarket_unshare.rb

View File

@ -162,7 +162,7 @@ func PackageMetadata(ctx *context.Context) {
// DownloadPackageFile serves the content of a package
func DownloadPackageFile(ctx *context.Context) {
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -182,8 +182,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackage creates a new package

View File

@ -453,7 +453,7 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe
return
}
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -474,8 +474,12 @@ func downloadFile(ctx *context.Context, fileFilter container.Set[string], fileKe
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// DeleteRecipeV1 deletes the requested recipe(s)

View File

@ -292,11 +292,15 @@ func DownloadPackageFile(ctx *context.Context) {
pf := pfs[0]
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}

View File

@ -482,7 +482,22 @@ func GetBlob(ctx *context.Context) {
return
}
serveBlob(ctx, blob)
s, _, err := packages_service.GetPackageFileStream(ctx, blob.File)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
setResponseHeaders(ctx.Resp, &containerHeaders{
ContentDigest: blob.Properties.GetByName(container_module.PropertyDigest),
ContentType: blob.Properties.GetByName(container_module.PropertyMediaType),
ContentLength: blob.Blob.Size,
Status: http.StatusOK,
})
if _, err := io.Copy(ctx.Resp, s); err != nil {
log.Error("Error whilst copying content to response: %v", err)
}
}
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-blobs
@ -621,7 +636,22 @@ func GetManifest(ctx *context.Context) {
return
}
serveBlob(ctx, manifest)
s, _, err := packages_service.GetPackageFileStream(ctx, manifest.File)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
setResponseHeaders(ctx.Resp, &containerHeaders{
ContentDigest: manifest.Properties.GetByName(container_module.PropertyDigest),
ContentType: manifest.Properties.GetByName(container_module.PropertyMediaType),
ContentLength: manifest.Blob.Size,
Status: http.StatusOK,
})
if _, err := io.Copy(ctx.Resp, s); err != nil {
log.Error("Error whilst copying content to response: %v", err)
}
}
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#deleting-tags
@ -656,36 +686,6 @@ func DeleteManifest(ctx *context.Context) {
})
}
func serveBlob(ctx *context.Context, pfd *packages_model.PackageFileDescriptor) {
s, u, _, err := packages_service.GetPackageBlobStream(ctx, pfd.File, pfd.Blob)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
headers := &containerHeaders{
ContentDigest: pfd.Properties.GetByName(container_module.PropertyDigest),
ContentType: pfd.Properties.GetByName(container_module.PropertyMediaType),
ContentLength: pfd.Blob.Size,
Status: http.StatusOK,
}
if u != nil {
headers.Status = http.StatusTemporaryRedirect
headers.Location = u.String()
setResponseHeaders(ctx.Resp, headers)
return
}
defer s.Close()
setResponseHeaders(ctx.Resp, headers)
if _, err := io.Copy(ctx.Resp, s); err != nil {
log.Error("Error whilst copying content to response: %v", err)
}
}
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#content-discovery
func GetTagList(ctx *context.Context) {
image := ctx.Params("image")

View File

@ -249,7 +249,7 @@ func downloadPackageFile(ctx *context.Context, opts *cran_model.SearchOptions) {
return
}
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
@ -258,6 +258,10 @@ func downloadPackageFile(ctx *context.Context, opts *cran_model.SearchOptions) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}

View File

@ -59,7 +59,7 @@ func GetRepositoryFile(ctx *context.Context) {
key += "|" + component + "|" + architecture
}
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
s, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pv,
&packages_service.PackageFileInfo{
@ -75,8 +75,12 @@ func GetRepositoryFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// https://wiki.debian.org/DebianRepository/Format#indices_acquisition_via_hashsums_.28by-hash.29
@ -106,7 +110,7 @@ func GetRepositoryFileByHash(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
@ -115,8 +119,12 @@ func GetRepositoryFileByHash(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
func UploadPackageFile(ctx *context.Context) {
@ -209,7 +217,7 @@ func DownloadPackageFile(ctx *context.Context) {
name := ctx.Params("name")
version := ctx.Params("version")
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -230,8 +238,9 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf, &context.ServeHeaderOptions{
ctx.ServeContent(s, &context.ServeHeaderOptions{
ContentType: "application/vnd.debian.binary-package",
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),

View File

@ -30,7 +30,7 @@ func apiError(ctx *context.Context, status int, obj interface{}) {
// DownloadPackageFile serves the specific generic package.
func DownloadPackageFile(ctx *context.Context) {
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -50,8 +50,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackage uploads the specific generic package.

View File

@ -105,7 +105,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}
s, u, _, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, _, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if errors.Is(err, util.ErrNotExist) {
apiError(ctx, http.StatusNotFound, err)
@ -114,8 +114,12 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pfs[0])
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pfs[0].Name,
LastModified: pfs[0].CreatedUnix.AsLocalTime(),
})
}
func resolvePackage(ctx *context.Context, ownerID int64, name, version string) (*packages_model.PackageVersion, error) {

View File

@ -121,7 +121,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
s, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pvs[0],
&packages_service.PackageFileInfo{
@ -136,8 +136,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackage creates a new package

View File

@ -5,11 +5,8 @@ package helper
import (
"fmt"
"io"
"net/http"
"net/url"
packages_model "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
@ -38,26 +35,3 @@ func LogAndProcessError(ctx *context.Context, status int, obj interface{}, cb fu
cb(message)
}
}
// Serves the content of the package file
// If the url is set it will redirect the request, otherwise the content is copied to the response.
func ServePackageFile(ctx *context.Context, s io.ReadSeekCloser, u *url.URL, pf *packages_model.PackageFile, forceOpts ...*context.ServeHeaderOptions) {
if u != nil {
ctx.Redirect(u.String())
return
}
defer s.Close()
var opts *context.ServeHeaderOptions
if len(forceOpts) > 0 {
opts = forceOpts[0]
} else {
opts = &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
}
}
ctx.ServeContent(s, opts)
}

View File

@ -210,15 +210,21 @@ func servePackageFile(ctx *context.Context, params parameters, serveContent bool
return
}
s, u, _, err := packages_service.GetPackageBlobStream(ctx, pf, pb)
s, err := packages_module.NewContentStore().Get(packages_module.BlobHash256Key(pb.HashSHA256))
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
if pf.IsLead {
if err := packages_model.IncrementDownloadCounter(ctx, pv.ID); err != nil {
log.Error("Error incrementing download counter: %v", err)
}
}
opts.Filename = pf.Name
helper.ServePackageFile(ctx, s, u, pf, opts)
ctx.ServeContent(s, opts)
}
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.

View File

@ -83,7 +83,7 @@ func DownloadPackageFile(ctx *context.Context) {
packageVersion := ctx.Params("version")
filename := ctx.Params("filename")
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -103,8 +103,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// DownloadPackageFileByName finds the version and serves the contents of a package
@ -130,7 +134,7 @@ func DownloadPackageFileByName(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
s, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pvs[0],
&packages_service.PackageFileInfo{
@ -145,8 +149,12 @@ func DownloadPackageFileByName(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackage creates a new package

View File

@ -362,7 +362,7 @@ func DownloadPackageFile(ctx *context.Context) {
packageVersion := ctx.Params("version")
filename := ctx.Params("filename")
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -382,8 +382,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackage creates a new package with the metadata contained in the uploaded nupgk file
@ -596,7 +600,7 @@ func DownloadSymbolFile(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
s, pf, err := packages_service.GetPackageFileStream(ctx, pfs[0])
if err != nil {
if err == packages_model.ErrPackageNotExist || err == packages_model.ErrPackageFileNotExist {
apiError(ctx, http.StatusNotFound, err)
@ -605,8 +609,12 @@ func DownloadSymbolFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// DeletePackage hard deletes the package

View File

@ -273,11 +273,15 @@ func DownloadPackageFile(ctx *context.Context) {
pf := pd.Files[0].File
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}

View File

@ -80,7 +80,7 @@ func DownloadPackageFile(ctx *context.Context) {
packageVersion := ctx.Params("version")
filename := ctx.Params("filename")
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -100,8 +100,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.

View File

@ -65,7 +65,7 @@ func GetRepositoryFile(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
s, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pv,
&packages_service.PackageFileInfo{
@ -80,8 +80,12 @@ func GetRepositoryFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
func UploadPackageFile(ctx *context.Context) {
@ -169,7 +173,7 @@ func DownloadPackageFile(ctx *context.Context) {
name := ctx.Params("name")
version := ctx.Params("version")
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -189,8 +193,13 @@ func DownloadPackageFile(ctx *context.Context) {
}
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
ContentType: "application/x-rpm",
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
func DeletePackageFile(webctx *context.Context) {

View File

@ -175,7 +175,7 @@ func DownloadPackageFile(ctx *context.Context) {
return
}
s, u, pf, err := packages_service.GetFileStreamByPackageVersion(
s, pf, err := packages_service.GetFileStreamByPackageVersion(
ctx,
pvs[0],
&packages_service.PackageFileInfo{
@ -190,8 +190,12 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}
// UploadPackageFile adds a file to the package. If the package does not exist, it gets created.

View File

@ -397,17 +397,18 @@ func DownloadPackageFile(ctx *context.Context) {
pf := pd.Files[0].File
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, _, err := packages_service.GetPackageFileStream(ctx, pf)
if err != nil {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
setResponseHeaders(ctx.Resp, &headers{
Digest: pd.Files[0].Blob.HashSHA256,
})
helper.ServePackageFile(ctx, s, u, pf, &context.ServeHeaderOptions{
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
ContentType: "application/zip",
LastModified: pf.CreatedUnix.AsLocalTime(),

View File

@ -216,7 +216,7 @@ func UploadPackageFile(ctx *context.Context) {
}
func DownloadPackageFile(ctx *context.Context) {
s, u, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
s, pf, err := packages_service.GetFileStreamByPackageNameAndVersion(
ctx,
&packages_service.PackageInfo{
Owner: ctx.Package.Owner,
@ -236,6 +236,10 @@ func DownloadPackageFile(ctx *context.Context) {
apiError(ctx, http.StatusInternalServerError, err)
return
}
defer s.Close()
helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}

View File

@ -201,7 +201,7 @@ func SignInPost(ctx *context.Context) {
u, source, err := auth_service.UserSignIn(form.UserName, form.Password)
if err != nil {
if errors.Is(err, util.ErrNotExist) || errors.Is(err, util.ErrInvalidArgument) {
if user_model.IsErrUserNotExist(err) || user_model.IsErrEmailAddressNotExist(err) {
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplSignIn, &form)
log.Info("Failed authentication attempt for %s from %s: %v", form.UserName, ctx.RemoteAddr(), err)
} else if user_model.IsErrEmailAlreadyUsed(err) {

View File

@ -13,9 +13,7 @@ import (
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/auth/source/oauth2"
@ -83,32 +81,6 @@ func LinkAccount(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplLinkAccount)
}
func handleSignInError(ctx *context.Context, userName string, ptrForm any, tmpl base.TplName, invoker string, err error) {
if errors.Is(err, util.ErrNotExist) {
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tmpl, ptrForm)
} else if errors.Is(err, util.ErrInvalidArgument) {
ctx.Data["user_exists"] = true
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tmpl, ptrForm)
} else if user_model.IsErrUserProhibitLogin(err) {
ctx.Data["user_exists"] = true
log.Info("Failed authentication attempt for %s from %s: %v", userName, ctx.RemoteAddr(), err)
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
} else if user_model.IsErrUserInactive(err) {
ctx.Data["user_exists"] = true
if setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(http.StatusOK, TplActivate)
} else {
log.Info("Failed authentication attempt for %s from %s: %v", userName, ctx.RemoteAddr(), err)
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
}
} else {
ctx.ServerError(invoker, err)
}
}
// LinkAccountPostSignIn handle the coupling of external account with another account using signIn
func LinkAccountPostSignIn(ctx *context.Context) {
signInForm := web.GetForm(ctx).(*forms.SignInForm)
@ -144,7 +116,12 @@ func LinkAccountPostSignIn(ctx *context.Context) {
u, _, err := auth_service.UserSignIn(signInForm.UserName, signInForm.Password)
if err != nil {
handleSignInError(ctx, signInForm.UserName, &signInForm, tplLinkAccount, "UserLinkAccount", err)
if user_model.IsErrUserNotExist(err) {
ctx.Data["user_exists"] = true
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplLinkAccount, &signInForm)
} else {
ctx.ServerError("UserLinkAccount", err)
}
return
}

View File

@ -282,7 +282,11 @@ func ConnectOpenIDPost(ctx *context.Context) {
u, _, err := auth.UserSignIn(form.UserName, form.Password)
if err != nil {
handleSignInError(ctx, form.UserName, &form, tplConnectOID, "ConnectOpenIDPost", err)
if user_model.IsErrUserNotExist(err) {
ctx.RenderWithErr(ctx.Tr("form.username_password_incorrect"), tplConnectOID, &form)
} else {
ctx.ServerError("ConnectOpenIDPost", err)
}
return
}

View File

@ -34,7 +34,7 @@ func List(ctx *context.Context) {
func FetchActionTest(ctx *context.Context) {
_ = ctx.Req.ParseForm()
ctx.Flash.Info("fetch-action: " + ctx.Req.Method + " " + ctx.Req.RequestURI + "<br>" +
ctx.Flash.Info(ctx.Req.Method + " " + ctx.Req.RequestURI + "<br>" +
"Form: " + ctx.Req.Form.Encode() + "<br>" +
"PostForm: " + ctx.Req.PostForm.Encode(),
)
@ -52,15 +52,5 @@ func Tmpl(ctx *context.Context) {
ctx.Data["TimePast1y"] = now.Add(-1 * 366 * 86400 * time.Second)
ctx.Data["TimeFuture1y"] = now.Add(1 * 366 * 86400 * time.Second)
if ctx.Req.Method == "POST" {
_ = ctx.Req.ParseForm()
ctx.Flash.Info("form: "+ctx.Req.Method+" "+ctx.Req.RequestURI+"<br>"+
"Form: "+ctx.Req.Form.Encode()+"<br>"+
"PostForm: "+ctx.Req.PostForm.Encode(),
true,
)
time.Sleep(2 * time.Second)
}
ctx.HTML(http.StatusOK, base.TplName("devtest"+path.Clean("/"+ctx.Params("sub"))))
}

View File

@ -22,7 +22,6 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
packages_helper "code.gitea.io/gitea/routers/api/packages/helper"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/forms"
packages_service "code.gitea.io/gitea/services/packages"
@ -444,11 +443,18 @@ func DownloadPackageFile(ctx *context.Context) {
return
}
s, u, _, err := packages_service.GetPackageFileStream(ctx, pf)
s, _, err := packages_service.GetPackageFileStream(
ctx,
pf,
)
if err != nil {
ctx.ServerError("GetPackageFileStream", err)
return
}
defer s.Close()
packages_helper.ServePackageFile(ctx, s, u, pf)
ctx.ServeContent(s, &context.ServeHeaderOptions{
Filename: pf.Name,
LastModified: pf.CreatedUnix.AsLocalTime(),
})
}

View File

@ -4,54 +4,19 @@
package db
import (
"fmt"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
)
// ErrUserPasswordNotSet represents a "ErrUserPasswordNotSet" kind of error.
type ErrUserPasswordNotSet struct {
UID int64
Name string
}
func (err ErrUserPasswordNotSet) Error() string {
return fmt.Sprintf("user's password isn't set [uid: %d, name: %s]", err.UID, err.Name)
}
// Unwrap unwraps this error as a ErrInvalidArgument error
func (err ErrUserPasswordNotSet) Unwrap() error {
return util.ErrInvalidArgument
}
// ErrUserPasswordInvalid represents a "ErrUserPasswordInvalid" kind of error.
type ErrUserPasswordInvalid struct {
UID int64
Name string
}
func (err ErrUserPasswordInvalid) Error() string {
return fmt.Sprintf("user's password is invalid [uid: %d, name: %s]", err.UID, err.Name)
}
// Unwrap unwraps this error as a ErrInvalidArgument error
func (err ErrUserPasswordInvalid) Unwrap() error {
return util.ErrInvalidArgument
}
// Authenticate authenticates the provided user against the DB
func Authenticate(user *user_model.User, login, password string) (*user_model.User, error) {
if user == nil {
return nil, user_model.ErrUserNotExist{Name: login}
}
if !user.IsPasswordSet() {
return nil, ErrUserPasswordNotSet{UID: user.ID, Name: user.Name}
} else if !user.ValidatePassword(password) {
return nil, ErrUserPasswordInvalid{UID: user.ID, Name: user.Name}
if !user.IsPasswordSet() || !user.ValidatePassword(password) {
return nil, user_model.ErrUserNotExist{UID: user.ID, Name: user.Name}
}
// Update password hash if server password hash algorithm have changed

View File

@ -9,7 +9,6 @@ import (
"errors"
"fmt"
"io"
"net/url"
"strings"
"code.gitea.io/gitea/models/db"
@ -21,7 +20,6 @@ import (
"code.gitea.io/gitea/modules/notification"
packages_module "code.gitea.io/gitea/modules/packages"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
)
@ -564,62 +562,70 @@ func DeletePackageFile(ctx context.Context, pf *packages_model.PackageFile) erro
}
// GetFileStreamByPackageNameAndVersion returns the content of the specific package file
func GetFileStreamByPackageNameAndVersion(ctx context.Context, pvi *PackageInfo, pfi *PackageFileInfo) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
func GetFileStreamByPackageNameAndVersion(ctx context.Context, pvi *PackageInfo, pfi *PackageFileInfo) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
log.Trace("Getting package file stream: %v, %v, %s, %s, %s, %s", pvi.Owner.ID, pvi.PackageType, pvi.Name, pvi.Version, pfi.Filename, pfi.CompositeKey)
pv, err := packages_model.GetVersionByNameAndVersion(ctx, pvi.Owner.ID, pvi.PackageType, pvi.Name, pvi.Version)
if err != nil {
if err == packages_model.ErrPackageNotExist {
return nil, nil, nil, err
return nil, nil, err
}
log.Error("Error getting package: %v", err)
return nil, nil, nil, err
return nil, nil, err
}
return GetFileStreamByPackageVersion(ctx, pv, pfi)
}
// GetFileStreamByPackageVersionAndFileID returns the content of the specific package file
func GetFileStreamByPackageVersionAndFileID(ctx context.Context, owner *user_model.User, versionID, fileID int64) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
log.Trace("Getting package file stream: %v, %v, %v", owner.ID, versionID, fileID)
pv, err := packages_model.GetVersionByID(ctx, versionID)
if err != nil {
if err != packages_model.ErrPackageNotExist {
log.Error("Error getting package version: %v", err)
}
return nil, nil, err
}
p, err := packages_model.GetPackageByID(ctx, pv.PackageID)
if err != nil {
log.Error("Error getting package: %v", err)
return nil, nil, err
}
if p.OwnerID != owner.ID {
return nil, nil, packages_model.ErrPackageNotExist
}
pf, err := packages_model.GetFileForVersionByID(ctx, versionID, fileID)
if err != nil {
log.Error("Error getting file: %v", err)
return nil, nil, err
}
return GetPackageFileStream(ctx, pf)
}
// GetFileStreamByPackageVersion returns the content of the specific package file
func GetFileStreamByPackageVersion(ctx context.Context, pv *packages_model.PackageVersion, pfi *PackageFileInfo) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
func GetFileStreamByPackageVersion(ctx context.Context, pv *packages_model.PackageVersion, pfi *PackageFileInfo) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
pf, err := packages_model.GetFileForVersionByName(ctx, pv.ID, pfi.Filename, pfi.CompositeKey)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
return GetPackageFileStream(ctx, pf)
}
// GetPackageFileStream returns the content of the specific package file
func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
func GetPackageFileStream(ctx context.Context, pf *packages_model.PackageFile) (io.ReadSeekCloser, *packages_model.PackageFile, error) {
pb, err := packages_model.GetBlobByID(ctx, pf.BlobID)
if err != nil {
return nil, nil, nil, err
}
return GetPackageBlobStream(ctx, pf, pb)
}
// GetPackageBlobStream returns the content of the specific package blob
// If the storage supports direct serving and it's enabled, only the direct serving url is returned.
func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, pb *packages_model.PackageBlob) (io.ReadSeekCloser, *url.URL, *packages_model.PackageFile, error) {
key := packages_module.BlobHash256Key(pb.HashSHA256)
cs := packages_module.NewContentStore()
var s io.ReadSeekCloser
var u *url.URL
var err error
if cs.ShouldServeDirect() {
u, err = cs.GetServeDirectURL(key, pf.Name)
if err != nil && !errors.Is(err, storage.ErrURLNotSupported) {
log.Error("Error getting serve direct url: %v", err)
}
}
if u == nil {
s, err = cs.Get(key)
return nil, nil, err
}
s, err := packages_module.NewContentStore().Get(packages_module.BlobHash256Key(pb.HashSHA256))
if err == nil {
if pf.IsLead {
if err := packages_model.IncrementDownloadCounter(ctx, pf.VersionID); err != nil {
@ -627,7 +633,7 @@ func GetPackageBlobStream(ctx context.Context, pf *packages_model.PackageFile, p
}
}
}
return s, u, pf, err
return s, pf, err
}
// RemoveAllPackages for User

View File

@ -1,18 +1,5 @@
{{template "base/head" .}}
<div class="page-content devtest ui container">
{{template "base/alert" .}}
<button class="show-modal" data-modal="#test-modal-form">show modal form</button>
<div id="test-modal-form" class="ui mini modal">
<div class="header">Form dialog</div>
<form class="content" method="post">
<div class="ui input"><input name="user_input"></div>
{{template "base/modal_actions_confirm" (dict "locale" $.locale "ModalButtonTypes" "confirm")}}
</form>
</div>
<div class="divider"></div>
<div class="ui g-modal-confirm modal" id="test-modal-default">
<div class="header">{{svg "octicon-file"}} Default dialog <span>title</span></div>
<div class="content">

View File

@ -39,26 +39,32 @@
{{.locale.Tr "settings.manage_emails"}}
</h4>
<div class="ui attached segment">
<div class="ui list">
<div class="ui email list">
{{if $.EnableNotifyMail}}
<div class="item">
<div class="gt-mb-3">{{.locale.Tr "settings.email_desc"}}</div>
<form action="{{AppSubUrl}}/user/settings/account/email" class="ui form" method="post">
{{$.CsrfTokenHtml}}
<input name="_method" type="hidden" value="NOTIFICATION">
<div class="gt-df gt-fw gt-gap-3">
<div class="ui selection dropdown">
<input name="preference" type="hidden" value="{{.EmailNotificationsPreference}}">
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="text"></div>
<div class="menu">
<div data-value="enabled" class="{{if eq .EmailNotificationsPreference "enabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.enable"}}</div>
<div data-value="andyourown" class="{{if eq .EmailNotificationsPreference "andyourown"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.andyourown"}}</div>
<div data-value="onmention" class="{{if eq .EmailNotificationsPreference "onmention"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.onmention"}}</div>
<div data-value="disabled" class="{{if eq .EmailNotificationsPreference "disabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.disable"}}</div>
{{.locale.Tr "settings.email_desc"}}
<div class="right floated content">
<div class="field">
<button class="ui green button">{{$.locale.Tr "settings.email_notifications.submit"}}</button>
</div>
</div>
<div class="right floated content">
{{$.CsrfTokenHtml}}
<input name="_method" type="hidden" value="NOTIFICATION">
<div class="field">
<div class="ui selection dropdown" tabindex="0">
<input name="preference" type="hidden" value="{{.EmailNotificationsPreference}}">
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="text"></div>
<div class="menu">
<div data-value="enabled" class="{{if eq .EmailNotificationsPreference "enabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.enable"}}</div>
<div data-value="andyourown" class="{{if eq .EmailNotificationsPreference "andyourown"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.andyourown"}}</div>
<div data-value="onmention" class="{{if eq .EmailNotificationsPreference "onmention"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.onmention"}}</div>
<div data-value="disabled" class="{{if eq .EmailNotificationsPreference "disabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.disable"}}</div>
</div>
</div>
</div>
<button class="ui green button">{{$.locale.Tr "settings.email_notifications.submit"}}</button>
</div>
</form>
</div>
@ -96,7 +102,7 @@
</form>
</div>
{{end}}
<div class="content gt-py-3">
<div class="content">
<strong>{{.Email}}</strong>
{{if .IsPrimary}}
<div class="ui primary label">{{$.locale.Tr "settings.primary"}}</div>

View File

@ -22,19 +22,7 @@
</div>
{{end}}
</div>
<div class="ui g-modal-confirm delete modal" id="remove-gitea-oauth2-application">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.remove_oauth2_application"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.oauth2_application_remove_description"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
</div>
<div class="ui attached bottom segment">
<h5 class="ui top header">
{{.locale.Tr "settings.create_oauth2_application"}}
@ -58,3 +46,14 @@
</button>
</form>
</div>
<div class="ui g-modal-confirm delete modal" id="remove-gitea-oauth2-application">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.remove_oauth2_application"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.oauth2_application_remove_description"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>

View File

@ -26,15 +26,15 @@
</div>
{{end}}
</div>
<div class="ui g-modal-confirm delete modal" id="revoke-gitea-oauth2-grant">
<div class="header">
{{svg "octicon-shield" 16 "gt-mr-2"}}
{{.locale.Tr "settings.revoke_oauth2_grant"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.revoke_oauth2_grant_description"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
</div>
<div class="ui g-modal-confirm delete modal" id="revoke-gitea-oauth2-grant">
<div class="header">
{{svg "octicon-shield" 16 "gt-mr-2"}}
{{.locale.Tr "settings.revoke_oauth2_grant"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.revoke_oauth2_grant_description"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>

View File

@ -39,16 +39,16 @@
</div>
{{end}}
</div>
</div>
<div class="ui g-modal-confirm delete modal" id="delete-account-link">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.remove_account_link"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.remove_account_link_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
<div class="ui g-modal-confirm delete modal" id="delete-account-link">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.remove_account_link"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.remove_account_link_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
{{end}}

View File

@ -48,15 +48,15 @@
{{.locale.Tr "settings.add_openid"}}
</button>
</form>
<div class="ui g-modal-confirm delete modal" id="delete-openid">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.openid_deletion"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.openid_deletion_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
</div>
<div class="ui g-modal-confirm delete modal" id="delete-openid">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.openid_deletion"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.openid_deletion_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>

View File

@ -21,15 +21,15 @@
<a class="ui green button" href="{{AppSubUrl}}/user/settings/security/two_factor/enroll">{{$.locale.Tr "settings.twofa_enroll"}}</a>
</div>
{{end}}
<div class="ui g-modal-confirm delete modal" id="disable-twofa">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.twofa_disable"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.twofa_disable_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
</div>
<div class="ui g-modal-confirm delete modal" id="disable-twofa">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.twofa_disable"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.twofa_disable_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>

View File

@ -24,14 +24,15 @@
</div>
<button id="register-webauthn" class="ui green button">{{svg "octicon-key"}} {{.locale.Tr "settings.webauthn_register_key"}}</button>
</div>
<div class="ui g-modal-confirm delete modal" id="delete-registration">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.webauthn_delete_key"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.webauthn_delete_key_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>
</div>
<div class="ui g-modal-confirm delete modal" id="delete-registration">
<div class="header">
{{svg "octicon-trash"}}
{{.locale.Tr "settings.webauthn_delete_key"}}
</div>
<div class="content">
<p>{{.locale.Tr "settings.webauthn_delete_key_desc"}}</p>
</div>
{{template "base/modal_actions_confirm" .}}
</div>

View File

@ -6,7 +6,6 @@ package integration
import (
"bytes"
"fmt"
"io"
"net/http"
"testing"
@ -140,42 +139,6 @@ func TestPackageGeneric(t *testing.T) {
req = NewRequest(t, "GET", url+"/dummy.bin")
MakeRequest(t, req, http.StatusUnauthorized)
})
t.Run("ServeDirect", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
if setting.Packages.Storage.Type != setting.MinioStorageType {
t.Skip("Test skipped for non-Minio-storage.")
return
}
if !setting.Packages.Storage.MinioConfig.ServeDirect {
old := setting.Packages.Storage.MinioConfig.ServeDirect
defer func() {
setting.Packages.Storage.MinioConfig.ServeDirect = old
}()
setting.Packages.Storage.MinioConfig.ServeDirect = true
}
req := NewRequest(t, "GET", url+"/"+filename)
resp := MakeRequest(t, req, http.StatusSeeOther)
checkDownloadCount(3)
location := resp.Header().Get("Location")
assert.NotEmpty(t, location)
resp2, err := (&http.Client{}).Get(location)
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, resp2.StatusCode)
body, err := io.ReadAll(resp2.Body)
assert.NoError(t, err)
assert.Equal(t, content, body)
checkDownloadCount(3)
})
})
t.Run("Delete", func(t *testing.T) {

View File

@ -375,6 +375,16 @@ progress::-moz-progress-bar {
opacity: 1 !important;
}
.svg {
display: inline-block;
vertical-align: text-top;
fill: currentcolor;
}
.middle .svg {
vertical-align: middle;
}
.unselectable,
.button,
.lines-num,

View File

@ -10,7 +10,6 @@
@import "./modules/navbar.css";
@import "./modules/toast.css";
@import "./modules/divider.css";
@import "./modules/svg.css";
@import "./shared/issuelist.css";
@import "./shared/milestone.css";

View File

@ -1,41 +0,0 @@
.svg {
display: inline-block;
vertical-align: text-top;
fill: currentcolor;
}
.middle .svg {
vertical-align: middle;
}
/* prevent SVGs from shrinking, like in space-starved flexboxes. the sizes
here are cherry-picked for our use cases, feel free to add more. after
https://developer.mozilla.org/en-US/docs/Web/CSS/attr#type-or-unit is
supported in browsers, use `attr(width px)` instead for a generic
solution. */
.svg[height="12"] { min-height: 12px; }
.svg[height="13"] { min-height: 13px; }
.svg[height="14"] { min-height: 14px; }
.svg[height="15"] { min-height: 15px; }
.svg[height="16"] { min-height: 16px; }
.svg[height="18"] { min-height: 18px; }
.svg[height="20"] { min-height: 20px; }
.svg[height="22"] { min-height: 22px; }
.svg[height="24"] { min-height: 24px; }
.svg[height="36"] { min-height: 36px; }
.svg[height="48"] { min-height: 48px; }
.svg[height="56"] { min-height: 56px; }
.svg[width="12"] { min-width: 12px; }
.svg[width="13"] { min-width: 13px; }
.svg[width="14"] { min-width: 14px; }
.svg[width="15"] { min-width: 15px; }
.svg[width="16"] { min-width: 16px; }
.svg[width="18"] { min-width: 18px; }
.svg[width="20"] { min-width: 20px; }
.svg[width="22"] { min-width: 22px; }
.svg[width="24"] { min-width: 24px; }
.svg[width="36"] { min-width: 36px; }
.svg[width="48"] { min-width: 48px; }
.svg[width="56"] { min-width: 56px; }

View File

@ -2358,6 +2358,10 @@
color: var(--color-text-light-2);
}
.settings .list.email > .item:not(:first-child) {
min-height: 60px;
}
.settings .list.collaborator > .item {
padding: 0;
}

View File

@ -1,26 +0,0 @@
import $ from 'jquery';
const fomanticModalFn = $.fn.modal;
// use our own `$.fn.modal` to patch Fomantic's modal module
export function initAriaModalPatch() {
if ($.fn.modal === ariaModalFn) throw new Error('initAriaModalPatch could only be called once');
$.fn.modal = ariaModalFn;
ariaModalFn.settings = fomanticModalFn.settings;
}
// the patched `$.fn.modal` modal function
// * it does the one-time attaching on the first call
function ariaModalFn(...args) {
const ret = fomanticModalFn.apply(this, args);
if (args[0] === 'show' || args[0]?.autoShow) {
for (const el of this) {
// If there is a form in the modal, there might be a "cancel" button before "ok" button (all buttons are "type=submit" by default).
// In such case, the "Enter" key will trigger the "cancel" button instead of "ok" button, then the dialog will be closed.
// It breaks the user experience - the "Enter" key should confirm the dialog and submit the form.
// So, all "cancel" buttons without "[type]" must be marked as "type=button".
$(el).find('form button.cancel:not([type])').attr('type', 'button');
}
}
return ret;
}

View File

@ -1,7 +1,6 @@
import $ from 'jquery';
import {initAriaCheckboxPatch} from './aria/checkbox.js';
import {initAriaDropdownPatch} from './aria/dropdown.js';
import {initAriaModalPatch} from './aria/modal.js';
import {svg} from '../svg.js';
export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)');
@ -27,7 +26,6 @@ export function initGiteaFomantic() {
// Use the patches to improve accessibility, these patches are designed to be as independent as possible, make it easy to modify or remove in the future.
initAriaCheckboxPatch();
initAriaDropdownPatch();
initAriaModalPatch();
}
function initFomanticApiPatch() {