// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package main

import (
	"archive/tar"
	"compress/gzip"
	"context"
	"crypto/md5"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"syscall"
	"time"

	"go.fuchsia.dev/fuchsia/tools/lib/color"
	"go.fuchsia.dev/fuchsia/tools/lib/logger"
	"go.fuchsia.dev/fuchsia/tools/sdk-tools/sdkcommon"
)

var (
	// ExecCommand exports exec.Command as a variable so it can be mocked.
	ExecCommand = exec.Command
	// OsStat exports os.Stat as a variable so it can be mocked.
	OsStat = os.Stat
	// Logger level.
	level = logger.InfoLevel
)

const (
	ffxConfigServerModeKey string = "fserve.server-mode"

	defaultServerMode string = "pm"
)

var osExit = os.Exit

// Allow mocking of Kill.
type osProcess interface {
	Kill() error
}

func defaultFindProcess(pid int) (osProcess, error) {
	return os.FindProcess(pid)
}

var findProcess = defaultFindProcess

// allow mocking of syscalls.Wait4

func defaultsyscallWait4(pid int, wstatus *syscall.WaitStatus, flags int, usage *syscall.Rusage) (int, error) {
	return syscall.Wait4(pid, wstatus, flags, usage)
}

var syscallWait4 = defaultsyscallWait4

const logFlags = log.Ltime

type sdkProvider interface {
	GetSDKDataPath() string
	GetToolsDir() (string, error)
	GetAvailableImages(version string, bucket string) ([]sdkcommon.GCSImage, error)
	RunFFX(args []string, interactive bool) (string, error)
	RunSSHCommand(targetAddress string, sshConfig string, privateKey string, sshPort string,
		verbose bool, sshArgs []string) (string, error)
}

