mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-19 18:49:29 +08:00
170 lines
3.8 KiB
Go
170 lines
3.8 KiB
Go
package gidevice
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"howett.net/plist"
|
|
|
|
"github.com/httprunner/httprunner/v4/hrp/pkg/gidevice/pkg/libimobiledevice"
|
|
)
|
|
|
|
var _ CrashReportMover = (*crashReportMover)(nil)
|
|
|
|
func newCrashReportMover(client *libimobiledevice.CrashReportMoverClient) *crashReportMover {
|
|
return &crashReportMover{
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
type crashReportMover struct {
|
|
client *libimobiledevice.CrashReportMoverClient
|
|
afc Afc
|
|
}
|
|
|
|
func (c *crashReportMover) readPing() (err error) {
|
|
var data []byte
|
|
if data, err = c.client.InnerConn().Read(4); err != nil {
|
|
return err
|
|
}
|
|
if string(data) != "ping" {
|
|
return fmt.Errorf("crashReportMover ping: %v", data)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *crashReportMover) Move(hostDir string, opts ...CrashReportMoverOption) (err error) {
|
|
opt := defaultCrashReportMoverOption()
|
|
for _, fn := range opts {
|
|
fn(opt)
|
|
}
|
|
|
|
toExtract := make([]string, 0, 64)
|
|
|
|
fn := func(cwd string, info *AfcFileInfo) {
|
|
if info.IsDir() {
|
|
return
|
|
}
|
|
if cwd == "." {
|
|
cwd = ""
|
|
}
|
|
|
|
devFilename := path.Join(cwd, info.Name())
|
|
hostElem := strings.Split(devFilename, "/")
|
|
hostFilename := filepath.Join(hostDir, filepath.Join(hostElem...))
|
|
hostFilename = strings.TrimSuffix(hostFilename, ".synced")
|
|
|
|
if opt.extract && strings.HasSuffix(hostFilename, ".plist") {
|
|
toExtract = append(toExtract, hostFilename)
|
|
}
|
|
|
|
var afcFile *AfcFile
|
|
if afcFile, err = c.afc.Open(devFilename, AfcFileModeRdOnly); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover open %s: %s", devFilename, err))
|
|
return
|
|
}
|
|
defer func() {
|
|
if err = afcFile.Close(); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover device file close: %s", err))
|
|
}
|
|
}()
|
|
|
|
if err = os.MkdirAll(filepath.Dir(hostFilename), 0o755); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover mkdir %s: %s", filepath.Dir(hostFilename), err))
|
|
return
|
|
}
|
|
var hostFile *os.File
|
|
if hostFile, err = os.Create(hostFilename); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover create %s: %s", hostFilename, err))
|
|
return
|
|
}
|
|
defer func() {
|
|
if err = hostFile.Close(); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover host file close: %s", err))
|
|
}
|
|
}()
|
|
|
|
if _, err = io.Copy(hostFile, afcFile); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover copy %s", err))
|
|
return
|
|
}
|
|
|
|
opt.whenDone(devFilename)
|
|
|
|
if opt.keep {
|
|
return
|
|
}
|
|
|
|
if err = c.afc.Remove(devFilename); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover remove %s: %s", devFilename, err))
|
|
return
|
|
}
|
|
}
|
|
if err = c.walkDir(".", fn); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !opt.extract {
|
|
return nil
|
|
}
|
|
|
|
for _, name := range toExtract {
|
|
data, err := os.ReadFile(name)
|
|
if err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover extract read %s: %s", name, err))
|
|
continue
|
|
}
|
|
m := make(map[string]interface{})
|
|
if _, err = plist.Unmarshal(data, &m); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover extract plist %s: %s", name, err))
|
|
continue
|
|
}
|
|
|
|
desc, ok := m["description"]
|
|
if !ok {
|
|
continue
|
|
}
|
|
hostExtCrash := strings.TrimSuffix(name, ".plist") + ".crash"
|
|
if err = os.WriteFile(hostExtCrash, []byte(fmt.Sprintf("%v", desc)), 0o755); err != nil {
|
|
debugLog(fmt.Sprintf("crashReportMover extract save %s: %s", name, err))
|
|
continue
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (c *crashReportMover) walkDir(dirname string, fn func(path string, info *AfcFileInfo)) (err error) {
|
|
var names []string
|
|
if names, err = c.afc.ReadDir(dirname); err != nil {
|
|
return err
|
|
}
|
|
|
|
cwd := dirname
|
|
|
|
for _, n := range names {
|
|
if n == "." || n == ".." {
|
|
continue
|
|
}
|
|
|
|
var info *AfcFileInfo
|
|
if info, err = c.afc.Stat(path.Join(cwd, n)); err != nil {
|
|
return err
|
|
}
|
|
if info.IsDir() {
|
|
if err = c.walkDir(path.Join(cwd, info.name), fn); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
fn(cwd, info)
|
|
}
|
|
|
|
return
|
|
}
|