2016-11-04 01:16:01 +03:00
// Copyright 2015 The Gogs Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2016-11-04 01:16:01 +03:00
package git
import (
"fmt"
2020-12-17 17:00:47 +03:00
"io"
2016-11-04 01:16:01 +03:00
"os"
2019-10-16 16:42:42 +03:00
"strconv"
2016-11-04 01:16:01 +03:00
"strings"
"sync"
2021-11-16 21:18:25 +03:00
"code.gitea.io/gitea/modules/util"
2016-11-04 01:16:01 +03:00
)
2021-07-08 14:38:13 +03:00
// ObjectCache provides thread-safe cache operations.
2016-12-22 12:30:52 +03:00
type ObjectCache struct {
2016-11-04 01:16:01 +03:00
lock sync . RWMutex
cache map [ string ] interface { }
}
2016-12-22 12:30:52 +03:00
func newObjectCache ( ) * ObjectCache {
return & ObjectCache {
2016-11-04 01:16:01 +03:00
cache : make ( map [ string ] interface { } , 10 ) ,
}
}
2016-12-22 12:30:52 +03:00
// Set add obj to cache
func ( oc * ObjectCache ) Set ( id string , obj interface { } ) {
2016-11-04 01:16:01 +03:00
oc . lock . Lock ( )
defer oc . lock . Unlock ( )
oc . cache [ id ] = obj
}
2016-12-22 12:30:52 +03:00
// Get get cached obj by id
func ( oc * ObjectCache ) Get ( id string ) ( interface { } , bool ) {
2016-11-04 01:16:01 +03:00
oc . lock . RLock ( )
defer oc . lock . RUnlock ( )
obj , has := oc . cache [ id ]
return obj , has
}
// isDir returns true if given path is a directory,
// or returns false when it's a file or does not exist.
func isDir ( dir string ) bool {
f , e := os . Stat ( dir )
if e != nil {
return false
}
return f . IsDir ( )
}
// isFile returns true if given path is a file,
// or returns false when it's a directory or does not exist.
func isFile ( filePath string ) bool {
f , e := os . Stat ( filePath )
if e != nil {
return false
}
return ! f . IsDir ( )
}
// isExist checks whether a file or directory exists.
// It returns false when the file or directory does not exist.
func isExist ( path string ) bool {
_ , err := os . Stat ( path )
return err == nil || os . IsExist ( err )
}
2020-12-17 17:00:47 +03:00
// ConcatenateError concatenats an error with stderr string
func ConcatenateError ( err error , stderr string ) error {
2016-11-04 01:16:01 +03:00
if len ( stderr ) == 0 {
return err
}
2020-12-17 17:00:47 +03:00
return fmt . Errorf ( "%w - %s" , err , stderr )
2016-11-04 01:16:01 +03:00
}
2016-12-22 12:30:52 +03:00
// RefEndName return the end name of a ref name
2016-11-04 01:16:01 +03:00
func RefEndName ( refStr string ) string {
2016-12-22 12:30:52 +03:00
if strings . HasPrefix ( refStr , BranchPrefix ) {
return refStr [ len ( BranchPrefix ) : ]
2016-11-04 01:16:01 +03:00
}
2016-12-22 12:30:52 +03:00
if strings . HasPrefix ( refStr , TagPrefix ) {
return refStr [ len ( TagPrefix ) : ]
2016-11-04 01:16:01 +03:00
}
return refStr
}
2019-10-16 16:42:42 +03:00
2020-05-15 01:55:43 +03:00
// RefURL returns the absolute URL for a ref in a repository
func RefURL ( repoURL , ref string ) string {
2021-11-16 21:18:25 +03:00
refName := util . PathEscapeSegments ( RefEndName ( ref ) )
2020-05-15 01:55:43 +03:00
switch {
case strings . HasPrefix ( ref , BranchPrefix ) :
return repoURL + "/src/branch/" + refName
case strings . HasPrefix ( ref , TagPrefix ) :
return repoURL + "/src/tag/" + refName
2022-11-22 15:58:49 +03:00
case ! IsValidSHAPattern ( ref ) :
// assume they mean a branch
return repoURL + "/src/branch/" + refName
2020-05-15 01:55:43 +03:00
default :
return repoURL + "/src/commit/" + refName
}
}
2019-11-24 08:16:59 +03:00
// SplitRefName splits a full refname to reftype and simple refname
func SplitRefName ( refStr string ) ( string , string ) {
if strings . HasPrefix ( refStr , BranchPrefix ) {
return BranchPrefix , refStr [ len ( BranchPrefix ) : ]
}
if strings . HasPrefix ( refStr , TagPrefix ) {
return TagPrefix , refStr [ len ( TagPrefix ) : ]
}
return "" , refStr
}
2019-10-16 16:42:42 +03:00
// ParseBool returns the boolean value represented by the string as per git's git_config_bool
// true will be returned for the result if the string is empty, but valid will be false.
// "true", "yes", "on" are all true, true
// "false", "no", "off" are all false, true
// 0 is false, true
// Any other integer is true, true
// Anything else will return false, false
2021-12-20 07:41:31 +03:00
func ParseBool ( value string ) ( result , valid bool ) {
2019-10-16 16:42:42 +03:00
// Empty strings are true but invalid
if len ( value ) == 0 {
return true , false
}
// These are the git expected true and false values
if strings . EqualFold ( value , "true" ) || strings . EqualFold ( value , "yes" ) || strings . EqualFold ( value , "on" ) {
return true , true
}
if strings . EqualFold ( value , "false" ) || strings . EqualFold ( value , "no" ) || strings . EqualFold ( value , "off" ) {
return false , true
}
// Try a number
intValue , err := strconv . ParseInt ( value , 10 , 32 )
if err != nil {
return false , false
}
return intValue != 0 , true
}
2020-12-17 17:00:47 +03:00
// LimitedReaderCloser is a limited reader closer
type LimitedReaderCloser struct {
R io . Reader
C io . Closer
N int64
}
// Read implements io.Reader
func ( l * LimitedReaderCloser ) Read ( p [ ] byte ) ( n int , err error ) {
if l . N <= 0 {
_ = l . C . Close ( )
return 0 , io . EOF
}
if int64 ( len ( p ) ) > l . N {
p = p [ 0 : l . N ]
}
n , err = l . R . Read ( p )
l . N -= int64 ( n )
2022-06-20 13:02:49 +03:00
return n , err
2020-12-17 17:00:47 +03:00
}
// Close implements io.Closer
func ( l * LimitedReaderCloser ) Close ( ) error {
return l . C . Close ( )
}