# Conflicts:
#	public/js/index.js
This commit is contained in:
kolaente 2017-12-02 18:29:32 +01:00 committed by Konrad
commit 1fded52044
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
50 changed files with 1314 additions and 171 deletions

View File

@ -48,9 +48,9 @@ getting free help.
## Discuss your design
The project welcomes submissions. If you want to change or add something,
please let everyone know what you're working on—[file an issue](https://github.com/go-gitea/gitea/issues/new)!
Significant changes must go through the change proposal process
The project welcomes submissions. If you want to change or add something,
please let everyone know what you're working on—[file an issue](https://github.com/go-gitea/gitea/issues/new)!
Significant changes must go through the change proposal process
before they can be accepted. To create a proposal, file an issue with
your proposed changes documented, and make sure to note in the title
of the issue that it is a proposal.
@ -69,8 +69,8 @@ and keep the compatibility on upgrade. To make sure you are
running the test suite exactly like we do, you should install
the CLI for [Drone CI](https://github.com/drone/drone), as
we are using the server for continous testing, following [these
instructions](http://readme.drone.io/usage/getting-started-cli). After that,
you can simply call `drone exec` within your working directory and it will try
instructions](http://readme.drone.io/usage/getting-started-cli). After that,
you can simply call `drone exec` within your working directory and it will try
to run the test suite locally.
## Vendoring
@ -100,7 +100,7 @@ Generally, the go build tools are installed as-needed in the `Makefile`.
An exception are the tools to build the CSS and images.
- To build CSS: Install [Node.js](https://nodejs.org/en/download/package-manager)
with `npm` and then run `npm install` and `make stylesheets`.
with `npm` and then run `npm install` and `make generate-stylesheets`.
- To build Images: ImageMagick, inkscape and zopflipng binaries must be
available in your `PATH` to run `make generate-images`.
@ -111,7 +111,7 @@ makes the change, even if they are an owner or a maintainer. We use GitHub's
pull request workflow to do that. And, we also use [LGTM](http://lgtm.co)
to ensure every PR is reviewed by at least 2 maintainers.
Please try to make your pull request easy to review for us. And, please read
Please try to make your pull request easy to review for us. And, please read
the *[How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/devel/pull-requests.md#best-practices-for-faster-reviews)* guide;
it has lots of useful tips for any project you may want to contribute.
Some of the key points:
@ -174,11 +174,11 @@ obtain a final version that is maintained in this branch. A release is
maintained by issuing patch releases to only correct critical problems
such as crashes or security issues.
Major release cycles are bimonthly. They always begin on the 25th and end on
the 24th (i.e., the 25th of December to February 24th).
Major release cycles are bimonthly. They always begin on the 25th and end on
the 24th (i.e., the 25th of December to February 24th).
During a development cycle, we may also publish any necessary minor releases
for the previous version. For example, if the latest, published release is
During a development cycle, we may also publish any necessary minor releases
for the previous version. For example, if the latest, published release is
v1.2, then minor changes for the previous release—e.g., v1.1.0 -> v1.1.1—are
still possible.

View File

@ -158,18 +158,10 @@ func runServ(c *cli.Context) error {
}
os.Setenv(models.EnvRepoName, reponame)
repoUser, err := models.GetUserByName(username)
if err != nil {
if models.IsErrUserNotExist(err) {
fail("Repository owner does not exist", "Unregistered owner: %s", username)
}
fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
}
repo, err := models.GetRepositoryByName(repoUser.ID, reponame)
repo, err := models.GetRepositoryByOwnerAndName(username, reponame)
if err != nil {
if models.IsErrRepoNotExist(err) {
fail(accessDenied, "Repository does not exist: %s/%s", repoUser.Name, reponame)
fail(accessDenied, "Repository does not exist: %s/%s", username, reponame)
}
fail("Internal error", "Failed to get repository: %v", err)
}
@ -263,7 +255,7 @@ func runServ(c *cli.Context) error {
//LFS token authentication
if verb == lfsAuthenticateVerb {
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, repoUser.Name, repo.Name)
url := fmt.Sprintf("%s%s/%s.git/info/lfs", setting.AppURL, username, repo.Name)
now := time.Now()
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{

View File

@ -234,3 +234,46 @@ languages:
url: https://discourse.gitea.io/
weight: 80
pre: group
fr-fr:
weight: 5
languageName: Français
menu:
page:
- name: Site
url: /fr-fr/
weight: 10
pre: home
post: active
- name: Documentation
url: https://docs.gitea.io/fr-fr/
weight: 20
pre: question
- name: API
url: https://try.gitea.io/api/swagger
weight: 25
pre: plug
- name: Blog
url: https://blog.gitea.io/
weight: 30
pre: rss
- name: Code
url: https://code.gitea.io/
weight: 40
pre: code
- name: Téléchargement
url: https://dl.gitea.io/
weight: 50
pre: download
- name: GitHub
url: https://github.com/go-gitea/
weight: 60
pre: github
- name: Discord Chat
url: https://discord.gg/NsatcWJ
weight: 70
pre: comment
- name: Forum
url: https://discourse.gitea.io/
weight: 80
pre: group

View File

@ -0,0 +1,13 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Avancé"
slug: "advanced"
weight: 30
toc: false
draft: false
menu:
sidebar:
name: "Avancé"
weight: 40
identifier: "advanced"
---

View File

@ -0,0 +1,44 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Make"
slug: "make"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "advanced"
name: "Make"
weight: 30
identifier: "make"
---
# Make
Gitea fait largement usage de Make pour automatiser les tâches et avoir un développement plus rapide. Ce guide explique comment installer Make.
### Linux
Vous pouvez installer Make avec votre gestionnaire de paquetages
Depuis Ubuntu/Debian:
```bash
sudo apt-get install build-essential
```
Depuis Fedora/RHEL/CentOS:
```bash
sudo yum install make
```
### Windows
Si vous utilisez Windows, vous pouvez télécharger une des versions suivantes de Make:
- [Simple binaire](http://www.equation.com/servlet/equation.cmd?fa=make). Copiez le quelque part et mettez à jour `PATH`.
- [32-bits version](ftp://ftp.equation.com/make/32/make.exe)
- [64-bits version](ftp://ftp.equation.com/make/64/make.exe)
- [MinGW](http://www.mingw.org/) includes a build. The binary is called `mingw32-make.exe` instead of `make.exe`. Add the `bin` folder to your `PATH`.
- [Chocolatey package](https://chocolatey.org/packages/make). Run `choco install make`

View File

@ -95,6 +95,17 @@ Both the LDAP via BindDN and the simple auth LDAP share the following fields:
matching supplied login name against multiple attributes such as user
identifier, email or even phone number.
- Example: `(&(objectClass=Person)(|(uid=%[1]s)(mail=%[1]s)(mobile=%[1]s)))`
- Enable user synchronization
- This option enables a periodic task that synchronizes the Gitea users with
the LDAP server. The default period is every 24 hours but that can be
changed in the app.ini file. See the *cron.sync_external_users* section in
the [sample
app.ini](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample)
for detailed comments about that section. The *User Search Base* and *User
Filter* settings described above will limit which users can use Gitea and
which users will be synchronized. When initially run the task will create
all LDAP users that match the given settings so take care if working with
large Enterprise LDAP directories.
**LDAP using simple auth** adds the following fields:

View File

@ -0,0 +1,13 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Installation"
slug: "installation"
weight: 10
toc: false
draft: false
menu:
sidebar:
name: "Installation"
weight: 10
identifier: "installation"
---

View File

@ -0,0 +1,45 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Installation avec le binaire pré-compilé"
slug: "install-from-binary"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "installation"
name: "Binaire pré-compilé"
weight: 20
identifier: "install-from-binary"
---
# Installation avec le binaire pré-compilé
Tous les binaires sont livrés avec le support de SQLite, MySQL et PostgreSQL, et sont construits avec les ressources incorporées. Gardez à l'esprit que cela peut être différent pour les versions antérieures. L'installation basée sur nos binaires est assez simple, il suffit de choisir le fichier correspondant à votre plateforme à partir de la [page de téléchargement](https://dl.gitea.io/gitea). Copiez l'URL et remplacer l'URL dans les commandes suivantes par la nouvelle:
```
wget -O gitea https://dl.gitea.io/gitea/1.0.1/gitea-1.0.1-linux-amd64
chmod +x gitea
```
## Test
Après avoir suivi les étapes ci-dessus, vous aurez un binaire `gitea` dans votre répertoire de travail. En premier lieu, vous pouvez tester si le binaire fonctionne comme prévu et ensuite vous pouvez le copier vers la destination où vous souhaitez le stocker. Lorsque vous lancez Gitea manuellement à partir de votre CLI, vous pouvez toujours le tuer en appuyant sur `Ctrl + C`.
```
./gitea web
```
## Dépannage
### Anciennes version de glibc
Les anciennes distributions Linux (comme Debian 7 ou CentOS 6) peuvent ne pas être capable d'exécuter le binaire Gitea, résultant généralement une erreur du type ```./gitea: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by ./gitea)```. Cette erreur est due au driver SQLite que nous intégrons dans le binaire Gitea. Dans le futur, nous fournirons des binaires sans la dépendance pour la bibliothèque glibc. En attendant, vous pouvez mettre à jour votre distribution ou installer Gitea depuis le [code source]({{< relref "from-source.fr-fr.md" >}}).
### Exécuter Gitea avec un autre port
Si vous obtenez l'erreur `702 runWeb()] [E] Failed to start server: listen tcp 0.0.0.0:3000: bind: address already in use`, Gitea à besoin d'utiliser un autre port. Vous pouvez changer le port par défaut en utilisant `./gitea web -p $PORT`.
## Il manque quelque chose ?
Est-ce que nous avons oublié quelque chose sur cette page ? N'hésitez pas à nous contacter sur notre [serveur Discord](https://discord.gg/NsatcWJ), vous obtiendrez des réponses à toute vos questions assez rapidement.

View File

@ -0,0 +1,57 @@
---
date: "2016-12-01T16:00:00+02:00"
title: "Installation depuis le gestionnaire de paquets"
slug: "install-from-package"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "installation"
name: "Gestionnaire de paquets"
weight: 20
identifier: "install-from-package"
---
# Installation depuis le gestionnaire de paquets
## Linux
Nous n'avons pas encore publié de paquet pour Linux, nous allons mettre à jour cette page directement lorsque nous commencerons à publier des paquets pour toutes distributions Linux. En attendant, vous devriez suivre les [instructions d'installation]({{< relref "from-binary.fr-fr.md" >}}) avec le binaire pré-compilé.
## Windows
Nous n'avons pas encore publié de paquet pour Windows, nous allons mettre à jour cette page directement lorsque nous commencerons à publier des paquets sous la forme de fichiers `MSI` ou via [Chocolatey](https://chocolatey.org/). En attendant, vous devriez suivre les [instructions d'installation]({{< relref "from-binary.fr-fr.md" >}}) avec le binaire pré-compilé.
## macOS
Actuellement, nous ne supportons que l'installation via `brew` pour macOS. Si vous n'utilisez pas [Homebrew](http://brew.sh/), vous pouvez suivre les [instructions d'installation]({{< relref "from-binary.fr-fr.md" >}}) avec le binaire pré-compilé. Pour installer Gitea depuis `brew`, utilisez les commandes suivantes :
```
brew tap go-gitea/gitea
brew install gitea
```
## FreeBSD
Le portage FreeBSD `www/gitea` est disponible. Vous pouvez également installer le paquet pré-compilé avec la commande suivante:
```
pkg install gitea
```
Pour une version plus récente, ou pour les instructions de compilations, veuillez consulter la documentation officielle de FreeBSD : [install it from the port](https://www.freebsd.org/doc/handbook/ports-using.html)
```
su -
cd /usr/ports/www/gitea
make install clean
```
Le port utilise la schéma standard du système de fichiers FreeBSD : Les fichiers de configuration sont localisés dans le répertoire `/usr/local/etc/gitea`, les modèles, options, plugins et thèmes sont localisés dans le répertoire `/usr/local/share/gitea`, et le script de démarrage se situe dans `/usr/local/etc/rc.d/gitea`.
Pour exécuter Gitea en tant que service, utilisez la commande `sysrc gitea_enable=YES` et la commande `service gitea start` pour démarrer le service.
## Il manque quelque chose ?
Est-ce que nous avons oublié quelque chose sur cette page ? N'hésitez pas à nous contacter sur notre [serveur Discord](https://discord.gg/NsatcWJ), vous obtiendrez des réponses à toute vos questions assez rapidement.

View File

@ -0,0 +1,80 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Installation depuis le code source"
slug: "install-from-source"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "installation"
name: "Code source"
weight: 30
identifier: "install-from-source"
---
# Installation depuis le code source
Nous ne couvrirons pas les bases de la configuration de Golang dans ce guide. Si vous ne savez pas comment démarrer un environnement fonctionnel, vous devrez suivre les [instructions d'installation](https://golang.org/doc/install) officielles.
**Attention**: La version 1.7 ou suppérieur de Go est nécessaire
## Téléchargement
Tout d'abord, vous devez récupérer le code source, la manière la plus simple est d'utiliser directement Go. Il suffit d'appeler les commandes suivantes pour récupérer le code source et passer au répertoire de travail.
```
go get -d -u code.gitea.io/gitea
cd $GOPATH/src/code.gitea.io/gitea
```
Maintenant, il est temps de décider quelle version de Gitea vous souhaitez compiler et installer. Actuellement, ils existent plusieurs options possibles. Si vous voulez compiler notre branche `master`, vous pouvez directement passer à la [section compilation](#compilation), cette branche représente la dernière version en cours de développement et n'a pas vocation à être utiliser en production.
Si vous souhaitez compiler la dernière version stable, utilisez les étiquettes ou les différentes branches disponibles. Vous pouvez voir les branches disponibles et comment utiliser cette branche avec ces commandes:
```
git branch -a
git checkout v1.0
```
Si vous souhaitez valider une demande d'ajout (_Pull request_), vous devez activer cette branche en premier :
```
git fetch origin pull/xyz/head:pr-xyz # xyz is PR value
```
Enfin, vous pouvez directement utiliser les versions étiquettées (ex : `v1.0.0`). Pour utiliser les étiquettes, vous devez lister les étiquettes disponibles et choisir une étiquette spécifique avec les commandes suivantes :
```
git tag -l
git checkout v1.0.0
git checkout pr-xyz
```
## Compilation
Comme nous regroupons déjà toutes les bibliothèques requises pour compiler Gitea, vous pouvez continuer avec le processus de compilation lui-même. Nous fournissons diverses [tâches Make](https://github.com/go-gitea/gitea/blob/master/Makefile) pour rendre le processus de construction aussi simple que possible. <a href='{{< relref "doc/advanced/make.fr-fr.md" >}}'>Voyez ici comment obtenir Make</a>. Selon vos besoins, vous pourrez éventuellement ajouter diverses options de compilation, vous pouvez choisir entre ces options :
* `bindata`: Intègre toutes les ressources nécessaires à l'exécution d'une instance de Gitea, ce qui rend un déploiement facile car il n'est pas nécessaire de se préoccuper des fichiers supplémentaires.
* `sqlite`: Active la prise en charge d'une base de données [SQLite3](https://sqlite.org/), ceci n'est recommandé que pour les petites installations de Gitea.
* `tidb`: Active la prise en charge d'une base de données [TiDB](https://github.com/pingcap/tidb), c'est une base de données simplet et basée sur des fichiers. Elle est comparable à SQLite.
* `pam`: Active la prise en charge de PAM (mLinux Pluggable Authentication Modules), très utile si vos utilisateurs doivent être authentifiés avec les comptes du système.
Il est temps de compiler le binaire, nous suggérons d'intégrer les ressources avec l'option de compilation `bindata`. Pour inclure les ressources, vous devrez également exécuter la tâche Make `generate`. Dans le cas échéant, les ressources ne pourront pas être intégrées:
```
TAGS="bindata" make generate build
```
## Test
Après avoir suivi toutes les étapes, vous devriez avoir le binaire `gitea` dans votre répertoire courant. Dans un premier temps, vous pouvez tester qu'il fonctionne puis, dans un second temps, vous pouvez le copier dans la destination de votre choix. Lorsque vous lancez Gitea manuellement à partir de votre CLI, vous pouvez toujours le tuer en appuyant sur `Ctrl + C`.
```
./gitea web
```
## Il manque quelque chose ?
Est-ce que nous avons oublié quelque chose sur cette page ? N'hésitez pas à nous contacter sur notre [serveur Discord](https://discord.gg/NsatcWJ), vous obtiendrez des réponses à toute vos questions assez rapidement.

View File

@ -0,0 +1,34 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Démarrer en tant que service Windows"
slug: "windows-service"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "installation"
name: "Service Windows"
weight: 30
identifier: "windows-service"
---
# Activer un service Windows
Pour activer le service Windows Gitea, ouvrez une `cmd` en tant qu'Administrateur puis utilisez la commande suivante :
```
sc create gitea start= auto binPath= ""C:\gitea\gitea.exe" web --config "C:\gitea\custom\conf\app.ini""
```
N'oubliez pas de remplacer `C:\gitea` par le chemin que vous avez utilisez pour votre installation.
Ensuite, ouvrez "Services Windows", puis recherchez le service `gitea`, faites un clique droit et selectionnez "Run". Si tout fonctionne, vous devriez être capable d'accèder à Gitea à l'URL `http://localhost:3000` (ou sur le port configuré si différent de 3000).
## Désactiver un service Windows
Pour désactiver le service Windows Gitea, ouvrez une `cmd` en tant qu'Administrateur puis utilisez la commande suivante :
```
sc delete gitea
```

View File

@ -183,6 +183,8 @@ To start this setup based on `docker-compose` you just have to execute `docker-c
If you want to shutdown the setup again just execute `docker-compose down`, this will stop and kill the containers, the volumes will still exist.
Notice: if you use a non 3000 port on http, you need change app.ini `LOCAL_ROOT_URL = http://localhost:3000/`.
## Install
After starting the Docker setup via `docker-compose` you should access Gitea with your favorite browser to finalize the installation. Please visit http://server-ip:3000 and follow the installation wizard. If you have started a database with the `docker-compose` setup as documented above please note that you have to use `db` as the database hostname.

View File

@ -0,0 +1,110 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Installation avec Docker"
slug: "install-with-docker"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "installation"
name: "Docker"
weight: 10
identifier: "install-with-docker"
---
# Installation avec Docker
Nous fournissons des images Docker mises à jour automatiquement via le Docker Hub de notre organisation. C'est à vous, lors devotre déploiement, de vous assurez d'utiliser toujours la dernière version stable ou d'utiliser un autre service qui met à jour l'image Docker pour vous.
## Données stockées sur l'hôte
Tout d'abord, vous devez simplement récupérer l'image Docker avec la commande suivante :
```
docker pull gitea/gitea:latest
```
Pour garder vos dépôts et certaines autres données persistantes, vous devez créer un répertoire qui contiendra ces données à l'avenir.
```
sudo mkdir -p /var/lib/gitea
```
Il est temps de démarrer votre instance Docker, c'est un processus assez simple. Vous avez à définir le mappage des ports et le volume à utiliser pour la persistance de vos données :
```
docker run -d --name=gitea -p 10022:22 -p 10080:3000 -v /var/lib/gitea:/data gitea/gitea:latest
```
Vous devriez avoir une instance fonctionnelle de Gitea. Pour accèder à l'interface web, visitez l'adresse http://hostname:10080 avec votre navigateur web préféré. Si vous voulez clôner un dépôt, vous pouvez le faire avec la commande `git clone ssh://git@hostname:10022/username/repo.git`.
## Named Volumes
Ce guide aboutira à une installation avec les données Gita et PostgreSQL stockées dans des volumes nommés. Cela permet une sauvegarde, une restauration et des mises à niveau en toute simplicité.
### The Database
Création du volume nommé pour la base de données :
```
$ docker volume create --name gitea-db-data
```
Une fois votre volume pret, vous pouvez récupérer l'image Docker de PostgreSQL et créer une instance. Tout comme Gitea, c'est également une image Docker basée sur Alpine Linux, Le montage des données se fera sans aucun problème.
```
$ docker pull postgres:alpine
$ docker run -d --name gitea-db \
-e POSTGRES_PASSWORD=<PASSWORD> \
-v gitea-db-data:/var/lib/postgresql/data \
-p 5432:5432 \
postgres:alpine
```
Maintenant que la base de données est démarrée, il faut la configurer. N'oubliez pas le mot de passe que vous avez choisi, vous en aurez besoin lors de l'installation de Gitea.
```
$ docker exec -it gitea-db psql -U postgres
psql (9.6.1)
Type "help" for help.
postgres=# CREATE USER gitea WITH PASSWORD '<PASSWORD>';
CREATE ROLE
postgres=# CREATE DATABASE gitea OWNER gitea;
CREATE DATABASE
postgres=# \q
$
```
### Gitea
Premièrement, le volume nommé :
```
$ docker volume create --name gitea-data
```
Puis l'instance de Gitea :
```
$ docker run -d --name gitea \
--link gitea-db:gitea-db \
--dns 10.12.10.160 \
-p 11180:3000 \
-p 8322:22 \
-v gitea-data:/data \
gitea/gitea:latest
```
Vous devriez maintenant avoir deux conteneurs Docker pour Gitea et PostgreSQL plus deux volumes nommés Docker.
# Personnalisation
Les fichier personnalisés ([voir les instructions](https://docs.gitea.io/en-us/customizing-gitea/)) peuvent être placés dans le répertoire `/data/gitea`.
Le fichier de configuration sera sauvegardé à l'emplacement suivant : `/data/gitea/conf/app.ini`
## Il manque quelque chose ?
Est-ce que nous avons oublié quelque chose sur cette page ? N'hésitez pas à nous contacter sur notre [serveur Discord](https://discord.gg/NsatcWJ), vous obtiendrez des réponses à toute vos questions assez rapidement.

View File

@ -37,6 +37,8 @@ docker run -d --name=gitea -p 10022:22 -p 10080:3000 -v /var/lib/gitea:/data git
然后 容器已经运行成功,在浏览器中访问 http://hostname:10080 就可以看到界面了。你可以尝试在上面创建项目clone操作 `git clone ssh://git@hostname:10022/username/repo.git`.
注意目前端口改为非3000时需要修改配置文件 `LOCAL_ROOT_URL = http://localhost:3000/`
## 需要帮助?
如果从本页中没有找到你需要的内容,请访问 [帮助页面]({{< relref "seek-help.zh-cn.md" >}})

View File

@ -0,0 +1,13 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Mise à jour"
slug: "upgrade"
weight: 10
toc: false
draft: false
menu:
sidebar:
name: "Mise à jour"
weight: 20
identifier: "upgrade"
---

View File

@ -0,0 +1,80 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Mise à jour depuis Gogs"
slug: "upgrade-from-gogs"
weight: 10
toc: true
draft: false
menu:
sidebar:
parent: "upgrade"
name: "Depuis Gogs"
weight: 10
identifier: "upgrade-from-gogs"
---
# Mise à jour depuis Gogs
À partir de la version 0.9.146 (schéma de la base de données : version 15) de Gogs, Il est possible de migrer vers Gitea simplement et sans encombre.
Veuillez suivre les étapes ci-dessous. Sur Unix, toute les commandes s'exécutent en tant que l'utilisateur utilisé pour votre installation de Gogs :
* Crééer une sauvegarde de Gogs avec la commande `gogs dump`. Le fichier nouvellement créé `gogs-dump-[timestamp].zip` contient toutes les données de votre instance de Gogs.
* Téléchargez le fichier correspondant à votre plateforme à partir de la [page de téléchargements](https://dl.gitea.io/gitea).
* Mettez la binaire dans le répertoire d'installation souhaité.
* Copiez le fichier `gogs/custom/conf/app.ini` vers `gitea/custom/conf/app.ini`.
* Si vous avez personnalisé les répertoires `templates, public` dans `gogs/custom/`, copiez-les vers `gitea/custom/`.
* Si vous avez d'autres répertoires personnalisés comme `gitignore, label, license, locale, readme` dans `gogs/custom/conf` copiez-les vers `gitea/custom/options`.
* Copiez le répertoire `gogs/data/` vers `gitea/data/`.
* Vérifiez votre installation en exécutant Gitea avec la commande `gitea web`.
* Connectez vous au panel d'administration de Gitea et exécutez l'action `Rewrite '.ssh/authorized_keys' file`, puis l'action `Rewrite all update hook of repositories` (obligatoire si le chemin menant à votre configuration personnalisée à changé).
### Modifier les informations spécifiques de gogs
* Renommez `gogs-repositories/` vers `gitea-repositories/`
* Renommez `gogs-data/` to `gitea-data/`
* Dans votre fichier `gitea/custom/conf/app.ini`, modifiez les éléments suivants:
DE :
```
[database]
PATH = /home/:USER/gogs/data/:DATABASE.db
[attachment]
PATH = /home/:USER/gogs-data/attachments
[picture]
AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars
[log]
ROOT_PATH = /home/:USER/gogs/log
```
VERS :
```
[database]
PATH = /home/:USER/gitea/data/:DATABASE.db
[attachment]
PATH = /home/:USER/gitea-data/attachments
[picture]
AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars
[log]
ROOT_PATH = /home/:USER/gitea/log
```
* Vérifiez votre installation en exécutant Gitea avec la commande `gitea web`.
### Dépannage
* Si vous rencontrez des erreurs relatives à des modèles personnalisés dans le dossier `gitea/custom/templates`, essayez de déplacer un par un les modèles provoquant les erreurs. Il est possible qu'ils ne soient pas compatibles avec Gitea.
### Démarrer automatiquement Gitea (Unix)
Distributions utilisant systemd:
* Copiez le script mis à jour vers `/etc/systemd/system/gitea.service`
* Ajoutez le service avec la commande `sudo systemctl enable gitea`
* Désactivez Gogs avec la commande `sudo systemctl disable gogs`
Distributions utilisant SysVinit:
* Copiez le script mis à jour vers `/etc/init.d/gitea`
* Ajoutez le service avec la commande `sudo rc-update add gitea`
* Désactivez Gogs avec la commande `sudo rc-update del gogs`

278
docs/content/page/index.fr-fr.md Executable file
View File

@ -0,0 +1,278 @@
---
date: "2017-08-23T09:00:00+02:00"
title: "Documentation"
slug: "documentation"
weight: 10
toc: true
draft: false
---
# A propos de Gitea
Gitea est un service Git auto-hébergé très simple à installer et à utiliser. Il est similaire à GitHub, Bitbucket ou Gitlab. Le développement initial provient sur [Gogs] (http://gogs.io), mais nous l'avons forké puis renommé Gitea. Si vous souhaitez en savoir plus sur les raisons pour lesquelles nous avons fait cela, lisez [cette publication] (https://blog.gitea.io/2016/12/welcome-to-gitea/) sur le blog.
## Objectif
Le but de ce projet est de fournir de la manière la plus simple, la plus rapide et sans complication un service Git auto-hébergé. Grâce à Go, cela peut se faire via un binaire indépendant fonctionnant sur toutes les plateformes que Go prend en charge, y compris Linux, macOS et Windows, même sur des architectures comme ARM ou PowerPC.
## Fonctionalités
- Tableau de bord de l'utilisateur
- Choix du contexte (organisation ou utilisateur actuel)
- Chronologie de l'activité
- Révisions (_Commits_)
- Tickets
- Demande d'ajout (_Pull request_)
- Création de dépôts
- Liste des dépôts
- Liste de vos organisations
- Liste des dépôts miroires
- Tableau de bord des tickets
- Choix du contexte (organisation ou utilisateur actuel)
- Filtres
- Ouvert
- Fermé
- Vos dépôts
- Tickets assignés
- Vos tickets
- Dépôts
- Options de tri
- Plus vieux
- Dernière mise à jour
- Nombre de commentaires
- Tableau de bord des demandes d'ajout
- Identique au tableau de bord des tickets
- Types de dépôt
- Miroire
- Normal
- Migré
- Notifications (courriel et web)
- Lu
- Non lu
- Épinglé
- Page d'exploration
- Utilisateurs
- Dépôts
- Organisations
- Moteur de recherche
- Interface personnalisables
- Fichiers publiques remplaçables (logo, css, etc)
- Protection CSRF et XSS
- Support d'HTTPS
- Configuration des types et de la taille maximale des fichiers téléversés
- Journalisation (_Log_)
- Configuration
- Base de données
- MySQL
- PostgreSQL
- SQLite3
- MSSQL
- [TiDB](https://github.com/pingcap/tidb) (expérimental)
- Fichier de configuration
- Voir [ici](https://github.com/go-gitea/gitea/blob/master/conf/app.ini)
- Panel d'administration
- Statistiques
- Actions
- Suppression des comptes inactifs
- Suppression des dépôts archivés
- Suppression des dépôts pour lesquels il manque leurs fichiers
- Exécution du _garbage collector_ sur les dépôts
- Ré-écriture des clefs SSH
- Resynchronisation des hooks
- Recreation des dépôts manquants
- Status du server
- Temps de disponibilité
- Mémoire
- Nombre de goroutines
- et bien plus...
- Gestion des utilisateurs
- Recherche
- Tri
- Dernière connexion
- Méthode d'authentification
- Nombre maximum de dépôts
- Désactivation du compte
- Permissions d'administration
- Permission pour crééer des hooks
- Permission pour crééer des organisations
- Permission pour importer des dépôts
- Gestion des organisations
- Membres
- Équipes
- Avatar
- Hooks
- Gestion des depôts
- Voir toutes les informations pour un dépôt donné et gérer tous les dépôts
- Méthodes d'authentification
- OAuth
- PAM
- LDAP
- SMTP
- Visualisation de la configuration
- Tout ce que contient le fichier de configuration
- Alertes du système
- Quand quelque chose d'inattendu survient
- Surveillance
- Processus courrants
- Tâches CRON
- Mise à jour des dépôts miroires
- Vérification de l'état des dépôts
- Vérification des statistiques des dépôts
- Nettoyage des anciennes archives
- Variables d'environement
- Options de ligne de commande
- Internationalisation ([21 langues](https://github.com/go-gitea/gitea/tree/master/options/locale))
- Courriel
- Notifications
- Confirmation d'inscription
- Ré-initialisation du mot de passe
- Support de _reverse proxy_
- _subpaths_ inclus
- Utilisateurs
- Profil
- Nom
- Prénom
- Courriel
- Site internet
- Date de création
- Abonnés et abonnements
- Organisations
- Dépôts
- Activité
- Dépôts suivis
- Paramètres
- Identiques au profil avec en plus les éléments ci-dessous
- Rendre l'adresse de courriel privée
- Avatar
- Gravatar
- Libravatar
- Personnalisé
- Mot de passe
- Courriels multiples
- Clefs SSH
- Applications connectées
- Authentification à double facteurs
- Identités OAuth2 attachées
- Suppression du compte
- Dépôts
- Clone à partir de SSH / HTTP / HTTPS
- Git LFS
- Suivre, Voter, Fork
- Voir les personnes qui suivent, les votes et les forks
- Code
- Navigation entre les branches
- Création ou téléversement de fichier depuis le navigateur
- URLs pour clôner le dépôt
- Téléchargement
- ZIP
- TAR.GZ
- Édition en ligne
- Éditeur Markdown
- Éditeur de texte
- Coloration syntaxique
- Visualisation des Diffs
- Visualisation
- Possibilité de choisir où sauvegarder la révision
- Historiques des fichiers
- Suppression de fichiers
- Voir le fichier brut
- Tickets
- Modèle de ticket
- Jalons
- Étiquettes
- Affecter des tickets
- Filtres
- Ouvert
- Ferme
- Personne assignée
- Créer par vous
- Qui vous mentionne
- Tri
- Plus vieux
- Dernière mise à jour
- Nombre de commentaires
- Moteur de recherche
- Commentaires
- Joindre des fichiers
- Demande dajout (_Pull request_)
- Les mêmes fonctionnalités que pour les tickets
- Révisions (_Commits_)
- Representation graphique des révisions
- Révisions par branches
- Moteur de recherche
- Voir les différences
- Voir les numéro de révision SHA
- Voir l'auteur
- Naviguer dans les fichiers d'une révision donnée
- Publication
- Pièces jointes
- Titre
- Contenu
- Suppression
- Définir comme une pré-publication
- Choix de la branche
- Wiki
- Import
- Éditeur Markdown
- Paramètres
- Options
- Nom
- Description
- Privé / Publique
- Site internet
- Wiki
- Activé / Désactivé
- Interne / externe
- Tickets
- Activé / Désactivé
- Interne / externe
- URL personnalisable pour une meilleur intégration avec un gestionnaire de tickets externe
- Activer / désactiver les demandes d'ajout (_Pull request_)
- Transfert du dépôt
- Suppression du wiki
- Suppression du dépôt
- Collaboration
- Lecture / Écriture / Administration
- Branches
- Branche par défaut
- Protection
- Webhooks
- Git hooks
- Clefs de déploiement
## Configuration requise
- Un simple Raspberry Pi est assez puissant pour les fonctionnalités de base.
- Un processeur double coeurs et 1Gb de RAM est une bonne base pour une utilisation en équipe.
- Gitea est censé être exécuté avec un compte utilisateur dédié et non root, aucun autre mode de fonctionnement n'est pris en charge. (**NOTE**: Dans le cas où vous l'exécutez avec votre propre compte d'utilisateur et que le serveur SSH intégré est désactivé, Gitea modifie le fichier `~ /.ssh /authorized_keys` afin que vous ne soyez **plus capable** de vous connecter interactivement).
## Navigateurs supportés
- Consultez [Semantic UI](https://github.com/Semantic-Org/Semantic-UI#browser-support) pour la liste des navigateurs supportés.
- La taille minimale supportée officielement est de **1024*768**, l'interface utilisateur peut toujours fonctionner à une taille plus petite, mais ce n'est pas garanti et les problèmes remontés ne seront pas corrigés.
## Composants
* Framework web : [Macaron](http://go-macaron.com/)
* ORM : [XORM](https://github.com/go-xorm/xorm)
* Interface graphique :
* [Semantic UI](http://semantic-ui.com/)
* [GitHub Octicons](https://octicons.github.com/)
* [Font Awesome](http://fontawesome.io/)
* [DropzoneJS](http://www.dropzonejs.com/)
* [Highlight](https://highlightjs.org/)
* [Clipboard](https://zenorocha.github.io/clipboard.js/)
* [Emojify](https://github.com/Ranks/emojify.js)
* [CodeMirror](https://codemirror.net/)
* [jQuery Date Time Picker](https://github.com/xdan/datetimepicker)
* [jQuery MiniColors](https://github.com/claviska/jquery-minicolors)
* Connecteurs de base de données :
* [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
* [github.com/lib/pq](https://github.com/lib/pq)
* [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
* [github.com/pingcap/tidb](https://github.com/pingcap/tidb)
* [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
## Logiciels et services
- [Drone](https://github.com/drone/drone) (Intégration continue)

View File

@ -1,7 +1,7 @@
:80 {
root /srv/www
locale en-US zh-CN zh-TW pt-BR nl-NL {
locale en-US zh-CN zh-TW pt-BR nl-NL fr-FR {
detect header
}
@ -35,5 +35,10 @@
to /nl-nl/{1}
}
rewrite /fr-FR/ {
regexp (.*)
to /fr-fr/{1}
}
header / Vary "Accept-Language"
}

View File

@ -12,6 +12,7 @@ set -e
#
declare -a LOCALES=(
"fr-fr"
"nl-nl"
"pt-br"
"zh-cn"

View File

@ -297,7 +297,7 @@ func TestCommitRepoAction(t *testing.T) {
}
for _, s := range samples {
prepareTestEnv(t)
PrepareTestEnv(t)
user := AssertExistsAndLoadBean(t, &User{ID: s.userID}).(*User)
repo := AssertExistsAndLoadBean(t, &Repository{ID: s.repositoryID, OwnerID: user.ID}).(*Repository)

View File

@ -572,9 +572,10 @@ func (err ErrLFSLockAlreadyExist) Error() string {
// ErrRepoNotExist represents a "RepoNotExist" kind of error.
type ErrRepoNotExist struct {
ID int64
UID int64
Name string
ID int64
UID int64
OwnerName string
Name string
}
// IsErrRepoNotExist checks if an error is a ErrRepoNotExist.
@ -584,7 +585,8 @@ func IsErrRepoNotExist(err error) bool {
}
func (err ErrRepoNotExist) Error() string {
return fmt.Sprintf("repository does not exist [id: %d, uid: %d, name: %s]", err.ID, err.UID, err.Name)
return fmt.Sprintf("repository does not exist [id: %d, uid: %d, owner_name: %s, name: %s]",
err.ID, err.UID, err.OwnerName, err.Name)
}
// ErrRepoAlreadyExist represents a "RepoAlreadyExist" kind of error.

View File

@ -964,7 +964,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
// GetIssueByRef returns an Issue specified by a GFM reference.
// See https://help.github.com/articles/writing-on-github#references for more information on the syntax.
func GetIssueByRef(ref string) (*Issue, error) {
n := strings.IndexByte(ref, byte('#'))
n := strings.IndexByte(ref, '#')
if n == -1 {
return nil, errMissingIssueNumber
}
@ -974,7 +974,12 @@ func GetIssueByRef(ref string) (*Issue, error) {
return nil, errInvalidIssueNumber
}
repo, err := GetRepositoryByRef(ref[:n])
i := strings.IndexByte(ref[:n], '/')
if i < 2 {
return nil, ErrInvalidReference
}
repo, err := GetRepositoryByOwnerAndName(ref[:i], ref[i+1:n])
if err != nil {
return nil, err
}

View File

@ -1,14 +1,8 @@
package models
import (
"fmt"
"os"
"path/filepath"
"testing"
"code.gitea.io/gitea/modules/setting"
_ "github.com/mattn/go-sqlite3" // for the test engine
"github.com/stretchr/testify/assert"
)
@ -19,17 +13,5 @@ func TestFixturesAreConsistent(t *testing.T) {
}
func TestMain(m *testing.M) {
if err := CreateTestEngine("fixtures/"); err != nil {
fmt.Printf("Error creating test engine: %v\n", err)
os.Exit(1)
}
setting.AppURL = "https://try.gitea.io/"
setting.RunUser = "runuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
os.Exit(m.Run())
MainTest(m, "..")
}

View File

@ -1744,13 +1744,13 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
if err != nil {
return err
} else if !has {
return ErrRepoNotExist{repoID, uid, ""}
return ErrRepoNotExist{repoID, uid, "", ""}
}
if cnt, err := sess.ID(repoID).Delete(&Repository{}); err != nil {
return err
} else if cnt != 1 {
return ErrRepoNotExist{repoID, uid, ""}
return ErrRepoNotExist{repoID, uid, "", ""}
}
if org.IsOrganization() {
@ -1895,21 +1895,20 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
return nil
}
// GetRepositoryByRef returns a Repository specified by a GFM reference.
// See https://help.github.com/articles/writing-on-github#references for more information on the syntax.
func GetRepositoryByRef(ref string) (*Repository, error) {
n := strings.IndexByte(ref, byte('/'))
if n < 2 {
return nil, ErrInvalidReference
}
userName, repoName := ref[:n], ref[n+1:]
user, err := GetUserByName(userName)
// GetRepositoryByOwnerAndName returns the repository by given ownername and reponame.
func GetRepositoryByOwnerAndName(ownerName, repoName string) (*Repository, error) {
var repo Repository
has, err := x.Select("repository.*").
Join("INNER", "user", "`user`.id = repository.owner_id").
Where("repository.lower_name = ?", strings.ToLower(repoName)).
And("`user`.lower_name = ?", strings.ToLower(ownerName)).
Get(&repo)
if err != nil {
return nil, err
} else if !has {
return nil, ErrRepoNotExist{0, 0, ownerName, repoName}
}
return GetRepositoryByName(user.ID, repoName)
return &repo, nil
}
// GetRepositoryByName returns the repository by given name under user if exists.
@ -1922,7 +1921,7 @@ func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrRepoNotExist{0, ownerID, name}
return nil, ErrRepoNotExist{0, ownerID, "", name}
}
return repo, err
}
@ -1933,7 +1932,7 @@ func getRepositoryByID(e Engine, id int64) (*Repository, error) {
if err != nil {
return nil, err
} else if !has {
return nil, ErrRepoNotExist{id, 0, ""}
return nil, ErrRepoNotExist{id, 0, "", ""}
}
return repo, nil
}

View File

@ -5,7 +5,9 @@
package models
import (
"fmt"
"os"
"path/filepath"
"testing"
"code.gitea.io/gitea/modules/setting"
@ -13,6 +15,7 @@ import (
"github.com/Unknwon/com"
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
_ "github.com/mattn/go-sqlite3" // for the test engine
"github.com/stretchr/testify/assert"
"gopkg.in/testfixtures.v2"
)
@ -20,9 +23,30 @@ import (
// NonexistentID an ID that will never exist
const NonexistentID = 9223372036854775807
// CreateTestEngine create in-memory sqlite database for unit tests
// Any package that calls this must import github.com/mattn/go-sqlite3
func CreateTestEngine(fixturesDir string) error {
// giteaRoot a path to the gitea root
var giteaRoot string
// MainTest a reusable TestMain(..) function for unit tests that need to use a
// test database. Creates the test database, and sets necessary settings.
func MainTest(m *testing.M, pathToGiteaRoot string) {
giteaRoot = pathToGiteaRoot
fixturesDir := filepath.Join(pathToGiteaRoot, "models", "fixtures")
if err := createTestEngine(fixturesDir); err != nil {
fmt.Fprintf(os.Stderr, "Error creating test engine: %v\n", err)
os.Exit(1)
}
setting.AppURL = "https://try.gitea.io/"
setting.RunUser = "runuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
os.Exit(m.Run())
}
func createTestEngine(fixturesDir string) error {
var err error
x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
if err != nil {
@ -45,10 +69,13 @@ func PrepareTestDatabase() error {
return LoadFixtures()
}
func prepareTestEnv(t testing.TB) {
// PrepareTestEnv prepares the environment for unit tests. Can only be called
// by tests that use the above MainTest(..) function.
func PrepareTestEnv(t testing.TB) {
assert.NoError(t, PrepareTestDatabase())
assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
assert.NoError(t, com.CopyDir("../integrations/gitea-repositories-meta", setting.RepoRootPath))
metaPath := filepath.Join(giteaRoot, "integrations", "gitea-repositories-meta")
assert.NoError(t, com.CopyDir(metaPath, setting.RepoRootPath))
}
type testCond struct {

View File

@ -74,6 +74,14 @@ func TestWikiFilenameToName(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, test.Expected, name)
}
for _, badFilename := range []string{
"nofileextension",
"wrongfileextension.txt",
"badescaping%%.md",
} {
_, err := WikiFilenameToName(badFilename)
assert.Error(t, err)
}
}
func TestWikiNameToFilenameToName(t *testing.T) {
@ -115,7 +123,7 @@ func TestRepository_WikiPath(t *testing.T) {
}
func TestRepository_HasWiki(t *testing.T) {
prepareTestEnv(t)
PrepareTestEnv(t)
repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
assert.True(t, repo1.HasWiki())
repo2 := AssertExistsAndLoadBean(t, &Repository{ID: 2}).(*Repository)
@ -123,7 +131,7 @@ func TestRepository_HasWiki(t *testing.T) {
}
func TestRepository_InitWiki(t *testing.T) {
prepareTestEnv(t)
PrepareTestEnv(t)
// repo1 already has a wiki
repo1 := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
assert.NoError(t, repo1.InitWiki())
@ -135,7 +143,7 @@ func TestRepository_InitWiki(t *testing.T) {
}
func TestRepository_LocalWikiPath(t *testing.T) {
prepareTestEnv(t)
PrepareTestEnv(t)
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
expected := filepath.Join(setting.AppDataPath, "tmp/local-wiki/1")
assert.Equal(t, expected, repo.LocalWikiPath())
@ -150,11 +158,23 @@ func TestRepository_AddWikiPage(t *testing.T) {
"Another page",
"Here's a <tag> and a/slash",
} {
prepareTestEnv(t)
PrepareTestEnv(t)
assert.NoError(t, repo.AddWikiPage(doer, wikiName, wikiContent, commitMsg))
expectedPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(wikiName))
assert.True(t, com.IsExist(expectedPath))
}
// test for already-existing wiki name
PrepareTestEnv(t)
err := repo.AddWikiPage(doer, "Home", wikiContent, commitMsg)
assert.Error(t, err)
assert.True(t, IsErrWikiAlreadyExist(err))
// test for reserved wiki name
PrepareTestEnv(t)
err = repo.AddWikiPage(doer, "_edit", wikiContent, commitMsg)
assert.Error(t, err)
assert.True(t, IsErrWikiReservedName(err))
}
func TestRepository_EditWikiPage(t *testing.T) {
@ -163,20 +183,23 @@ func TestRepository_EditWikiPage(t *testing.T) {
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
for _, newWikiName := range []string{
"Home", // same name as before
"New home",
"New/name/with/slashes",
} {
prepareTestEnv(t)
PrepareTestEnv(t)
assert.NoError(t, repo.EditWikiPage(doer, "Home", newWikiName, newWikiContent, commitMsg))
newPath := path.Join(repo.LocalWikiPath(), WikiNameToFilename(newWikiName))
assert.True(t, com.IsExist(newPath))
oldPath := path.Join(repo.LocalWikiPath(), "Home.md")
assert.False(t, com.IsExist(oldPath))
if newWikiName != "Home" {
oldPath := path.Join(repo.LocalWikiPath(), "Home.md")
assert.False(t, com.IsExist(oldPath))
}
}
}
func TestRepository_DeleteWikiPage(t *testing.T) {
prepareTestEnv(t)
PrepareTestEnv(t)
repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
doer := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
assert.NoError(t, repo.DeleteWikiPage(doer, "Home"))

View File

@ -363,10 +363,9 @@ func (f *EditReleaseForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
// NewWikiForm form for creating wiki
type NewWikiForm struct {
OldTitle string
Title string `binding:"Required"`
Content string `binding:"Required"`
Message string
Title string `binding:"Required"`
Content string `binding:"Required"`
Message string
}
// Validate validates the fields

View File

@ -176,12 +176,9 @@ func Contexter() macaron.Handler {
repoName := c.Params(":reponame")
branchName := "master"
owner, err := models.GetUserByName(ownerName)
if err == nil {
repo, err := models.GetRepositoryByName(owner.ID, repoName)
if err == nil && len(repo.DefaultBranch) > 0 {
branchName = repo.DefaultBranch
}
repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
if err == nil && len(repo.DefaultBranch) > 0 {
branchName = repo.DefaultBranch
}
prefix := setting.AppURL + path.Join(ownerName, repoName, "src", "branch", branchName)
c.PlainText(http.StatusOK, []byte(com.Expand(`

View File

@ -108,10 +108,9 @@ func ObjectOidHandler(ctx *context.Context) {
}
func getAuthenticatedRepoAndMeta(ctx *context.Context, rv *RequestVars, requireWrite bool) (*models.LFSMetaObject, *models.Repository) {
repositoryString := rv.User + "/" + rv.Repo
repository, err := models.GetRepositoryByRef(repositoryString)
repository, err := models.GetRepositoryByOwnerAndName(rv.User, rv.Repo)
if err != nil {
log.Debug("Could not find repository: %s - %s", repositoryString, err)
log.Debug("Could not find repository: %s/%s - %s", rv.User, rv.Repo, err)
writeStatus(ctx, 404)
return nil, nil
}
@ -197,7 +196,6 @@ func getMetaHandler(ctx *context.Context) {
// PostHandler instructs the client how to upload data
func PostHandler(ctx *context.Context) {
if !setting.LFS.StartServer {
writeStatus(ctx, 404)
return
@ -210,10 +208,9 @@ func PostHandler(ctx *context.Context) {
rv := unpack(ctx)
repositoryString := rv.User + "/" + rv.Repo
repository, err := models.GetRepositoryByRef(repositoryString)
repository, err := models.GetRepositoryByOwnerAndName(rv.User, rv.Repo)
if err != nil {
log.Debug("Could not find repository: %s - %s", repositoryString, err)
log.Debug("Could not find repository: %s/%s - %s", rv.User, rv.Repo, err)
writeStatus(ctx, 404)
return
}
@ -261,12 +258,10 @@ func BatchHandler(ctx *context.Context) {
// Create a response object
for _, object := range bv.Objects {
repositoryString := object.User + "/" + object.Repo
repository, err := models.GetRepositoryByRef(repositoryString)
repository, err := models.GetRepositoryByOwnerAndName(object.User, object.Repo)
if err != nil {
log.Debug("Could not find repository: %s - %s", repositoryString, err)
log.Debug("Could not find repository: %s/%s - %s", object.User, object.Repo, err)
writeStatus(ctx, 404)
return
}

View File

@ -331,6 +331,7 @@ var (
LibravatarService *libravatar.Libravatar
// Log settings
LogLevel string
LogRootPath string
LogModes []string
LogConfigs []string
@ -659,6 +660,7 @@ func NewContext() {
}
homeDir = strings.Replace(homeDir, "\\", "/", -1)
LogLevel = getLogLevel("log", "LEVEL", "Info")
LogRootPath = Cfg.Section("log").Key("ROOT_PATH").MustString(path.Join(AppWorkPath, "log"))
forcePathSeparator(LogRootPath)
@ -1194,6 +1196,11 @@ var logLevels = map[string]string{
"Critical": "5",
}
func getLogLevel(section string, key string, defaultValue string) string {
validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
return Cfg.Section(section).Key(key).In(defaultValue, validLevels)
}
func newLogService() {
log.Info("Gitea v%s%s", AppVer, AppBuiltWith)
@ -1218,11 +1225,8 @@ func newLogService() {
sec, _ = Cfg.NewSection("log." + mode)
}
validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
// Log level.
levelName := Cfg.Section("log."+mode).Key("LEVEL").In(
Cfg.Section("log").Key("LEVEL").In("Trace", validLevels),
validLevels)
levelName := getLogLevel("log."+mode, "LEVEL", LogLevel)
level, ok := logLevels[levelName]
if !ok {
log.Fatal(4, "Unknown log level: %s", levelName)
@ -1286,11 +1290,8 @@ func NewXORMLogService(disableConsole bool) {
sec, _ = Cfg.NewSection("log." + mode)
}
validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"}
// Log level.
levelName := Cfg.Section("log."+mode).Key("LEVEL").In(
Cfg.Section("log").Key("LEVEL").In("Trace", validLevels),
validLevels)
levelName := getLogLevel("log."+mode, "LEVEL", LogLevel)
level, ok := logLevels[levelName]
if !ok {
log.Fatal(4, "Unknown log level: %s", levelName)

View File

@ -110,8 +110,10 @@ func NewFuncMap() []template.FuncMap {
"EscapePound": func(str string) string {
return strings.NewReplacer("%", "%25", "#", "%23", " ", "%20", "?", "%3F").Replace(str)
},
"RenderCommitMessage": RenderCommitMessage,
"RenderCommitMessageLink": RenderCommitMessageLink,
"RenderCommitMessage": RenderCommitMessage,
"RenderCommitMessageLink": RenderCommitMessageLink,
"RenderCommitBody": RenderCommitBody,
"IsMultilineCommitMessage": IsMultilineCommitMessage,
"ThemeColorMetaTag": func() string {
return setting.UI.ThemeColorMetaTag
},
@ -280,6 +282,29 @@ func renderCommitMessage(msg string, opts markup.RenderIssueIndexPatternOptions)
return template.HTML(msgLines[0])
}
// RenderCommitBody extracts the body of a commit message without its title.
func RenderCommitBody(msg, urlPrefix string, metas map[string]string) template.HTML {
return renderCommitBody(msg, markup.RenderIssueIndexPatternOptions{
URLPrefix: urlPrefix,
Metas: metas,
})
}
func renderCommitBody(msg string, opts markup.RenderIssueIndexPatternOptions) template.HTML {
cleanMsg := template.HTMLEscapeString(msg)
fullMessage := string(markup.RenderIssueIndexPattern([]byte(cleanMsg), opts))
body := strings.Split(strings.TrimSpace(fullMessage), "\n")
if len(body) == 0 {
return template.HTML("")
}
return template.HTML(strings.Join(body[1:], "\n"))
}
// IsMultilineCommitMessage checks to see if a commit message contains multiple lines.
func IsMultilineCommitMessage(msg string) bool {
return strings.Count(strings.TrimSpace(msg), "\n") > 1
}
// Actioner describes an action
type Actioner interface {
GetOpType() models.ActionType

View File

@ -9,33 +9,48 @@ import (
"net/url"
"testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"github.com/go-macaron/session"
_ "github.com/mattn/go-sqlite3" // for the test engine
"github.com/stretchr/testify/assert"
macaron "gopkg.in/macaron.v1"
"gopkg.in/macaron.v1"
)
// MockContext mock context for unit tests
func MockContext(t *testing.T) *context.Context {
var macaronContext *macaron.Context
mac := macaron.New()
mac.Get("*/", func(ctx *macaron.Context) {
macaronContext = ctx
})
req, err := http.NewRequest("GET", "star", nil)
assert.NoError(t, err)
req.Form = url.Values{}
mac.ServeHTTP(&mockResponseWriter{}, req)
assert.NotNil(t, macaronContext)
assert.EqualValues(t, req, macaronContext.Req.Request)
func MockContext(t *testing.T, path string) *context.Context {
var macaronContext macaron.Context
macaronContext.ReplaceAllParams(macaron.Params{})
macaronContext.Locale = &mockLocale{}
requestURL, err := url.Parse(path)
assert.NoError(t, err)
macaronContext.Req = macaron.Request{Request: &http.Request{
URL: requestURL,
Form: url.Values{},
}}
macaronContext.Resp = &mockResponseWriter{}
macaronContext.Render = &mockRender{ResponseWriter: macaronContext.Resp}
macaronContext.Data = map[string]interface{}{}
return &context.Context{
Context: macaronContext,
Context: &macaronContext,
Flash: &session.Flash{
Values: make(url.Values),
},
}
}
// LoadRepo load a repo into a test context.
func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) {
ctx.Repo = &context.Repository{}
ctx.Repo.Repository = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repoID}).(*models.Repository)
}
// LoadUser load a user into a test context.
func LoadUser(t *testing.T, ctx *context.Context, userID int64) {
ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: userID}).(*models.User)
}
type mockLocale struct{}
func (l mockLocale) Language() string {
@ -43,7 +58,7 @@ func (l mockLocale) Language() string {
}
func (l mockLocale) Tr(s string, _ ...interface{}) string {
return "test translation"
return s
}
type mockResponseWriter struct {
@ -91,7 +106,8 @@ func (tr *mockRender) SetResponseWriter(rw http.ResponseWriter) {
tr.ResponseWriter = rw
}
func (tr *mockRender) JSON(int, interface{}) {
func (tr *mockRender) JSON(status int, _ interface{}) {
tr.Status(status)
}
func (tr *mockRender) JSONString(interface{}) (string, error) {

View File

@ -405,6 +405,7 @@ key_state_desc=Dieser Schlüssel wurde in den letzten 7 Tagen verwendet
token_state_desc=Dieser Token wurde in den letzten 7 Tagen benutzt
show_openid=Im Profil anzeigen
hide_openid=Nicht im Profil anzeigen
ssh_disabled=SSH ist deaktiviert
manage_social=Verknüpfte soziale Konten verwalten
social_desc=Dies ist eine Liste der zugeordneten Konten von sozialen Netzwerken. Bitte stelle sicher, dass du alle dieser Accounts kennst, da sie benutzt werden können, um sich mit deinem Account anzumelden.
@ -803,6 +804,7 @@ wiki.new_page_button=Neue Seite
wiki.delete_page_button=Seite löschen
wiki.delete_page_notice_1=Die Seite <code>"%s"</code> wird gelöscht. Bitte stelle sicher, dass das deine Absicht ist.
wiki.page_already_exists=Eine Wiki-Seite mit dem gleichen Namen existiert bereits.
wiki.reserved_page=Die Wiki-Seite namens %s ist reserviert, Bitte wähle einen anderen Namen.
wiki.pages=Seiten
wiki.last_updated=Zuletzt aktualisiert %s
@ -977,6 +979,7 @@ settings.slack_token=Token
settings.slack_domain=Domain
settings.slack_channel=Kanal
settings.add_discord_hook_desc=<a href="%s">Discord</a>-Integration zu deinem Repository hinzufügen.
settings.add_dingtalk_hook_desc=<a href="%s">Dingtalk</a>-Integration zu deinem Repository hinzufügen.
settings.deploy_keys=Deploy-Schlüssel
settings.add_deploy_key=Deploy-Schlüssel hinzufügen
settings.deploy_key_desc=Deploy-Schlüssel haben nur lesenden Zugriff. Sie sind nicht identisch mit dem SSH-Schlüssel des persönlichen Kontos.

File diff suppressed because one or more lines are too long

View File

@ -2017,6 +2017,10 @@ function initFilterBranchTagDropdown(selector) {
});
}
$(".commit-button").click(function() {
$(this).parent().find('.commit-body').toggle();
});
function deleteDependencyModal(id, type) {
$('.remove-dependency')
.modal({

View File

@ -66,7 +66,6 @@
font-size: 13px;
}
.issue.title {
line-height: 1.1em;
width: 80%;
}
.push.news .content ul {

View File

@ -1606,3 +1606,11 @@
}
}
}
tbody.commit-list {
vertical-align: baseline;
}
.commit-body {
white-space: pre-wrap;
}

View File

@ -310,7 +310,7 @@ func InstallPost(ctx *context.Context, form auth.InstallForm) {
cfg.Section("session").Key("PROVIDER").SetValue("file")
cfg.Section("log").Key("MODE").SetValue("file")
cfg.Section("log").Key("LEVEL").SetValue("Info")
cfg.Section("log").Key("LEVEL").SetValue(setting.LogLevel)
cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath)
cfg.Section("security").Key("INSTALL_LOCK").SetValue("true")

View File

@ -64,23 +64,9 @@ func HTTP(ctx *context.Context) {
reponame = reponame[:len(reponame)-5]
}
repoUser, err := models.GetUserByName(username)
repo, err := models.GetRepositoryByOwnerAndName(username, reponame)
if err != nil {
if models.IsErrUserNotExist(err) {
ctx.Handle(http.StatusNotFound, "GetUserByName", nil)
} else {
ctx.Handle(http.StatusInternalServerError, "GetUserByName", err)
}
return
}
repo, err := models.GetRepositoryByName(repoUser.ID, reponame)
if err != nil {
if models.IsErrRepoNotExist(err) {
ctx.Handle(http.StatusNotFound, "GetRepositoryByName", nil)
} else {
ctx.Handle(http.StatusInternalServerError, "GetRepositoryByName", err)
}
ctx.NotFoundOrServerError("GetRepositoryByOwnerAndName", models.IsErrRepoNotExist, err)
return
}

16
routers/repo/main_test.go Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"path/filepath"
"testing"
"code.gitea.io/gitea/models"
)
func TestMain(m *testing.M) {
models.MainTest(m, filepath.Join("..", ".."))
}

171
routers/repo/wiki_test.go Normal file
View File

@ -0,0 +1,171 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"io/ioutil"
"net/http"
"path/filepath"
"testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/test"
"github.com/Unknwon/com"
"github.com/stretchr/testify/assert"
)
const content = "Wiki contents for unit tests"
const message = "Wiki commit message for unit tests"
func wikiPath(repo *models.Repository, wikiName string) string {
return filepath.Join(repo.LocalWikiPath(), models.WikiNameToFilename(wikiName))
}
func wikiContent(t *testing.T, repo *models.Repository, wikiName string) string {
bytes, err := ioutil.ReadFile(wikiPath(repo, wikiName))
assert.NoError(t, err)
return string(bytes)
}
func assertWikiExists(t *testing.T, repo *models.Repository, wikiName string) {
assert.True(t, com.IsExist(wikiPath(repo, wikiName)))
}
func assertWikiNotExists(t *testing.T, repo *models.Repository, wikiName string) {
assert.False(t, com.IsExist(wikiPath(repo, wikiName)))
}
func assertPagesMetas(t *testing.T, expectedNames []string, metas interface{}) {
pageMetas, ok := metas.([]PageMeta)
if !assert.True(t, ok) {
return
}
if !assert.EqualValues(t, len(expectedNames), len(pageMetas)) {
return
}
for i, pageMeta := range pageMetas {
assert.EqualValues(t, expectedNames[i], pageMeta.Name)
}
}
func TestWiki(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
ctx.SetParams(":page", "Home")
test.LoadRepo(t, ctx, 1)
Wiki(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, "Home", ctx.Data["Title"])
assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
}
func TestWikiPages(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_pages")
test.LoadRepo(t, ctx, 1)
WikiPages(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assertPagesMetas(t, []string{"Home"}, ctx.Data["Pages"])
}
func TestNewWiki(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
NewWiki(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, ctx.Tr("repo.wiki.new_page"), ctx.Data["Title"])
}
func TestNewWikiPost(t *testing.T) {
for _, title := range []string{
"New page",
"&&&&",
} {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
NewWikiPost(ctx, auth.NewWikiForm{
Title: title,
Content: content,
Message: message,
})
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
assertWikiExists(t, ctx.Repo.Repository, title)
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
}
}
func TestNewWikiPost_ReservedName(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
NewWikiPost(ctx, auth.NewWikiForm{
Title: "_edit",
Content: content,
Message: message,
})
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, ctx.Tr("repo.wiki.reserved_page"), ctx.Flash.ErrorMsg)
assertWikiNotExists(t, ctx.Repo.Repository, "_edit")
}
func TestEditWiki(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_edit/Home")
ctx.SetParams(":page", "Home")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
EditWiki(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assert.EqualValues(t, "Home", ctx.Data["Title"])
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, "Home"), ctx.Data["content"])
}
func TestEditWikiPost(t *testing.T) {
for _, title := range []string{
"Home",
"New/<page>",
} {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/_new/Home")
ctx.SetParams(":page", "Home")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
EditWikiPost(ctx, auth.NewWikiForm{
Title: title,
Content: content,
Message: message,
})
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
assertWikiExists(t, ctx.Repo.Repository, title)
assert.Equal(t, wikiContent(t, ctx.Repo.Repository, title), content)
if title != "Home" {
assertWikiNotExists(t, ctx.Repo.Repository, "Home")
}
}
}
func TestDeleteWikiPagePost(t *testing.T) {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user2/repo1/wiki/Home/delete")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
DeleteWikiPagePost(ctx)
assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
assertWikiNotExists(t, ctx.Repo.Repository, "Home")
}

View File

@ -19,8 +19,8 @@ func TestIssues(t *testing.T) {
setting.UI.IssuePagingNum = 1
assert.NoError(t, models.LoadFixtures())
ctx := test.MockContext(t)
ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: 2}).(*models.User)
ctx := test.MockContext(t, "issues")
test.LoadUser(t, ctx, 2)
ctx.SetParams(":type", "issues")
ctx.Req.Form.Set("state", "closed")
Issues(ctx)

View File

@ -5,29 +5,12 @@
package user
import (
"fmt"
"os"
"path/filepath"
"testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/setting"
_ "github.com/mattn/go-sqlite3" // for the test engine
)
func TestMain(m *testing.M) {
if err := models.CreateTestEngine("../../models/fixtures/"); err != nil {
fmt.Printf("Error creating test engine: %v\n", err)
os.Exit(1)
}
setting.AppURL = "https://try.gitea.io/"
setting.RunUser = "runuser"
setting.SSH.Port = 3000
setting.SSH.Domain = "try.gitea.io"
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
os.Exit(m.Run())
models.MainTest(m, filepath.Join("..", ".."))
}

View File

@ -30,7 +30,6 @@ import (
const (
tplSettingsProfile base.TplName = "user/settings/profile"
tplSettingsAvatar base.TplName = "user/settings/avatar"
tplSettingsPassword base.TplName = "user/settings/password"
tplSettingsEmails base.TplName = "user/settings/email"
tplSettingsKeys base.TplName = "user/settings/keys"
tplSettingsSocial base.TplName = "user/settings/social"
@ -223,7 +222,9 @@ func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) {
return
}
if ctx.User.IsPasswordSet() && !ctx.User.ValidatePassword(form.OldPassword) {
if len(form.Password) < setting.MinPasswordLength {
ctx.Flash.Error(ctx.Tr("auth.password_too_short", setting.MinPasswordLength))
} else if ctx.User.IsPasswordSet() && !ctx.User.ValidatePassword(form.OldPassword) {
ctx.Flash.Error(ctx.Tr("settings.password_incorrect"))
} else if form.Password != form.Retype {
ctx.Flash.Error(ctx.Tr("form.password_not_match"))

View File

@ -0,0 +1,68 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package user
import (
"net/http"
"testing"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
"github.com/stretchr/testify/assert"
)
func TestChangePassword(t *testing.T) {
oldPassword := "password"
setting.MinPasswordLength = 6
for _, req := range []struct {
OldPassword string
NewPassword string
Retype string
Message string
}{
{
OldPassword: oldPassword,
NewPassword: "123456",
Retype: "123456",
Message: "",
},
{
OldPassword: oldPassword,
NewPassword: "12345",
Retype: "12345",
Message: "auth.password_too_short",
},
{
OldPassword: "12334",
NewPassword: "123456",
Retype: "123456",
Message: "settings.password_incorrect",
},
{
OldPassword: oldPassword,
NewPassword: "123456",
Retype: "12345",
Message: "form.password_not_match",
},
} {
models.PrepareTestEnv(t)
ctx := test.MockContext(t, "user/settings/security")
test.LoadUser(t, ctx, 2)
test.LoadRepo(t, ctx, 1)
SettingsSecurityPost(ctx, auth.ChangePasswordForm{
OldPassword: req.OldPassword,
Password: req.NewPassword,
Retype: req.Retype,
})
assert.EqualValues(t, req.Message, ctx.Flash.ErrorMsg)
assert.EqualValues(t, http.StatusFound, ctx.Resp.Status())
}
}

View File

@ -30,7 +30,7 @@
<th class="three wide right aligned">{{.i18n.Tr "repo.commits.date"}}</th>
</tr>
</thead>
<tbody>
<tbody class="commit-list">
{{ $r:= List .Commits}}
{{range $r}}
<tr>
@ -61,6 +61,10 @@
</td>
<td class="message collapsing">
<span class="has-emoji{{if gt .ParentCount 1}} grey text{{end}}">{{RenderCommitMessage .Summary $.RepoLink $.Repository.ComposeMetas}}</span>
{{if IsMultilineCommitMessage .Message}}
<button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
<pre class="commit-body" style="display: none;">{{RenderCommitBody .Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
{{template "repo/commit_status" .Status}}
</td>
<td class="grey text right aligned">{{TimeSince .Author.When $.Lang}}</td>

View File

@ -10,6 +10,9 @@
{{.i18n.Tr "repo.diff.browse_source"}}
</a>
<h3>{{RenderCommitMessage .Commit.Message $.RepoLink $.Repository.ComposeMetas}}{{template "repo/commit_status" .CommitStatus}}</h3>
{{if IsMultilineCommitMessage .Commit.Message}}
<pre class="commit-body">{{RenderCommitBody .Commit.Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
</div>
<div class="ui attached info segment {{if .Commit.Signature}} isSigned {{if .Verification.Verified }} isVerified {{end}}{{end}}">
{{if .Author}}

View File

@ -38,7 +38,7 @@
<div class="ui attached table segment">
<div class="file-view {{if .IsMarkup}}markdown{{else if .IsRenderedHTML}}plain-text{{else if .IsTextFile}}code-view{{end}} has-emoji">
{{if .IsMarkup}}
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
{{if .FileContent}}{{.FileContent | Safe}}{{end}}
{{else if .IsRenderedHTML}}
<pre>{{if .FileContent}}{{.FileContent | Str2html}}{{end}}</pre>
{{else if not .IsTextFile}}

View File

@ -1,6 +1,6 @@
<table id="repo-files-table" class="ui fixed single line table">
<thead>
<tr>
<tr class="commit-list">
<th class="four wide">
{{if .LatestCommitUser}}
<img class="ui avatar image img-12" src="{{.LatestCommitUser.RelAvatarLink}}" />
@ -28,6 +28,10 @@
{{end}}
</a>
<span class="grey has-emoji">{{RenderCommitMessage .LatestCommit.Summary .RepoLink $.Repository.ComposeMetas}}
{{if IsMultilineCommitMessage .LatestCommit.Message}}
<button class="basic compact mini ui icon button commit-button"><i class="ellipsis horizontal icon"></i></button>
<pre class="commit-body" style="display: none;">{{RenderCommitBody .LatestCommit.Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
{{template "repo/commit_status" .LatestCommitStatus}}</span>
</th>
<th class="nine wide">

View File

@ -13,12 +13,11 @@
</div>
<form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="old_title" value="{{.old_title}}">
<div class="field {{if .Err_Title}}error{{end}}">
<input name="title" value="{{.title}}" autofocus required>
</div>
<div class="field">
<textarea id="edit_area" name="content" data-id="wiki-{{.old_title}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/wiki">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required>
<textarea id="edit_area" name="content" data-id="wiki-{{.title}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}/wiki">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required>
</div>
<div class="field">
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">