func main() {
	var (
		err error
	)

	dataPathFlag := flag.String("data-path", "", "Specifies the data path for SDK tools. Defaults to $HOME/.fuchsia.")
	helpFlag := flag.Bool("help", false, "Show the usage message")
	repoFlag := flag.String("repo-dir", "", "Specify the path to the package repository.")
	bucketFlag := flag.String("bucket", "", "Specify the GCS bucket for the prebuilt packages.")
	imageFlag := flag.String("image", "", "Specify the GCS file name for prebuild packages.")
	nameFlag := flag.String("name", "devhost", "Name is used as the update channel identifier, as reported by fuchsia.update.channel.Provider.")
	repoPortFlag := flag.String("server-port", "", "Port number to use when serving the packages.")
	killFlag := flag.Bool("kill", false, "Kills any existing package manager server.")
	cleanFlag := flag.Bool("clean", false, "Cleans the package repository first.")
	prepareFlag := flag.Bool("prepare", false, "Downloads any dependencies but does not start the package server.")
	versionFlag := flag.String("version", "", "SDK Version to use for prebuilt packages.")
	persistFlag := flag.Bool("persist", false, "Persist repository metadata to allow serving resolved packages across reboot.")
	packageArchiveFlag := flag.String("package-archive", "",
		"Specify the source package archive in .tgz or directory format. If specified, no packages are downloaded from GCS.")
	flag.Var(&level, "level", "Output verbosity, can be fatal, error, warning, info, debug or trace.")

	// target related options
	privateKeyFlag := flag.String("private-key", "", "Uses additional private key when using ssh to access the device.")
	deviceNameFlag := flag.String("device-name", "", `Serves packages to a device with the given device hostname. Cannot be used with --device-ip."
	  If neither --device-name nor --device-ip are specified, the device-name configured using fconfig is used.`)
	deviceIPFlag := flag.String("device-ip", "", `Serves packages to a device with the given device ip address. Cannot be used with --device-name."
	  If neither --device-name nor --device-ip are specified, the device-name configured using fconfig is used.`)
	sshConfigFlag := flag.String("sshconfig", "", "Use the specified sshconfig file instead of fssh's version.")
	serverMode := flag.String("server-mode", "", "Specify the server mode 'pm' or 'ffx'.")

	flag.Parse()

	sdk, err := sdkcommon.NewWithDataPath(*dataPathFlag)
	if err != nil {
		log.Fatalf("Could not initialize SDK: %v", err)
	}

	log := logger.NewLogger(level, color.NewColor(color.ColorAuto), os.Stdout, os.Stderr, "fserve ")
	log.SetFlags(logFlags)
	ctx := logger.WithLogger(context.Background(), log)

	if *helpFlag {
		usage()
		osExit(0)
	}

	deviceConfig, err := sdk.ResolveTargetAddress(*deviceIPFlag, *deviceNameFlag)
	if err != nil {
		log.Fatalf("%v", err)
	}
	log.Infof("Using target address: %v", deviceConfig.DeviceIP)

	// Set the defaults from the SDK if not present.
	if *repoFlag == "" {
		// The device-name is needed to build the repo path.
		if deviceConfig.DeviceName == "" {
			log.Fatalf("Package repository directory cannot be determined. Use --repo-dir to set, or --device-name to select the target device.")
		}
		flag.Set("repo-dir", deviceConfig.PackageRepo)
	}

	if *bucketFlag == "" {
		flag.Set("bucket", deviceConfig.Bucket)
	}

	if *imageFlag == "" {
		flag.Set("image", deviceConfig.Image)
	}

	if *versionFlag == "" {
		flag.Set("version", sdk.GetSDKVersion())
	}

	if *versionFlag == "" && *packageArchiveFlag == "" {
		log.Fatalf("SDK version not known. Use --version to specify it manually.\n")
	}

	// If the server mode was not passed in on the CLI, try to read it from the ffx config.
	if *serverMode == "" {
		*serverMode, err = getServerModeFromConfig(sdk)
		if err != nil {
			log.Fatalf("Error reading the server mode from FFX config: %v", err)
		}

		if *serverMode == "" {
			*serverMode = defaultServerMode
		}
	}

	// if no deviceIPFlag was given, then get the SSH Port from the configuration.
	// We can't look at the configuration if the ip address was passed in since we don't have the
	// device name which is needed to look up the property.
	sshPort := ""
	if *deviceIPFlag == "" {
		sshPort = deviceConfig.SSHPort
		if err != nil {
			log.Fatalf("Error reading SSH port configuration: %v", err)
		}
		log.Debugf("Using sshport address: %v", sshPort)
		if sshPort == "22" {
			sshPort = ""
		}
	}

	var server packageServer
	switch *serverMode {
	case "pm":
		if *repoPortFlag == "" {
			flag.Set("server-port", deviceConfig.PackagePort)
		}
		if err = killPMServers(ctx, *repoPortFlag); err != nil {
			log.Fatalf("Could not kill existing package servers: %v\n", err)
		}
		if *killFlag {
			osExit(0)
			// this return is needed for tests that overload osExit to not exit.
			return
		}

		server = &pmServer{
			repoPath:      *repoFlag,
			repoPort:      *repoPortFlag,
			name:          *nameFlag,
			targetAddress: deviceConfig.DeviceIP,
			sshConfig:     *sshConfigFlag,
			persist:       *persistFlag,
			privateKey:    *privateKeyFlag,
			sshPort:       sshPort,
		}
	case "ffx":
		if *repoPortFlag != "" {
			log.Errorf(
				"`-server-mode ffx` does not support `-server-port`. "+
					"Instead, to change the repository server port, run: "+
					"`ffx config set repository.server.listen '[::1]:%s' && ffx doctor --restart-daemon`", *repoPortFlag)
			osExit(1)
			// this return is needed for tests that overload osExit to not exit.
			return
		}

		if *killFlag {
			log.Errorf(
				"`-server-mode ffx` does not support `-kill`. " +
					"Instead, to turn off the repository server, run: " +
					"`ffx config set repository.server.listen '' && ffx doctor --restart-daemon`")
			osExit(1)
			// this return is needed for tests that overload osExit to not exit.
			return
		}

		if *privateKeyFlag != "" {
			log.Errorf(
				"`-server-mode ffx` does not support `-private-key` "+
					"Instead, if a specific private key is needed for ffx to communicate with the device, run: "+
					"`ffx config add ssh.priv %s && ffx doctor --restart-daemon`", *privateKeyFlag)
			osExit(1)
			// this return is needed for tests that overload osExit to not exit.
			return
		}

		if *sshConfigFlag != "" {
			log.Errorf("`server-mode ffx` does not support customizing the SSH config settings with `-sshconfig`")
			osExit(1)
			// this return is needed for tests that overload osExit to not exit.
			return
		}

		server = &ffxServer{
			repoPath:      *repoFlag,
			name:          *nameFlag,
			targetAddress: deviceConfig.DeviceIP,
			persist:       *persistFlag,
			sshPort:       sshPort,
		}
	default:
		log.Fatalf("Unknown server mode %v", *serverMode)
	}

	if *cleanFlag {
		if err = cleanPmRepo(ctx, *repoFlag); err != nil {
			log.Warningf("Could not clean up the package repository: %v\n", err)
		}
	} else {
		log.Infof("Using repository: %v (without cleaning, use -clean to clean the package repository first).\n", *repoFlag)
	}

	if *packageArchiveFlag != "" {
		absArchivePath, err := filepath.Abs(*packageArchiveFlag)
		if err != nil {
			log.Fatalf("Could not get absolute path of %v: %v\n", *packageArchiveFlag, err)
		}
		if err = prepareFromArchive(ctx, *repoFlag, absArchivePath); err != nil {
			log.Fatalf("Could not prepare packages: %v\n", err)
		}
	} else if err = prepare(ctx, sdk, *versionFlag, *repoFlag, *bucketFlag, *imageFlag); err != nil {
		log.Fatalf("Could not prepare packages: %v\n", err)
	}
	if *prepareFlag {
		osExit(0)
		// this return is needed for tests that overload osExit to not exit.
		return
	}

	if err := server.startServer(ctx, sdk); err != nil {
		log.Fatalf("Failed to serve packages: %v\n", err)
	}

	if err := server.registerRepository(ctx, sdk); err != nil {
		log.Fatalf("failed to register repository with device: %v", err)
	}

	log.Infof("Successfully started the package server! It is running the background.")

	osExit(0)
}

