# Conflicts:
#	models/migrations/migrations.go
#	models/migrations/v58.go
This commit is contained in:
kolaente 2018-03-18 15:23:32 +01:00
commit 2950021ddf
No known key found for this signature in database
GPG Key ID: F40E70337AB24C9B
62 changed files with 566 additions and 229 deletions

View File

@ -1,5 +0,0 @@
*
!gitea
!docker
!public
!templates

View File

@ -1,20 +1,41 @@
###################################
#Build stage
FROM golang:1.10-alpine3.7 AS build-env
ARG GITEA_VERSION
ARG TAGS="sqlite"
ENV TAGS "bindata $TAGS"
#Build deps
RUN apk --no-cache add build-base git
#Setup repo
COPY . ${GOPATH}/src/code.gitea.io/gitea
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
#Checkout version if set
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
&& make clean generate build
FROM alpine:3.7
LABEL maintainer="The Gitea Authors"
LABEL maintainer="maintainers@gitea.io"
EXPOSE 22 3000
RUN apk --no-cache add \
su-exec \
ca-certificates \
sqlite \
bash \
ca-certificates \
curl \
gettext \
git \
linux-pam \
s6 \
curl \
openssh \
gettext \
s6 \
sqlite \
su-exec \
tzdata
RUN addgroup \
-S -g 1000 \
git && \
@ -29,7 +50,6 @@ RUN addgroup \
ENV USER git
ENV GITEA_CUSTOM /data/gitea
ENV GODEBUG=netdns=go
VOLUME ["/data"]
@ -37,4 +57,4 @@ ENTRYPOINT ["/usr/bin/entrypoint"]
CMD ["/bin/s6-svscan", "/etc/s6"]
COPY docker /
COPY gitea /app/gitea/gitea
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea

View File

@ -21,3 +21,4 @@ David Schneiderbauer <dschneiderbauer@gmail.com> (@daviian)
Peter Žeby <morlinest@gmail.com> (@morlinest)
Matti Ranta <matti@mdranta.net> (@techknowlogick)
Michael Lustfield <mtecknology@debian.org> (@MTecknology)
Jonas Franz <info@jonasfranz.software> (@JonasFranzDEV)

6
docker/Makefile vendored
View File

@ -7,5 +7,9 @@ DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
.PHONY: docker
docker:
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" webhippie/golang:edge make clean generate build
docker build --disable-content-trust=false -t $(DOCKER_REF) .
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite" .
.PHONY: docker-build
docker-build:
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" webhippie/golang:edge make clean generate build

View File

