F-Droid desktop client
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.0 KiB

/* Copyright (c) 2015, Daniel Martí <mvdan@mvdan.cc> */
/* See LICENSE for licensing information */
package adb
import (
"bufio"
"fmt"
"net"
"os/exec"
"regexp"
"strconv"
"strings"
)
const (
port = 5037
)
func IsServerRunning() bool {
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", port))
if err != nil {
return false
}
conn.Close()
return true
}
func StartServer() error {
cmd := exec.Command("adb", "start-server")
err := cmd.Run()
if err != nil {
return err
}
return nil
}
type Device struct {
Id string
Usb string
Product string
Model string
Device string
}
var deviceRegex = regexp.MustCompile(`^([^\s]+)\s+device(.*)$`)
func Devices() ([]Device, error) {
cmd := exec.Command("adb", "devices", "-l")
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
var devices []Device
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
line := scanner.Text()
m := deviceRegex.FindStringSubmatch(line)
if m == nil {
continue
}
device := Device{
Id: m[1],
}
extras := m[2]
for _, extra := range strings.Split(extras, " ") {
sp := strings.SplitN(extra, ":", 2)
if len(sp) < 2 {
continue
}
switch sp[0] {
case "usb":
device.Usb = sp[1]
case "product":
device.Product = sp[1]
case "model":
device.Model = sp[1]
case "device":
device.Device = sp[1]
}
}
devices = append(devices, device)
}
return devices, nil
}
func (d Device) AdbCmd(args ...string) *exec.Cmd {
cmdArgs := append([]string{"-s", d.Id}, args...)
return exec.Command("adb", cmdArgs...)
}
func (d Device) AdbShell(args ...string) *exec.Cmd {
shellArgs := append([]string{"shell"}, args...)
return d.AdbCmd(shellArgs...)
}
func (d Device) Install(path string) error {
cmd := d.AdbCmd("install", path)
if err := cmd.Start(); err != nil {
return err
}
return nil
}
func (d Device) Uninstall(pkg string) error {
cmd := d.AdbCmd("uninstall", pkg)
if err := cmd.Start(); err != nil {
return err
}
return nil
}
type Package struct {
ID string
VCode int
VName string
}
var (
packageRegex = regexp.MustCompile(`^ Package \[([^\s]+)\]`)
verCodeRegex = regexp.MustCompile(`^ versionCode=([0-9]+)`)
verNameRegex = regexp.MustCompile(`^ versionName=(.+)`)
)
func (d Device) Installed() ([]Package, error) {
cmd := d.AdbShell("dumpsys", "package", "packages")
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
var packages []Package
scanner := bufio.NewScanner(stdout)
var cur *Package
for scanner.Scan() {
l := scanner.Text()
if m := packageRegex.FindStringSubmatch(l); m != nil {
packages = append(packages, Package{ID: m[1]})
cur = &packages[len(packages)-1]
} else if m := verCodeRegex.FindStringSubmatch(l); m != nil {
n, err := strconv.Atoi(m[1])
if err != nil {
panic(err)
}
cur.VCode = n
} else if m := verNameRegex.FindStringSubmatch(l); m != nil {
cur.VName = m[1]
}
}
return packages, nil
}