type packageServer interface {
	startServer(ctx context.Context, sdk sdkProvider) error
	registerRepository(ctx context.Context, sdk sdkProvider) error
}

type pmServer struct {
	repoPath      string
	repoPort      string
	name          string
	targetAddress string
	sshConfig     string
	privateKey    string
	persist       bool
	sshPort       string
}

func getServerModeFromConfig(sdk sdkProvider) (string, error) {
	args := []string{"config", "get", ffxConfigServerModeKey}
	output, err := sdk.RunFFX(args, false)
	if err != nil {
		// Exit code of 2 means no value was found.
		if exiterr, ok := err.(*exec.ExitError); ok && exiterr.ExitCode() == 2 {
			return "", nil
		}
		return "", fmt.Errorf("Error reading %s: %w %v", ffxConfigServerModeKey, err, output)
	}

	if len(output) == 0 {
		return "", nil
	}

	serverMode := ""
	if err := json.Unmarshal([]byte(output), &serverMode); err != nil {
		return "", err
	}

	return serverMode, nil
}

// startServer starts the `pm serve` command and returns the command object.
func (s *pmServer) startServer(ctx context.Context, sdk sdkProvider) error {
	log := logger.LoggerFromContext(ctx)
	log.Debugf("Starting package server")

	if _, err := startPMServer(sdk, s.repoPath, s.repoPort); err != nil {
		return err
	}

	return nil
}

func (s *pmServer) registerRepository(ctx context.Context, sdk sdkProvider) error {
	return registerPMRepository(ctx, sdk, s.repoPort, s.name, s.targetAddress, s.sshConfig, s.privateKey, s.persist, s.sshPort)
}