@ -785,6 +785,21 @@ func (err ErrBranchNameConflict) Error() string {
return fmt.Sprintf("branch conflicts with existing branch [name: %s]", err.BranchName)
}
// ErrNotAllowedToMerge represents an error that a branch is protected and the current user is not allowed to modify it
type ErrNotAllowedToMerge struct {
Reason string
}
// IsErrNotAllowedToMerge checks if an error is an ErrNotAllowedToMerge.
func IsErrNotAllowedToMerge(err error) bool {
_, ok := err.(ErrNotAllowedToMerge)
return ok
}
func (err ErrNotAllowedToMerge) Error() string {
return fmt.Sprintf("not allowed to merge [reason: %s]", err.Reason)
}
// ErrTagAlreadyExists represents an error that tag with such name already exists
type ErrTagAlreadyExists struct {
TagName string

View File

@ -19,22 +19,24 @@ import (
var labelColorPattern = regexp.MustCompile("#([a-fA-F0-9]{6})")
// GetLabelTemplateFile loads the label template file by given name,
// then parses and returns a list of name-color pairs.
func GetLabelTemplateFile(name string) ([][2]string, error) {
// then parses and returns a list of name-color pairs and optionally description.
func GetLabelTemplateFile(name string) ([][3]string, error) {
data, err := getRepoInitFile("label", name)
if err != nil {
return nil, fmt.Errorf("getRepoInitFile: %v", err)
}
lines := strings.Split(string(data), "\n")
list := make([][2]string, 0, len(lines))
list := make([][3]string, 0, len(lines))
for i := 0; i < len(lines); i++ {
line := strings.TrimSpace(lines[i])
if len(line) == 0 {
continue
}
fields := strings.SplitN(line, " ", 2)
parts := strings.SplitN(line, ";", 2)
fields := strings.SplitN(parts[0], " ", 2)
if len(fields) != 2 {
return nil, fmt.Errorf("line is malformed: %s", line)
}
@ -43,8 +45,14 @@ func GetLabelTemplateFile(name string) ([][2]string, error) {
return nil, fmt.Errorf("bad HTML color code in line: %s", line)
}
var description string
if len(parts) > 1 {
description = strings.TrimSpace(parts[1])
}
fields[1] = strings.TrimSpace(fields[1])
list = append(list, [2]string{fields[1], fields[0]})
list = append(list, [3]string{fields[1], fields[0], description})
}
return list, nil
@ -55,6 +63,7 @@ type Label struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"`
Name string
Description string
Color string `xorm:"VARCHAR(7)"`
NumIssues int
NumClosedIssues int

View File

@ -169,6 +169,8 @@ var migrations = []Migration{
// v57 -> v58
NewMigration("add closed_unix column for issues", addIssueClosedTime),
// v58 -> v59
NewMigration("add label descriptions", addLabelsDescriptions),
// v59 -> v60
NewMigration("add issue_dependencies", addIssueDependencies),
}

View File

@ -6,95 +6,17 @@ package migrations
import (
"fmt"
"time"
"code.gitea.io/gitea/modules/setting"
"github.com/go-xorm/xorm"
)
func addIssueDependencies(x *xorm.Engine) (err error) {
type IssueDependency struct {
ID int64 `xorm:"pk autoincr"`
UserID int64 `xorm:"NOT NULL"`
IssueID int64 `xorm:"NOT NULL"`
DependencyID int64 `xorm:"NOT NULL"`
Created time.Time `xorm:"-"`
CreatedUnix int64 `xorm:"INDEX created"`
Updated time.Time `xorm:"-"`
UpdatedUnix int64 `xorm:"updated"`
func addLabelsDescriptions(x *xorm.Engine) error {
type Label struct {
Description string
}
if err = x.Sync(new(IssueDependency)); err != nil {
return fmt.Errorf("Error creating issue_dependency_table column definition: %v", err)
if err := x.Sync2(new(Label)); err != nil {
return fmt.Errorf("Sync2: %v", err)
}
// Update Comment definition
// This (copied) struct does only contain fields used by xorm as the only use here is to update the database
// CommentType defines the comment type
type CommentType int
// TimeStamp defines a timestamp
type TimeStamp int64
type Comment struct {
ID int64 `xorm:"pk autoincr"`
Type CommentType
PosterID int64 `xorm:"INDEX"`
IssueID int64 `xorm:"INDEX"`
LabelID int64
OldMilestoneID int64
MilestoneID int64
OldAssigneeID int64
AssigneeID int64
OldTitle string
NewTitle string
DependentIssueID int64
CommitID int64
Line int64
Content string `xorm:"TEXT"`
CreatedUnix TimeStamp `xorm:"INDEX created"`
UpdatedUnix TimeStamp `xorm:"INDEX updated"`
// Reference issue in commit message
CommitSHA string `xorm:"VARCHAR(40)"`
}
if err = x.Sync(new(Comment)); err != nil {
return fmt.Errorf("Error updating issue_comment table column definition: %v", err)
}
// RepoUnit describes all units of a repository
type RepoUnit struct {
ID int64
RepoID int64 `xorm:"INDEX(s)"`
Type int `xorm:"INDEX(s)"`
Config map[string]interface{} `xorm:"JSON"`
CreatedUnix int64 `xorm:"INDEX CREATED"`
Created time.Time `xorm:"-"`
}
//Updating existing issue units
units := make([]*RepoUnit, 0, 100)
err = x.Where("`type` = ?", V16UnitTypeIssues).Find(&units)
if err != nil {
return fmt.Errorf("Query repo units: %v", err)
}
for _, unit := range units {
if unit.Config == nil {
unit.Config = make(map[string]interface{})
}
if _, ok := unit.Config["EnableDependencies"]; !ok {
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
}
if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil {
return err
}
}
return err
return nil
}

1
models/migrations/v59.go Normal file
View File

@ -0,0 +1 @@
package migrations

View File

@ -272,6 +272,31 @@ const (
MergeStyleSquash MergeStyle = "squash"
)
// CheckUserAllowedToMerge checks whether the user is allowed to merge
func (pr *PullRequest) CheckUserAllowedToMerge(doer *User) (err error) {
if doer == nil {
return ErrNotAllowedToMerge{
"Not signed in",
}
}
if pr.BaseRepo == nil {
if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err)
}
}
if protected, err := pr.BaseRepo.IsProtectedBranch(pr.BaseBranch, doer); err != nil {
return fmt.Errorf("IsProtectedBranch: %v", err)
} else if protected {
return ErrNotAllowedToMerge{
"The branch is protected",
}
}
return nil
}
// Merge merges pull request to base repository.
// FIXME: add repoWorkingPull make sure two merges does not happen at same time.
func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle MergeStyle, message string) (err error) {
@ -287,6 +312,10 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
}
prConfig := prUnit.PullRequestsConfig()
if err := pr.CheckUserAllowedToMerge(doer); err != nil {
return fmt.Errorf("CheckUserAllowedToMerge: %v", err)
}
// Check if merge style is correct and allowed
if !prConfig.IsMergeStyleAllowed(mergeStyle) {
return ErrInvalidMergeStyle{pr.BaseRepo.ID, mergeStyle}

View File

@ -1949,6 +1949,12 @@ func GetRepositoryByID(id int64) (*Repository, error) {
return getRepositoryByID(x, id)
}
// GetRepositoriesMapByIDs returns the repositories by given id slice.
func GetRepositoriesMapByIDs(ids []int64) (map[int64]*Repository, error) {
var repos = make(map[int64]*Repository, len(ids))
return repos, x.In("id", ids).Find(&repos)
}
// GetUserRepositories returns a list of repositories of given user.
func GetUserRepositories(userID int64, private bool, page, pageSize int, orderBy string) ([]*Repository, error) {
if len(orderBy) == 0 {

View File

@ -249,3 +249,28 @@ func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, err
return repos, count, nil
}
// FindUserAccessibleRepoIDs find all accessible repositories' ID by user's id
func FindUserAccessibleRepoIDs(userID int64) ([]int64, error) {
var accessCond builder.Cond = builder.Eq{"is_private": false}
if userID > 0 {
accessCond = accessCond.Or(
builder.Eq{"owner_id": userID},
builder.And(
builder.Expr("id IN (SELECT repo_id FROM `access` WHERE access.user_id = ?)", userID),
builder.Neq{"owner_id": userID},
),
)
}
repoIDs := make([]int64, 0, 10)
if err := x.
Table("repository").
Cols("id").
Where(accessCond).
Find(&repoIDs); err != nil {
return nil, fmt.Errorf("FindUserAccesibleRepoIDs: %v", err)
}
return repoIDs, nil
}

View File

@ -311,9 +311,10 @@ func (f *CreateMilestoneForm) Validate(ctx *macaron.Context, errs binding.Errors
// CreateLabelForm form for creating label
type CreateLabelForm struct {
ID int64
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_name"`
Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
ID int64
Title string `binding:"Required;MaxSize(50)" locale:"repo.issues.label_title"`
Description string `binding:"MaxSize(200)" locale:"repo.issues.label_description"`
Color string `binding:"Required;Size(7)" locale:"repo.issues.label_color"`
}
// Validate validates the fields

View File

@ -9,6 +9,7 @@ import (
"html/template"
"io"
"net/http"
"net/url"
"path"
"strings"
"time"
@ -75,6 +76,26 @@ func (ctx *Context) HasValue(name string) bool {
return ok
}
// RedirectToFirst redirects to first not empty URL
func (ctx *Context) RedirectToFirst(location ...string) {
for _, loc := range location {
if len(loc) == 0 {
continue
}
u, err := url.Parse(loc)
if err != nil || (u.Scheme != "" && !strings.HasPrefix(strings.ToLower(loc), strings.ToLower(setting.AppURL))) {
continue
}
ctx.Redirect(loc)
return
}
ctx.Redirect(setting.AppSubURL + "/")
return
}
// HTML calls Context.HTML and converts template name to string.
func (ctx *Context) HTML(status int, name base.TplName) {
log.Debug("Template: %s", name)

View File

@ -16,6 +16,7 @@ import (
"github.com/blevesearch/bleve/analysis/token/lowercase"
"github.com/blevesearch/bleve/analysis/token/unique"
"github.com/blevesearch/bleve/analysis/tokenizer/unicode"
"github.com/blevesearch/bleve/search/query"
"github.com/ethantkoenig/rupture"
)
@ -158,6 +159,7 @@ func DeleteRepoFromIndexer(repoID int64) error {
// RepoSearchResult result of performing a search in a repo
type RepoSearchResult struct {
RepoID int64
StartIndex int
EndIndex int
Filename string
@ -166,17 +168,29 @@ type RepoSearchResult struct {
// SearchRepoByKeyword searches for files in the specified repo.
// Returns the matching file-paths
func SearchRepoByKeyword(repoID int64, keyword string, page, pageSize int) (int64, []*RepoSearchResult, error) {
func SearchRepoByKeyword(repoIDs []int64, keyword string, page, pageSize int) (int64, []*RepoSearchResult, error) {
phraseQuery := bleve.NewMatchPhraseQuery(keyword)
phraseQuery.FieldVal = "Content"
phraseQuery.Analyzer = repoIndexerAnalyzer
indexerQuery := bleve.NewConjunctionQuery(
numericEqualityQuery(repoID, "RepoID"),
phraseQuery,
)
var indexerQuery query.Query
if len(repoIDs) > 0 {
var repoQueries = make([]query.Query, 0, len(repoIDs))
for _, repoID := range repoIDs {
repoQueries = append(repoQueries, numericEqualityQuery(repoID, "RepoID"))
}
indexerQuery = bleve.NewConjunctionQuery(
bleve.NewDisjunctionQuery(repoQueries...),
phraseQuery,
)
} else {
indexerQuery = phraseQuery
}
from := (page - 1) * pageSize
searchRequest := bleve.NewSearchRequestOptions(indexerQuery, pageSize, from, false)
searchRequest.Fields = []string{"Content"}
searchRequest.Fields = []string{"Content", "RepoID"}
searchRequest.IncludeLocations = true
result, err := repoIndexer.Search(searchRequest)
@ -199,6 +213,7 @@ func SearchRepoByKeyword(repoID int64, keyword string, page, pageSize int) (int6
}
}
searchResults[i] = &RepoSearchResult{
RepoID: int64(hit.Fields["RepoID"].(float64)),
StartIndex: startIndex,
EndIndex: endIndex,
Filename: filenameOfIndexerID(hit.ID),

View File

@ -17,6 +17,7 @@ import (
// Result a search result to display
type Result struct {
RepoID int64
Filename string
HighlightClass string
LineNumbers []int
@ -98,6 +99,7 @@ func searchResult(result *indexer.RepoSearchResult, startIndex, endIndex int) (*
index += len(line)
}
return &Result{
RepoID: result.RepoID,
Filename: result.Filename,
HighlightClass: highlight.FileNameToHighlightClass(result.Filename),
LineNumbers: lineNumbers,
@ -106,12 +108,12 @@ func searchResult(result *indexer.RepoSearchResult, startIndex, endIndex int) (*
}
// PerformSearch perform a search on a repository
func PerformSearch(repoID int64, keyword string, page, pageSize int) (int, []*Result, error) {
func PerformSearch(repoIDs []int64, keyword string, page, pageSize int) (int, []*Result, error) {
if len(keyword) == 0 {
return 0, nil, nil
}
total, results, err := indexer.SearchRepoByKeyword(repoID, keyword, page, pageSize)
total, results, err := indexer.SearchRepoByKeyword(repoIDs, keyword, page, pageSize)
if err != nil {
return 0, nil, err
}

View File

@ -1,7 +1,7 @@
#ee0701 bug
#cccccc duplicate
#84b6eb enhancement
#128a0c help wanted
#e6e6e6 invalid
#cc317c question
#ffffff wontfix
#ee0701 bug ; Something is not working
#cccccc duplicate ; This issue or pull request already exists
#84b6eb enhancement ; New feature
#128a0c help wanted ; Need some help
#e6e6e6 invalid ; Something is wrong
#cc317c question ; More information is needed
#ffffff wontfix ; This won't be fixed

View File

@ -660,7 +660,6 @@ people=Участници
teams=Екипи
lower_members=участници
lower_repositories=хранилища
create_new_team=Създай нов екип
org_desc=Описание
team_name=Име на екипа
team_desc=Описание

View File

@ -661,7 +661,6 @@ people=Lidé
teams=Týmy
lower_members=členové
lower_repositories=repositáře
create_new_team=Vytvořit nový tým
org_desc=Popis
team_name=Název týmu
team_desc=Popis

View File

@ -169,9 +169,11 @@ repos=Repositories
users=Benutzer
organizations=Organisationen
search=Suche
code=Code
repo_no_results=Es konnten keine passenden Repositories gefunden werden.
user_no_results=Es konnten keine passenden Benutzer gefunden werden.
org_no_results=Es konnten keine passenden Organisation gefunden werden.
code_search_results=Suchergebnisse für "%s
[auth]
create_new_account=Konto erstellen
@ -627,6 +629,7 @@ issues.no_ref=Keine Branch/Tag angegeben
issues.create=Issue erstellen
issues.new_label=Neues Label
issues.new_label_placeholder=Label-Name…
issues.new_label_desc_placeholder=Beschreibung…
issues.create_label=Label erstellen
issues.label_templates.title=Lade vordefinierte Label
issues.label_templates.info=Es sind noch keine Label vorhanden. Du kannst vordefinierte Label benutzen, oder auf "Neues Label" klicken um eines zu erstellen.
@ -697,6 +700,7 @@ issues.edit=Bearbeiten
issues.cancel=Abbrechen
issues.save=Speichern
issues.label_title=Labelname
issues.label_description=Labelbeschreibung
issues.label_color=Labelfarbe
issues.label_count=%d Label
issues.label_open_issues=%d offene Issues
@ -1113,7 +1117,8 @@ people=Personen
teams=Teams
lower_members=Mitglieder
lower_repositories=Repositories
create_new_team=Neues Team erstellen
create_new_team=Neues Team
create_team=Team erstellen
org_desc=Beschreibung
team_name=Teamname
team_desc=Beschreibung

View File

@ -169,9 +169,12 @@ repos = Repositories
users = Users
organizations = Organizations
search = Search
code = Code
repo_no_results = No matching repositories have been found.
user_no_results = No matching users have been found.
org_no_results = No matching organizations have been found.
code_no_results = No code matching your search term has been found.
code_search_results = Search results for "%s"
[auth]
create_new_account = Create Account
@ -627,6 +630,7 @@ issues.no_ref = No Branch/Tag Specified
issues.create = Create Issue
issues.new_label = New Label
issues.new_label_placeholder = Label name…
issues.new_label_desc_placeholder = Description…
issues.create_label = Create Label
issues.label_templates.title = Load a predefined set of labels
issues.label_templates.info = There are not any labels yet. You can click on the "New Label" button above to create one or use a predefined set below.
@ -697,6 +701,7 @@ issues.edit = Edit
issues.cancel = Cancel
issues.save = Save
issues.label_title = Label name
issues.label_description = Label description
issues.label_color = Label color
issues.label_count = %d labels
issues.label_open_issues = %d open issues

View File

@ -1009,7 +1009,6 @@ people=Personas
teams=Equipos
lower_members=miembros
lower_repositories=repositorios
create_new_team=Crear un nuevo equipo
org_desc=Descripción
team_name=Nombre del equipo
team_desc=Descripción

View File

@ -632,7 +632,6 @@ people=Ihmiset
teams=Tiimit
lower_members=jäsenet
lower_repositories=repot
create_new_team=Luo uusi tiimi
org_desc=Kuvaus
team_name=Tiimin nimi
team_desc=Kuvaus

View File

@ -1097,7 +1097,6 @@ people=Contacts
teams=Équipes
lower_members=Membres
lower_repositories=dépôts
create_new_team=Créer une nouvelle équipe
org_desc=Description
team_name=Nom de l'équipe
team_desc=Description

View File

@ -169,9 +169,12 @@ repos=Tárolók
users=Felhasználók
organizations=Szervezetek
search=Keresés
code=Kód
repo_no_results=Nem található a keresésnek megfelelő tároló.
user_no_results=Nem található a keresésnek megfelelő felhasználó.
org_no_results=Nem található a keresésnek megfelelő szervezet.
code_no_results=Nem található a keresésnek megfelelő kód.
code_search_results=Keresési találatok "%s
[auth]
create_new_account=Felhasználó létrehozása
@ -627,6 +630,7 @@ issues.no_ref=Nincsen ág/címke megadva
issues.create=Hibajegy létrehozása
issues.new_label=Új címke
issues.new_label_placeholder=Címke neve…
issues.new_label_desc_placeholder=Leírás…
issues.create_label=Címke létrehozása
issues.label_templates.title=Előre definiált címkék betöltése
issues.label_templates.info=Még nincsenek címkék. Rákattinthatsz az "Új Címke" gombra felül hogy létrehozz egyet, vagy választhatsz egy már létezőt a lenti listából.
@ -697,6 +701,7 @@ issues.edit=Szerkesztés
issues.cancel=Mégsem
issues.save=Mentés
issues.label_title=Címke neve
issues.label_description=Címke leírása
issues.label_color=Címke színe
issues.label_count=%d címke
issues.label_open_issues=%d nyitott hibajegy
@ -1113,7 +1118,8 @@ people=Emberek
teams=Csoportok
lower_members=tagok
lower_repositories=tárolók
create_new_team=Új csoport létrehozása
create_new_team=Új Csapat
create_team=Csapat létrehozása
org_desc=Leírás
team_name=Csoport neve
team_desc=Leírás

View File

@ -1097,7 +1097,6 @@ people=Orang
teams=Tim
lower_members=anggota
lower_repositories=repositori
create_new_team=Buat Tim Baru
org_desc=Deskripsi
team_name=Nama tim
team_desc=Deskripsi

View File

@ -811,7 +811,6 @@ people=Utenti
teams=Team
lower_members=membri
lower_repositories=repository
create_new_team=Crea Nuovo Team
org_desc=Descrizione
team_name=Nome Team
team_desc=Descrizione

View File

@ -1095,7 +1095,6 @@ people=人々
teams=チーム
lower_members=メンバー
lower_repositories=リポジトリ
create_new_team=新しいチームを作成
org_desc=説明
team_name=チーム名
team_desc=説明

View File

@ -894,7 +894,6 @@ people=사람
teams=
lower_members=회원
lower_repositories=저장소
create_new_team=새로운 팀 생성
org_desc=설명
team_name=팀 이름
team_desc=설명

View File

@ -1112,7 +1112,6 @@ people=Personas
teams=Komandas
lower_members=dalībnieki
lower_repositories=repozitoriji
create_new_team=Izveidot jaunu komandu
org_desc=Apraksts
team_name=Komandas nosaukums
team_desc=Apraksts

View File

@ -17,6 +17,7 @@ page=Pagina
template=Sjabloon
language=Taal
notifications=Meldingen
create_new=Maken…
user_profile_and_more=Gebruikersprofiel en meer
signed_in_as=Aangemeld als
enable_javascript=Deze website werkt beter met JavaScript
@ -154,10 +155,12 @@ uname_holder=Gebruikersnaam of e-mail
password_holder=Wachtwoord
switch_dashboard_context=Wissel voorpaginacontext
my_repos=Mijn repositories
show_more_repos=Toon meer repositories…
collaborative_repos=Gedeelde repositories
my_orgs=Mijn organisaties
my_mirrors=Mijn kopieën
view_home=Bekijk %s
search_repos=Zoek een repository…
issues.in_your_repos=In uw repositories
@ -331,6 +334,7 @@ enable_custom_avatar=Aangepaste avatar inschakelen
choose_new_avatar=Kies een nieuwe avatar
update_avatar=Avatar instelling bijwerken
delete_current_avatar=Verwijder huidige avatar
uploaded_avatar_not_a_image=Geüpload bestand is geen afbeelding.
update_avatar_success=Instellingen voor avatar succesvol bijgewerkt.
change_password=Verander wachtwoord
@ -377,6 +381,7 @@ add_new_gpg_key=GPG sleutel toevoegen
ssh_key_been_used=Deze public key wordt al gebruikt.
ssh_key_name_used=Een publieke sleutel met dezelfde naam bestaat al.
gpg_key_id_used=Een publieke GPG-sleutel met dezelfde naam bestaat al.
gpg_no_key_email_found=Geen van de e-mails die aan de GPG-sleutel gekoppeld zijn kan worden gevonden.
subkeys=Subkeys
key_id=Key-ID
key_name=Sleutel naam
@ -479,6 +484,7 @@ mirror_prune=Opschonen
mirror_interval=Kloon interval (geldige tijdseenheden "h", "m", "s")
mirror_interval_invalid=Kloon-interval is niet geldig
mirror_address=Kopie-adres
mirror_address_desc=Voeg alle noodzakelijke gebruikersgegevens toe aan de url.
mirror_last_synced=Laatste synchronisatie
watchers=Volgers
stargazers=Stargazers
@ -500,6 +506,7 @@ migrate.clone_local_path=of een lokaal pad
migrate.permission_denied=U bent niet gemachtigd om deze lokale repositories te importeren.
migrate.invalid_local_path=Ongeldig lokaal pad, het pad bestaat niet of het is geen map.
migrate.failed=Migratie is mislukt: %v
migrate.lfs_mirror_unsupported=Mirroring van LFS objecten wordt niet ondersteund - gebruik in plaat daarvan 'git lfs fetch --all' en 'git lfs push --all'.
mirror_from=kopie van
forked_from=geforked van
@ -547,11 +554,15 @@ editor.new_file=Nieuw bestand
editor.upload_file=Bestand uploaden
editor.edit_file=Bewerk bestand
editor.preview_changes=Voorbeeld tonen
editor.cannot_edit_non_text_files=Binaire bestanden kunnen niet bewerkt worden vanuit de webinterface
editor.edit_this_file=Bestand aanpassen
editor.must_be_on_a_branch=U moet in een branch zijn om aanpassingen te maken of voor te stellen
editor.fork_before_edit=U moet deze repository eerst forken om dit bestand aan te kunnen passen
editor.delete_this_file=Verwijder dit bestand
editor.must_have_write_access=U moet schrijftoegang hebben om aanpassingen te maken of voor te stellen in dit bestand
editor.file_delete_success=Bestand '%s' is succesvol verwijderd!
editor.name_your_file=Bestandsnaam…
editor.filename_help=Om een map toe te voegen, begin met typen en druk op /. Om een map te verwijderen, ga naar het begin van het veld en druk op backspace.
editor.or=of
editor.cancel_lower=annuleer
editor.commit_changes=Wijzigingen doorvoeren
@ -559,7 +570,9 @@ editor.add_tmpl='%s/<filename>' toevoegen
editor.add='%s' toevoegen
editor.update='%s' updaten
editor.delete='%s' verwijderen
editor.commit_message_desc=Voeg een optionele uitgebreide omschrijving toe…
editor.create_new_branch=Maak een <strong>nieuwe branch</strong> voor deze commit en start van een pull-aanvraag.
editor.new_branch_name_desc=Nieuwe branch naam…
editor.cancel=Annuleer
editor.filename_cannot_be_empty=Bestandsnaam mag niet leeg zijn.
editor.branch_already_exists=Branch '%s' bestaat al in deze repository.
@ -570,6 +583,7 @@ editor.file_changed_while_editing=Inhoud van het bestand is gewijzigd sinds u be
editor.file_already_exists=Een bestand met de naam '%s' bestaat al in deze repository.
editor.no_changes_to_show=Er zijn geen wijzigingen om weer te geven.
editor.fail_to_update_file=Update/maken van bestand '%s' is mislukt: %v
editor.add_subdir=Submap toevoegen…
editor.upload_files_to_dir=Bestanden uploaden naar '%s'
commits.commits=Commits
@ -605,6 +619,7 @@ issues.label_templates.use=Deze labelset gebruiken
issues.change_milestone_at='mijlpaal bewerkt van <b>%s</b> <b>%s</b> %s'
issues.remove_milestone_at=' %s is verwijderd uit de <b>%s</b> mijlpaal'
issues.deleted_milestone=` (verwijderd)`
issues.add_assignee_at=`was toegekend door <b>%s</b> %s`
issues.open_tab=%d Open
issues.close_tab=%d gesloten
issues.filter_label=Label
@ -675,13 +690,20 @@ issues.subscribe=Abonneren
issues.unsubscribe=Uitschrijven
issues.start_tracking_short=Start
issues.start_tracking=Start tijdregistratie
issues.start_tracking_history=`%s is begonnen`
issues.tracking_already_started=Je houd al tijd bij voor dit <a href="%s">issue</a>!`
issues.stop_tracking=Stop
issues.stop_tracking_history=`gestopt met werken aan %s`
issues.add_time=Vul tijd handmatig in
issues.add_time_short=Toevoegen
issues.add_time_cancel=Annuleren
issues.add_time_history=`heeft besteedde tijd toegevoegd: %s`
issues.add_time_hours=Uren
issues.add_time_minutes=Minuten
issues.add_time_sum_to_small=Geen tijd werd ingevoerd
issues.cancel_tracking=Annuleren
issues.cancel_tracking_history=`tijd bijhouden geannuleerd: %s`
issues.time_spent_total=Totaal besteden tijd
pulls.new=Nieuwe Pull aanvraag
pulls.compare_changes=Vergelijk veranderingen
@ -973,7 +995,6 @@ people=Mensen
teams=Teams
lower_members=leden
lower_repositories=repositories
create_new_team=Nieuw team aanmaken
org_desc=Omschrijving
team_name=Teamnaam
team_desc=Omschrijving

View File

@ -1089,7 +1089,6 @@ people=Ludzie
teams=Zespoły
lower_members=członkowie
lower_repositories=repozytoria
create_new_team=Utwórz nowy zespół
org_desc=Opis
team_name=Nazwa zespołu
team_desc=Opis

View File

@ -1097,7 +1097,6 @@ people=Pessoas
teams=Equipes
lower_members=membros
lower_repositories=repositórios
create_new_team=Criar nova equipe
org_desc=Descrição
team_name=Nome da equipe
team_desc=Descrição

View File

@ -169,9 +169,12 @@ repos=Репозитории
users=Пользователи
organizations=Организации
search=Поиск
code=Код
repo_no_results=Подходящие репозитории не найдены.
user_no_results=Подходящие пользователи не найдены.
org_no_results=Подходящие организации не найдены.
code_no_results=Подходящие фрагменты кода не найдены.
code_search_results=Результаты поиска для "%s
[auth]
create_new_account=Регистрация
@ -627,6 +630,7 @@ issues.no_ref=Не указана ветка или тэг
issues.create=Добавить задачу
issues.new_label=Новая метка
issues.new_label_placeholder=Имя метки…
issues.new_label_desc_placeholder=Описание…
issues.create_label=Добавить метку
issues.label_templates.title=Загрузить набор предопределённых меток
issues.label_templates.info=Меток пока нет. Вы можете нажать на кнопку «Создать метку», чтобы создать новую или использовать одну из готового набора ниже.
@ -697,6 +701,7 @@ issues.edit=Изменить
issues.cancel=Отмена
issues.save=Сохранить
issues.label_title=Имя метки
issues.label_description=Описание метки
issues.label_color=Цвет метки
issues.label_count=%d меток
issues.label_open_issues=%d открытых задач
@ -1113,7 +1118,8 @@ people=Люди
teams=Команды
lower_members=Участники
lower_repositories=Репозитории
create_new_team=Создать новую команду
create_new_team=Создание команды
create_team=Создать команду
org_desc=Описание
team_name=Название команды
team_desc=Описание

View File

@ -657,7 +657,6 @@ people=Особе
teams=Тимови
lower_members=чланови
lower_repositories=спремишта
create_new_team=Креирај нови тим
org_desc=Опис
team_name=Име тима
team_desc=Опис

View File

@ -960,7 +960,6 @@ people=Personer
teams=Grupper
lower_members=medlemmar
lower_repositories=utvecklingskataloger
create_new_team=Skapa ny grupp
org_desc=Beskrivning
team_name=Gruppnamn
team_desc=Beskrivning

View File

@ -1083,7 +1083,6 @@ people=İnsanlar
teams=Ekipler
lower_members=üyeler
lower_repositories=depolar
create_new_team=Yeni Ekip Oluştur
org_desc=ıklama
team_name=Ekip Adı
team_desc=ıklama

View File

@ -1097,7 +1097,6 @@ people=组织成员
teams=组织团队
lower_members=名成员
lower_repositories=个仓库
create_new_team=创建新的团队
org_desc=组织描述
team_name=团队名称
team_desc=团队描述

View File

@ -965,7 +965,6 @@ people=組織成員
teams=組織團隊
lower_members=名成員
lower_repositories=個儲存庫
create_new_team=建立新的團隊
org_desc=組織描述
team_name=團隊名稱
team_desc=團隊描述

View File

@ -1071,7 +1071,6 @@ people=組織成員
teams=組織團隊
lower_members=名成員
lower_repositories=個儲存庫
create_new_team=建立新的團隊
org_desc=組織描述
team_name=團隊名稱
team_desc=團隊描述

File diff suppressed because one or more lines are too long

View File

@ -491,6 +491,7 @@ function initRepository() {
$('.edit-label-button').click(function () {
$('#label-modal-id').val($(this).data('id'));
$('.edit-label .new-label-input').val($(this).data('title'));
$('.edit-label .new-label-desc-input').val($(this).data('description'));
$('.edit-label .color-picker').val($(this).data('color'));
$('.minicolors-swatch-color').css("background-color", $(this).data('color'));
$('.edit-label.modal').modal({

View File

@ -134,6 +134,17 @@
}
}
.select-label {
.item {
max-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
}
.desc {
padding-left: 16px;
}
}
.ui.tabs {
&.container {
margin-top: 14px;

View File

@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/search"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers/user"
@ -27,6 +28,8 @@ const (
tplExploreUsers base.TplName = "explore/users"
// tplExploreOrganizations explore organizations page template
tplExploreOrganizations base.TplName = "explore/organizations"
// tplExploreCode explore code page template
tplExploreCode base.TplName = "explore/code"
)
// Home render home page
@ -49,6 +52,7 @@ func Home(ctx *context.Context) {
}
ctx.Data["PageIsHome"] = true
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.HTML(200, tplHome)
}
@ -124,6 +128,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
ctx.Data["Total"] = count
ctx.Data["Page"] = paginater.New(int(count), opts.PageSize, page, 5)
ctx.Data["Repos"] = repos
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.HTML(200, opts.TplName)
}
@ -133,6 +138,7 @@ func ExploreRepos(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("explore")
ctx.Data["PageIsExplore"] = true
ctx.Data["PageIsExploreRepositories"] = true
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
var ownerID int64
if ctx.User != nil && !ctx.User.IsAdmin {
@ -194,6 +200,7 @@ func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplN
ctx.Data["Page"] = paginater.New(int(count), opts.PageSize, opts.Page, 5)
ctx.Data["Users"] = users
ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.HTML(200, tplName)
}
@ -203,6 +210,7 @@ func ExploreUsers(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("explore")
ctx.Data["PageIsExplore"] = true
ctx.Data["PageIsExploreUsers"] = true
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
RenderUserSearch(ctx, &models.SearchUserOptions{
Type: models.UserTypeIndividual,
@ -216,6 +224,7 @@ func ExploreOrganizations(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("explore")
ctx.Data["PageIsExplore"] = true
ctx.Data["PageIsExploreOrganizations"] = true
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
RenderUserSearch(ctx, &models.SearchUserOptions{
Type: models.UserTypeOrganization,
@ -223,6 +232,113 @@ func ExploreOrganizations(ctx *context.Context) {
}, tplExploreOrganizations)
}
// ExploreCode render explore code page
func ExploreCode(ctx *context.Context) {
if !setting.Indexer.RepoIndexerEnabled {
ctx.Redirect("/explore", 302)
return
}
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
ctx.Data["Title"] = ctx.Tr("explore")
ctx.Data["PageIsExplore"] = true
ctx.Data["PageIsExploreCode"] = true
keyword := strings.TrimSpace(ctx.Query("q"))
page := ctx.QueryInt("page")
if page <= 0 {
page = 1
}
var (
repoIDs []int64
err error
isAdmin bool
userID int64
)
if ctx.User != nil {
userID = ctx.User.ID
isAdmin = ctx.User.IsAdmin
}
// guest user or non-admin user
if ctx.User == nil || !isAdmin {
repoIDs, err = models.FindUserAccessibleRepoIDs(userID)
if err != nil {
ctx.ServerError("SearchResults", err)
return
}
}
var (
total int
searchResults []*search.Result
)
// if non-admin login user, we need check UnitTypeCode at first
if ctx.User != nil && len(repoIDs) > 0 {
repoMaps, err := models.GetRepositoriesMapByIDs(repoIDs)
if err != nil {
ctx.ServerError("SearchResults", err)
return
}
var rightRepoMap = make(map[int64]*models.Repository, len(repoMaps))
repoIDs = make([]int64, 0, len(repoMaps))
for id, repo := range repoMaps {
if repo.CheckUnitUser(userID, isAdmin, models.UnitTypeCode) {
rightRepoMap[id] = repo
repoIDs = append(repoIDs, id)
}
}
ctx.Data["RepoMaps"] = rightRepoMap
total, searchResults, err = search.PerformSearch(repoIDs, keyword, page, setting.UI.RepoSearchPagingNum)
if err != nil {
ctx.ServerError("SearchResults", err)
return
}
// if non-login user or isAdmin, no need to check UnitTypeCode
} else if (ctx.User == nil && len(repoIDs) > 0) || isAdmin {
total, searchResults, err = search.PerformSearch(repoIDs, keyword, page, setting.UI.RepoSearchPagingNum)
if err != nil {
ctx.ServerError("SearchResults", err)
return
}
var loadRepoIDs = make([]int64, 0, len(searchResults))
for _, result := range searchResults {
var find bool
for _, id := range loadRepoIDs {
if id == result.RepoID {
find = true
break
}
}
if !find {
loadRepoIDs = append(loadRepoIDs, result.RepoID)
}
}
repoMaps, err := models.GetRepositoriesMapByIDs(loadRepoIDs)
if err != nil {
ctx.ServerError("SearchResults", err)
return
}
ctx.Data["RepoMaps"] = repoMaps
}
ctx.Data["Keyword"] = keyword
pager := paginater.New(total, setting.UI.RepoSearchPagingNum, page, 5)
ctx.Data["Page"] = pager
ctx.Data["SearchResults"] = searchResults
ctx.Data["RequireHighlightJS"] = true
ctx.Data["PageIsViewCode"] = true
ctx.HTML(200, tplExploreCode)
}
// NotFound render 404 page
func NotFound(ctx *context.Context) {
ctx.Data["Title"] = "Page Not Found"

View File

@ -746,6 +746,15 @@ func ViewIssue(ctx *context.Context) {
}
prConfig := prUnit.PullRequestsConfig()
ctx.Data["AllowMerge"] = ctx.Data["IsRepositoryWriter"]
if err := pull.CheckUserAllowedToMerge(ctx.User); err != nil {
if !models.IsErrNotAllowedToMerge(err) {
ctx.ServerError("CheckUserAllowedToMerge", err)
return
}
ctx.Data["AllowMerge"] = false
}
// Check correct values and select default
if ms, ok := ctx.Data["MergeStyle"].(models.MergeStyle); !ok ||
!prConfig.IsMergeStyleAllowed(ms) {

View File

@ -42,9 +42,10 @@ func InitializeLabels(ctx *context.Context, form auth.InitializeLabelsForm) {
labels := make([]*models.Label, len(list))
for i := 0; i < len(list); i++ {
labels[i] = &models.Label{
RepoID: ctx.Repo.Repository.ID,
Name: list[i][0],
Color: list[i][1],
RepoID: ctx.Repo.Repository.ID,
Name: list[i][0],
Description: list[i][2],
Color: list[i][1],
}
}
if err := models.NewLabels(labels...); err != nil {
@ -81,9 +82,10 @@ func NewLabel(ctx *context.Context, form auth.CreateLabelForm) {
}
l := &models.Label{
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Color: form.Color,
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Description: form.Description,
Color: form.Color,
}
if err := models.NewLabel(l); err != nil {
ctx.ServerError("NewLabel", err)
@ -106,6 +108,7 @@ func UpdateLabel(ctx *context.Context, form auth.CreateLabelForm) {
}
l.Name = form.Title
l.Description = form.Description
l.Color = form.Color
if err := models.UpdateLabel(l); err != nil {
ctx.ServerError("UpdateLabel", err)

View File

@ -307,11 +307,7 @@ func Action(ctx *context.Context) {
return
}
redirectTo := ctx.Query("redirect_to")
if len(redirectTo) == 0 {
redirectTo = ctx.Repo.RepoLink
}
ctx.Redirect(redirectTo)
ctx.RedirectToFirst(ctx.Query("redirect_to"), ctx.Repo.RepoLink)
}
// Download download an archive of a repository

View File

@ -29,7 +29,8 @@ func Search(ctx *context.Context) {
if page <= 0 {
page = 1
}
total, searchResults, err := search.PerformSearch(ctx.Repo.Repository.ID, keyword, page, setting.UI.RepoSearchPagingNum)
total, searchResults, err := search.PerformSearch([]int64{ctx.Repo.Repository.ID},
keyword, page, setting.UI.RepoSearchPagingNum)
if err != nil {
ctx.ServerError("SearchResults", err)
return

View File

@ -170,6 +170,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/repos", routers.ExploreRepos)
m.Get("/users", routers.ExploreUsers)
m.Get("/organizations", routers.ExploreOrganizations)
m.Get("/code", routers.ExploreCode)
}, ignSignIn)
m.Combo("/install", routers.InstallInit).Get(routers.Install).
Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost)

View File

@ -93,12 +93,8 @@ func checkAutoLogin(ctx *context.Context) bool {
}
if isSucceed {
if len(redirectTo) > 0 {
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
ctx.Redirect(redirectTo)
} else {
ctx.Redirect(setting.AppSubURL + string(setting.LandingPageURL))
}
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL))
return true
}
@ -350,7 +346,7 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 {
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
if obeyRedirect {
ctx.Redirect(redirectTo)
ctx.RedirectToFirst(redirectTo)
}
return
}
@ -439,7 +435,7 @@ func handleOAuth2SignIn(u *models.User, gothUser goth.User, ctx *context.Context
if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 {
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
ctx.Redirect(redirectTo)
ctx.RedirectToFirst(redirectTo)
return
}

View File

@ -50,12 +50,8 @@ func SignInOpenID(ctx *context.Context) {
}
if isSucceed {
if len(redirectTo) > 0 {
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
ctx.Redirect(redirectTo)
} else {
ctx.Redirect(setting.AppSubURL + "/")
}
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL)
ctx.RedirectToFirst(redirectTo)
return
}

View File

@ -271,9 +271,5 @@ func Action(ctx *context.Context) {
return
}
redirectTo := ctx.Query("redirect_to")
if len(redirectTo) == 0 {
redirectTo = u.HomeLink()
}
ctx.Redirect(redirectTo)
ctx.RedirectToFirst(ctx.Query("redirect_to"), u.HomeLink())
}

View File

@ -0,0 +1,55 @@
{{template "base/head" .}}
<div class="explore users">
{{template "explore/navbar" .}}
<div class="ui container">
<form class="ui form" style="max-width: 100%">
<div class="ui fluid action input">
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus>
<input type="hidden" name="tab" value="{{$.TabName}}">
<button class="ui blue button">{{.i18n.Tr "explore.search"}}</button>
</div>
</form>
<div class="ui divider"></div>
<div class="ui user list">
{{if .SearchResults}}
<h3>
{{.i18n.Tr "explore.code_search_results" (.Keyword|Escape) | Str2html }}
</h3>
<div class="repository search">
{{range $result := .SearchResults}}
{{$repo := (index $.RepoMaps .RepoID)}}
<div class="diff-file-box diff-box file-content non-diff-file-content repo-search-result">
<h4 class="ui top attached normal header">
<span class="file"><a rel="nofollow" href="{{EscapePound $repo.HTMLURL}}">{{$repo.FullName}}</a> - {{.Filename}}</span>
<a class="ui basic grey tiny button" rel="nofollow" href="{{EscapePound $repo.HTMLURL}}/src/branch/{{$repo.DefaultBranch}}/{{EscapePound .Filename}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
</h4>
<div class="ui attached table segment">
<div class="file-body file-code code-view">
<table>
<tbody>
<tr>
<td class="lines-num">
{{range .LineNumbers}}
<a href="{{EscapePound $repo.HTMLURL}}/src/branch/{{$repo.DefaultBranch}}/{{EscapePound $result.Filename}}#L{{.}}"><span>{{.}}</span></a>
{{end}}
</td>
<td class="lines-code"><pre><code class="{{.HighlightClass}}"><ol class="linenums">{{.FormattedLines}}</ol></code></pre></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{{end}}
</div>
{{else}}
<div>{{$.i18n.Tr "explore.code_no_results"}}</div>
{{end}}
</div>
{{template "base/paginate" .}}
</div>
</div>
{{template "base/footer" .}}

View File

@ -8,4 +8,9 @@
<a class="{{if .PageIsExploreOrganizations}}active{{end}} item" href="{{AppSubUrl}}/explore/organizations">
<span class="octicon octicon-organization"></span> {{.i18n.Tr "explore.organizations"}}
</a>
{{if .IsRepoIndexerEnabled}}
<a class="{{if .PageIsExploreCode}}active{{end}} item" href="{{AppSubUrl}}/explore/code">
<span class="octicon octicon-code"></span> {{.i18n.Tr "explore.code"}}
</a>
{{end}}
</div>

View File

@ -14,11 +14,16 @@
<form class="ui form" action="{{$.RepoLink}}/labels/new" method="post">
{{.CsrfTokenHtml}}
<div class="ui grid">
<div class="five wide column">
<div class="three wide column">
<div class="ui small input">
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required>
</div>
</div>
<div class="five wide column">
<div class="ui small fluid input">
<input class="new-label-desc-input" name="description" placeholder="{{.i18n.Tr "repo.issues.new_label_desc_placeholder"}}">
</div>
</div>
<div class="color picker column">
<input class="color-picker" name="color" value="#70c24a" required>
</div>
@ -85,14 +90,27 @@
</div>
{{end}}
<div class="ui divider"></div>
{{range .Labels}}
<li class="item">
<div class="ui label" style="color: {{.ForegroundColor}}; background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div>
{{if $.IsRepositoryWriter}}
<a class="ui right delete-button" href="#" data-url="{{$.RepoLink}}/labels/delete" data-id="{{.ID}}"><i class="octicon octicon-trashcan"></i> {{$.i18n.Tr "repo.issues.label_delete"}}</a>
<a class="ui right edit-label-button" href="#" data-id={{.ID}} data-title={{.Name}} data-color={{.Color}}><i class="octicon octicon-pencil"></i> {{$.i18n.Tr "repo.issues.label_edit"}}</a>
{{end}}
<a class="ui right open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}"><i class="octicon octicon-issue-opened"></i> {{$.i18n.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
<div class="ui grid">
<div class="three wide column">
<div class="ui label" style="color: {{.ForegroundColor}}; background-color: {{.Color}}"><i class="octicon octicon-tag"></i> {{.Name}}</div>
</div>
<div class="seven wide column">
{{.Description}}
</div>
<div class="three wide column">
<a class="ui right open-issues" href="{{$.RepoLink}}/issues?labels={{.ID}}"><i class="octicon octicon-issue-opened"></i> {{$.i18n.Tr "repo.issues.label_open_issues" .NumOpenIssues}}</a>
</div>
<div class="three wide column">
{{if $.IsRepositoryWriter}}
<a class="ui right delete-button" href="#" data-url="{{$.RepoLink}}/labels/delete" data-id="{{.ID}}"><i class="octicon octicon-trashcan"></i> {{$.i18n.Tr "repo.issues.label_delete"}}</a>
<a class="ui right edit-label-button" href="#" data-id="{{.ID}}" data-title="{{.Name}}" data-description="{{.Description}}" data-color={{.Color}}><i class="octicon octicon-pencil"></i> {{$.i18n.Tr "repo.issues.label_edit"}}</a>
{{end}}
</div>
</div>
</li>
{{end}}
</div>
@ -129,11 +147,16 @@
{{.CsrfTokenHtml}}
<input id="label-modal-id" name="id" type="hidden">
<div class="ui grid">
<div class="five wide column">
<div class="three wide column">
<div class="ui small input">
<input class="new-label-input" name="title" placeholder="{{.i18n.Tr "repo.issues.new_label_placeholder"}}" autofocus required>
</div>
</div>
<div class="five wide column">
<div class="ui small fluid input">
<input class="new-label-desc-input" name="description" placeholder="{{.i18n.Tr "repo.issues.new_label_desc_placeholder"}}">
</div>
</div>
<div class="color picker column">
<input class="color-picker" name="color" value="#70c24a" required>
</div>

View File

@ -191,7 +191,7 @@
<a class="ui label" href="{{$.RepoLink}}/src/branch/{{.Ref}}">{{.Ref}}</a>
{{end}}
{{range .Labels}}
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}">{{.Name}}</a>
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
{{end}}
{{if .NumComments}}

View File

@ -37,7 +37,7 @@
<span class="octicon octicon-check"></span>
{{$.i18n.Tr "repo.pulls.can_auto_merge_desc"}}
</div>
{{if .IsRepositoryWriter}}
{{if .AllowMerge}}
{{$prUnit := .Repository.MustGetUnit $.UnitTypePullRequests}}
{{if or $prUnit.PullRequestsConfig.AllowMerge $prUnit.PullRequestsConfig.AllowRebase $prUnit.PullRequestsConfig.AllowSquash}}
<div class="ui divider"></div>

View File

@ -10,7 +10,8 @@
<div class="filter menu" data-action="update" data-issue-id="{{$.Issue.ID}}" data-update-url="{{$.RepoLink}}/issues/labels">
<div class="no-select item">{{.i18n.Tr "repo.issues.new.clear_labels"}}</div>
{{range .Labels}}
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon {{if .IsChecked}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}</a>
<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon {{if .IsChecked}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}
{{if .Description }}<br><small class="desc">{{.Description}}</small>{{end}}</a>
{{end}}
</div>
</div>
@ -18,7 +19,7 @@
<span class="no-select item {{if .HasSelectedLabel}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_label"}}</span>
{{range .Labels}}
<div class="item">
<a class="ui label {{if not .IsChecked}}hide{{end}}" id="label_{{.ID}}" href="{{$.RepoLink}}/issues?labels={{.ID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}">{{.Name}}</a>
<a class="ui label {{if not .IsChecked}}hide{{end}}" id="label_{{.ID}}" href="{{$.RepoLink}}/issues?labels={{.ID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
</div>
{{end}}

View File

@ -71,7 +71,7 @@
especially on mobile views. */}}
<span style="line-height: 2.5">
{{range .}}
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}">{{.Name}}</a>
<a class="ui label" href="{{$.Link}}?q={{$.Keyword}}&type={{$.ViewType}}&state={{$.State}}&labels={{.ID}}&milestone={{$.MilestoneID}}&assignee={{$.AssigneeID}}" style="color: {{.ForegroundColor}}; background-color: {{.Color}}" title="{{.Description}}">{{.Name}}</a>
{{end}}
</span>
{{end}}

View File

@ -132,7 +132,7 @@ func GetAuthURL(res http.ResponseWriter, req *http.Request) (string, error) {
return "", err
}
err = storeInSession(providerName, sess.Marshal(), req, res)
err = StoreInSession(providerName, sess.Marshal(), req, res)
if err != nil {
return "", err
@ -166,7 +166,7 @@ var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.Us
return goth.User{}, err
}
value, err := getFromSession(providerName, req)
value, err := GetFromSession(providerName, req)
if err != nil {
return goth.User{}, err
}
@ -193,7 +193,7 @@ var CompleteUserAuth = func(res http.ResponseWriter, req *http.Request) (goth.Us
return goth.User{}, err
}
err = storeInSession(providerName, sess.Marshal(), req, res)
err = StoreInSession(providerName, sess.Marshal(), req, res)
if err != nil {
return goth.User{}, err
@ -284,8 +284,9 @@ func getProviderName(req *http.Request) (string, error) {
return "", errors.New("you must select a provider")
}
func storeInSession(key string, value string, req *http.Request, res http.ResponseWriter) error {
session, _ := Store.Get(req, SessionName)
// StoreInSession stores a specified key/value pair in the session.
func StoreInSession(key string, value string, req *http.Request, res http.ResponseWriter) error {
session, _ := Store.New(req, SessionName)
if err := updateSessionValue(session, key, value); err != nil {
return err
@ -294,7 +295,9 @@ func storeInSession(key string, value string, req *http.Request, res http.Respon
return session.Save(req, res)
}
func getFromSession(key string, req *http.Request) (string, error) {
// GetFromSession retrieves a previously-stored value from the session.
// If no value has previously been stored at the specified key, it will return an error.
func GetFromSession(key string, req *http.Request) (string, error) {
session, _ := Store.Get(req, SessionName)
value, err := getSessionValue(session, key)
if err != nil {

View File

@ -2,9 +2,11 @@
package dropbox
import (
"bytes"
"encoding/json"
"errors"
"io"
"io/ioutil"
"net/http"
"strings"
@ -25,6 +27,7 @@ type Provider struct {
ClientKey string
Secret string
CallbackURL string
AccountURL string
HTTPClient *http.Client
config *oauth2.Config
providerName string
@ -44,6 +47,7 @@ func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
ClientKey: clientKey,
Secret: secret,
CallbackURL: callbackURL,
AccountURL: accountURL,
providerName: "dropbox",
}
p.config = newConfig(p, scopes)
@ -87,7 +91,7 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
}
req, err := http.NewRequest("POST", accountURL, nil)
req, err := http.NewRequest("POST", p.AccountURL, nil)
if err != nil {
return user, err
}
@ -102,7 +106,17 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, resp.StatusCode)
}
err = userFromReader(resp.Body, &user)
bits, err := ioutil.ReadAll(resp.Body)
if err != nil {
return user, err
}
err = json.NewDecoder(bytes.NewReader(bits)).Decode(&user.RawData)
if err != nil {
return user, err
}
err = userFromReader(bytes.NewReader(bits), &user)
return user, err
}
@ -162,22 +176,29 @@ func newConfig(p *Provider, scopes []string) *oauth2.Config {
func userFromReader(r io.Reader, user *goth.User) error {
u := struct {
Name string `json:"display_name"`
NameDetails struct {
NickName string `json:"familiar_name"`
} `json:"name_details"`
Location string `json:"country"`
Email string `json:"email"`
AccountID string `json:"account_id"`
Name struct {
GivenName string `json:"given_name"`
Surname string `json:"surname"`
DisplayName string `json:"display_name"`
} `json:"name"`
Country string `json:"country"`
Email string `json:"email"`
ProfilePhotoURL string `json:"profile_photo_url"`
}{}
err := json.NewDecoder(r).Decode(&u)
if err != nil {
return err
}
user.UserID = u.AccountID // The user's unique Dropbox ID.
user.FirstName = u.Name.GivenName
user.LastName = u.Name.Surname
user.Name = strings.TrimSpace(fmt.Sprintf("%s %s", u.Name.GivenName, u.Name.Surname))
user.Description = u.Name.DisplayName // Full name plus parenthetical team naem
user.Email = u.Email
user.Name = u.Name
user.NickName = u.NameDetails.NickName
user.UserID = u.Email // Dropbox doesn't provide a separate user ID
user.Location = u.Location
user.NickName = u.Email // Email is the dropbox username
user.Location = u.Country
user.AvatarURL = u.ProfilePhotoURL // May be blank
return nil
}

54
vendor/vendor.json vendored
View File

@ -667,63 +667,73 @@
},
{
"checksumSHA1": "q9MD1ienC+kmKq5i51oAktQEV1E=",
"origin": "github.com/go-gitea/goth",
"path": "github.com/markbates/goth",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "+nosptSgGb2qCAR6CSHV2avwmNg=",
"checksumSHA1": "FISfgOkoMtn98wglLUvfBTZ6baE=",
"origin": "github.com/go-gitea/goth/gothic",
"path": "github.com/markbates/goth/gothic",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "pJ+Cws/TU22K6tZ/ALFOvvH1K5U=",
"origin": "github.com/go-gitea/goth/providers/bitbucket",
"path": "github.com/markbates/goth/providers/bitbucket",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "bKokLof0Pkk5nEhW8NdbfcVzuqk=",
"checksumSHA1": "XsF5HI4240QHbFXbtWWnGgTsoq8=",
"origin": "github.com/go-gitea/goth/providers/dropbox",
"path": "github.com/markbates/goth/providers/dropbox",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "VzbroIA9R00Ig3iGnOlZLU7d4ls=",
"origin": "github.com/go-gitea/goth/providers/facebook",
"path": "github.com/markbates/goth/providers/facebook",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "P6nBZ850aaekpOcoXNdRhK86bH8=",
"origin": "github.com/go-gitea/goth/providers/github",
"path": "github.com/markbates/goth/providers/github",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "ld488t+yGoTwtmiCSSggEX4fxVk=",
"origin": "github.com/go-gitea/goth/providers/gitlab",
"path": "github.com/markbates/goth/providers/gitlab",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "qXEulD7vnwY9hFrxh91Pm5YrvTM=",
"origin": "github.com/go-gitea/goth/providers/gplus",
"path": "github.com/markbates/goth/providers/gplus",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "wsOBzyp4LKDhfCPmX1LLP7T0S3U=",
"origin": "github.com/go-gitea/goth/providers/openidConnect",
"path": "github.com/markbates/goth/providers/openidConnect",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "o6RqMbbE8QNZhNT9TsAIRMPI8tg=",
"origin": "github.com/go-gitea/goth/providers/twitter",
"path": "github.com/markbates/goth/providers/twitter",
"revision": "bc7deaf077a50416cf3a23aa5903d2a7b5a30ada",
"revisionTime": "2018-02-15T02:27:40Z"
"revision": "3b54d96084a5e11030f19556cf68a6ab5d93ba20",
"revisionTime": "2018-03-12T06:32:04Z"
},
{
"checksumSHA1": "61HNjGetaBoMp8HBOpuEZRSim8g=",