github.com/bhameyie/otto@v0.2.1-0.20160406174117-16052efa52ec/builtin/app/ruby/ruby_version.go (about) 1 package rubyapp 2 3 import ( 4 "bufio" 5 "fmt" 6 "log" 7 "os" 8 "path/filepath" 9 "regexp" 10 11 "github.com/hashicorp/otto/helper/oneline" 12 ) 13 14 var rubyVersionGemfileRegexp = regexp.MustCompile(`ruby\s+['"]([.\d]+)['"]`) 15 16 // detectRubyVersion attempts to detect the Ruby version that needs to 17 // be installed by inspecting the environment (Gemfile, .ruby-version, etc.). 18 func detectRubyVersion(dir string) (result string, err error) { 19 log.Printf("[DEBUG] ruby: Attempting to detect Ruby version for: %s", dir) 20 21 // .ruby-version 22 result, err = detectRubyVersionFile(dir) 23 if result != "" || err != nil { 24 return 25 } 26 27 // Gemfile 28 result, err = detectRubyVersionGemfile(dir) 29 if result != "" || err != nil { 30 return 31 } 32 33 // No version detected 34 return "", nil 35 } 36 37 func detectRubyVersionFile(dir string) (result string, err error) { 38 path := filepath.Join(dir, ".ruby-version") 39 40 // Verify the .ruby-version exists 41 if _, err = os.Stat(path); err != nil { 42 if os.IsNotExist(err) { 43 log.Printf("[DEBUG] ruby: .ruby-version not found, will not detect Ruby version this way") 44 err = nil 45 } 46 47 return 48 } 49 50 log.Printf("[DEBUG] ruby: .ruby-version found! Attempting to detect Ruby version") 51 52 // Read the first line of the file 53 result, err = oneline.Read(path) 54 log.Printf("[DEBUG] ruby: .ruby-version detected Ruby: %q", result) 55 return 56 } 57 58 func detectRubyVersionGemfile(dir string) (result string, err error) { 59 path := filepath.Join(dir, "Gemfile") 60 61 // Verify the Gemfile exists 62 if _, err = os.Stat(path); err != nil { 63 if os.IsNotExist(err) { 64 log.Printf("[DEBUG] ruby: Gemfile not found, will not detect Ruby version this way") 65 err = nil 66 } 67 68 return 69 } 70 71 log.Printf("[DEBUG] ruby: Gemfile found! Attempting to detect Ruby version") 72 73 // Open our file. We wrap the reader in a bufio so we can do a 74 // streaming regexp 75 f, err := os.Open(path) 76 if err != nil { 77 return 78 } 79 defer f.Close() 80 81 // Try to find a direct match. 82 idx := rubyVersionGemfileRegexp.FindReaderSubmatchIndex(bufio.NewReader(f)) 83 if idx == nil { 84 log.Printf("[DEBUG] ruby: Gemfile has no 'ruby' declaration, no version found") 85 return 86 } 87 88 // Seek to the left of the first submatch 89 if _, err = f.Seek(int64(idx[2]), 0); err != nil { 90 return 91 } 92 93 resultBytes := make([]byte, idx[3]-idx[2]) 94 n, err := f.Read(resultBytes) 95 if err != nil { 96 return 97 } 98 if n != len(resultBytes) { 99 err = fmt.Errorf("failed to read proper amount of bytes for Ruby version") 100 return 101 } 102 103 result = string(resultBytes) 104 log.Printf("[DEBUG] ruby: Gemfile detected Ruby: %q", result) 105 return 106 }