type ffxServer struct {
	repoPath      string
	name          string
	targetAddress string
	persist       bool
	sshPort       string
}

func (s *ffxServer) startServer(ctx context.Context, sdk sdkProvider) error {
	// TODO(http://fxbug.dev/83720): We need `ffx_repository=true` until
	// ffx repository has graduated from experimental.
	args := []string{"--config", "ffx_repository=true", "repository",
		"add-from-pm", "--repository", s.name, s.repoPath}
	logger.Debugf(ctx, "running %v", args)
	if _, err := sdk.RunFFX(args, false); err != nil {
		var exitError *exec.ExitError
		if errors.As(err, &exitError) {
			return fmt.Errorf("Error adding repository %v: %w", string(exitError.Stderr), err)
		}
		return err
	}
	return nil
}

func (s *ffxServer) registerRepository(ctx context.Context, sdk sdkProvider) error {
	targetAddress := s.targetAddress
	if s.sshPort != "" {
		targetAddress = fmt.Sprintf("[%s]:%s", targetAddress, s.sshPort)
	}

	// TODO(http://fxbug.dev/83720): We need `ffx_repository=true` until
	// ffx repository has graduated from experimental.
	args := []string{
		"--config", "ffx_repository=true",
		"--target", targetAddress,
		"target", "repository", "register",
		"--repository", s.name,
		"--alias", "fuchsia.com",
	}
	if s.persist {
		args = append(args, "--storage-type", "persistent")
	}
	logger.Debugf(ctx, "running %v", args)
	if _, err := sdk.RunFFX(args, false); err != nil {
		var exitError *exec.ExitError
		if errors.As(err, &exitError) {
			return fmt.Errorf("Error adding repository %v: %w", string(exitError.Stderr), err)
		}
		return err
	}
	return nil
}

func usage() {
	fmt.Printf("Usage: %s [options]\n", filepath.Base(os.Args[0]))
	flag.PrintDefaults()
}

// copy or untar a package archive into the repo dir.
func prepareFromArchive(ctx context.Context, repoPath string, archivePath string) error {
	packageDir := filepath.Dir(repoPath)
	log := logger.LoggerFromContext(ctx)

	if sdkcommon.FileExists(archivePath) {
		// untar it.
		log.Debugf("processing package-archive %v", archivePath)
		return processArchiveTarball(ctx, packageDir, archivePath)
	}
	if sdkcommon.DirectoryExists(archivePath) {
		// if it is the same as the dest - a no op.
		if archivePath == packageDir {
			log.Infof("Package archive directory is the same as repo directory, using repo unchanged.")
			return nil
		}
		// Always remove the existing directory when using a directory as the source.

		logger.Debugf(context.Background(), "Removing directory %s\n", packageDir)
		err := os.RemoveAll(packageDir)
		if err != nil {
			logger.Fatalf(ctx, "Could not remove directory %v: %v", packageDir, err)
		}
		// copy it to the repo.
		return copyDir(ctx, archivePath, packageDir)
	}
	return fmt.Errorf("Invalid archive path: %v. Needs to be .tgz file or directory", archivePath)
}

// prepare method -  downloads and untars the packages from GCS if needed.
func prepare(ctx context.Context, sdk sdkcommon.SDKProperties, version string, repoPath string, bucket string, image string) error {
	log := logger.LoggerFromContext(ctx)
	log.Debugf("Preparing package repository at %v for %v:%v@%v", repoPath, bucket, image, version)
	if image == "list" || image == "" {
		if image == "" {
			log.Warningf("Cannot determine image name")
		}
		printValidImages(sdk, version, bucket)
		osExit(1)
	}

	targetPackage := sdk.GetPackageSourcePath(version, bucket, image)
	imageFilename := fmt.Sprintf("%v_%v.tar.gz", version, image)

	log.Infof("Serving %v packages for SDK version %v from %v\n", image, version, targetPackage)

	err := downloadImageIfNeeded(ctx, sdk, version, bucket, targetPackage, imageFilename, repoPath)
	if err != nil {
		return fmt.Errorf("Could not download %v:  %v", targetPackage, err)
	}
	return nil
}

