@@ -756,19 +756,11 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
756756type RepoRefType int
757757
758758const (
759- // RepoRefLegacy unknown type, make educated guess and redirect.
760- // for backward compatibility with previous URL scheme
761- RepoRefLegacy RepoRefType = iota
762- // RepoRefAny is for usage where educated guess is needed
763- // but redirect can not be made
764- RepoRefAny
765- // RepoRefBranch branch
759+ // RepoRefUnknown is for legacy support, makes the code to "guess" the ref type
760+ RepoRefUnknown RepoRefType = iota
766761 RepoRefBranch
767- // RepoRefTag tag
768762 RepoRefTag
769- // RepoRefCommit commit
770763 RepoRefCommit
771- // RepoRefBlob blob
772764 RepoRefBlob
773765)
774766
@@ -781,22 +773,6 @@ func RepoRef() func(*Context) context.CancelFunc {
781773 return RepoRefByType (RepoRefBranch )
782774}
783775
784- // RefTypeIncludesBranches returns true if ref type can be a branch
785- func (rt RepoRefType ) RefTypeIncludesBranches () bool {
786- if rt == RepoRefLegacy || rt == RepoRefAny || rt == RepoRefBranch {
787- return true
788- }
789- return false
790- }
791-
792- // RefTypeIncludesTags returns true if ref type can be a tag
793- func (rt RepoRefType ) RefTypeIncludesTags () bool {
794- if rt == RepoRefLegacy || rt == RepoRefAny || rt == RepoRefTag {
795- return true
796- }
797- return false
798- }
799-
800776func getRefNameFromPath (repo * Repository , path string , isExist func (string ) bool ) string {
801777 refName := ""
802778 parts := strings .Split (path , "/" )
@@ -810,28 +786,49 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
810786 return ""
811787}
812788
789+ func isStringLikelyCommitID (objFmt git.ObjectFormat , s string , minLength ... int ) bool {
790+ minLen := util .OptionalArg (minLength , objFmt .FullLength ())
791+ if len (s ) < minLen || len (s ) > objFmt .FullLength () {
792+ return false
793+ }
794+ for _ , c := range s {
795+ isHex := (c >= '0' && c <= '9' ) || (c >= 'a' && c <= 'f' )
796+ if ! isHex {
797+ return false
798+ }
799+ }
800+ return true
801+ }
802+
803+ func getRefNameLegacy (ctx * Base , repo * Repository , optionalExtraRef ... string ) (string , RepoRefType ) {
804+ extraRef := util .OptionalArg (optionalExtraRef )
805+ reqPath := ctx .PathParam ("*" )
806+ reqPath = path .Join (extraRef , reqPath )
807+
808+ if refName := getRefName (ctx , repo , RepoRefBranch ); refName != "" {
809+ return refName , RepoRefBranch
810+ }
811+ if refName := getRefName (ctx , repo , RepoRefTag ); refName != "" {
812+ return refName , RepoRefTag
813+ }
814+
815+ // For legacy support only full commit sha
816+ parts := strings .Split (reqPath , "/" )
817+ if isStringLikelyCommitID (git .ObjectFormatFromName (repo .Repository .ObjectFormatName ), parts [0 ]) {
818+ repo .TreePath = strings .Join (parts [1 :], "/" )
819+ return parts [0 ], RepoRefCommit
820+ }
821+
822+ if refName := getRefName (ctx , repo , RepoRefBlob ); len (refName ) > 0 {
823+ return refName , RepoRefBlob
824+ }
825+ repo .TreePath = reqPath
826+ return repo .Repository .DefaultBranch , RepoRefBranch
827+ }
828+
813829func getRefName (ctx * Base , repo * Repository , pathType RepoRefType ) string {
814830 path := ctx .PathParam ("*" )
815831 switch pathType {
816- case RepoRefLegacy , RepoRefAny :
817- if refName := getRefName (ctx , repo , RepoRefBranch ); len (refName ) > 0 {
818- return refName
819- }
820- if refName := getRefName (ctx , repo , RepoRefTag ); len (refName ) > 0 {
821- return refName
822- }
823- // For legacy and API support only full commit sha
824- parts := strings .Split (path , "/" )
825-
826- if len (parts ) > 0 && len (parts [0 ]) == git .ObjectFormatFromName (repo .Repository .ObjectFormatName ).FullLength () {
827- repo .TreePath = strings .Join (parts [1 :], "/" )
828- return parts [0 ]
829- }
830- if refName := getRefName (ctx , repo , RepoRefBlob ); len (refName ) > 0 {
831- return refName
832- }
833- repo .TreePath = path
834- return repo .Repository .DefaultBranch
835832 case RepoRefBranch :
836833 ref := getRefNameFromPath (repo , path , repo .GitRepo .IsBranchExist )
837834 if len (ref ) == 0 {
@@ -867,12 +864,12 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
867864 case RepoRefCommit :
868865 parts := strings .Split (path , "/" )
869866
870- if len ( parts ) > 0 && len ( parts [ 0 ]) >= 7 && len ( parts [0 ]) <= repo . GetObjectFormat (). FullLength ( ) {
867+ if isStringLikelyCommitID ( repo . GetObjectFormat (), parts [0 ], 7 ) {
871868 repo .TreePath = strings .Join (parts [1 :], "/" )
872869 return parts [0 ]
873870 }
874871
875- if len ( parts ) > 0 && parts [0 ] == headRefName {
872+ if parts [0 ] == headRefName {
876873 // HEAD ref points to last default branch commit
877874 commit , err := repo .GitRepo .GetBranchCommit (repo .Repository .DefaultBranch )
878875 if err != nil {
@@ -888,14 +885,19 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
888885 }
889886 return path
890887 default :
891- log . Error ("Unrecognized path type: %v" , path )
888+ panic ( fmt . Sprintf ("Unrecognized path type: %v" , pathType ) )
892889 }
893890 return ""
894891}
895892
893+ type RepoRefByTypeOptions struct {
894+ IgnoreNotExistErr bool
895+ }
896+
896897// RepoRefByType handles repository reference name for a specific type
897898// of repository reference
898- func RepoRefByType (refType RepoRefType , ignoreNotExistErr ... bool ) func (* Context ) context.CancelFunc {
899+ func RepoRefByType (refType RepoRefType , opts ... RepoRefByTypeOptions ) func (* Context ) context.CancelFunc {
900+ opt := util .OptionalArg (opts )
899901 return func (ctx * Context ) (cancel context.CancelFunc ) {
900902 // Empty repository does not have reference information.
901903 if ctx .Repo .Repository .IsEmpty {
@@ -956,7 +958,12 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
956958 }
957959 ctx .Repo .IsViewBranch = true
958960 } else {
959- refName = getRefName (ctx .Base , ctx .Repo , refType )
961+ guessLegacyPath := refType == RepoRefUnknown
962+ if guessLegacyPath {
963+ refName , refType = getRefNameLegacy (ctx .Base , ctx .Repo )
964+ } else {
965+ refName = getRefName (ctx .Base , ctx .Repo , refType )
966+ }
960967 ctx .Repo .RefName = refName
961968 isRenamedBranch , has := ctx .Data ["IsRenamedBranch" ].(bool )
962969 if isRenamedBranch && has {
@@ -967,7 +974,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
967974 return cancel
968975 }
969976
970- if refType . RefTypeIncludesBranches () && ctx .Repo .GitRepo .IsBranchExist (refName ) {
977+ if refType == RepoRefBranch && ctx .Repo .GitRepo .IsBranchExist (refName ) {
971978 ctx .Repo .IsViewBranch = true
972979 ctx .Repo .BranchName = refName
973980
@@ -977,7 +984,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
977984 return cancel
978985 }
979986 ctx .Repo .CommitID = ctx .Repo .Commit .ID .String ()
980- } else if refType . RefTypeIncludesTags () && ctx .Repo .GitRepo .IsTagExist (refName ) {
987+ } else if refType == RepoRefTag && ctx .Repo .GitRepo .IsTagExist (refName ) {
981988 ctx .Repo .IsViewTag = true
982989 ctx .Repo .TagName = refName
983990
@@ -991,7 +998,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
991998 return cancel
992999 }
9931000 ctx .Repo .CommitID = ctx .Repo .Commit .ID .String ()
994- } else if len ( refName ) >= 7 && len ( refName ) <= ctx .Repo .GetObjectFormat (). FullLength ( ) {
1001+ } else if isStringLikelyCommitID ( ctx .Repo .GetObjectFormat (), refName , 7 ) {
9951002 ctx .Repo .IsViewCommit = true
9961003 ctx .Repo .CommitID = refName
9971004
@@ -1006,14 +1013,14 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
10061013 util .URLJoin (setting .AppURL , strings .Replace (ctx .Req .URL .RequestURI (), util .PathEscapeSegments (refName ), url .PathEscape (ctx .Repo .Commit .ID .String ()), 1 ))))
10071014 }
10081015 } else {
1009- if len ( ignoreNotExistErr ) > 0 && ignoreNotExistErr [ 0 ] {
1016+ if opt . IgnoreNotExistErr {
10101017 return cancel
10111018 }
10121019 ctx .NotFound ("RepoRef invalid repo" , fmt .Errorf ("branch or tag not exist: %s" , refName ))
10131020 return cancel
10141021 }
10151022
1016- if refType == RepoRefLegacy {
1023+ if guessLegacyPath {
10171024 // redirect from old URL scheme to new URL scheme
10181025 prefix := strings .TrimPrefix (setting .AppSubURL + strings .ToLower (strings .TrimSuffix (ctx .Req .URL .Path , ctx .PathParam ("*" ))), strings .ToLower (ctx .Repo .RepoLink ))
10191026 redirect := path .Join (
0 commit comments