Added transfer progress reporting for push and pull commands.

Added a new '-p' switch to the 'push' and 'pull' commands that outputs
the file transfer progress (bytes transmitted, total bytes, and % done).
This provides useful feedback when transferring large files, and also
makes it possible for other tools to easily monitor the progress of a
forked push/pull command.

Change-Id: Iee6f42f5bd41292e5bc80fba779f526f0072e356
diff --git a/commandline.c b/commandline.c
index c9bb437..83b568d 100644
--- a/commandline.c
+++ b/commandline.c
@@ -107,8 +107,12 @@
         "                                 will disconnect from all connected TCP/IP devices.\n"
         "\n"
         "device commands:\n"
-        "  adb push <local> <remote>    - copy file/dir to device\n"
-        "  adb pull <remote> [<local>]  - copy file/dir from device\n"
+        "  adb push [-p] <local> <remote>\n"
+        "                               - copy file/dir to device\n"
+        "                                 ('-p' to display the transfer progress)\n"
+        "  adb pull [-p] <remote> [<local>]\n"
+        "                               - copy file/dir from device\n"
+        "                                 ('-p' to display the transfer progress)\n"
         "  adb sync [ <directory> ]     - copy host->device only if changed\n"
         "                                 (-l means list but don't copy)\n"
         "                                 (see 'adb help all')\n"
@@ -921,6 +925,28 @@
     return path_buf;
 }
 
+
+static void parse_push_pull_args(char** arg, int narg, char const** path1, char const** path2,
+                                 int* show_progress) {
+    *show_progress = 0;
+
+    if ((narg > 0) && !strcmp(*arg, "-p")) {
+        *show_progress = 1;
+        ++arg;
+        --narg;
+    }
+
+    if (narg > 0) {
+        *path1 = *arg;
+        ++arg;
+        --narg;
+    }
+
+    if (narg > 0) {
+        *path2 = *arg;
+    }
+}
+
 int adb_commandline(int argc, char **argv)
 {
     char buf[4096];
@@ -1368,18 +1394,29 @@
     }
 
     if(!strcmp(argv[0], "push")) {
-        if(argc != 3) return usage();
-        return do_sync_push(argv[1], argv[2], 0 /* no verify APK */);
+        int show_progress = 0;
+        const char* lpath = NULL, *rpath = NULL;
+
+        parse_push_pull_args(&argv[1], argc - 1, &lpath, &rpath, &show_progress);
+
+        if ((lpath != NULL) && (rpath != NULL)) {
+            return do_sync_push(lpath, rpath, 0 /* no verify APK */, show_progress);
+        }
+
+        return usage();
     }
 
     if(!strcmp(argv[0], "pull")) {
-        if (argc == 2) {
-            return do_sync_pull(argv[1], ".");
-        } else if (argc == 3) {
-            return do_sync_pull(argv[1], argv[2]);
-        } else {
-            return usage();
+        int show_progress = 0;
+        const char* rpath = NULL, *lpath = ".";
+
+        parse_push_pull_args(&argv[1], argc - 1, &rpath, &lpath, &show_progress);
+
+        if (rpath != NULL) {
+            return do_sync_pull(rpath, lpath, show_progress);
         }
+
+        return usage();
     }
 
     if(!strcmp(argv[0], "install")) {
@@ -1717,7 +1754,7 @@
         }
     }
 
-    err = do_sync_push(apk_file, apk_dest, verify_apk);
+    err = do_sync_push(apk_file, apk_dest, verify_apk, 0 /* no show progress */);
     if (err) {
         goto cleanup_apk;
     } else {
@@ -1725,7 +1762,8 @@
     }
 
     if (verification_file != NULL) {
-        err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */);
+        err = do_sync_push(verification_file, verification_dest, 0 /* no verify APK */,
+                           0 /* no show progress */);
         if (err) {
             goto cleanup_apk;
         } else {