// cleanPmRepo removes any files in the package repository.
func cleanPmRepo(ctx context.Context, repoDir string) error {
	log := logger.LoggerFromContext(ctx)
	log.Infof("Cleaning the package repository %v.\n", repoDir)

	if _, err := OsStat(repoDir); os.IsNotExist(err) {
		// The repository does not exist and thus is already clean.
		return nil
	}

	args := []string{"-Rf", repoDir}
	cmd := ExecCommand("rm", args...)
	_, err := cmd.Output()
	if err != nil {
		return err
	}
	return nil
}

func killPMServers(ctx context.Context, portNum string) error {
	log := logger.LoggerFromContext(ctx)
	log.Debugf("Killing existing servers")
	// First get all the pm commands for the user
	cmd := ExecCommand("pgrep", "pm")
	output, err := cmd.Output()
	if err != nil {
		var exitError *exec.ExitError
		if errors.As(err, &exitError) {
			if string(exitError.Stderr) != "" {
				err = errors.New(string(exitError.Stderr))
			}
			// Special case for some environments which if pgrep does not match
			// the exit code  can be non-zero. In this case check to see if any output
			// was generated and if not, then treat it as if there are no matching processes.
			if exitError.ExitCode() == 1 && len(exitError.Stderr) == 0 && len(output) == 0 {
				return nil
			}
			return fmt.Errorf("Error running pgrep: %v", err)
		}
		return fmt.Errorf("Non exitError encountered: %v", err)
	}

	if len(output) == 0 {
		return nil
	}

	pids := []string{}
	for _, p := range strings.Split(string(output), "\n") {
		tp := strings.TrimSpace(p)
		if tp != "" {
			pids = append(pids, tp)
		}
	}

	// Now run ps to look for pm
	cmd = ExecCommand("ps", pids...)
	output, err = cmd.Output()
	if err != nil {
		var exitError *exec.ExitError
		if errors.As(err, &exitError) {
			return fmt.Errorf("Error running ps %v: %w", string(exitError.Stderr), err)
		}
		return err
	}

	// Split on lines
	for _, line := range strings.Split(string(output), "\n") {
		line = strings.TrimSpace(line)
		parts := strings.Fields(line)
		if len(parts) == 0 {
			continue
		}
		// skip header
		if parts[0] == "PID" {
			continue
		}

		// check the process name ends in /pm
		if strings.HasSuffix(parts[4], "/pm") {
			// if a port number was passed in, match that so we avoid killing unrelated servers.
			portMatches := true
			if portNum != "" {
				portMatches = false
				for _, arg := range parts {
					if arg == fmt.Sprintf(":%s", portNum) {
						log.Debugf("matched port %v\n", parts[4:])
						portMatches = true
					}
				}
			}
			if portMatches {
				pid, _ := strconv.Atoi(parts[0])
				proc, _ := findProcess(pid)
				return proc.Kill()
			}

		}
	}

	logger.Infof(context.Background(), "No running pm package servers found.\n")
	return nil
}

