diff --git a/README.md b/README.md index 39fd09b..4b6ad4c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ This library aims at providing idiomatic `adb` bindings for go developers, in order to make it easier to write system tooling using golang. This tool tries to take guesswork out of arbitrarily shelling out to `adb` by providing a structured, thoroughly-tested wrapper for the `adb` functions most-likely to be used in a system program. -If `adb` must be installed in your path `PATH`. +If `adb` must be installed in your path `PATH`. At this time, while this library may work on Windows or MacOS, only Linux is supported. +If you would like to add support for Windows, MacOS, *BSD..., please [Submit a Pull Request](https://github.com/taigrr/adb/pulls). ## What is adb @@ -75,10 +76,12 @@ func main() { if err != nil { log.Fatalf("unable to connect to device %s: %v", opts.Address, err) } - err = dev.Disconnect() + defer dev.Disconnect() + stdout, stderr, err := dev.Shell("ls") if err != nil { - log.Fatalf("unable to disconnect from device %s: %v", opts.Address, err) + log.Fatalf("unable to shell into device %s: %v", opts.Address, err) } + log.Printf("Stdout: %s\nStderr: %s\n", stdout, stderr) } ``` diff --git a/adb.go b/adb.go new file mode 100644 index 0000000..ecbfc98 --- /dev/null +++ b/adb.go @@ -0,0 +1,62 @@ +package adb + +import ( + "context" + "net" + "sync" +) + +type Serial string + +type Connection int + +const ( + USB Connection = iota + Network +) + +type Device struct { + IsConnected bool + SerialNo Serial + ConnType Connection + IP net.IPAddr + FileHandle string // TODO change this to a discrete type + Lock sync.Mutex +} + +type ConnOptions struct { + Address net.IPAddr + SerialNo Serial +} + +// Connect to a device by serial number or IP. +// +// This will return a Device struct, which can be used to call other methods. +// If the connection fails or cannot complete on time, Connect will return an error. +func Connect(ctx context.Context, opts ConnOptions) (Device, error) { + return Device{}, nil +} + +// Connect to a previously discovered device. +// +// This function is helpful when connecting to a device found from the Devices call +// or when reconnecting to a previously connected device. +func (d Device) Connect(ctx context.Context) (Device, error) { + return d, nil +} + +// Equivalent to running `adb devices`. +// +// This function returns a list of discovered devices, but note that they may not be connected. +// It is recommended to call IsConnected() against the device you're interested in using and connect +// if not already connected before proceeding. +func Devices(ctx context.Context) ([]Device, error) { + return []Device{}, nil +} + +// Disconnect from a device. +// +// If a device is already disconnected or otherwise not found, returns an error. +func (d Device) Disconnect(ctx context.Context) error { + return nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..970c368 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/taigrr/adb + +go 1.16 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/util.go b/util.go new file mode 100644 index 0000000..dce4f91 --- /dev/null +++ b/util.go @@ -0,0 +1,63 @@ +package adb + +import ( + "bytes" + "context" + "fmt" + "log" + "os/exec" +) + +var adb string + +const killed = 130 + +func init() { + path, err := exec.LookPath("adb") + if err != nil { + log.Printf("%v", ErrNotInstalled) + adb = "" + return + } + adb = path +} + +func execute(ctx context.Context, args []string) (string, string, int, error) { + var ( + err error + stderr bytes.Buffer + stdout bytes.Buffer + code int + output string + warnings string + ) + + if adb == "" { + panic(ErrNotInstalled) + } + cmd := exec.CommandContext(ctx, adb, args...) + cmd.Stdout = &stdout + cmd.Stderr = &stderr + err = cmd.Run() + output = stdout.String() + warnings = stderr.String() + code = cmd.ProcessState.ExitCode() + + customErr := filterErr(warnings) + if customErr != nil { + err = customErr + } + if code != 0 && err == nil { + err = fmt.Errorf("received error code %d for stderr `%s`: %w", code, warnings, ErrUnspecified) + } + + return output, warnings, code, err +} + +// filterErr matches known output strings against the stderr. +// +// The inferred error type is then returned. +// TODO: implement +func filterErr(stderr string) error { + return nil +}