github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/misc/ios/detect.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build ignore 6 7 // detect attempts to autodetect the correct 8 // values of the environment variables 9 // used by go_darwin_arm_exec. 10 // detect shells out to ideviceinfo, a third party program that can 11 // be obtained by following the instructions at 12 // https://github.com/libimobiledevice/libimobiledevice. 13 package main 14 15 import ( 16 "bytes" 17 "fmt" 18 "io/ioutil" 19 "os" 20 "os/exec" 21 "strings" 22 ) 23 24 func main() { 25 devID := detectDevID() 26 fmt.Printf("export GOIOS_DEV_ID=%s\n", devID) 27 28 udid := detectUDID() 29 mp := detectMobileProvisionFile(udid) 30 31 f, err := ioutil.TempFile("", "go_ios_detect_") 32 check(err) 33 fname := f.Name() 34 defer os.Remove(fname) 35 36 out := combinedOutput(parseMobileProvision(mp)) 37 _, err = f.Write(out) 38 check(err) 39 check(f.Close()) 40 41 appID, err := plistExtract(fname, "ApplicationIdentifierPrefix:0") 42 check(err) 43 fmt.Printf("export GOIOS_APP_ID=%s\n", appID) 44 45 teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier") 46 check(err) 47 fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID) 48 } 49 50 func detectDevID() string { 51 cmd := exec.Command("security", "find-identity", "-p", "codesigning", "-v") 52 lines := getLines(cmd) 53 54 for _, line := range lines { 55 if !bytes.Contains(line, []byte("iPhone Developer")) { 56 continue 57 } 58 fields := bytes.Fields(line) 59 return string(fields[1]) 60 } 61 fail("no code signing identity found") 62 panic("unreachable") 63 } 64 65 var udidPrefix = []byte("UniqueDeviceID: ") 66 67 func detectUDID() []byte { 68 cmd := exec.Command("ideviceinfo") 69 lines := getLines(cmd) 70 for _, line := range lines { 71 if bytes.HasPrefix(line, udidPrefix) { 72 return bytes.TrimPrefix(line, udidPrefix) 73 } 74 } 75 fail("udid not found; is the device connected?") 76 panic("unreachable") 77 } 78 79 func detectMobileProvisionFile(udid []byte) string { 80 cmd := exec.Command("mdfind", "-name", ".mobileprovision") 81 lines := getLines(cmd) 82 83 for _, line := range lines { 84 if len(line) == 0 { 85 continue 86 } 87 xmlLines := getLines(parseMobileProvision(string(line))) 88 for _, xmlLine := range xmlLines { 89 if bytes.Contains(xmlLine, udid) { 90 return string(line) 91 } 92 } 93 } 94 fail("did not find mobile provision matching device udid %s", udid) 95 panic("ureachable") 96 } 97 98 func parseMobileProvision(fname string) *exec.Cmd { 99 return exec.Command("security", "cms", "-D", "-i", string(fname)) 100 } 101 102 func plistExtract(fname string, path string) ([]byte, error) { 103 out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput() 104 if err != nil { 105 return nil, err 106 } 107 return bytes.TrimSpace(out), nil 108 } 109 110 func getLines(cmd *exec.Cmd) [][]byte { 111 out := combinedOutput(cmd) 112 return bytes.Split(out, []byte("\n")) 113 } 114 115 func combinedOutput(cmd *exec.Cmd) []byte { 116 out, err := cmd.CombinedOutput() 117 if err != nil { 118 fmt.Println(strings.Join(cmd.Args, "\n")) 119 fmt.Fprintln(os.Stderr, err) 120 os.Exit(1) 121 } 122 return out 123 } 124 125 func check(err error) { 126 if err != nil { 127 fail(err.Error()) 128 } 129 } 130 131 func fail(msg string, v ...interface{}) { 132 fmt.Fprintf(os.Stderr, msg, v...) 133 fmt.Fprintln(os.Stderr) 134 os.Exit(1) 135 }