github.com/suzuken/ghq@v0.7.5-0.20160607064937-214ded0f64ec/git.go (about)

     1  package main
     2  
     3  import (
     4  	"os"
     5  	"os/exec"
     6  	"regexp"
     7  	"strconv"
     8  	"strings"
     9  	"syscall"
    10  
    11  	"github.com/motemen/ghq/utils"
    12  )
    13  
    14  // GitConfigSingle fetches single git-config variable.
    15  // returns an empty string and no error if no variable is found with the given key.
    16  func GitConfigSingle(key string) (string, error) {
    17  	return GitConfig("--get", key)
    18  }
    19  
    20  // GitConfigAll fetches git-config variable of multiple values.
    21  func GitConfigAll(key string) ([]string, error) {
    22  	value, err := GitConfig("--get-all", key)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	// No results found, return an empty slice
    28  	if value == "" {
    29  		return nil, nil
    30  	}
    31  
    32  	return strings.Split(value, "\000"), nil
    33  }
    34  
    35  // GitConfig invokes 'git config' and handles some errors properly.
    36  func GitConfig(args ...string) (string, error) {
    37  	gitArgs := append([]string{"config", "--path", "--null"}, args...)
    38  	cmd := exec.Command("git", gitArgs...)
    39  	cmd.Stderr = os.Stderr
    40  
    41  	buf, err := cmd.Output()
    42  
    43  	if exitError, ok := err.(*exec.ExitError); ok {
    44  		if waitStatus, ok := exitError.Sys().(syscall.WaitStatus); ok {
    45  			if waitStatus.ExitStatus() == 1 {
    46  				// The key was not found, do not treat as an error
    47  				return "", nil
    48  			}
    49  		}
    50  
    51  		return "", err
    52  	}
    53  
    54  	return strings.TrimRight(string(buf), "\000"), nil
    55  }
    56  
    57  var versionRx = regexp.MustCompile(`(\d+)\.(\d+)\.(\d+)`)
    58  
    59  var featureConfigURLMatchVersion = []uint{1, 8, 5}
    60  
    61  func GitHasFeatureConfigURLMatch() bool {
    62  	cmd := exec.Command("git", "--version")
    63  	buf, err := cmd.Output()
    64  
    65  	if err != nil {
    66  		return false
    67  	}
    68  
    69  	return gitVersionOutputSatisfies(string(buf), featureConfigURLMatchVersion)
    70  }
    71  
    72  func gitVersionOutputSatisfies(gitVersionOutput string, baseVersionParts []uint) bool {
    73  	versionStrings := versionRx.FindStringSubmatch(gitVersionOutput)
    74  	if versionStrings == nil {
    75  		return false
    76  	}
    77  
    78  	for i, v := range baseVersionParts {
    79  		thisV64, err := strconv.ParseUint(versionStrings[i+1], 10, 0)
    80  		utils.PanicIf(err)
    81  
    82  		thisV := uint(thisV64)
    83  
    84  		if thisV > v {
    85  			return true
    86  		} else if v == thisV {
    87  			continue
    88  		} else {
    89  			return false
    90  		}
    91  	}
    92  
    93  	return true
    94  }