Compare commits

...

11 Commits

Author SHA1 Message Date
Brecht Van Lommel
d647e74502
Improve squash merge commit author and co-author with private emails (#22977)
When emails addresses are private, squash merges always use
`@noreply.localhost` for the author of the squash commit. And the author
is redundantly added as a co-author in the commit message.

Also without private mails, the redundant co-author is possible when
committing with a signature that's different than the user full name and
primary email.

Now try to find a commit by the same user in the list of commits, and
prefer the signature from that over one constructed from the account
settings.
2023-03-09 22:17:04 -05:00
wxiaoguang
0141d1667d
Fix broken Chroma CSS styles (#23174)
The CSS styles in Gitea themes are out-of-sync of Chroma's styles.

This PR introduces a `chroma-style-diff.go` tool to compare the diff.
The missing CSS styles have been added manually. They are left as empty
to reduce arguments because there was no color for them before.

And this PR fixes #22348, with just 2 lines changed: `.chroma .kt & .n`,
these colors are taken from GitHub.

It's good enough for #22348


![image](https://user-images.githubusercontent.com/2114189/221551941-0d27d11d-e71e-498f-8e88-92b558fe4a18.png)

---------

Co-authored-by: silverwind <me@silverwind.io>
2023-03-09 22:16:16 -05:00
InsanusMokrassar
92d3e2a6f8
Add gradle samples in maven doc of packages (#23374)
Samples for gitea.io docs to help to use maven packages with
gradle-oriented projects

---------

Co-authored-by: KN4CK3R <admin@oldschoolhack.me>
2023-03-09 22:14:59 -05:00
silverwind
17c8a0523a
Fix and move "Use this template" button (#23398)
Before:
<img width="1157" alt="Screenshot 2023-03-09 at 23 21 25"
src="https://user-images.githubusercontent.com/115237/224174168-869966cc-fa59-4231-b449-23bd9db12862.png">

After:
<img width="1145" alt="Screenshot 2023-03-09 at 23 24 34"
src="https://user-images.githubusercontent.com/115237/224174173-7f5b9c22-44c4-4eed-990c-da49d749eb0e.png">

---------

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2023-03-09 22:14:45 -05:00
GiteaBot
c775053476 [skip ci] Updated translations via Crowdin 2023-03-10 00:15:59 +00:00
Lycolia Rizzim
79af6e367c
Add init file for Ubuntu (#23362)
Created an init file for Ubuntu that will be useful when running it on
WSL.
2023-03-09 16:54:37 -06:00
yp05327
e6df743eca
Rename canWriteUnit to canWriteProjects (#23386)
A part of https://github.com/go-gitea/gitea/pull/22865
2023-03-09 13:57:20 -06:00
Brecht Van Lommel
8bdc0acf97
Fix pull request update showing too many commits with multiple branches (#22856)
When the base repository contains multiple branches with the same
commits as the base branch, pull requests can show a long list of
commits already in the base branch as having been added.

What this is supposed to do is exclude commits already in the base
branch. But the mechansim to do so assumed a commit only exists in a
single branch. Now use `git rev-list A B --not branchName` instead of
filtering commits afterwards.

The logic to detect if there was a force push also was wrong for
multiple branches. If the old commit existed in any branch in the base
repository it would assume there was no force push. Instead check if the
old commit is an ancestor of the new commit.
2023-03-09 12:14:22 -06:00
yp05327
689770c928
Fix incorrect NotFound conditions in org/projects.go (#23384)
A part of https://github.com/go-gitea/gitea/pull/22865

user/org project's `RepoID` is always 0, we need to check `OwnerID`
2023-03-09 10:59:50 -06:00
wxiaoguang
542cec98f8
Refactor merge/update git command calls (#23366)
Follow #22568

* Remove unnecessary ToTrustedCmdArgs calls 
    * the FAQ in  #22678
* Quote: When using ToTrustedCmdArgs, the code will be very complex (see
the changes for examples). Then developers and reviewers can know that
something might be unreasonable.
* The `signArg` couldn't be empty, it's either `-S{keyID}` or
`--no-gpg-sign`.
* Use `signKeyID` instead, add comment "empty for no-sign, non-empty to
sign"
* 5-line code could be extracted to a common `NewGitCommandCommit()` to
handle the `signKeyID`, but I think it's not a must, current code is
clear enough.
2023-03-09 09:48:52 -06:00
yp05327
e52ac62d8e
Redirect to project again after editing it (#23326)
A part of https://github.com/go-gitea/gitea/pull/22865

We have edit buttons in projects list page and project view page.
But after user edit a project, it will always redirect to the projects
list page.
2023-03-09 08:38:29 -06:00
28 changed files with 657 additions and 190 deletions

View File

@ -1,12 +1,18 @@
plugins:
- stylelint-declaration-strict-value
ignoreFiles:
- "**/*.go"
overrides:
- files: ["**/*.less"]
customSyntax: postcss-less
- files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"]
rules:
scale-unlimited/declaration-strict-value: null
- files: ["**/chroma/*", "**/codemirror/*"]
rules:
block-no-empty: null
rules:
alpha-value-notation: null

84
contrib/init/ubuntu/gitea Normal file
View File

@ -0,0 +1,84 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: gitea
# Required-Start: $syslog $network
# Required-Stop: $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: A self-hosted Git service written in Go.
# Description: A self-hosted Git service written in Go.
### END INIT INFO
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="Gitea - Git with a cup of tea"
NAME=gitea
SERVICEVERBOSE=yes
PIDFILE=/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
WORKINGDIR=/var/lib/$NAME
DAEMON=/usr/local/bin/$NAME
DAEMON_ARGS="web -c /etc/$NAME/app.ini"
USER=git
STOP_SCHEDULE="${STOP_SCHEDULE:-QUIT/5/TERM/1/KILL/5}"
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
do_start()
{
GITEA_ENVS="USER=$USER GITEA_WORK_DIR=$WORKINGDIR HOME=/home/$USER"
GITEA_EXEC="$DAEMON -- $DAEMON_ARGS"
sh -c "start-stop-daemon --start --quiet --pidfile $PIDFILE --make-pidfile \\
--background --chdir $WORKINGDIR --chuid $USER \\
--exec /bin/bash -- -c '/usr/bin/env $GITEA_ENVS $GITEA_EXEC'"
}
do_stop()
{
start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PIDFILE --name $NAME --oknodo
rm -f $PIDFILE
}
do_status()
{
if [ -f $PIDFILE ]; then
if kill -0 $(cat "$PIDFILE"); then
echo "$NAME is running, PID is $(cat $PIDFILE)"
else
echo "$NAME process is dead, but pidfile exists"
fi
else
echo "$NAME is not running"
fi
}
case "$1" in
start)
echo "Starting $DESC" "$NAME"
do_start
;;
stop)
echo "Stopping $DESC" "$NAME"
do_stop
;;
status)
do_status
;;
restart)
echo "Restarting $DESC" "$NAME"
do_stop
do_start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart}" >&2
exit 2
;;
esac
exit 0

View File

@ -23,7 +23,7 @@ Publish [Maven](https://maven.apache.org) packages for your user or organization
## Requirements
To work with the Maven package registry, you can use [Maven](https://maven.apache.org/install.html) or [Gradle](https://gradle.org/install/).
The following examples use `Maven`.
The following examples use `Maven` and `Gradle Groovy`.
## Configuring the package registry
@ -73,6 +73,40 @@ Afterwards add the following sections to your project `pom.xml` file:
| `access_token` | Your [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}). |
| `owner` | The owner of the package. |
### Gradle variant
When you plan to add some packages from Gitea instance in your project, you should add it in repositories section:
```groovy
repositories {
// other repositories
maven { url "https://gitea.example.com/api/packages/{owner}/maven" }
}
```
In Groovy gradle you may include next script in your publishing part:
```groovy
publishing {
// other settings of publication
repositories {
maven {
name = "Gitea"
url = uri("https://gitea.example.com/api/packages/{owner}/maven")
credentials(HttpHeaderCredentials) {
name = "Authorization"
value = "token {access_token}"
}
authentication {
header(HttpHeaderAuthentication)
}
}
}
}
```
## Publish a package
To publish a package simply run:
@ -81,6 +115,12 @@ To publish a package simply run:
mvn deploy
```
Or call `gradle` with task `publishAllPublicationsToGiteaRepository` in case you are using gradle:
```groovy
./gradlew publishAllPublicationsToGiteaRepository
```
If you want to publish a prebuild package to the registry, you can use [`mvn deploy:deploy-file`](https://maven.apache.org/plugins/maven-deploy-plugin/deploy-file-mojo.html):
```shell
@ -105,6 +145,12 @@ To install a Maven package from the package registry, add a new dependency to yo
</dependency>
```
And analog in gradle groovy:
```groovy
implementation "com.test.package:test_project:1.0.0"
```
Afterwards run:
```shell

View File

@ -179,7 +179,7 @@ func (c *Command) AddDashesAndList(list ...string) *Command {
}
// ToTrustedCmdArgs converts a list of strings (trusted as argument) to TrustedCmdArgs
// In most cases, it shouldn't be used. Use AddXxx function instead
// In most cases, it shouldn't be used. Use NewCommand().AddXxx() function instead
func ToTrustedCmdArgs(args []string) TrustedCmdArgs {
ret := make(TrustedCmdArgs, len(args))
for i, arg := range args {

View File

@ -218,6 +218,19 @@ func (c *Commit) HasPreviousCommit(commitHash SHA1) (bool, error) {
return false, err
}
// IsForcePush returns true if a push from oldCommitHash to this is a force push
func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
if oldCommitID == EmptySHA {
return false, nil
}
oldCommit, err := c.repo.GetCommit(oldCommitID)
if err != nil {
return false, err
}
hasPreviousCommit, err := c.HasPreviousCommit(oldCommit.ID)
return !hasPreviousCommit, err
}
// CommitsBeforeLimit returns num commits before current revision
func (c *Commit) CommitsBeforeLimit(num int) ([]*Commit, error) {
return c.repo.getCommitsBeforeLimit(c.ID, num)

View File

@ -323,6 +323,27 @@ func (repo *Repository) CommitsBetweenLimit(last, before *Commit, limit, skip in
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
}
// CommitsBetweenNotBase returns a list that contains commits between [before, last), excluding commits in baseBranch.
// If before is detached (removed by reset + push) it is not included.
func (repo *Repository) CommitsBetweenNotBase(last, before *Commit, baseBranch string) ([]*Commit, error) {
var stdout []byte
var err error
if before == nil {
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
} else {
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String()+".."+last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
if err != nil && strings.Contains(err.Error(), "no merge base") {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list before last so let's try that...
stdout, _, err = NewCommand(repo.Ctx, "rev-list").AddDynamicArguments(before.ID.String(), last.ID.String()).AddOptionValues("--not", baseBranch).RunStdBytes(&RunOpts{Dir: repo.Path})
}
}
if err != nil {
return nil, err
}
return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
}
// CommitsBetweenIDs return commits between twoe commits
func (repo *Repository) CommitsBetweenIDs(last, before string) ([]*Commit, error) {
lastCommit, err := repo.GetCommit(last)

View File

@ -4,10 +4,8 @@
package repository
import (
"context"
"strings"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/git"
)
@ -96,19 +94,3 @@ func (opts *PushUpdateOptions) RefName() string {
func (opts *PushUpdateOptions) RepoFullName() string {
return opts.RepoUserName + "/" + opts.RepoName
}
// IsForcePush detect if a push is a force push
func IsForcePush(ctx context.Context, opts *PushUpdateOptions) (bool, error) {
if !opts.IsUpdateBranch() {
return false, nil
}
output, _, err := git.NewCommand(ctx, "rev-list", "--max-count=1").AddDynamicArguments(opts.OldCommitID, "^"+opts.NewCommitID).
RunStdString(&git.RunOpts{Dir: repo_model.RepoPath(opts.RepoUserName, opts.RepoName)})
if err != nil {
return false, err
} else if len(output) > 0 {
return true, nil
}
return false, nil
}

View File

@ -57,6 +57,7 @@ new_mirror=Nové zrcadlo
new_fork=Nové rozštěpení repozitáře
new_org=Nová organizace
new_project=Nový projekt
new_project_column=Nový sloupec
manage_org=Spravovat organizace
admin_panel=Administrace
account_settings=Nastavení účtu
@ -90,9 +91,11 @@ disabled=Zakázané
copy=Kopírovat
copy_url=Kopírovat URL
copy_content=Kopírovat obsah
copy_branch=Kopírovat jméno větve
copy_success=Zkopírováno!
copy_error=Kopírování se nezdařilo
copy_type_unsupported=Tento typ souboru nelze zkopírovat
write=Zapsat
preview=Náhled
@ -109,6 +112,10 @@ never=Nikdy
rss_feed=RSS kanál
[aria]
navbar=Navigační lišta
footer=Patička
footer.software=O softwaru
footer.links=Odkazy
[filter]
string.asc=A Z
@ -292,23 +299,71 @@ code_search_results=Výsledky hledání pro „%s“
code_last_indexed_at=Naposledy indexováno %s
relevant_repositories_tooltip=Repozitáře, které jsou rozštěpení nebo nemají žádné téma, ikonu a žádný popis jsou skryty.
relevant_repositories=`Zobrazují se pouze relevantní repositáře, <a href="`
internal_token_failed=Nepodařilo se vytvořit interní token: %v
secret_key_failed=Nepodařilo se vytvořit tajný klíč: %v
save_config_failed=Uložení konfigurace se nezdařilo: %v
invalid_admin_setting=Nastavení účtu správce není správné: %v
invalid_log_root_path=Kořenový adresář logů není správný: %v
default_keep_email_private=Jako počáteční nastavení skrýt e-mailové adresy
default_keep_email_private_popup=Nastaví e-mailové adresy novým uživatelským účtům jako skryté.
default_allow_create_organization=Dovolí novým uživatelům zakládat organizace
default_allow_create_organization_popup=Povolit novým uživatelským účtům vytvářet organizace.
default_enable_timetracking=Povolit sledování času ve výchozím nastavení
default_enable_timetracking_popup=Povolí sledování času pro nové repozitáře.
no_reply_address=Skrytá e-mailová doména
no_reply_address_helper=Název domény pro uživatele se skrytou e-mailovou adresou. Příklad: Pokud je název skryté e-mailové domény nastaven na „noreply.example.org“, uživatelské jméno „joe“ bude zaznamenáno v Gitu jako „joe@noreply.example.org“.
password_algorithm=Hash algoritmus hesla
password_algorithm_helper=Nastavte algoritmus hashování hesla. Algoritmy mají odlišné požadavky a sílu. `argon2` používá mnoho paměti a může být nevhodný pro malé systémy.
enable_update_checker=Povolit kontrolu aktualizací
enable_update_checker_helper=Kontroluje vydání nových verzí pravidelně připojením ke gitea.io.
[home]
uname_holder=Uživatelské jméno nebo e-mailová adresa
password_holder=Heslo
switch_dashboard_context=Přepnout kontext přehledu
my_repos=Repozitáře
show_more_repos=Zobrazit více repozitářů…
collaborative_repos=Společné repozitáře
my_orgs=Mé organizace
my_mirrors=Má zrcadla
view_home=Zobrazit %s
search_repos=Nalézt repozitář…
filter=Ostatní filtry
filter_by_team_repositories=Filtrovat podle repozitářů týmu
feed_of=Kanál z „%s“
show_archived=Archivováno
show_both_archived_unarchived=Zobrazeny jak archivované tak nearchivované
show_only_archived=Zobrazeny pouze archivované
show_only_unarchived=Zobrazeny pouze nearchivované
show_private=Soukromý
show_both_private_public=Zobrazeny jak veřejné tak soukromé
show_only_private=Zobrazeny pouze soukromé
show_only_public=Zobrazeny pouze veřejné
issues.in_your_repos=Ve vašich repozitářích
[explore]
repos=Repozitáře
users=Uživatelé
organizations=Organizace
search=Vyhledat
code=Kód
search.type.tooltip=Druh vyhledávání
search.fuzzy=Fuzzy
search.fuzzy.tooltip=Zahrnout výsledky, které také úzce odpovídají hledanému výrazu
search.match=Shoda
search.match.tooltip=Zahrnout pouze výsledky, které odpovídají přesnému hledanému výrazu
code_search_unavailable=V současné době není vyhledávání kódu dostupné. Obraťte se na správce webu.
repo_no_results=Nebyly nalezeny žádné odpovídající repozitáře.
user_no_results=Nebyly nalezeni žádní odpovídající uživatelé.
org_no_results=Nebyly nalezeny žádné odpovídající organizace.
code_no_results=Nebyl nalezen žádný zdrojový kód odpovídající hledanému výrazu.
code_search_results=Výsledky hledání pro „%s“
code_last_indexed_at=Naposledy indexováno %s
relevant_repositories_tooltip=Repozitáře, které jsou rozštěpení nebo nemají žádné téma, ikonu a žádný popis jsou skryty.
relevant_repositories=Zobrazují se pouze relevantní repositáře, <a href="%s">zobrazit nefiltrované výsledky</a>.
[auth]
@ -338,6 +393,7 @@ email_not_associate=Tato e-mailová adresa není spojena s žádným účtem.
send_reset_mail=Zaslat e-mail pro obnovení účtu
reset_password=Obnovení účtu
invalid_code=Tento potvrzující kód je neplatný nebo mu vypršela platnost.
invalid_password=Vaše heslo se neshoduje s heslem, které bylo použito k vytvoření účtu.
reset_password_helper=Obnovit účet
reset_password_wrong_user=Jste přihlášen/a jako %s, ale odkaz pro obnovení účtu je pro %s
password_too_short=Délka hesla musí být minimálně %d znaků.
@ -381,6 +437,7 @@ password_pwned_err=Nelze dokončit požadavek na HaveIBeenPwned
[mail]
view_it_on=Zobrazit na %s
reply=nebo přímo odpovědět na tento e-mail
link_not_working_do_paste=Nefunguje? Zkuste jej zkopírovat a vložit do svého prohlížeče.
hi_user_x=Ahoj <b>%s</b>,
@ -484,6 +541,7 @@ url_error=`„%s“ není platná adresa URL.`
include_error=` musí obsahovat řetězec „%s“.`
glob_pattern_error=`zástupný vzor je neplatný: %s.`
regex_pattern_error=` regex vzor je neplatný: %s.`
invalid_group_team_map_error=` mapování je neplatné: %s`
unknown_error=Neznámá chyba:
captcha_incorrect=CAPTCHA kód není správný.
password_not_match=Zadaná hesla nesouhlasí.
@ -520,10 +578,12 @@ team_not_exist=Tento tým neexistuje.
last_org_owner=Nemůžete odstranit posledního uživatele z týmu „vlastníci“. Musí existovat alespoň jeden vlastník pro organizaci.
cannot_add_org_to_team=Organizace nemůže být přidána jako člen týmu.
duplicate_invite_to_team=Uživatel byl již pozván jako člen týmu.
organization_leave_success=Úspěšně jste opustili organizaci %s.
invalid_ssh_key=Nelze ověřit váš SSH klíč: %s
invalid_gpg_key=Nelze ověřit váš GPG klíč: %s
invalid_ssh_principal=Neplatný SSH Principal certifikát: %s
must_use_public_key=Zadaný klíč je soukromý klíč. Nenahrávejte svůj soukromý klíč nikde. Místo toho použijte váš veřejný klíč.
unable_verify_ssh_key=Nelze ověřit váš SSH klíč
auth_failed=Ověření selhalo: %v
@ -1185,6 +1245,7 @@ commits.signed_by_untrusted_user_unmatched=Podepsáno nedůvěryhodným uživate
commits.gpg_key_id=ID GPG klíče
commits.ssh_key_fingerprint=Otisk klíče SSH
commit.operations=Operace
commit.revert=Vrátit
commit.revert-header=Vrátit: %s
commit.revert-content=Vyberte větev pro návrat na:
@ -1217,11 +1278,21 @@ projects.type.bug_triage=Třídění chyb
projects.template.desc=Šablona projektu
projects.template.desc_helper=Vyberte šablonu projektu pro začátek
projects.type.uncategorized=Nezařazené
projects.column.edit=Upravit sloupec
projects.column.edit_title=Název
projects.column.new_title=Název
projects.column.new_submit=Vytvořit sloupec
projects.column.new=Nový sloupec
projects.column.set_default=Nastavit jako výchozí
projects.column.set_default_desc=Nastavit tento sloupec jako výchozí pro nekategorizované úkoly a požadavky na natažení
projects.column.delete=Smazat sloupec
projects.column.deletion_desc=Smazání projektového sloupce přesune všechny související problémy do kategorie „Nezařazené“. Pokračovat?
projects.column.color=Barva
projects.open=Otevřít
projects.close=Zavřít
projects.column.assigned_to=Přiřazeno k
projects.card_type.images_and_text=Obrázky a text
projects.card_type.text_only=Pouze text
issues.desc=Organizování hlášení chyb, úkolů a milníků.
issues.filter_assignees=Filtrovat zpracovatele
@ -1298,6 +1369,7 @@ issues.filter_label_no_select=Všechny štítky
issues.filter_milestone=Milník
issues.filter_milestone_no_select=Všechny milníky
issues.filter_project=Projekt
issues.filter_project_all=Všechny projekty
issues.filter_project_none=Žádný projekt
issues.filter_assignee=Zpracovatel
issues.filter_assginee_no_select=Všichni zpracovatelé
@ -1383,6 +1455,7 @@ issues.save=Uložit
issues.label_title=Název štítku
issues.label_description=Popis štítku
issues.label_color=Barva štítku
issues.label_exclusive=Exkluzivní
issues.label_count=%d štítků
issues.label_open_issues=%d otevřených úkolů
issues.label_edit=Upravit
@ -1828,6 +1901,7 @@ settings.mirror_sync_in_progress=Právě probíhá synchronizace zrcadla. Zkuste
settings.site=Webová stránka
settings.update_settings=Aktualizovat nastavení
settings.branches.update_default_branch=Aktualizovat výchozí větev
settings.branches.add_new_rule=Přidat nové pravidlo
settings.advanced_settings=Pokročilá nastavení
settings.wiki_desc=Povolit Wiki repozitáře
settings.use_internal_wiki=Používat vestavěnou Wiki
@ -2022,6 +2096,8 @@ settings.event_package=Balíček
settings.event_package_desc=Balíček vytvořen nebo odstraněn v repozitáři.
settings.branch_filter=Filtr větví
settings.branch_filter_desc=Povolené větve pro události nahrání, vytvoření větve a smazání větve jsou určeny pomocí zástupného vzoru. Pokud je prázdný nebo <code>*</code>, všechny události jsou ohlášeny. Podívejte se na dokumentaci syntaxe na <a href="https://pkg.go.dev/github.com/gobwas/glob#Compile">github.com/gobwas/glob</a>. Příklady: <code>master</code>, <code>{master,release*}</code>.
settings.authorization_header=Autorizační hlavička
settings.authorization_header_desc=Pokud vyplněno, bude připojeno k požadavkům jako autorizační hlavička. Příklady: %s.
settings.active=Aktivní
settings.active_helper=Informace o spuštěných událostech budou odeslány na URL webového háčku.
settings.add_hook_success=Webový háček byl přidán.
@ -2066,6 +2142,8 @@ settings.deploy_key_deletion_desc=Odstranění klíče pro nasazení zruší jeh
settings.deploy_key_deletion_success=Klíč pro nasazení byl odstraněn.
settings.branches=Větve
settings.protected_branch=Ochrana větví
settings.protected_branch.save_rule=Uložit pravidlo
settings.protected_branch.delete_rule=Odstranit pravidlo
settings.protected_branch_can_push=Povolit nahrání?
settings.protected_branch_can_push_yes=Můžete nahrávat
settings.protected_branch_can_push_no=Nemůžete nahrávat
@ -2543,6 +2621,9 @@ dashboard.delete_old_actions=Odstranit všechny staré akce z databáze
dashboard.delete_old_actions.started=Začalo odstraňování všech starých akcí z databáze.
dashboard.update_checker=Kontrola aktualizací
dashboard.delete_old_system_notices=Odstranit všechna stará systémová upozornění z databáze
dashboard.stop_zombie_tasks=Zastavit zombie úkoly
dashboard.stop_endless_tasks=Zastavit nekonečné úkoly
dashboard.cancel_abandoned_jobs=Zrušit opuštěné úlohy
users.user_manage_panel=Správa uživatelských účtů
users.new_account=Vytvořit uživatelský účet
@ -2724,6 +2805,7 @@ auths.oauth2_required_claim_value_helper=Nastavte tuto hodnotu pro omezení při
auths.oauth2_group_claim_name=Název tvrzení poskytující názvy skupin pro tento zdroj. (nepovinné)
auths.oauth2_admin_group=Hodnota tvrzení pro skupinu uživatelů administrátorů. (Volitelné - vyžaduje název tvrzení výše)
auths.oauth2_restricted_group=Hodnota tvrzení pro skupinu omezených uživatelů. (Volitelné - vyžaduje název tvrzení výše)
auths.oauth2_map_group_to_team_removal=Odebrat uživatele z synchronizovaných týmů, pokud uživatel nepatří do odpovídající skupiny.
auths.enable_auto_register=Povolit zaregistrování se
auths.sspi_auto_create_users=Automaticky vytvářet uživatele
auths.sspi_auto_create_users_helper=Povolit SSPI autentizační metodě automaticky vytvářet nové účty pro uživatele, kteří se poprvé přihlásili
@ -2986,6 +3068,7 @@ monitor.queue.pool.cancel_desc=Opustit frontu bez skupin workerů může způsob
notices.system_notice_list=Systémová oznámení
notices.view_detail_header=Zobrazit detaily oznámení
notices.operations=Operace
notices.select_all=Vybrat vše
notices.deselect_all=Zrušit výběr všech
notices.inverse_selection=Inverzní výběr
@ -3011,6 +3094,7 @@ reopen_pull_request=`znovuotevřel/a požadavek na natažení <a href="%[1]s">%[
comment_issue=`okomentoval/a problém <a href="%[1]s">%[3]s#%[2]s</a>`
comment_pull=`okomentoval/a požadavek na natažení <a href="%[1]s">%[3]s#%[2]s</a>`
merge_pull_request=`sloučil/a požadavek na natažení <a href="%[1]s">%[3]s#%[2]s</a>`
auto_merge_pull_request=`automaticky sloučen požadavek na natažení <a href="%[1]s">%[3]s#%[2]s</a>`
transfer_repo=předal/a repozitář <code>%s</code> uživateli/organizaci <a href="%s">%s</a>
push_tag=nahrál/a značku <a href="%[2]s">%[3]s</a> do <a href="%[1]s">%[4]s</a>
delete_tag=smazal/a značku %[2]s z <a href="%[1]s">%[3]s</a>
@ -3109,6 +3193,8 @@ keywords=Klíčová slova
details=Podrobnosti
details.author=Autor
details.project_site=Stránka projektu
details.repository_site=Stránka repositáře
details.documentation_site=Stránka dokumentace
details.license=Licence
assets=Prostředky
versions=Verze
@ -3116,7 +3202,13 @@ versions.on=
versions.view_all=Zobrazit všechny
dependency.id=ID
dependency.version=Verze
cargo.install=Chcete-li nainstalovat balíček pomocí Cargo, spusťte následující příkaz:
cargo.documentation=Další informace o registru Cargo naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/cargo/">dokumentaci</a>.
cargo.details.repository_site=Stránka repositáře
cargo.details.documentation_site=Stránka dokumentace
chef.registry=Nastavit tento registr v souboru <code>~/.chef/config.rb</code>:
chef.install=Pro instalaci balíčku spusťte následující příkaz:
chef.documentation=Další informace o registru Chef naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/chef/">dokumentaci</a>.
composer.registry=Nastavit tento registr v souboru <code>~/.composer/config.json</code>:
composer.install=Pro instalaci balíčku pomocí Compposer spusťte následující příkaz:
composer.documentation=Další informace o registru Composer naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/composer/">dokumentaci</a>.
@ -3126,6 +3218,11 @@ conan.details.repository=Repozitář
conan.registry=Nastavte tento registr z příkazového řádku:
conan.install=Pro instalaci balíčku pomocí Conan spusťte následující příkaz:
conan.documentation=Další informace o registru Conan naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conan/">dokumentaci</a>.
conda.registry=Nastavte tento registr jako Conda repozitář ve vašem <code>.condarc</code>:
conda.install=Pro instalaci balíčku pomocí Conda spusťte následující příkaz:
conda.documentation=Další informace o registru Conda naleznete v <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/conda/">dokumentaci</a>.
conda.details.repository_site=Stránka repositáře
conda.details.documentation_site=Stránka dokumentace
container.details.type=Typ obrazu
container.details.platform=Platforma
container.pull=Stáhněte obraz z příkazové řádky:
@ -3184,26 +3281,79 @@ settings.delete.description=Smazání balíčku je trvalé a nelze ho vrátit zp
settings.delete.notice=Chystáte se odstranit %s (%s). Tato operace je nevratná, jste si jisti?
settings.delete.success=Balíček byl odstraněn.
settings.delete.error=Nepodařilo se odstranit balíček.
owner.settings.cargo.initialize=Inicializovat index
owner.settings.cargo.initialize.description=K použití registru Cargo je zapotřebí speciální indexový repozitář git. Zde jej můžete (znovu) vytvořit s požadovanou konfigurací.
owner.settings.cargo.initialize.error=Nepodařilo se inicializovat Cargo index: %v
owner.settings.cargo.initialize.success=Index Cargo byl úspěšně vytvořen.
owner.settings.cargo.rebuild=Znovu vytvořit Index
owner.settings.cargo.rebuild.description=Pokud index není synchronizován s uloženými balíčky Cargo, můžete jej zde obnovit.
owner.settings.cargo.rebuild.error=Obnovení Cargo indexu se nezdařilo: %v
owner.settings.cargo.rebuild.success=Cargo Index byl úspěšně obnoven.
owner.settings.cleanuprules.title=Spravovat pravidla pro čištění
owner.settings.cleanuprules.add=Přidat pravidlo pro čištění
owner.settings.cleanuprules.edit=Upravit pravidlo pro čištění
owner.settings.cleanuprules.none=Nejsou k dispozici žádná pravidla čištění. Přečtěte si dokumentaci a dozvíte se více.
owner.settings.cleanuprules.preview=Náhled pravidla pro čištění
owner.settings.cleanuprules.preview.overview=%d balíčků má být odstraněno.
owner.settings.cleanuprules.preview.none=Pravidlo čištění neodpovídá žádným balíčkům.
owner.settings.cleanuprules.enabled=Povolený
owner.settings.cleanuprules.pattern_full_match=Použít vzor na úplný název balíčku
owner.settings.cleanuprules.keep.title=Verze, které odpovídají těmto pravidlům, jsou zachovány, i když odpovídají níže uvedenému pravidlu pro odstranění.
owner.settings.cleanuprules.keep.count=Zachovat nejnovější
owner.settings.cleanuprules.keep.count.1=1 verze na balíček
owner.settings.cleanuprules.keep.count.n=%d verzí na balíček
owner.settings.cleanuprules.keep.pattern=Ponechat odpovídající verze
owner.settings.cleanuprules.keep.pattern.container=U balíčků Container je vždy zachována <code>nejnovější</code> verze.
owner.settings.cleanuprules.remove.title=Verze, které odpovídají těmto pravidlům, jsou odstraněny, pokud výše uvedené pravidlo neukládá jejich zachování.
owner.settings.cleanuprules.remove.days=Odstranit verze starší než
owner.settings.cleanuprules.remove.pattern=Odstranit odpovídající verze
owner.settings.cleanuprules.success.update=Pravidlo pro čištění bylo aktualizováno.
owner.settings.cleanuprules.success.delete=Pravidlo pro čištění bylo odstraněno.
owner.settings.chef.keypair=Generovat pár klíčů
[secrets]
secrets=Tajné klíče
value=Hodnota
name=Název
[actions]
actions=Akce
unit.desc=Spravovat akce
status.unknown=Neznámý
status.waiting=Čekání
status.running=Probíhá
status.success=Úspěch
status.failure=Chyba
status.cancelled=Zrušeno
status.skipped=Přeskočeno
status.blocked=Blokováno
runners.status=Status
runners.id=ID
runners.name=Název
runners.owner_type=Typ
runners.description=Popis
runners.labels=Štítky
runners.last_online=Poslední čas online
runners.agent_labels=Štítky agenta
runners.custom_labels=Vlastní štítky
runners.custom_labels_helper=Vlastní štítky jsou štítky, které správce přidává ručně. Štítky se oddělují čárkou, bílé znaky na začátku a na konci každého štítku se ignorují.
runners.task_list.run=Spustit
runners.task_list.status=Status
runners.task_list.repository=Repozitář
runners.task_list.commit=Commit
runners.task_list.done_at=Dokončeno v
runners.update_runner=Aktualizovat změny
runners.status.unspecified=Neznámý
runners.status.idle=Nečinný
runners.status.active=Aktivní
runners.status.offline=Offline
runs.all_workflows=Všechny pracovní postupy
runs.open_tab=%d otevřeno
runs.closed_tab=%d uzavřeno
runs.commit=Commit

View File

@ -328,6 +328,7 @@ email_not_associate=此電子信箱未與任何帳戶連結
send_reset_mail=發送帳戶救援信
reset_password=帳戶救援
invalid_code=您的確認代碼無效或已過期。
invalid_password=您的密碼和用來建立帳戶的不符。
reset_password_helper=帳戶救援
reset_password_wrong_user=您已經使用 %s 的帳戶登入,但帳戶救援連結是給 %s 的
password_too_short=密碼長度不能少於 %d 個字!
@ -430,6 +431,10 @@ repo.transfer.body=請造訪 %s 以接受或拒絕轉移,您也可以忽略它
repo.collaborator.added.subject=%s 把您加入到 %s
repo.collaborator.added.text=您已被新增為儲存庫的協作者:
team_invite.subject=%[1]s 邀請您加入組織 %[2]s
team_invite.text_1=%[1]s 邀請您加入組織 %[3]s 中的 %[2]s 團隊
team_invite.text_2=請點擊下方連結加入團隊:
team_invite.text_3=備註: 這是寄給 %[1]s 的邀請。若您未預期收到此邀請,請忽略此郵件。
[modal]
yes=
@ -446,7 +451,7 @@ SSHTitle=SSH 金鑰名稱
HttpsUrl=HTTPS URL 地址
PayloadUrl=推送地址
TeamName=團隊名稱
AuthName=認證名稱
AuthName=授權名稱
AdminEmail=管理員電子信箱
NewBranchName=新的分支名稱
@ -506,11 +511,13 @@ user_not_exist=該用戶名不存在
team_not_exist=團隊不存在
last_org_owner=你不能從「Owners」團隊中刪除最後一個使用者。每個組織中至少要有一個擁有者。
cannot_add_org_to_team=組織不能被新增為團隊成員。
duplicate_invite_to_team=該使用者已經被邀請為團隊成員。
organization_leave_success=您已成功離開組織 %s。
invalid_ssh_key=無法驗證您的 SSH 密鑰:%s
invalid_gpg_key=無法驗證您的 GPG 密鑰:%s
invalid_ssh_principal=無效的主體: %s
must_use_public_key=您提供的金鑰是私有金鑰,請勿上傳您的私有金鑰到任何地方,請使用您的公鑰。
unable_verify_ssh_key=無法驗證 SSH 密鑰
auth_failed=授權認證失敗:%v
@ -747,6 +754,8 @@ access_token_deletion_cancel_action=取消
access_token_deletion_confirm_action=刪除
access_token_deletion_desc=刪除 Token 後,使用此 Token 的應用程式將無法再存取您的帳戶,此動作不可還原。是否繼續?
delete_token_success=已刪除 Token。使用此 Token 的應用程式無法再存取您的帳戶。
select_scopes=選擇範圍 (Scope)
scopes_list=範圍 (Scope):
manage_oauth2_applications=管理 OAuth2 應用程式
edit_oauth2_application=編輯 OAuth2 應用程式
@ -759,6 +768,7 @@ create_oauth2_application_button=建立應用程式
create_oauth2_application_success=您已成功新增一個 OAuth2 應用程式。
update_oauth2_application_success=您已成功更新了 OAuth2 應用程式。
oauth2_application_name=應用程式名稱
oauth2_confidential_client=機密客戶端 (Confidential Client)。請為能保持機密性的程式勾選,例如網頁應用程式。使用原生程式時不要勾選,包含桌面、行動應用程式。
oauth2_redirect_uri=重新導向 URI
save_application=儲存
oauth2_client_id=客戶端 ID
@ -1203,7 +1213,7 @@ projects.edit_success=已更新專案「%s」。
projects.type.none=
projects.type.basic_kanban=基本看板
projects.type.bug_triage=Bug 檢傷分類
projects.template.desc=專案範本
projects.template.desc=範本
projects.template.desc_helper=選擇專案範本以開始
projects.type.uncategorized=未分類
projects.column.edit=編輯欄位
@ -1215,7 +1225,7 @@ projects.column.set_default=設為預設
projects.column.set_default_desc=將此欄位設定為未分類問題及合併請求的預設預設值
projects.column.delete=刪除欄位
projects.column.deletion_desc=刪除專案欄位會將所有相關的問題移動到「未分類」,是否繼續?
projects.column.color=
projects.column.color=
projects.open=開啟
projects.close=關閉
projects.column.assigned_to=已指派給
@ -1310,6 +1320,7 @@ issues.filter_type.assigned_to_you=指派給您的
issues.filter_type.created_by_you=由您建立的
issues.filter_type.mentioning_you=提及您的
issues.filter_type.review_requested=已提出審核請求
issues.filter_type.reviewed_by_you=由您審核
issues.filter_sort=排序
issues.filter_sort.latest=最新建立
issues.filter_sort.oldest=最早建立
@ -1383,11 +1394,14 @@ issues.sign_in_require_desc=<a href="%s"> 登入</a> 才能加入這對話。
issues.edit=編輯
issues.cancel=取消
issues.save=儲存
issues.label_title=標籤名稱
issues.label_description=標籤描述
issues.label_color=標籤顏色
issues.label_title=名稱
issues.label_description=描述
issues.label_color=顏色
issues.label_exclusive=互斥
issues.label_exclusive_desc=請以此格式命名標籤: <code>scope/item</code>,使它和其他 <code>scope/</code> (相同範圍) 標籤互斥。
issues.label_exclusive_warning=在編輯問題及合併請求的標籤時,將會刪除任何有相同範圍的標籤。
issues.label_count=%d 個標籤
issues.label_open_issues=%d 個開放中的問題
issues.label_open_issues=%d 個開放中的問題/合併請求
issues.label_edit=編輯
issues.label_delete=刪除
issues.label_modify=編輯標籤
@ -1640,6 +1654,7 @@ pulls.reopened_at=`重新開放了這個合併請求 <a id="%[1]s" href="#%[1]s"
pulls.merge_instruction_hint=`您也可以查看<a class="show-instruction">命令列指南</a>。`
pulls.merge_instruction_step1_desc=在您的儲存庫中切換到新分支並測試變更。
pulls.merge_instruction_step2_desc=合併變更並更新到 Gitea。
pulls.clear_merge_message=清除合併訊息
pulls.auto_merge_button_when_succeed=(當通過檢查後)
pulls.auto_merge_when_succeed=通過所有檢查後自動合併
@ -2423,7 +2438,7 @@ teams.leave.detail=確定要離開 %s 嗎?
teams.can_create_org_repo=建立儲存庫
teams.can_create_org_repo_helper=成員可以在組織中新增儲存庫。建立者將自動取得新儲存庫的管理員權限。
teams.none_access=沒有權限
teams.none_access_helper=成員無法檢視此單元或對其執行其他動作
teams.none_access_helper=成員無法檢視此單元或對其執行其他動作,這對公開儲存庫沒有影響
teams.general_access=一般權限
teams.general_access_helper=成員權限將由下列權限表決定。
teams.read_access=讀取
@ -2561,6 +2576,10 @@ dashboard.delete_old_actions=從資料庫刪除所有舊行為
dashboard.delete_old_actions.started=從資料庫刪除所有舊行為的任務已啟動。
dashboard.update_checker=更新檢查器
dashboard.delete_old_system_notices=從資料庫刪除所有舊系統提示
dashboard.gc_lfs=對 LFS meta objects 進行垃圾回收
dashboard.stop_zombie_tasks=停止殭屍任務
dashboard.stop_endless_tasks=停止永不停止的任務
dashboard.cancel_abandoned_jobs=取消已放棄的工作
users.user_manage_panel=使用者帳戶管理
users.new_account=建立使用者帳戶
@ -2649,6 +2668,7 @@ repos.size=大小
packages.package_manage_panel=套件管理
packages.total_size=總大小: %s
packages.unreferenced_size=未參考大小: %s
packages.owner=擁有者
packages.creator=建立者
packages.name=名稱
@ -2742,6 +2762,7 @@ auths.oauth2_required_claim_value_helper=填寫此名稱以限制 Claim 中有
auths.oauth2_group_claim_name=Claim 名稱提供群組名稱給此來源。(選用)
auths.oauth2_admin_group=管理員使用者的群組 Claim 值。(選用 - 需要上面的 Claim 名稱)
auths.oauth2_restricted_group=受限制使用者的群組 Claim 值。(選用 - 需要上面的 Claim 名稱)
auths.oauth2_map_group_to_team_removal=如果使用者不屬於相對應的群組,將使用者從已同步的團隊移除。
auths.enable_auto_register=允許授權用戶自動註冊
auths.sspi_auto_create_users=自動建立使用者
auths.sspi_auto_create_users_helper=允許 SSPI 認證方法於使用者首次登入時自動建立新帳戶
@ -3218,8 +3239,14 @@ settings.delete.description=刪除套件是永久且不可還原的。
settings.delete.notice=您正要刪除 %s (%s),此動作是無法還原的,您確定嗎?
settings.delete.success=已刪除該套件。
settings.delete.error=刪除套件失敗。
owner.settings.cargo.title=Cargo Registry 索引
owner.settings.cargo.initialize=初始化索引
owner.settings.cargo.initialize.error=初始化 Cargo 索引失敗: %v
owner.settings.cargo.initialize.success=成功建立了 Cargo 索引。
owner.settings.cargo.rebuild=重建索引
owner.settings.cargo.rebuild.description=如果索引和 Cargo 套件不同步,您可在此重建它。
owner.settings.cargo.rebuild.error=重建 Cargo 索引失敗: %v
owner.settings.cargo.rebuild.success=成功重建了 Cargo 索引。
owner.settings.cleanuprules.title=管理清理規則
owner.settings.cleanuprules.add=加入清理規則
owner.settings.cleanuprules.edit=編輯清理規則
@ -3239,32 +3266,80 @@ owner.settings.cleanuprules.remove.days=移除早於天數的版本
owner.settings.cleanuprules.remove.pattern=移除版本的比對規則
owner.settings.cleanuprules.success.update=已更新清理規則。
owner.settings.cleanuprules.success.delete=已刪除清理規則。
owner.settings.chef.title=Chef Registry
owner.settings.chef.keypair=產生密鑰組
owner.settings.chef.keypair.description=產生用來認證 Chef Registry 的密鑰組,之前的密鑰未來將無法使用。
[secrets]
secrets=Secret
description=Secret 會被傳給特定的 Action其他情況無法讀取。
none=還沒有 Secret。
value=
name=組織名稱
creation=加入 Secret
creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。
creation.success=已加入 Secret「%s」。
creation.failed=加入 Secret 失敗。
deletion=移除 Secret
deletion.description=移除 Secret 是永久的且不可還原,是否繼續?
deletion.success=已移除此 Secret。
deletion.failed=移除 Secret 失敗。
[actions]
actions=Actions
unit.desc=管理 Actions
status.unknown=未知
status.waiting=正在等候
status.running=正在執行
status.success=成功
status.failure=失敗
status.cancelled=已取消
status.skipped=已略過
status.blocked=已阻塞
runners=Runner
runners.runner_manage_panel=Runner 管理
runners.new=建立 Runner
runners.new_notice=如何啟動 Runner
runners.status=狀態
runners.id=ID
runners.name=組織名稱
runners.owner_type=認證類型
runners.description=組織描述
runners.labels=標籤
runners.last_online=最後上線時間
runners.agent_labels=代理程式標籤
runners.custom_labels=自訂標籤
runners.custom_labels_helper=自訂標籤是由管理員手動加上的標籤。標籤之間以半形逗號「,」分隔,標籤頭尾的空白將被忽略。
runners.runner_title=Runner
runners.task_list=最近在此 Runner 上的任務
runners.task_list.run=執行
runners.task_list.status=狀態
runners.task_list.repository=儲存庫
runners.task_list.commit=提交
runners.task_list.done_at=完成於
runners.edit_runner=編輯 Runner
runners.update_runner=更新變更
runners.update_runner_success=更新 Runner 成功
runners.update_runner_failed=更新 Runner 失敗
runners.delete_runner=刪除此 Runner
runners.delete_runner_success=刪除 Runner 成功
runners.delete_runner_failed=刪除 Runner 失敗
runners.delete_runner_header=確認刪除此 Runner
runners.delete_runner_notice=如果有任務正在此 Runner 上執行,它可能會被中止並標記為失敗,這可能會打斷建置工作流程。
runners.none=沒有可用的 Runner
runners.status.unspecified=未知
runners.status.idle=閒置
runners.status.active=啟用
runners.status.offline=離線
runs.all_workflows=所有工作流程
runs.open_tab=%d 開放中
runs.closed_tab=%d 已關閉
runs.commit=提交
runs.pushed_by=推送者
need_approval_desc=來自 Frok 儲存庫的合併請求需要核可才能執行工作流程。

View File

@ -103,7 +103,7 @@ func Projects(ctx *context.Context) {
pager.AddParam(ctx, "state", "State")
ctx.Data["Page"] = pager
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["IsShowClosed"] = isShowClosed
ctx.Data["PageIsViewProjects"] = true
ctx.Data["SortType"] = sortType
@ -111,7 +111,7 @@ func Projects(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplProjects)
}
func canWriteUnit(ctx *context.Context) bool {
func canWriteProjects(ctx *context.Context) bool {
if ctx.ContextUser.IsOrganization() {
return ctx.Org.CanWriteUnit(ctx, unit.TypeProjects)
}
@ -122,7 +122,7 @@ func canWriteUnit(ctx *context.Context) bool {
func NewProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.new")
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["HomeLink"] = ctx.ContextUser.HomeLink()
shared_user.RenderUserHeader(ctx)
ctx.HTML(http.StatusOK, tplProjectsNew)
@ -135,7 +135,7 @@ func NewProjectPost(ctx *context.Context) {
shared_user.RenderUserHeader(ctx)
if ctx.HasError() {
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["PageIsViewProjects"] = true
ctx.Data["BoardTypes"] = project_model.GetBoardConfig()
ctx.HTML(http.StatusOK, tplProjectsNew)
@ -193,7 +193,7 @@ func DeleteProject(ctx *context.Context) {
}
return
}
if p.RepoID != ctx.Repo.Repository.ID {
if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
@ -214,7 +214,7 @@ func EditProject(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
shared_user.RenderUserHeader(ctx)
p, err := project_model.GetProjectByID(ctx, ctx.ParamsInt64(":id"))
@ -226,13 +226,14 @@ func EditProject(ctx *context.Context) {
}
return
}
if p.RepoID != ctx.Repo.Repository.ID {
if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description
ctx.Data["redirect"] = ctx.FormString("redirect")
ctx.HTML(http.StatusOK, tplProjectsNew)
}
@ -243,7 +244,7 @@ func EditProjectPost(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("repo.projects.edit")
ctx.Data["PageIsEditProjects"] = true
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
shared_user.RenderUserHeader(ctx)
if ctx.HasError() {
@ -260,7 +261,7 @@ func EditProjectPost(ctx *context.Context) {
}
return
}
if p.RepoID != ctx.Repo.Repository.ID {
if p.OwnerID != ctx.ContextUser.ID {
ctx.NotFound("", nil)
return
}
@ -273,7 +274,11 @@ func EditProjectPost(ctx *context.Context) {
}
ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
if ctx.FormString("redirect") == "project" {
ctx.Redirect(p.Link())
} else {
ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects")
}
}
// ViewProject renders the project board for a project
@ -332,7 +337,7 @@ func ViewProject(ctx *context.Context) {
project.RenderedContent = project.Description
ctx.Data["LinkedPRs"] = linkedPrsMap
ctx.Data["PageIsViewProjects"] = true
ctx.Data["CanWriteProjects"] = canWriteUnit(ctx)
ctx.Data["CanWriteProjects"] = canWriteProjects(ctx)
ctx.Data["Project"] = project
ctx.Data["IssuesMap"] = issuesMap
ctx.Data["Boards"] = boards

View File

@ -235,6 +235,7 @@ func EditProject(ctx *context.Context) {
ctx.Data["title"] = p.Title
ctx.Data["content"] = p.Description
ctx.Data["card_type"] = p.CardType
ctx.Data["redirect"] = ctx.FormString("redirect")
ctx.HTML(http.StatusOK, tplProjectsNew)
}
@ -275,7 +276,11 @@ func EditProjectPost(ctx *context.Context) {
}
ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title))
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
if ctx.FormString("redirect") == "project" {
ctx.Redirect(p.Link())
} else {
ctx.Redirect(ctx.Repo.RepoLink + "/projects")
}
}
// ViewProject renders the project board for a project

View File

@ -14,58 +14,6 @@ import (
issue_service "code.gitea.io/gitea/services/issue"
)
type commitBranchCheckItem struct {
Commit *git.Commit
Checked bool
}
func commitBranchCheck(gitRepo *git.Repository, startCommit *git.Commit, endCommitID, baseBranch string, commitList map[string]*commitBranchCheckItem) error {
if startCommit.ID.String() == endCommitID {
return nil
}
checkStack := make([]string, 0, 10)
checkStack = append(checkStack, startCommit.ID.String())
for len(checkStack) > 0 {
commitID := checkStack[0]
checkStack = checkStack[1:]
item, ok := commitList[commitID]
if !ok {
continue
}
if item.Commit.ID.String() == endCommitID {
continue
}
if err := item.Commit.LoadBranchName(); err != nil {
return err
}
if item.Commit.Branch == baseBranch {
continue
}
if item.Checked {
continue
}
item.Checked = true
parentNum := item.Commit.ParentCount()
for i := 0; i < parentNum; i++ {
parentCommit, err := item.Commit.Parent(i)
if err != nil {
return err
}
checkStack = append(checkStack, parentCommit.ID.String())
}
}
return nil
}
// getCommitIDsFromRepo get commit IDs from repo in between oldCommitID and newCommitID
// isForcePush will be true if oldCommit isn't on the branch
// Commit on baseBranch will skip
@ -82,47 +30,33 @@ func getCommitIDsFromRepo(ctx context.Context, repo *repo_model.Repository, oldC
return nil, false, err
}
if err = oldCommit.LoadBranchName(); err != nil {
return nil, false, err
}
if len(oldCommit.Branch) == 0 {
commitIDs = make([]string, 2)
commitIDs[0] = oldCommitID
commitIDs[1] = newCommitID
return commitIDs, true, err
}
newCommit, err := gitRepo.GetCommit(newCommitID)
if err != nil {
return nil, false, err
}
commits, err := newCommit.CommitsBeforeUntil(oldCommitID)
isForcePush, err = newCommit.IsForcePush(oldCommitID)
if err != nil {
return nil, false, err
}
if isForcePush {
commitIDs = make([]string, 2)
commitIDs[0] = oldCommitID
commitIDs[1] = newCommitID
return commitIDs, isForcePush, err
}
// Find commits between new and old commit exclusing base branch commits
commits, err := gitRepo.CommitsBetweenNotBase(newCommit, oldCommit, baseBranch)
if err != nil {
return nil, false, err
}
commitIDs = make([]string, 0, len(commits))
commitChecks := make(map[string]*commitBranchCheckItem)
for _, commit := range commits {
commitChecks[commit.ID.String()] = &commitBranchCheckItem{
Commit: commit,
Checked: false,
}
}
if err = commitBranchCheck(gitRepo, newCommit, oldCommitID, baseBranch, commitChecks); err != nil {
return
}
for i := len(commits) - 1; i >= 0; i-- {
commitID := commits[i].ID.String()
if item, ok := commitChecks[commitID]; ok && item.Checked {
commitIDs = append(commitIDs, commitID)
}
commitIDs = append(commitIDs, commits[i].ID.String())
}
return commitIDs, isForcePush, err

View File

@ -332,8 +332,13 @@ func doMergeAndPush(ctx context.Context, pr *issues_model.PullRequest, doer *use
}
func commitAndSignNoAuthor(ctx *mergeContext, message string) error {
if err := git.NewCommand(ctx, "commit").AddArguments(ctx.signArg...).AddOptionFormat("--message=%s", message).
Run(ctx.RunOpts()); err != nil {
cmdCommit := git.NewCommand(ctx, "commit").AddOptionFormat("--message=%s", message)
if ctx.signKeyID == "" {
cmdCommit.AddArguments("--no-gpg-sign")
} else {
cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
}
if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit %v: %w\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
}

View File

@ -28,7 +28,7 @@ type mergeContext struct {
doer *user_model.User
sig *git.Signature
committer *git.Signature
signArg git.TrustedCmdArgs
signKeyID string // empty for no-sign, non-empty to sign
env []string
}
@ -85,12 +85,10 @@ func createTemporaryRepoForMerge(ctx context.Context, pr *issues_model.PullReque
// Determine if we should sign
sign, keyID, signer, _ := asymkey_service.SignMerge(ctx, mergeCtx.pr, mergeCtx.doer, mergeCtx.tmpBasePath, "HEAD", trackingBranch)
if sign {
mergeCtx.signArg = git.ToTrustedCmdArgs([]string{"-S" + keyID})
mergeCtx.signKeyID = keyID
if pr.BaseRepo.GetTrustModel() == repo_model.CommitterTrustModel || pr.BaseRepo.GetTrustModel() == repo_model.CollaboratorCommitterTrustModel {
mergeCtx.committer = signer
}
} else {
mergeCtx.signArg = git.ToTrustedCmdArgs([]string{"--no-gpg-sign"})
}
commitTimeStr := time.Now().Format(time.RFC3339)
@ -136,18 +134,11 @@ func prepareTemporaryRepoForMerge(ctx *mergeContext) error {
return fmt.Errorf("Unable to close .git/info/sparse-checkout file in tmpBasePath: %w", err)
}
gitConfigCommand := func() *git.Command {
return git.NewCommand(ctx, "config", "--local")
}
setConfig := func(key, value string) error {
if err := gitConfigCommand().AddArguments(git.ToTrustedCmdArgs([]string{key, value})...).
if err := git.NewCommand(ctx, "config", "--local").AddDynamicArguments(key, value).
Run(ctx.RunOpts()); err != nil {
if value == "" {
value = "<>"
}
log.Error("git config [%s -> %s ]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git config [%s -> %s ]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
log.Error("git config [%s -> %q]: %v\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git config [%s -> %q]: %w\n%s\n%s", key, value, err, ctx.outbuf.String(), ctx.errbuf.String())
}
ctx.outbuf.Reset()
ctx.errbuf.Reset()

View File

@ -7,45 +7,77 @@ import (
"fmt"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
// doMergeStyleSquash gets a commit author signature for squash commits
func getAuthorSignatureSquash(ctx *mergeContext) (*git.Signature, error) {
if err := ctx.pr.Issue.LoadPoster(ctx); err != nil {
log.Error("%-v Issue[%d].LoadPoster: %v", ctx.pr, ctx.pr.Issue.ID, err)
return nil, err
}
// Try to get an signature from the same user in one of the commits, as the
// poster email might be private or commits might have a different signature
// than the primary email address of the poster.
gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, ctx.tmpBasePath)
if err != nil {
log.Error("%-v Unable to open base repository: %v", ctx.pr, err)
return nil, err
}
defer closer.Close()
commits, err := gitRepo.CommitsBetweenIDs(trackingBranch, "HEAD")
if err != nil {
log.Error("%-v Unable to get commits between: %s %s: %v", ctx.pr, "HEAD", trackingBranch, err)
return nil, err
}
uniqueEmails := make(container.Set[string])
for _, commit := range commits {
if commit.Author != nil && uniqueEmails.Add(commit.Author.Email) {
commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
if commitUser != nil && commitUser.ID == ctx.pr.Issue.Poster.ID {
return commit.Author, nil
}
}
}
return ctx.pr.Issue.Poster.NewGitSig(), nil
}
// doMergeStyleSquash squashes the tracking branch on the current HEAD (=base)
func doMergeStyleSquash(ctx *mergeContext, message string) error {
cmd := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch)
if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmd); err != nil {
sig, err := getAuthorSignatureSquash(ctx)
if err != nil {
return fmt.Errorf("getAuthorSignatureSquash: %w", err)
}
cmdMerge := git.NewCommand(ctx, "merge", "--squash").AddDynamicArguments(trackingBranch)
if err := runMergeCommand(ctx, repo_model.MergeStyleSquash, cmdMerge); err != nil {
log.Error("%-v Unable to merge --squash tracking into base: %v", ctx.pr, err)
return err
}
if err := ctx.pr.Issue.LoadPoster(ctx); err != nil {
log.Error("%-v Issue[%d].LoadPoster: %v", ctx.pr, ctx.pr.Issue.ID, err)
return fmt.Errorf("LoadPoster: %w", err)
if setting.Repository.PullRequest.AddCoCommitterTrailers && ctx.committer.String() != sig.String() {
// add trailer
message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
}
sig := ctx.pr.Issue.Poster.NewGitSig()
if len(ctx.signArg) == 0 {
if err := git.NewCommand(ctx, "commit").
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
AddOptionFormat("--message=%s", message).
Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String())
}
cmdCommit := git.NewCommand(ctx, "commit").
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
AddOptionFormat("--message=%s", message)
if ctx.signKeyID == "" {
cmdCommit.AddArguments("--no-gpg-sign")
} else {
if setting.Repository.PullRequest.AddCoCommitterTrailers && ctx.committer.String() != sig.String() {
// add trailer
message += fmt.Sprintf("\nCo-authored-by: %s\nCo-committed-by: %s\n", sig.String(), sig.String())
}
if err := git.NewCommand(ctx, "commit").
AddArguments(ctx.signArg...).
AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email).
AddOptionFormat("--message=%s", message).
Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String())
}
cmdCommit.AddOptionFormat("-S%s", ctx.signKeyID)
}
if err := cmdCommit.Run(ctx.RunOpts()); err != nil {
log.Error("git commit %-v: %v\n%s\n%s", ctx.pr, err, ctx.outbuf.String(), ctx.errbuf.String())
return fmt.Errorf("git commit [%s:%s -> %s:%s]: %w\n%s\n%s", ctx.pr.HeadRepo.FullName(), ctx.pr.HeadBranch, ctx.pr.BaseRepo.FullName(), ctx.pr.BaseBranch, err, ctx.outbuf.String(), ctx.errbuf.String())
}
ctx.outbuf.Reset()
ctx.errbuf.Reset()

View File

@ -669,7 +669,12 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
authorString := commit.Author.String()
if uniqueAuthors.Add(authorString) && authorString != posterSig {
authors = append(authors, authorString)
// Compare use account as well to avoid adding the same author multiple times
// times when email addresses are private or multiple emails are used.
commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
if commitUser == nil || commitUser.ID != pr.Issue.Poster.ID {
authors = append(authors, authorString)
}
}
}
@ -690,7 +695,10 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
for _, commit := range commits {
authorString := commit.Author.String()
if uniqueAuthors.Add(authorString) && authorString != posterSig {
authors = append(authors, authorString)
commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
if commitUser == nil || commitUser.ID != pr.Issue.Poster.ID {
authors = append(authors, authorString)
}
}
}
skip += limit

View File

@ -206,12 +206,12 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
return fmt.Errorf("newCommit.CommitsBeforeUntil: %w", err)
}
isForce, err := repo_module.IsForcePush(ctx, opts)
isForcePush, err := newCommit.IsForcePush(opts.OldCommitID)
if err != nil {
log.Error("isForcePush %s:%s failed: %v", repo.FullName(), branch, err)
log.Error("IsForcePush %s:%s failed: %v", repo.FullName(), branch, err)
}
if isForce {
if isForcePush {
log.Trace("Push %s is a force push", opts.NewCommitID)
cache.Remove(repo.GetCommitsCountCacheKey(opts.RefName(), true))

View File

@ -21,6 +21,7 @@
<form class="ui form grid" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="eleven wide column">
<input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
<div class="field {{if .Err_Title}}error{{end}}">
<label>{{.locale.Tr "repo.projects.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>

View File

@ -46,7 +46,7 @@
{{if or $.CanWriteIssues $.CanWritePulls}}
<div class="column right aligned">
<div class="ui compact right small menu">
<a class="item" href="{{$.Link}}/edit" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
<a class="item" href="{{$.Link}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
{{svg "octicon-pencil"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_edit"}}</span>
</a>

View File

@ -63,7 +63,7 @@
{{end}}
{{template "repo/sub_menu" .}}
<div class="repo-button-row gt-df gt-ac gt-sb gt-fw">
<div class="gt-df gt-ac">
<div class="gt-df gt-ac gt-fw gt-gap-y-3">
{{template "repo/branch_dropdown" dict "root" .}}
{{$n := len .TreeNames}}
{{$l := Subtract $n 1}}
@ -99,20 +99,16 @@
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
</button>
{{end}}
{{if and (eq $n 0) (.Repository.IsTemplate)}}
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
{{.locale.Tr "repo.use_template"}}
</a>
{{end}}
{{if ne $n 0}}
<span class="ui breadcrumb repo-path gt-ml-2"><a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{EllipsisString .Repository.Name 30}}</a>{{range $i, $v := .TreeNames}}<span class="divider">/</span>{{if eq $i $l}}<span class="active section" title="{{$v}}">{{EllipsisString $v 30}}</span>{{else}}{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span>
{{end}}
</div>
<div class="gt-df gt-ac">
{{if eq $n 0}}
{{if .Repository.IsTemplate}}
<div class="ui tiny primary buttons">
<a href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}" class="ui button">
{{.locale.Tr "repo.use_template"}}
</a>
</div>
{{end}}
{{end}}
<!-- Only show clone panel in repository home page -->
{{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel">

View File

@ -24,6 +24,7 @@
<form class="ui form grid" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="eleven wide column">
<input type="hidden" id="redirect" name="redirect" value="{{.redirect}}">
<div class="field {{if .Err_Title}}error{{end}}">
<label>{{.locale.Tr "repo.projects.title"}}</label>
<input name="title" placeholder="{{.locale.Tr "repo.projects.title"}}" value="{{.title}}" autofocus required>

View File

@ -50,7 +50,7 @@
{{if and (or $.CanWriteIssues $.CanWritePulls) (not $.Repository.IsArchived)}}
<div class="column right aligned">
<div class="ui compact right small menu">
<a class="item" href="{{$.RepoLink}}/projects/{{.Project.ID}}/edit" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
<a class="item" href="{{$.RepoLink}}/projects/{{.Project.ID}}/edit?redirect=project" data-id={{$.Project.ID}} data-title={{$.Project.Title}}>
{{svg "octicon-pencil"}}
<span class="gt-mx-3">{{$.locale.Tr "repo.issues.label_edit"}}</span>
</a>

View File

@ -2876,7 +2876,7 @@
}
.repo-button-row > * {
margin-top: 10px;
margin-top: 8px;
}
.wiki .repo-button-row {

View File

@ -0,0 +1,79 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//go:build ignore
/*
This tool is used to compare the CSS names in a chroma builtin styles with the Gitea theme CSS names.
It outputs the difference between the two sets of CSS names, eg:
```
CSS names not in builtin:
.chroma .ln
----
Builtin CSS names not in file:
.chroma .vm
```
Developers could use this tool to re-sync the CSS names in the Gitea theme.
*/
package main
import (
"os"
"regexp"
"strings"
"github.com/alecthomas/chroma/v2"
)
func main() {
if len(os.Args) != 2 {
println("Usage: chroma-style-diff css-or-less-file")
os.Exit(1)
}
data, err := os.ReadFile(os.Args[1])
if err != nil {
println(err.Error())
os.Exit(1)
}
content := string(data)
// a simple CSS parser to collect CSS names
content = regexp.MustCompile("//.*\r?\n").ReplaceAllString(content, "\n")
content = regexp.MustCompile("/\\*.*?\\*/").ReplaceAllString(content, "")
matches := regexp.MustCompile("\\s*([-.#:\\w\\s]+)\\s*\\{[^}]*}").FindAllStringSubmatch(content, -1)
cssNames := map[string]bool{}
for _, matchGroup := range matches {
cssName := strings.TrimSpace(matchGroup[1])
cssNames[cssName] = true
}
// collect Chroma builtin CSS names
builtin := map[string]bool{}
for tokenType, cssName := range chroma.StandardTypes {
if tokenType > 0 && cssName != "" {
builtin[".chroma ."+cssName] = true
}
}
// show the diff
println("CSS names not in builtin:")
for cssName := range cssNames {
if !builtin[cssName] {
println(cssName)
}
}
println("----")
println("Builtin CSS names not in file:")
for cssName := range builtin {
if !cssNames[cssName] {
println(cssName)
}
}
}

View File

@ -7,17 +7,19 @@
.chroma .cpf { color: #649bc4; } /* CommentPreprocFile */
.chroma .cs { color: #9075cd; } /* CommentSpecial */
.chroma .dl { color: #649bc4; } /* LiteralStringDelimiter */
.chroma .fm {} /* NameFunctionMagic */
.chroma .g {} /* Generic */
.chroma .gd { color: #ffffff; background-color: #5f3737; } /* GenericDeleted */
.chroma .ge { color: #ddee30; } /* GenericEmph */
.chroma .gh { color: #ffaa10; } /* GenericHeading */
.chroma .gi { color: #ffffff; background-color: #3a523a; } /* GenericInserted */
.chroma .gl {} /* GenericUnderline */
.chroma .go { color: #777e94; } /* GenericOutput */
.chroma .gp { color: #ebdbb2; } /* GenericPrompt */
.chroma .gr { color: #ff4433; } /* GenericError */
.chroma .gs { color: #ebdbb2; } /* GenericStrong */
.chroma .gt { color: #ff7540; } /* GenericTraceback */
.chroma .gu { color: #b8bb26; } /* GenericSubheading */
.chroma .hl { background-color: #3f424d; } /* LineHighlight */
.chroma .il { color: #649bc4; } /* LiteralNumberIntegerLong */
.chroma .k { color: #ff7540; } /* Keyword */
.chroma .kc { color: #649bc4; } /* KeywordConstant */
@ -25,16 +27,16 @@
.chroma .kn { color: #ffaa10; } /* KeywordNamespace */
.chroma .kp { color: #5f8700; } /* KeywordPseudo */
.chroma .kr { color: #ff7540; } /* KeywordReserved */
.chroma .kt { color: #fabd2f; } /* KeywordType */
.chroma .ln { color: #7f8699; } /* LineNumbers */
.chroma .lnt { color: #7f8699; } /* LineNumbersTable */
.chroma .kt { color: #ff7b72; } /* KeywordType */
.chroma .l {} /* Literal */
.chroma .ld {} /* LiteralDate */
.chroma .m { color: #649bc4; } /* LiteralNumber */
.chroma .mb { color: #649bc4; } /* LiteralNumberBin */
.chroma .mf { color: #649bc4; } /* LiteralNumberFloat */
.chroma .mh { color: #649bc4; } /* LiteralNumberHex */
.chroma .mi { color: #649bc4; } /* LiteralNumberInteger */
.chroma .mo { color: #649bc4; } /* LiteralNumberOct */
.chroma .n { color: #fabd2f; } /* Name */
.chroma .n { color: #c9d1d9; } /* Name */
.chroma .na { color: #b8bb26; } /* NameAttribute */
.chroma .nb { color: #fabd2f; } /* NameBuiltin */
.chroma .nc { color: #ffaa10; } /* NameClass */
@ -51,6 +53,7 @@
.chroma .o { color: #ff7540; } /* Operator */
.chroma .ow { color: #5f8700; } /* OperatorWord */
.chroma .p { color: #d2d4db; } /* Punctuation */
.chroma .py {} /* NameProperty */
.chroma .s { color: #b8bb26; } /* LiteralString */
.chroma .s1 { color: #b8bb26; } /* LiteralStringSingle */
.chroma .s2 { color: #b8bb26; } /* LiteralStringDouble */
@ -67,4 +70,5 @@
.chroma .vc { color: #ff7540; } /* NameVariableClass */
.chroma .vg { color: #ffaa10; } /* NameVariableGlobal */
.chroma .vi { color: #ffaa10; } /* NameVariableInstance */
.chroma .vm {} /* NameVariableMagic */
.chroma .w { color: #7f8699; } /* TextWhitespace */

View File

@ -7,16 +7,19 @@
.chroma .cpf { color: #4c4dbc; } /* CommentPreprocFile */
.chroma .cs { color: #999999; } /* CommentSpecial */
.chroma .dl { color: #106303; } /* LiteralStringDelimiter */
.chroma .fm {} /* NameFunctionMagic */
.chroma .g {} /* Generic */
.chroma .gd { color: #000000; background-color: #ffdddd; } /* GenericDeleted */
.chroma .ge { color: #000000; } /* GenericEmph */
.chroma .gh { color: #999999; } /* GenericHeading */
.chroma .gi { color: #000000; background-color: #ddffdd; } /* GenericInserted */
.chroma .gl {} /* GenericUnderline */
.chroma .go { color: #888888; } /* GenericOutput */
.chroma .gp { color: #555555; } /* GenericPrompt */
.chroma .gr { color: #aa0000; } /* GenericError */
.chroma .gs {} /* GenericStrong */
.chroma .gt { color: #aa0000; } /* GenericTraceback */
.chroma .gu { color: #aaaaaa; } /* GenericSubheading */
.chroma .hl { background-color: #e5e5e5; } /* LineHighlight */
.chroma .il { color: #009999; } /* LiteralNumberIntegerLong */
.chroma .k { color: #d73a49; } /* Keyword */
.chroma .kc { color: #d73a49; } /* KeywordConstant */
@ -25,14 +28,15 @@
.chroma .kp { color: #d73a49; } /* KeywordPseudo */
.chroma .kr { color: #d73a49; } /* KeywordReserved */
.chroma .kt { color: #445588; } /* KeywordType */
.chroma .ln { color: #7f7f7f; } /* LineNumbers */
.chroma .lnt { color: #7f7f7f; } /* LineNumbersTable */
.chroma .l {} /* Literal */
.chroma .ld {} /* LiteralDate */
.chroma .m { color: #009999; } /* LiteralNumber */
.chroma .mb { color: #009999; } /* LiteralNumberBin */
.chroma .mf { color: #009999; } /* LiteralNumberFloat */
.chroma .mh { color: #009999; } /* LiteralNumberHex */
.chroma .mi { color: #009999; } /* LiteralNumberInteger */
.chroma .mo { color: #009999; } /* LiteralNumberOct */
.chroma .n {} /* Name */
.chroma .na { color: #d73a49; } /* NameAttribute */
.chroma .nb { color: #005cc5; } /* NameBuiltin */
.chroma .nc { color: #445588; } /* NameClass */
@ -48,6 +52,8 @@
.chroma .nx { color: #24292e; } /* NameOther */
.chroma .o { color: #d73a49; } /* Operator */
.chroma .ow { color: #d73a49; } /* OperatorWord */
.chroma .p {} /* Punctuation */
.chroma .py {} /* NameProperty */
.chroma .s { color: #106303; } /* LiteralString */
.chroma .s1 { color: #cc7a00; } /* LiteralStringSingle */
.chroma .s2 { color: #106303; } /* LiteralStringDouble */
@ -64,4 +70,5 @@
.chroma .vc { color: #008080; } /* NameVariableClass */
.chroma .vg { color: #008080; } /* NameVariableGlobal */
.chroma .vi { color: #008080; } /* NameVariableInstance */
.chroma .vm {} /* NameVariableMagic */
.chroma .w { color: #bbbbbb; } /* TextWhitespace */

View File

@ -172,6 +172,27 @@
.gt-py-4 { padding-top: 1rem !important; padding-bottom: 1rem !important; }
.gt-py-5 { padding-top: 2rem !important; padding-bottom: 2rem !important; }
.gt-gap-0 { gap: 0 !important; }
.gt-gap-1 { gap: .125rem !important; }
.gt-gap-2 { gap: .25rem !important; }
.gt-gap-3 { gap: .5rem !important; }
.gt-gap-4 { gap: 1rem !important; }
.gt-gap-5 { gap: 2rem !important; }
.gt-gap-x-0 { column-gap: 0 !important; }
.gt-gap-x-1 { column-gap: .125rem !important; }
.gt-gap-x-2 { column-gap: .25rem !important; }
.gt-gap-x-3 { column-gap: .5rem !important; }
.gt-gap-x-4 { column-gap: 1rem !important; }
.gt-gap-x-5 { column-gap: 2rem !important; }
.gt-gap-y-0 { row-gap: 0 !important; }
.gt-gap-y-1 { row-gap: .125rem !important; }
.gt-gap-y-2 { row-gap: .25rem !important; }
.gt-gap-y-3 { row-gap: .5rem !important; }
.gt-gap-y-4 { row-gap: 1rem !important; }
.gt-gap-y-5 { row-gap: 2rem !important; }
.gt-content-center { align-content: center !important; }
@media @mediaSm {

View File

@ -1,3 +1,4 @@
@import "../chroma/base.less";
@import "../chroma/dark.less";
@import "../codemirror/dark.less";