// startServer starts the `pm serve` command and returns the command object.
// The server is started in the background.
func startPMServer(sdk sdkProvider, repoPath string, repoPort string) (*exec.Cmd, error) {
	toolsDir, err := sdk.GetToolsDir()
	if err != nil {
		return nil, fmt.Errorf("Could not determine tools directory %v", err)
	}
	cmd := filepath.Join(toolsDir, "pm")

	args := []string{"serve"}
	if level != logger.DebugLevel && level != logger.TraceLevel {
		args = append(args, "-q")
	}
	args = append(args, "-repo", repoPath, "-c", "2", "-l", fmt.Sprintf(":%s", repoPort))

	proc := ExecCommand(cmd, args...)
	proc.Stdout = os.Stdout
	proc.Stderr = os.Stderr
	err = proc.Start()
	if err != nil {
		return proc, err
	}

	// Once the process is started, wait for 2 seconds to look for an early exit
	// this allows catching things like "port in use" or other errors from pm before
	// losing control of pm.
	pid := proc.Process.Pid
	var wstat syscall.WaitStatus
	for i := 0; i < 4; i++ {
		_, err := syscallWait4(pid, &wstat, syscall.WNOHANG, nil)
		if err != nil {
			return proc, fmt.Errorf("Error waiting on pm: %v", err)
		}
		if wstat.Exited() && wstat.ExitStatus() != 0 {
			return proc, fmt.Errorf("Server started then exited with code %v", wstat.ExitStatus())
		}
		time.Sleep(500 * time.Millisecond)
	}
	return proc, nil
}

// printValidImages prints the bucket and image names found on GCS.
func printValidImages(sdk sdkProvider, version string, bucket string) error {
	images, err := sdk.GetAvailableImages(version, bucket)
	if err != nil {
		return fmt.Errorf("Could not get list of images: %v", err)
	}
	fmt.Printf("Available images are:\n")
	for _, image := range images {
		fmt.Printf("%s: %s\n", image.Bucket, image.Name)
	}
	return nil
}

// downloadImageIfNeeded downloads from GCS the packages for the given prebuillt image.
// The md5 hash of the tarball is stored to check for differences from the downloaded version.
// if the hash matches, the tarball is not un-tarred.
func downloadImageIfNeeded(ctx context.Context, sdk sdkProvider, version string, bucket string, srcPath string, imageFilename string, repoPath string) error {
	// Validate the image is found
	localImagePath := filepath.Join(sdk.GetSDKDataPath(), imageFilename)
	packageDir := filepath.Dir(repoPath)
	log := logger.LoggerFromContext(ctx)

	if !sdkcommon.FileExists(localImagePath) {
		_, err := sdkcommon.GCSFileExists(srcPath)
		if err != nil {
			if strings.Contains(err.Error(), "One or more URLs matched no objects") {
				log.Errorf("Could not locate %v: %v\n", srcPath, err)
				printValidImages(sdk, version, bucket)
			}
			return err
		}
		_, err = sdkcommon.GCSCopy(srcPath, localImagePath)
		if err != nil {
			return fmt.Errorf("Could not copy image from %v to %v: %v", srcPath, localImagePath, err)
		}
	} else {
		log.Debugf("Skipping download, packages tarball exists\n")
	}
	return processArchiveTarball(ctx, packageDir, localImagePath)
}

func processArchiveTarball(ctx context.Context, packageDir string, archiveFile string) error {
	log := logger.LoggerFromContext(ctx)

	// The checksum file contains the output from `md5`. This is used to detect content changes in the packages file.
	isDifferent := false
	checksumFile := filepath.Join(packageDir, "packages.md5")
	md5Hash, err := calculateMD5(archiveFile)
	if err != nil {
		return fmt.Errorf("could not checksum file %v: %v", archiveFile, err)
	}
	if sdkcommon.FileExists(checksumFile) {
		content, err := ioutil.ReadFile(checksumFile)
		if err != nil {
			log.Warningf("Could not read checksum file %v: %v\n", checksumFile, err)
			isDifferent = true
		}
		parts := strings.Fields(string(content))
		isDifferent = isDifferent || md5Hash != parts[0]

		// Look for old file name
		if len(parts) > 1 {
			oldFile := strings.TrimSpace(parts[1])
			if sdkcommon.FileExists(oldFile) && oldFile != archiveFile {
				err = os.Remove(oldFile)
				if err != nil {
					logger.Errorf(ctx, "Could not remove old archive %v: %v\n", oldFile, err)
				}
			} else {
				logger.Debugf(ctx, "%s does not exist or is the same as %s\n", oldFile, archiveFile)
			}
		} else {
			logger.Debugf(ctx, "Could not parse old file name from %v", parts)
		}
	} else {
		logger.Debugf(ctx, "%s does not exist so can't check the checksum\n", checksumFile)
		isDifferent = true
	}
	if isDifferent {
		log.Debugf("Removing directory %s\n", packageDir)
		err := os.RemoveAll(packageDir)
		if err != nil {
			return fmt.Errorf("Could not remove directory %v: %v", packageDir, err)
		}

		if err := os.MkdirAll(packageDir, 0755); err != nil {
			return fmt.Errorf("Could not create directory %v: %v", packageDir, err)
		}
	}
	if !sdkcommon.DirectoryExists(filepath.Join(packageDir, "amber-files")) {
		if err = extractTar(ctx, archiveFile, packageDir); err != nil {
			logger.Fatalf(ctx, "Could not create extract %v into %v: %v", archiveFile, packageDir, err)
		}
	}
	md5File, err := os.Create(checksumFile)
	if err != nil {
		logger.Fatalf(ctx, "Could not write checksum file %v: %v\n", checksumFile, err)
	}
	defer md5File.Close()
	_, err = md5File.WriteString(fmt.Sprintf("%v %v\n", md5Hash, archiveFile))

	return err
}

