misc/ios/detect.go GO 134 lines View on github.com → Search inside
1// Copyright 2015 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45//go:build ignore67// detect attempts to autodetect the correct8// values of the environment variables9// used by go_ios_exec.10// detect shells out to ideviceinfo, a third party program that can11// be obtained by following the instructions at12// https://github.com/libimobiledevice/libimobiledevice.13package main1415import (16	"bytes"17	"crypto/x509"18	"fmt"19	"os"20	"os/exec"21	"strings"22)2324func main() {25	udids := getLines(exec.Command("idevice_id", "-l"))26	if len(udids) == 0 {27		fail("no udid found; is a device connected?")28	}2930	mps := detectMobileProvisionFiles(udids)31	if len(mps) == 0 {32		fail("did not find mobile provision matching device udids %q", udids)33	}3435	fmt.Println("# Available provisioning profiles below.")36	fmt.Println("# NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID")37	fmt.Println("# will be overwritten when running Go programs.")38	for _, mp := range mps {39		fmt.Println()40		f, err := os.CreateTemp("", "go_ios_detect_")41		check(err)42		fname := f.Name()43		defer os.Remove(fname)4445		out := output(parseMobileProvision(mp))46		_, err = f.Write(out)47		check(err)48		check(f.Close())4950		cert, err := plistExtract(fname, "DeveloperCertificates:0")51		check(err)52		pcert, err := x509.ParseCertificate(cert)53		check(err)54		fmt.Printf("export GOIOS_DEV_ID=\"%s\"\n", pcert.Subject.CommonName)5556		appID, err := plistExtract(fname, "Entitlements:application-identifier")57		check(err)58		fmt.Printf("export GOIOS_APP_ID=%s\n", appID)5960		teamID, err := plistExtract(fname, "Entitlements:com.apple.developer.team-identifier")61		check(err)62		fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID)63	}64}6566func detectMobileProvisionFiles(udids [][]byte) []string {67	cmd := exec.Command("mdfind", "-name", ".mobileprovision")68	lines := getLines(cmd)6970	var files []string71	for _, line := range lines {72		if len(line) == 0 {73			continue74		}75		xmlLines := getLines(parseMobileProvision(string(line)))76		matches := 077		for _, udid := range udids {78			for _, xmlLine := range xmlLines {79				if bytes.Contains(xmlLine, udid) {80					matches++81				}82			}83		}84		if matches == len(udids) {85			files = append(files, string(line))86		}87	}88	return files89}9091func parseMobileProvision(fname string) *exec.Cmd {92	return exec.Command("security", "cms", "-D", "-i", string(fname))93}9495func plistExtract(fname string, path string) ([]byte, error) {96	out, err := exec.Command("/usr/libexec/PlistBuddy", "-c", "Print "+path, fname).CombinedOutput()97	if err != nil {98		return nil, err99	}100	return bytes.TrimSpace(out), nil101}102103func getLines(cmd *exec.Cmd) [][]byte {104	out := output(cmd)105	lines := bytes.Split(out, []byte("\n"))106	// Skip the empty line at the end.107	if len(lines[len(lines)-1]) == 0 {108		lines = lines[:len(lines)-1]109	}110	return lines111}112113func output(cmd *exec.Cmd) []byte {114	out, err := cmd.Output()115	if err != nil {116		fmt.Println(strings.Join(cmd.Args, "\n"))117		fmt.Fprintln(os.Stderr, err)118		os.Exit(1)119	}120	return out121}122123func check(err error) {124	if err != nil {125		fail(err.Error())126	}127}128129func fail(msg string, v ...interface{}) {130	fmt.Fprintf(os.Stderr, msg, v...)131	fmt.Fprintln(os.Stderr)132	os.Exit(1)133}

Code quality findings 11

Empty interface; prefer specific types or generics for type safety
empty-interface
func fail(msg string, v ...interface{}) {
Defer inside loop; deferred calls accumulate until the function returns, not until the loop iteration ends. This can cause resource leaks
warning correctness defer-in-loop
defer os.Remove(fname)
Unstructured output; use a structured logging library (e.g., slog, zap, zerolog, logrus)
info correctness fmt-println
fmt.Println("# Available provisioning profiles below.")
Unstructured output; use a structured logging library (e.g., slog, zap, zerolog, logrus)
info correctness fmt-println
fmt.Println("# NOTE: Any existing app on the device with the app id specified by GOIOS_APP_ID")
Unstructured output; use a structured logging library (e.g., slog, zap, zerolog, logrus)
info correctness fmt-println
fmt.Println("# will be overwritten when running Go programs.")
Unstructured output; use a structured logging library (e.g., slog, zap, zerolog, logrus)
info correctness fmt-println
fmt.Println()
Formatted output to console; prefer structured logging for consistency
info correctness fmt-printf
fmt.Printf("export GOIOS_DEV_ID=\"%s\"\n", pcert.Subject.CommonName)
Formatted output to console; prefer structured logging for consistency
info correctness fmt-printf
fmt.Printf("export GOIOS_APP_ID=%s\n", appID)
Formatted output to console; prefer structured logging for consistency
info correctness fmt-printf
fmt.Printf("export GOIOS_TEAM_ID=%s\n", teamID)
Multiple appends without pre-allocation; use make() with capacity when size is known
info performance append-without-prealloc
files = append(files, string(line))
Unstructured output; use a structured logging library (e.g., slog, zap, zerolog, logrus)
info correctness fmt-println
fmt.Println(strings.Join(cmd.Args, "\n"))

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.