@@ -756,19 +756,11 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
756
756
type RepoRefType int
757
757
758
758
const (
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
766
761
RepoRefBranch
767
- // RepoRefTag tag
768
762
RepoRefTag
769
- // RepoRefCommit commit
770
763
RepoRefCommit
771
- // RepoRefBlob blob
772
764
RepoRefBlob
773
765
)
774
766
@@ -781,22 +773,6 @@ func RepoRef() func(*Context) context.CancelFunc {
781
773
return RepoRefByType (RepoRefBranch )
782
774
}
783
775
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
-
800
776
func getRefNameFromPath (repo * Repository , path string , isExist func (string ) bool ) string {
801
777
refName := ""
802
778
parts := strings .Split (path , "/" )
@@ -810,28 +786,50 @@ func getRefNameFromPath(repo *Repository, path string, isExist func(string) bool
810
786
return ""
811
787
}
812
788
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
+ // FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
819
+ repo .TreePath = strings .Join (parts [1 :], "/" )
820
+ return parts [0 ], RepoRefCommit
821
+ }
822
+
823
+ if refName := getRefName (ctx , repo , RepoRefBlob ); len (refName ) > 0 {
824
+ return refName , RepoRefBlob
825
+ }
826
+ repo .TreePath = reqPath
827
+ return repo .Repository .DefaultBranch , RepoRefBranch
828
+ }
829
+
813
830
func getRefName (ctx * Base , repo * Repository , pathType RepoRefType ) string {
814
831
path := ctx .PathParam ("*" )
815
832
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
835
833
case RepoRefBranch :
836
834
ref := getRefNameFromPath (repo , path , repo .GitRepo .IsBranchExist )
837
835
if len (ref ) == 0 {
@@ -866,13 +864,13 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
866
864
return getRefNameFromPath (repo , path , repo .GitRepo .IsTagExist )
867
865
case RepoRefCommit :
868
866
parts := strings .Split (path , "/" )
869
-
870
- if len ( parts ) > 0 && len ( parts [ 0 ]) >= 7 && len ( parts [ 0 ]) <= repo . GetObjectFormat (). FullLength () {
867
+ if isStringLikelyCommitID ( repo . GetObjectFormat (), parts [ 0 ], 7 ) {
868
+ // FIXME: this logic is different from other types. Ideally, it should also try to GetCommit to check if it exists
871
869
repo .TreePath = strings .Join (parts [1 :], "/" )
872
870
return parts [0 ]
873
871
}
874
872
875
- if len ( parts ) > 0 && parts [0 ] == headRefName {
873
+ if parts [0 ] == headRefName {
876
874
// HEAD ref points to last default branch commit
877
875
commit , err := repo .GitRepo .GetBranchCommit (repo .Repository .DefaultBranch )
878
876
if err != nil {
@@ -888,15 +886,21 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string {
888
886
}
889
887
return path
890
888
default :
891
- log . Error ("Unrecognized path type: %v" , path )
889
+ panic ( fmt . Sprintf ("Unrecognized path type: %v" , pathType ) )
892
890
}
893
891
return ""
894
892
}
895
893
894
+ type RepoRefByTypeOptions struct {
895
+ IgnoreNotExistErr bool
896
+ }
897
+
896
898
// RepoRefByType handles repository reference name for a specific type
897
899
// of repository reference
898
- func RepoRefByType (refType RepoRefType , ignoreNotExistErr ... bool ) func (* Context ) context.CancelFunc {
900
+ func RepoRefByType (detectRefType RepoRefType , opts ... RepoRefByTypeOptions ) func (* Context ) context.CancelFunc {
901
+ opt := util .OptionalArg (opts )
899
902
return func (ctx * Context ) (cancel context.CancelFunc ) {
903
+ refType := detectRefType
900
904
// Empty repository does not have reference information.
901
905
if ctx .Repo .Repository .IsEmpty {
902
906
// assume the user is viewing the (non-existent) default branch
@@ -956,7 +960,12 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
956
960
}
957
961
ctx .Repo .IsViewBranch = true
958
962
} else {
959
- refName = getRefName (ctx .Base , ctx .Repo , refType )
963
+ guessLegacyPath := refType == RepoRefUnknown
964
+ if guessLegacyPath {
965
+ refName , refType = getRefNameLegacy (ctx .Base , ctx .Repo )
966
+ } else {
967
+ refName = getRefName (ctx .Base , ctx .Repo , refType )
968
+ }
960
969
ctx .Repo .RefName = refName
961
970
isRenamedBranch , has := ctx .Data ["IsRenamedBranch" ].(bool )
962
971
if isRenamedBranch && has {
@@ -967,7 +976,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
967
976
return cancel
968
977
}
969
978
970
- if refType . RefTypeIncludesBranches () && ctx .Repo .GitRepo .IsBranchExist (refName ) {
979
+ if refType == RepoRefBranch && ctx .Repo .GitRepo .IsBranchExist (refName ) {
971
980
ctx .Repo .IsViewBranch = true
972
981
ctx .Repo .BranchName = refName
973
982
@@ -977,7 +986,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
977
986
return cancel
978
987
}
979
988
ctx .Repo .CommitID = ctx .Repo .Commit .ID .String ()
980
- } else if refType . RefTypeIncludesTags () && ctx .Repo .GitRepo .IsTagExist (refName ) {
989
+ } else if refType == RepoRefTag && ctx .Repo .GitRepo .IsTagExist (refName ) {
981
990
ctx .Repo .IsViewTag = true
982
991
ctx .Repo .TagName = refName
983
992
@@ -991,7 +1000,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
991
1000
return cancel
992
1001
}
993
1002
ctx .Repo .CommitID = ctx .Repo .Commit .ID .String ()
994
- } else if len ( refName ) >= 7 && len ( refName ) <= ctx .Repo .GetObjectFormat (). FullLength ( ) {
1003
+ } else if isStringLikelyCommitID ( ctx .Repo .GetObjectFormat (), refName , 7 ) {
995
1004
ctx .Repo .IsViewCommit = true
996
1005
ctx .Repo .CommitID = refName
997
1006
@@ -1006,14 +1015,14 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
1006
1015
util .URLJoin (setting .AppURL , strings .Replace (ctx .Req .URL .RequestURI (), util .PathEscapeSegments (refName ), url .PathEscape (ctx .Repo .Commit .ID .String ()), 1 ))))
1007
1016
}
1008
1017
} else {
1009
- if len ( ignoreNotExistErr ) > 0 && ignoreNotExistErr [ 0 ] {
1018
+ if opt . IgnoreNotExistErr {
1010
1019
return cancel
1011
1020
}
1012
1021
ctx .NotFound ("RepoRef invalid repo" , fmt .Errorf ("branch or tag not exist: %s" , refName ))
1013
1022
return cancel
1014
1023
}
1015
1024
1016
- if refType == RepoRefLegacy {
1025
+ if guessLegacyPath {
1017
1026
// redirect from old URL scheme to new URL scheme
1018
1027
prefix := strings .TrimPrefix (setting .AppSubURL + strings .ToLower (strings .TrimSuffix (ctx .Req .URL .Path , ctx .PathParam ("*" ))), strings .ToLower (ctx .Repo .RepoLink ))
1019
1028
redirect := path .Join (
0 commit comments