// registerPMRepository sets the URL for the package server on the target device.
func registerPMRepository(ctx context.Context, sdk sdkProvider, repoPort string, name string,
	targetAddress string, sshConfig string, privateKey string, persist bool, sshPort string) error {

	var (
		err error
		log = logger.LoggerFromContext(ctx)
	)

	if targetAddress == "" {
		return errors.New("target address required")
	}

	log.Debugf("Using target address %v", targetAddress)

	hostIP, err := getHostIPAddressFromTarget(sdk, targetAddress, sshConfig, privateKey, sshPort)
	if err != nil {
		return fmt.Errorf("Could not get host address from target %v: %v", targetAddress, err)
	}
	// A simple heuristic for "is an ipv6 address", URL encase escape
	// the address.
	if strings.Contains(hostIP, ":") {
		hostIP = strings.ReplaceAll(hostIP, "%", "%25")
		hostIP = fmt.Sprintf("[%s]", hostIP)
	}

	var sshArgs []string
	if persist {
		sshArgs = []string{"pkgctl", "repo", "add", "url", "-p", "-n", name,
			fmt.Sprintf("http://%v:%v/config.json", hostIP, repoPort)}
	} else {
		sshArgs = []string{"pkgctl", "repo", "add", "url", "-n", name,
			fmt.Sprintf("http://%v:%v/config.json", hostIP, repoPort)}
	}

	verbose := level == logger.DebugLevel || level == logger.TraceLevel
	if _, err = sdk.RunSSHCommand(targetAddress, sshConfig, privateKey, sshPort, verbose, sshArgs); err != nil {
		return fmt.Errorf("Could not set package server address on device: %v", err)
	}

	ruleTemplate := `'{"version":"1","content":[{"host_match":"fuchsia.com","host_replacement":"%v","path_prefix_match":"/","path_prefix_replacement":"/"}]}'`
	sshArgs = []string{"pkgctl", "rule", "replace", "json",
		fmt.Sprintf(ruleTemplate, name)}
	if _, err = sdk.RunSSHCommand(targetAddress, sshConfig, privateKey, sshPort, verbose, sshArgs); err != nil {
		return fmt.Errorf("Could not set package url rewriting rules on device: %v", err)
	}

	return nil
}

// getHostIPAddressFromTarget returns the host address reported from the SSH connection on the target device.
func getHostIPAddressFromTarget(sdk sdkProvider, targetAddress string, sshConfig string, privateKey string,
	sshPort string) (string, error) {

	var sshArgs = []string{"echo", "$SSH_CONNECTION"}

	verbose := level == logger.DebugLevel || level == logger.TraceLevel
	connectionString, err := sdk.RunSSHCommand(targetAddress, sshConfig, privateKey,
		sshPort, verbose, sshArgs)

	if err != nil {
		return "", err
	}

	parts := strings.Fields(connectionString)

	return strings.TrimSpace(parts[0]), nil
}

