mirror of https://github.com/golang/go.git
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>
This commit is contained in:
parent
8c62fc0ca3
commit
164718ae2a
|
|
@ -207,14 +207,29 @@ func assembleApp(appdir, bin string) error {
|
||||||
// to connect to.
|
// to connect to.
|
||||||
func mountDevImage() error {
|
func mountDevImage() error {
|
||||||
// Check for existing mount.
|
// Check for existing mount.
|
||||||
cmd := idevCmd(exec.Command("ideviceimagemounter", "-l"))
|
cmd := idevCmd(exec.Command("ideviceimagemounter", "-l", "-x"))
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Stderr.Write(out)
|
os.Stderr.Write(out)
|
||||||
return fmt.Errorf("ideviceimagemounter: %v", err)
|
return fmt.Errorf("ideviceimagemounter: %v", err)
|
||||||
}
|
}
|
||||||
if len(out) > 0 {
|
var info struct {
|
||||||
// Assume there is an image mounted
|
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
|
return nil
|
||||||
}
|
}
|
||||||
// No image is mounted. Find a suitable image.
|
// No image is mounted. Find a suitable image.
|
||||||
|
|
@ -257,6 +272,12 @@ func findDevImage() (string, error) {
|
||||||
if iosVer == "" || buildVer == "" {
|
if iosVer == "" || buildVer == "" {
|
||||||
return "", errors.New("failed to parse ideviceinfo output")
|
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"
|
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)}
|
patterns := []string{fmt.Sprintf("%s (%s)", iosVer, buildVer), fmt.Sprintf("%s (*)", iosVer), fmt.Sprintf("%s*", iosVer)}
|
||||||
for _, pattern := range patterns {
|
for _, pattern := range patterns {
|
||||||
|
|
@ -330,10 +351,25 @@ func findDeviceAppPath(bundleID string) (string, error) {
|
||||||
} `xml:"array>dict"`
|
} `xml:"array>dict"`
|
||||||
}
|
}
|
||||||
if err := xml.Unmarshal(out, &list); err != nil {
|
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 {
|
for _, app := range list.Apps {
|
||||||
d := xml.NewDecoder(bytes.NewReader(app.Data))
|
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 {
|
||||||
|
return path, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
values := make(map[string]string)
|
||||||
var key string
|
var key string
|
||||||
var hasKey bool
|
var hasKey bool
|
||||||
|
|
@ -343,35 +379,38 @@ func findDeviceAppPath(bundleID string) (string, error) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to device app data: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
if tok, ok := tok.(xml.StartElement); ok {
|
if tok, ok := tok.(xml.StartElement); ok {
|
||||||
if tok.Name.Local == "key" {
|
if tok.Name.Local == "key" {
|
||||||
if err := d.DecodeElement(&key, &tok); err != nil {
|
if err := d.DecodeElement(&key, &tok); err != nil {
|
||||||
return "", fmt.Errorf("failed to device app data: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
hasKey = true
|
hasKey = true
|
||||||
} else if hasKey {
|
} else if hasKey {
|
||||||
var val string
|
var val string
|
||||||
if err := d.DecodeElement(&val, &tok); err != nil {
|
var err error
|
||||||
return "", fmt.Errorf("failed to device app data: %v", err)
|
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
|
values[key] = val
|
||||||
hasKey = false
|
hasKey = false
|
||||||
} else {
|
} else {
|
||||||
if err := d.Skip(); err != nil {
|
if err := d.Skip(); err != nil {
|
||||||
return "", fmt.Errorf("failed to device app data: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if values["CFBundleIdentifier"] == bundleID {
|
return values, nil
|
||||||
if path, ok := values["Path"]; ok {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", fmt.Errorf("failed to find device path for bundle: %s", bundleID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func install(appdir string) error {
|
func install(appdir string) error {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue