diff --git a/adb/file_sync_client.cpp b/adb/file_sync_client.cpp index 463c1c0d1..239aaf8c0 100644 --- a/adb/file_sync_client.cpp +++ b/adb/file_sync_client.cpp @@ -76,6 +76,8 @@ class SyncConnection { ReadOrderlyShutdown(fd); } adb_close(fd); + + line_printer_.KeepInfoLine(); } bool IsValid() { return fd >= 0; } @@ -243,8 +245,7 @@ class SyncConnection { } void Print(const std::string& s) { - // TODO: we actually don't want ELIDE; we want "ELIDE if smart, FULL if dumb". - line_printer_.Print(s, LinePrinter::ELIDE); + line_printer_.Print(s, LinePrinter::INFO); } void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) { @@ -265,7 +266,7 @@ class SyncConnection { android::base::StringAppendV(&s, fmt, ap); va_end(ap); - line_printer_.Print(s, LinePrinter::FULL); + line_printer_.Print(s, LinePrinter::ERROR); } void Warning(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) { @@ -276,7 +277,7 @@ class SyncConnection { android::base::StringAppendV(&s, fmt, ap); va_end(ap); - line_printer_.Print(s, LinePrinter::FULL); + line_printer_.Print(s, LinePrinter::WARNING); } uint64_t total_bytes; @@ -664,7 +665,7 @@ static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, } } - sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s\n", rpath.c_str(), + sc.Printf("%s: %d file%s pushed. %d file%s skipped.%s", rpath.c_str(), pushed, (pushed == 1) ? "" : "s", skipped, (skipped == 1) ? "" : "s", sc.TransferRate().c_str()); return true; @@ -739,7 +740,6 @@ bool do_sync_push(const std::vector& srcs, const char* dst) { success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode); } - sc.Print("\n"); return success; } @@ -858,7 +858,7 @@ static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, } } - sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s\n", rpath.c_str(), + sc.Printf("%s: %d file%s pulled. %d file%s skipped.%s", rpath.c_str(), pulled, (pulled == 1) ? "" : "s", skipped, (skipped == 1) ? "" : "s", sc.TransferRate().c_str()); return true; @@ -967,7 +967,6 @@ bool do_sync_pull(const std::vector& srcs, const char* dst, } } - sc.Print("\n"); return success; } diff --git a/adb/line_printer.cpp b/adb/line_printer.cpp index 4c57c7eba..e8fe6c97d 100644 --- a/adb/line_printer.cpp +++ b/adb/line_printer.cpp @@ -43,7 +43,7 @@ string ElideMiddle(const string& str, size_t width) { return result; } -LinePrinter::LinePrinter() : have_blank_line_(true), console_locked_(false) { +LinePrinter::LinePrinter() : have_blank_line_(true) { #ifndef _WIN32 const char* term = getenv("TERM"); smart_terminal_ = unix_isatty(1) && term && string(term) != "dumb"; @@ -59,20 +59,24 @@ LinePrinter::LinePrinter() : have_blank_line_(true), console_locked_(false) { #endif } +static void Out(const std::string& s) { + // Avoid printf and C strings, since the actual output might contain null + // bytes like UTF-16 does (yuck). + fwrite(s.data(), 1, s.size(), stdout); +} + void LinePrinter::Print(string to_print, LineType type) { - if (console_locked_) { - line_buffer_ = to_print; - line_type_ = type; + if (!smart_terminal_) { + Out(to_print); return; } - if (smart_terminal_) { - printf("\r"); // Print over previous line, if any. - // On Windows, calling a C library function writing to stdout also handles - // pausing the executable when the "Pause" key or Ctrl-S is pressed. - } + // Print over previous line, if any. + // On Windows, calling a C library function writing to stdout also handles + // pausing the executable when the "Pause" key or Ctrl-S is pressed. + printf("\r"); - if (smart_terminal_ && type == ELIDE) { + if (type == INFO) { #ifdef _WIN32 CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(console_, &csbi); @@ -105,57 +109,19 @@ void LinePrinter::Print(string to_print, LineType type) { if ((ioctl(0, TIOCGWINSZ, &size) == 0) && size.ws_col) { to_print = ElideMiddle(to_print, size.ws_col); } - printf("%s", to_print.c_str()); + Out(to_print); printf("\x1B[K"); // Clear to end of line. fflush(stdout); #endif have_blank_line_ = false; } else { - printf("%s\n", to_print.c_str()); + Out(to_print); + Out("\n"); + have_blank_line_ = true; } } -void LinePrinter::PrintOrBuffer(const char* data, size_t size) { - if (console_locked_) { - output_buffer_.append(data, size); - } else { - // Avoid printf and C strings, since the actual output might contain null - // bytes like UTF-16 does (yuck). - fwrite(data, 1, size, stdout); - } -} - -void LinePrinter::PrintOnNewLine(const string& to_print) { - if (console_locked_ && !line_buffer_.empty()) { - output_buffer_.append(line_buffer_); - output_buffer_.append(1, '\n'); - line_buffer_.clear(); - } - if (!have_blank_line_) { - PrintOrBuffer("\n", 1); - } - if (!to_print.empty()) { - PrintOrBuffer(&to_print[0], to_print.size()); - } - have_blank_line_ = to_print.empty() || *to_print.rbegin() == '\n'; -} - -void LinePrinter::SetConsoleLocked(bool locked) { - if (locked == console_locked_) - return; - - if (locked) - PrintOnNewLine(""); - - console_locked_ = locked; - - if (!locked) { - PrintOnNewLine(output_buffer_); - if (!line_buffer_.empty()) { - Print(line_buffer_, line_type_); - } - output_buffer_.clear(); - line_buffer_.clear(); - } +void LinePrinter::KeepInfoLine() { + if (!have_blank_line_) Out("\n"); } diff --git a/adb/line_printer.h b/adb/line_printer.h index 3d0a5bd73..42345e2d6 100644 --- a/adb/line_printer.h +++ b/adb/line_printer.h @@ -26,20 +26,14 @@ struct LinePrinter { bool is_smart_terminal() const { return smart_terminal_; } void set_smart_terminal(bool smart) { smart_terminal_ = smart; } - enum LineType { - FULL, - ELIDE - }; - /// Overprints the current line. If type is ELIDE, elides to_print to fit on - /// one line. + enum LineType { INFO, WARNING, ERROR }; + + /// Outputs the given line. INFO output will be overwritten. + /// WARNING and ERROR appear on a line to themselves. void Print(std::string to_print, LineType type); - /// Prints a string on a new line, not overprinting previous output. - void PrintOnNewLine(const std::string& to_print); - - /// Lock or unlock the console. Any output sent to the LinePrinter while the - /// console is locked will not be printed until it is unlocked. - void SetConsoleLocked(bool locked); + /// If there's an INFO line, keep it. If not, do nothing. + void KeepInfoLine(); private: /// Whether we can do fancy terminal control codes. @@ -48,24 +42,9 @@ struct LinePrinter { /// Whether the caret is at the beginning of a blank line. bool have_blank_line_; - /// Whether console is locked. - bool console_locked_; - - /// Buffered current line while console is locked. - std::string line_buffer_; - - /// Buffered line type while console is locked. - LineType line_type_; - - /// Buffered console output while console is locked. - std::string output_buffer_; - #ifdef _WIN32 void* console_; #endif - - /// Print the given data to the console, or buffer it if it is locked. - void PrintOrBuffer(const char *data, size_t size); }; #endif // NINJA_LINE_PRINTER_H_