2014-03-15 20:03:23 +04:00
// Copyright 2014 The Gogs 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 middleware
import (
2014-03-20 08:12:33 +04:00
"fmt"
2014-05-06 03:58:13 +04:00
"net/url"
2015-10-31 19:04:04 +03:00
"path"
2014-03-17 12:47:42 +04:00
"strings"
2014-03-16 10:28:24 +04:00
2015-10-16 04:28:12 +03:00
"gopkg.in/macaron.v1"
2014-03-30 06:09:59 +04:00
2014-03-15 20:03:23 +04:00
"github.com/gogits/gogs/models"
2014-07-26 08:24:27 +04:00
"github.com/gogits/gogs/modules/git"
2014-04-11 08:01:38 +04:00
"github.com/gogits/gogs/modules/log"
2014-05-26 04:11:25 +04:00
"github.com/gogits/gogs/modules/setting"
2014-03-15 20:03:23 +04:00
)
2014-11-13 10:32:18 +03:00
func ApiRepoAssignment ( ) macaron . Handler {
return func ( ctx * Context ) {
userName := ctx . Params ( ":username" )
repoName := ctx . Params ( ":reponame" )
var (
2015-10-31 19:04:04 +03:00
owner * models . User
err error
2014-11-13 10:32:18 +03:00
)
2015-02-13 08:58:46 +03:00
// Check if the user is the same as the repository owner.
2015-02-13 10:14:57 +03:00
if ctx . IsSigned && ctx . User . LowerName == strings . ToLower ( userName ) {
2015-10-31 19:04:04 +03:00
owner = ctx . User
2015-02-05 16:29:08 +03:00
} else {
2015-10-31 19:04:04 +03:00
owner , err = models . GetUserByName ( userName )
2014-11-13 10:32:18 +03:00
if err != nil {
2015-08-05 06:14:17 +03:00
if models . IsErrUserNotExist ( err ) {
2014-11-13 10:32:18 +03:00
ctx . Error ( 404 )
} else {
2015-10-09 03:36:07 +03:00
ctx . APIError ( 500 , "GetUserByName" , err )
2014-11-13 10:32:18 +03:00
}
return
}
}
2015-10-31 19:04:04 +03:00
ctx . Repo . Owner = owner
2014-11-13 10:32:18 +03:00
// Get repository.
2015-10-31 19:04:04 +03:00
repo , err := models . GetRepositoryByName ( owner . Id , repoName )
2014-11-13 10:32:18 +03:00
if err != nil {
2015-03-16 11:04:27 +03:00
if models . IsErrRepoNotExist ( err ) {
2014-11-13 10:32:18 +03:00
ctx . Error ( 404 )
2015-02-05 16:29:08 +03:00
} else {
2015-10-09 03:36:07 +03:00
ctx . APIError ( 500 , "GetRepositoryByName" , err )
2014-11-13 10:32:18 +03:00
}
return
} else if err = repo . GetOwner ( ) ; err != nil {
2015-10-09 03:36:07 +03:00
ctx . APIError ( 500 , "GetOwner" , err )
2014-11-13 10:32:18 +03:00
return
}
2015-02-16 13:51:56 +03:00
mode , err := models . AccessLevel ( ctx . User , repo )
if err != nil {
2015-10-09 03:36:07 +03:00
ctx . APIError ( 500 , "AccessLevel" , err )
2015-02-16 13:51:56 +03:00
return
2014-11-13 10:32:18 +03:00
}
2015-02-16 13:51:56 +03:00
ctx . Repo . AccessMode = mode
2014-11-13 10:32:18 +03:00
// Check access.
2015-02-16 13:51:56 +03:00
if ctx . Repo . AccessMode == models . ACCESS_MODE_NONE {
2015-02-05 16:29:08 +03:00
ctx . Error ( 404 )
return
2014-11-13 10:32:18 +03:00
}
ctx . Repo . Repository = repo
}
}
2014-11-07 06:06:41 +03:00
// RepoRef handles repository reference name including those contain `/`.
func RepoRef ( ) macaron . Handler {
return func ( ctx * Context ) {
2015-11-15 22:05:51 +03:00
// Empty repository does not have reference information.
if ctx . Repo . Repository . IsBare {
return
}
2014-11-07 06:06:41 +03:00
var (
refName string
err error
)
2014-11-17 05:32:26 +03:00
// For API calls.
if ctx . Repo . GitRepo == nil {
repoPath := models . RepoPath ( ctx . Repo . Owner . Name , ctx . Repo . Repository . Name )
gitRepo , err := git . OpenRepository ( repoPath )
if err != nil {
ctx . Handle ( 500 , "RepoRef Invalid repo " + repoPath , err )
return
}
ctx . Repo . GitRepo = gitRepo
}
2014-11-07 06:06:41 +03:00
// Get default branch.
if len ( ctx . Params ( "*" ) ) == 0 {
refName = ctx . Repo . Repository . DefaultBranch
if ! ctx . Repo . GitRepo . IsBranchExist ( refName ) {
brs , err := ctx . Repo . GitRepo . GetBranches ( )
if err != nil {
ctx . Handle ( 500 , "GetBranches" , err )
return
}
refName = brs [ 0 ]
}
ctx . Repo . Commit , err = ctx . Repo . GitRepo . GetCommitOfBranch ( refName )
if err != nil {
ctx . Handle ( 500 , "GetCommitOfBranch" , err )
return
}
2015-11-04 06:49:06 +03:00
ctx . Repo . CommitID = ctx . Repo . Commit . ID . String ( )
2014-11-07 06:06:41 +03:00
ctx . Repo . IsBranch = true
} else {
hasMatched := false
parts := strings . Split ( ctx . Params ( "*" ) , "/" )
for i , part := range parts {
refName = strings . TrimPrefix ( refName + "/" + part , "/" )
if ctx . Repo . GitRepo . IsBranchExist ( refName ) ||
ctx . Repo . GitRepo . IsTagExist ( refName ) {
if i < len ( parts ) - 1 {
ctx . Repo . TreeName = strings . Join ( parts [ i + 1 : ] , "/" )
}
hasMatched = true
break
}
}
if ! hasMatched && len ( parts [ 0 ] ) == 40 {
refName = parts [ 0 ]
ctx . Repo . TreeName = strings . Join ( parts [ 1 : ] , "/" )
}
if ctx . Repo . GitRepo . IsBranchExist ( refName ) {
ctx . Repo . IsBranch = true
ctx . Repo . Commit , err = ctx . Repo . GitRepo . GetCommitOfBranch ( refName )
if err != nil {
ctx . Handle ( 500 , "GetCommitOfBranch" , err )
return
}
2015-11-04 06:49:06 +03:00
ctx . Repo . CommitID = ctx . Repo . Commit . ID . String ( )
2014-11-07 06:06:41 +03:00
} else if ctx . Repo . GitRepo . IsTagExist ( refName ) {
ctx . Repo . IsTag = true
ctx . Repo . Commit , err = ctx . Repo . GitRepo . GetCommitOfTag ( refName )
if err != nil {
ctx . Handle ( 500 , "GetCommitOfTag" , err )
return
}
2015-11-04 06:49:06 +03:00
ctx . Repo . CommitID = ctx . Repo . Commit . ID . String ( )
2014-11-07 06:06:41 +03:00
} else if len ( refName ) == 40 {
ctx . Repo . IsCommit = true
2015-08-31 10:24:28 +03:00
ctx . Repo . CommitID = refName
2014-11-07 06:06:41 +03:00
ctx . Repo . Commit , err = ctx . Repo . GitRepo . GetCommit ( refName )
if err != nil {
ctx . Handle ( 404 , "GetCommit" , nil )
return
}
} else {
ctx . Handle ( 404 , "RepoRef invalid repo" , fmt . Errorf ( "branch or tag not exist: %s" , refName ) )
return
}
}
ctx . Repo . BranchName = refName
ctx . Data [ "BranchName" ] = ctx . Repo . BranchName
2015-08-31 10:24:28 +03:00
ctx . Data [ "CommitID" ] = ctx . Repo . CommitID
2014-11-07 06:06:41 +03:00
ctx . Data [ "IsBranch" ] = ctx . Repo . IsBranch
ctx . Data [ "IsTag" ] = ctx . Repo . IsTag
ctx . Data [ "IsCommit" ] = ctx . Repo . IsCommit
ctx . Repo . CommitsCount , err = ctx . Repo . Commit . CommitsCount ( )
if err != nil {
ctx . Handle ( 500 , "CommitsCount" , err )
return
}
ctx . Data [ "CommitsCount" ] = ctx . Repo . CommitsCount
}
}
2015-09-01 18:43:53 +03:00
func RetrieveBaseRepo ( ctx * Context , repo * models . Repository ) {
// Non-fork repository will not return error in this method.
if err := repo . GetBaseRepo ( ) ; err != nil {
if models . IsErrRepoNotExist ( err ) {
repo . IsFork = false
repo . ForkID = 0
return
}
ctx . Handle ( 500 , "GetBaseRepo" , err )
return
} else if err = repo . BaseRepo . GetOwner ( ) ; err != nil {
ctx . Handle ( 500 , "BaseRepo.GetOwner" , err )
return
}
bsaeRepo := repo . BaseRepo
baseGitRepo , err := git . OpenRepository ( models . RepoPath ( bsaeRepo . Owner . Name , bsaeRepo . Name ) )
if err != nil {
ctx . Handle ( 500 , "OpenRepository" , err )
return
}
if len ( bsaeRepo . DefaultBranch ) > 0 && baseGitRepo . IsBranchExist ( bsaeRepo . DefaultBranch ) {
ctx . Data [ "BaseDefaultBranch" ] = bsaeRepo . DefaultBranch
} else {
baseBranches , err := baseGitRepo . GetBranches ( )
if err != nil {
ctx . Handle ( 500 , "GetBranches" , err )
return
}
if len ( baseBranches ) > 0 {
ctx . Data [ "BaseDefaultBranch" ] = baseBranches [ 0 ]
}
}
}
2014-07-26 08:24:27 +04:00
func RepoAssignment ( redirect bool , args ... bool ) macaron . Handler {
return func ( ctx * Context ) {
2014-08-14 10:12:21 +04:00
var (
displayBare bool // To display bare page if it is a bare repo.
)
2014-03-30 09:30:17 +04:00
if len ( args ) >= 1 {
2014-11-07 06:06:41 +03:00
displayBare = args [ 0 ]
2014-03-30 09:30:17 +04:00
}
2014-03-15 20:03:23 +04:00
var (
2015-10-31 19:04:04 +03:00
owner * models . User
err error
2014-03-15 20:03:23 +04:00
)
2014-07-26 08:24:27 +04:00
userName := ctx . Params ( ":username" )
repoName := ctx . Params ( ":reponame" )
refName := ctx . Params ( ":branchname" )
if len ( refName ) == 0 {
refName = ctx . Params ( ":path" )
}
2014-03-30 06:09:59 +04:00
2015-02-05 16:29:08 +03:00
// Check if the user is the same as the repository owner
2015-02-13 10:14:57 +03:00
if ctx . IsSigned && ctx . User . LowerName == strings . ToLower ( userName ) {
2015-10-31 19:04:04 +03:00
owner = ctx . User
2015-02-05 16:29:08 +03:00
} else {
2015-10-31 19:04:04 +03:00
owner , err = models . GetUserByName ( userName )
2014-03-15 20:03:23 +04:00
if err != nil {
2015-08-05 06:14:17 +03:00
if models . IsErrUserNotExist ( err ) {
2015-02-13 08:58:46 +03:00
ctx . Handle ( 404 , "GetUserByName" , err )
2014-08-14 10:12:21 +04:00
} else {
2015-02-13 08:58:46 +03:00
ctx . Handle ( 500 , "GetUserByName" , err )
2014-03-15 20:03:23 +04:00
}
return
}
}
2015-10-31 19:04:04 +03:00
ctx . Repo . Owner = owner
2014-03-15 20:03:23 +04:00
2014-08-24 17:09:05 +04:00
// Get repository.
2015-10-31 19:04:04 +03:00
repo , err := models . GetRepositoryByName ( owner . Id , repoName )
2014-03-15 20:03:23 +04:00
if err != nil {
2015-03-16 11:04:27 +03:00
if models . IsErrRepoNotExist ( err ) {
2015-02-13 08:58:46 +03:00
ctx . Handle ( 404 , "GetRepositoryByName" , err )
2015-02-05 16:29:08 +03:00
} else {
2015-02-13 08:58:46 +03:00
ctx . Handle ( 500 , "GetRepositoryByName" , err )
2014-03-15 20:03:23 +04:00
}
2014-07-26 08:24:27 +04:00
return
} else if err = repo . GetOwner ( ) ; err != nil {
2015-02-13 08:58:46 +03:00
ctx . Handle ( 500 , "GetOwner" , err )
2014-03-30 06:09:59 +04:00
return
}
2014-04-12 05:47:39 +04:00
2015-11-19 03:49:11 +03:00
// Admin has super access.
2015-11-19 19:40:00 +03:00
if ctx . IsSigned && ctx . User . IsAdmin {
2015-11-19 03:49:11 +03:00
ctx . Repo . AccessMode = models . ACCESS_MODE_OWNER
} else {
mode , err := models . AccessLevel ( ctx . User , repo )
if err != nil {
ctx . Handle ( 500 , "AccessLevel" , err )
return
}
ctx . Repo . AccessMode = mode
2014-05-14 03:26:13 +04:00
}
2014-04-12 05:47:39 +04:00
// Check access.
2015-02-16 13:51:56 +03:00
if ctx . Repo . AccessMode == models . ACCESS_MODE_NONE {
2015-02-13 08:58:46 +03:00
ctx . Handle ( 404 , "no access right" , err )
2015-02-05 16:29:08 +03:00
return
2014-04-12 05:47:39 +04:00
}
ctx . Data [ "HasAccess" ] = true
2014-04-13 06:30:00 +04:00
if repo . IsMirror {
2015-08-08 17:43:14 +03:00
ctx . Repo . Mirror , err = models . GetMirror ( repo . ID )
2014-04-13 06:30:00 +04:00
if err != nil {
2014-07-26 08:24:27 +04:00
ctx . Handle ( 500 , "GetMirror" , err )
2014-04-13 06:30:00 +04:00
return
}
ctx . Data [ "MirrorInterval" ] = ctx . Repo . Mirror . Interval
}
2014-03-30 06:09:59 +04:00
ctx . Repo . Repository = repo
2014-03-30 09:30:17 +04:00
ctx . Data [ "IsBareRepo" ] = ctx . Repo . Repository . IsBare
2014-03-30 06:09:59 +04:00
gitRepo , err := git . OpenRepository ( models . RepoPath ( userName , repoName ) )
if err != nil {
2014-04-11 06:03:31 +04:00
ctx . Handle ( 500 , "RepoAssignment Invalid repo " + models . RepoPath ( userName , repoName ) , err )
2014-03-15 20:03:23 +04:00
return
}
2014-03-30 06:09:59 +04:00
ctx . Repo . GitRepo = gitRepo
2014-10-19 09:35:24 +04:00
ctx . Repo . RepoLink , err = repo . RepoLink ( )
if err != nil {
ctx . Handle ( 500 , "RepoLink" , err )
return
}
2014-08-15 14:29:41 +04:00
ctx . Data [ "RepoLink" ] = ctx . Repo . RepoLink
2015-09-02 12:09:12 +03:00
ctx . Data [ "RepoRelPath" ] = ctx . Repo . Owner . Name + "/" + ctx . Repo . Repository . Name
2014-03-30 07:38:41 +04:00
2014-04-14 05:00:12 +04:00
tags , err := ctx . Repo . GitRepo . GetTags ( )
if err != nil {
2014-07-26 08:24:27 +04:00
ctx . Handle ( 500 , "GetTags" , err )
2014-04-14 05:00:12 +04:00
return
}
2014-09-23 21:47:54 +04:00
ctx . Data [ "Tags" ] = tags
2014-04-14 05:00:12 +04:00
ctx . Repo . Repository . NumTags = len ( tags )
2015-08-08 17:43:14 +03:00
if repo . IsFork {
2015-09-01 18:43:53 +03:00
RetrieveBaseRepo ( ctx , repo )
if ctx . Written ( ) {
2015-08-08 17:43:14 +03:00
return
}
2014-10-19 09:35:24 +04:00
}
2015-10-31 19:04:04 +03:00
ctx . Data [ "Title" ] = owner . Name + "/" + repo . Name
2014-03-30 07:38:41 +04:00
ctx . Data [ "Repository" ] = repo
2014-07-26 08:24:27 +04:00
ctx . Data [ "Owner" ] = ctx . Repo . Repository . Owner
2015-08-14 19:42:43 +03:00
ctx . Data [ "IsRepositoryOwner" ] = ctx . Repo . IsOwner ( )
ctx . Data [ "IsRepositoryAdmin" ] = ctx . Repo . IsAdmin ( )
2014-03-30 07:38:41 +04:00
2015-02-07 18:46:57 +03:00
ctx . Data [ "DisableSSH" ] = setting . DisableSSH
2014-12-14 00:46:00 +03:00
ctx . Repo . CloneLink , err = repo . CloneLink ( )
if err != nil {
ctx . Handle ( 500 , "CloneLink" , err )
return
2014-05-11 19:18:10 +04:00
}
2014-03-30 07:38:41 +04:00
ctx . Data [ "CloneLink" ] = ctx . Repo . CloneLink
2015-10-03 02:58:36 +03:00
if ctx . IsSigned {
ctx . Data [ "IsWatchingRepo" ] = models . IsWatching ( ctx . User . Id , repo . ID )
ctx . Data [ "IsStaringRepo" ] = models . IsStaring ( ctx . User . Id , repo . ID )
}
2014-03-30 09:30:17 +04:00
// repo is bare and display enable
2014-08-11 07:11:18 +04:00
if ctx . Repo . Repository . IsBare {
2014-04-20 06:13:22 +04:00
log . Debug ( "Bare repository: %s" , ctx . Repo . RepoLink )
2014-11-21 02:03:42 +03:00
// NOTE: to prevent templating error
ctx . Data [ "BranchName" ] = ""
2014-08-11 07:11:18 +04:00
if displayBare {
2015-10-03 02:58:36 +03:00
if ! ctx . Repo . IsAdmin ( ) {
ctx . Flash . Info ( ctx . Tr ( "repo.repo_is_empty" ) , true )
}
2014-08-11 07:11:18 +04:00
ctx . HTML ( 200 , "repo/bare" )
}
2014-03-30 09:30:17 +04:00
return
2014-03-30 06:09:59 +04:00
}
2014-03-15 20:03:23 +04:00
2014-06-28 19:56:41 +04:00
ctx . Data [ "TagName" ] = ctx . Repo . TagName
2014-04-13 05:35:36 +04:00
brs , err := ctx . Repo . GitRepo . GetBranches ( )
2014-04-11 08:01:38 +04:00
if err != nil {
2014-09-23 21:47:54 +04:00
ctx . Handle ( 500 , "GetBranches" , err )
return
2014-04-11 08:01:38 +04:00
}
ctx . Data [ "Branches" ] = brs
2014-07-26 08:24:27 +04:00
ctx . Data [ "BrancheCount" ] = len ( brs )
2014-07-22 16:46:04 +04:00
// If not branch selected, try default one.
// If default branch doesn't exists, fall back to some other branch.
2015-08-08 17:43:14 +03:00
if len ( ctx . Repo . BranchName ) == 0 {
if len ( ctx . Repo . Repository . DefaultBranch ) > 0 && gitRepo . IsBranchExist ( ctx . Repo . Repository . DefaultBranch ) {
2014-07-22 16:46:04 +04:00
ctx . Repo . BranchName = ctx . Repo . Repository . DefaultBranch
} else if len ( brs ) > 0 {
ctx . Repo . BranchName = brs [ 0 ]
}
}
ctx . Data [ "BranchName" ] = ctx . Repo . BranchName
2015-08-31 10:24:28 +03:00
ctx . Data [ "CommitID" ] = ctx . Repo . CommitID
2015-08-03 22:27:07 +03:00
2015-10-31 19:04:04 +03:00
if ctx . Query ( "go-get" ) == "1" {
ctx . Data [ "GoGetImport" ] = path . Join ( setting . Domain , setting . AppSubUrl , owner . Name , repo . Name )
prefix := path . Join ( setting . AppUrl , owner . Name , repo . Name , "src" , ctx . Repo . BranchName )
ctx . Data [ "GoDocDirectory" ] = prefix + "{/dir}"
ctx . Data [ "GoDocFile" ] = prefix + "{/dir}/{file}#L{line}"
}
2014-03-15 20:03:23 +04:00
}
}
2014-05-06 03:58:13 +04:00
2015-08-03 12:42:09 +03:00
func RequireRepoAdmin ( ) macaron . Handler {
2014-05-06 03:58:13 +04:00
return func ( ctx * Context ) {
2015-08-14 19:42:43 +03:00
if ! ctx . Repo . IsAdmin ( ) {
2014-05-06 03:58:13 +04:00
if ! ctx . IsSigned {
2014-09-21 16:07:00 +04:00
ctx . SetCookie ( "redirect_to" , "/" + url . QueryEscape ( setting . AppSubUrl + ctx . Req . RequestURI ) , 0 , setting . AppSubUrl )
2014-09-20 04:11:34 +04:00
ctx . Redirect ( setting . AppSubUrl + "/user/login" )
2014-05-06 03:58:13 +04:00
return
}
ctx . Handle ( 404 , ctx . Req . RequestURI , nil )
return
}
}
}
2014-10-07 01:50:00 +04:00
2014-12-07 04:22:48 +03:00
// GitHookService checks if repository Git hooks service has been enabled.
2014-10-07 01:50:00 +04:00
func GitHookService ( ) macaron . Handler {
return func ( ctx * Context ) {
2015-11-04 02:40:52 +03:00
if ! ctx . User . CanEditGitHook ( ) {
2014-10-07 01:50:00 +04:00
ctx . Handle ( 404 , "GitHookService" , nil )
return
}
}
}