github.com/catandhorse/git-lfs@v2.5.2+incompatible/git/version.go (about) 1 package git 2 3 import ( 4 "regexp" 5 "strconv" 6 "sync" 7 8 "github.com/git-lfs/git-lfs/subprocess" 9 "github.com/rubyist/tracerx" 10 ) 11 12 var ( 13 gitVersion *string 14 gitVersionMu sync.Mutex 15 ) 16 17 func Version() (string, error) { 18 gitVersionMu.Lock() 19 defer gitVersionMu.Unlock() 20 21 if gitVersion == nil { 22 v, err := subprocess.SimpleExec("git", "version") 23 gitVersion = &v 24 return v, err 25 } 26 27 return *gitVersion, nil 28 } 29 30 // IsVersionAtLeast returns whether the git version is the one specified or higher 31 // argument is plain version string separated by '.' e.g. "2.3.1" but can omit minor/patch 32 func IsGitVersionAtLeast(ver string) bool { 33 gitver, err := Version() 34 if err != nil { 35 tracerx.Printf("Error getting git version: %v", err) 36 return false 37 } 38 return IsVersionAtLeast(gitver, ver) 39 } 40 41 // IsVersionAtLeast compares 2 version strings (ok to be prefixed with 'git version', ignores) 42 func IsVersionAtLeast(actualVersion, desiredVersion string) bool { 43 // Capture 1-3 version digits, optionally prefixed with 'git version' and possibly 44 // with suffixes which we'll ignore (e.g. unstable builds, MinGW versions) 45 verregex := regexp.MustCompile(`(?:git version\s+)?(\d+)(?:.(\d+))?(?:.(\d+))?.*`) 46 47 var atleast uint64 48 // Support up to 1000 in major/minor/patch digits 49 const majorscale = 1000 * 1000 50 const minorscale = 1000 51 52 if match := verregex.FindStringSubmatch(desiredVersion); match != nil { 53 // Ignore errors as regex won't match anything other than digits 54 major, _ := strconv.Atoi(match[1]) 55 atleast += uint64(major * majorscale) 56 if len(match) > 2 { 57 minor, _ := strconv.Atoi(match[2]) 58 atleast += uint64(minor * minorscale) 59 } 60 if len(match) > 3 { 61 patch, _ := strconv.Atoi(match[3]) 62 atleast += uint64(patch) 63 } 64 } 65 66 var actual uint64 67 if match := verregex.FindStringSubmatch(actualVersion); match != nil { 68 major, _ := strconv.Atoi(match[1]) 69 actual += uint64(major * majorscale) 70 if len(match) > 2 { 71 minor, _ := strconv.Atoi(match[2]) 72 actual += uint64(minor * minorscale) 73 } 74 if len(match) > 3 { 75 patch, _ := strconv.Atoi(match[3]) 76 actual += uint64(patch) 77 } 78 } 79 80 return actual >= atleast 81 }