aboutsummaryrefslogtreecommitdiff
path: root/misc/ios
diff options
context:
space:
mode:
authorElias Naur <elias.naur@gmail.com>2018-05-03 13:43:52 +0200
committerElias Naur <elias.naur@gmail.com>2018-05-04 05:47:22 +0000
commit164718ae2a35d368bf5611bf77c0e8ca1c8ab6a5 (patch)
treeff18ad13fa858fb2ffd34221bbccb7ae97c0a7b7 /misc/ios
parent8c62fc0ca3c96ecbd3a6e81546aa8c53e32ff500 (diff)
downloadgo-164718ae2a35d368bf5611bf77c0e8ca1c8ab6a5.tar.gz
go-164718ae2a35d368bf5611bf77c0e8ca1c8ab6a5.zip
misc/ios: improve detection of missing developer image
It turns out that a non-empty result from ideviceimagemounter does not mean an image is mounted. Use ideviceimagemounter's xml output mode to improve the check. Also, iOS versions are reported as major.minor or major.minor.patch. Developer images are only specific to major.minor version, so cut off the patch number in the search, if present. Change-Id: Ia182e6f4655b7e6aa6feb8005cd3b533535b73cd Reviewed-on: https://go-review.googlesource.com/111235 Run-TryBot: Elias Naur <elias.naur@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
Diffstat (limited to 'misc/ios')
-rw-r--r--misc/ios/go_darwin_arm_exec.go109
1 files changed, 74 insertions, 35 deletions
diff --git a/misc/ios/go_darwin_arm_exec.go b/misc/ios/go_darwin_arm_exec.go
index 515bb8539c..d04f3725b3 100644
--- a/misc/ios/go_darwin_arm_exec.go
+++ b/misc/ios/go_darwin_arm_exec.go
@@ -207,14 +207,29 @@ func assembleApp(appdir, bin string) error {
// to connect to.
func mountDevImage() error {
// Check for existing mount.
- cmd := idevCmd(exec.Command("ideviceimagemounter", "-l"))
+ cmd := idevCmd(exec.Command("ideviceimagemounter", "-l", "-x"))
out, err := cmd.CombinedOutput()
if err != nil {
os.Stderr.Write(out)
return fmt.Errorf("ideviceimagemounter: %v", err)
}
- if len(out) > 0 {
- // Assume there is an image mounted
+ var info struct {
+ Dict struct {
+ Data []byte `xml:",innerxml"`
+ } `xml:"dict"`
+ }
+ if err := xml.Unmarshal(out, &info); err != nil {
+ return fmt.Errorf("mountDevImage: failed to decode mount information: %v", err)
+ }
+ dict, err := parsePlistDict(info.Dict.Data)
+ if err != nil {
+ return fmt.Errorf("mountDevImage: failed to parse mount information: %v", err)
+ }
+ if dict["ImagePresent"] == "true" && dict["Status"] == "Complete" {
+ return nil
+ }
+ // Some devices only give us an ImageSignature key.
+ if _, exists := dict["ImageSignature"]; exists {
return nil
}
// No image is mounted. Find a suitable image.
@@ -257,6 +272,12 @@ func findDevImage() (string, error) {
if iosVer == "" || buildVer == "" {
return "", errors.New("failed to parse ideviceinfo output")
}
+ verSplit := strings.Split(iosVer, ".")
+ if len(verSplit) > 2 {
+ // Developer images are specific to major.minor ios version.
+ // Cut off the patch version.
+ iosVer = strings.Join(verSplit[:2], ".")
+ }
sdkBase := "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport"
patterns := []string{fmt.Sprintf("%s (%s)", iosVer, buildVer), fmt.Sprintf("%s (*)", iosVer), fmt.Sprintf("%s*", iosVer)}
for _, pattern := range patterns {
@@ -330,40 +351,12 @@ func findDeviceAppPath(bundleID string) (string, error) {
} `xml:"array>dict"`
}
if err := xml.Unmarshal(out, &list); err != nil {
- return "", fmt.Errorf("failed to parse ideviceinstaller outout: %v", err)
+ return "", fmt.Errorf("failed to parse ideviceinstaller output: %v", err)
}
for _, app := range list.Apps {
- d := xml.NewDecoder(bytes.NewReader(app.Data))
- values := make(map[string]string)
- var key string
- var hasKey bool
- for {
- tok, err := d.Token()
- if err == io.EOF {
- break
- }
- if err != nil {
- return "", fmt.Errorf("failed to device app data: %v", err)
- }
- if tok, ok := tok.(xml.StartElement); ok {
- if tok.Name.Local == "key" {
- if err := d.DecodeElement(&key, &tok); err != nil {
- return "", fmt.Errorf("failed to device app data: %v", err)
- }
- hasKey = true
- } else if hasKey {
- var val string
- if err := d.DecodeElement(&val, &tok); err != nil {
- return "", fmt.Errorf("failed to device app data: %v", err)
- }
- values[key] = val
- hasKey = false
- } else {
- if err := d.Skip(); err != nil {
- return "", fmt.Errorf("failed to device app data: %v", err)
- }
- }
- }
+ values, err := parsePlistDict(app.Data)
+ if err != nil {
+ return "", fmt.Errorf("findDeviceAppPath: failed to parse app dict: %v", err)
}
if values["CFBundleIdentifier"] == bundleID {
if path, ok := values["Path"]; ok {
@@ -374,6 +367,52 @@ func findDeviceAppPath(bundleID string) (string, error) {
return "", fmt.Errorf("failed to find device path for bundle: %s", bundleID)
}
+// Parse an xml encoded plist. Plist values are mapped to string.
+func parsePlistDict(dict []byte) (map[string]string, error) {
+ d := xml.NewDecoder(bytes.NewReader(dict))
+ values := make(map[string]string)
+ var key string
+ var hasKey bool
+ for {
+ tok, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ if tok, ok := tok.(xml.StartElement); ok {
+ if tok.Name.Local == "key" {
+ if err := d.DecodeElement(&key, &tok); err != nil {
+ return nil, err
+ }
+ hasKey = true
+ } else if hasKey {
+ var val string
+ var err error
+ switch n := tok.Name.Local; n {
+ case "true", "false":
+ // Bools are represented as <true/> and <false/>.
+ val = n
+ err = d.Skip()
+ default:
+ err = d.DecodeElement(&val, &tok)
+ }
+ if err != nil {
+ return nil, err
+ }
+ values[key] = val
+ hasKey = false
+ } else {
+ if err := d.Skip(); err != nil {
+ return nil, err
+ }
+ }
+ }
+ }
+ return values, nil
+}
+
func install(appdir string) error {
attempt := 0
for {