// extractTar extracts the contents from the srcFile tarball into the destDir.
func extractTar(ctx context.Context, srcFile string, destDir string) error {

	log := logger.LoggerFromContext(ctx)
	f, err := os.Open(srcFile)
	if err != nil {
		return fmt.Errorf("Could not open %v: %v", srcFile, err)
	}
	defer f.Close()
	uncompressedStream, err := gzip.NewReader(f)
	if err != nil {
		return fmt.Errorf("extractTar: NewReader failed: %v", err)
	}

	tarReader := tar.NewReader(uncompressedStream)

	for true {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			return fmt.Errorf("extractTar: Next() failed: %v", err)
		}

		switch header.Typeflag {
		case tar.TypeDir:
			dir := filepath.Join(destDir, header.Name)
			log.Debugf("mkdir %v", dir)
			if err := os.MkdirAll(dir, 0755); err != nil {
				return fmt.Errorf("extractTar: Mkdir() failed: %v", err)
			}
		case tar.TypeReg:
			newFile := filepath.Join(destDir, header.Name)
			log.Debugf("extracting %v", newFile)
			if err := os.MkdirAll(filepath.Dir(newFile), 0755); err != nil {
				return fmt.Errorf("extractTar: MkdirAll in Create() failed: %v", err)
			}
			outFile, err := os.Create(newFile)
			if err != nil {
				return fmt.Errorf("extractTar: Create() failed: %v", err)
			}
			if _, err := io.Copy(outFile, tarReader); err != nil {
				return fmt.Errorf("extractTar: Copy() failed: %v", err)
			}
			outFile.Close()

		default:
			return fmt.Errorf("extractTar: uknown type: %v in %v", header.Typeflag, header.Name)
		}
	}
	return nil
}

// calculateMD5 for the given file.
func calculateMD5(filename string) (string, error) {
	f, err := os.Open(filename)
	if err != nil {
		return "", fmt.Errorf("Cannot open %v: %v", filename, err)
	}
	defer f.Close()

	h := md5.New()
	if _, err := io.Copy(h, f); err != nil {
		return "", fmt.Errorf("Cannot calculate md5 for %v: %v", filename, err)
	}
	return fmt.Sprintf("%x", h.Sum(nil)), nil
}

func copyDir(ctx context.Context, srcDir string, destDir string) error {
	log := logger.LoggerFromContext(ctx)

	log.Debugf("Copying directory %v to %v", srcDir, destDir)

	srcDirFile, err := os.Open(srcDir)
	if err != nil {
		return fmt.Errorf("Error opening src dir: %v", err)
	}
	defer srcDirFile.Close()

	srcDirStat, err := srcDirFile.Stat()
	if err != nil {
		return err
	}
	if !srcDirStat.IsDir() {
		return fmt.Errorf("Source %v is not a directory", srcDir)
	}

	err = os.MkdirAll(destDir, 0755)
	if err != nil {
		return err
	}

	// Process the contents of srcDir
	contents, err := ioutil.ReadDir(srcDir)
	if err != nil {
		return err
	}
	for _, item := range contents {
		if item.IsDir() {
			// recurse
			err := copyDir(ctx, filepath.Join(srcDir, item.Name()), filepath.Join(destDir, item.Name()))
			if err != nil {
				return err
			}
		} else {
			srcName := filepath.Join(srcDir, item.Name())
			destName := filepath.Join(destDir, item.Name())
			log.Debugf("Copying file %v to %v", srcName, destName)

			srcFile, err := os.Open(srcName)
			if err != nil {
				return err
			}
			defer srcFile.Close()
			destFile, err := os.Create(destName)
			if err != nil {
				return err
			}
			defer destFile.Close()
			// dest is first - which is backwards from cp.
			_, err = io.Copy(destFile, srcFile)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
