mirror of https://github.com/vitalif/grive2
Updated Progress Bar
parent
422447fc19
commit
90d5ce823d
|
@ -127,6 +127,7 @@ int Main( int argc, char **argv )
|
|||
( "ignore", po::value<std::string>(), "Perl RegExp to ignore files (matched against relative paths)." )
|
||||
( "upload-speed,U", po::value<unsigned>(), "Limit upload speed in kbytes per second" )
|
||||
( "download-speed,D", po::value<unsigned>(), "Limit download speed in kbytes per second" )
|
||||
( "progress-bar", "Enable progress bar for upload/download of files")
|
||||
;
|
||||
|
||||
po::variables_map vm;
|
||||
|
@ -150,13 +151,16 @@ int Main( int argc, char **argv )
|
|||
InitLog(vm) ;
|
||||
|
||||
Config config(vm) ;
|
||||
|
||||
|
||||
Log( "config file name %1%", config.Filename(), log::verbose );
|
||||
|
||||
std::unique_ptr<http::Agent> http( new http::CurlAgent );
|
||||
if ( vm.count( "log-http" ) )
|
||||
http->SetLog( new http::ResponseLog( vm["log-http"].as<std::string>(), ".txt" ) );
|
||||
|
||||
ProgressBar *pb = new ProgressBar(vm.count( "progress-bar" ) != 0);
|
||||
http->SetProgressBar(pb);
|
||||
|
||||
if ( vm.count( "auth" ) )
|
||||
{
|
||||
OAuth2 token( http.get(), client_id, client_secret ) ;
|
||||
|
@ -179,6 +183,7 @@ int Main( int argc, char **argv )
|
|||
config.Set( "refresh_token", Val( token.RefreshToken() ) ) ;
|
||||
config.Save() ;
|
||||
}
|
||||
|
||||
|
||||
std::string refresh_token ;
|
||||
try
|
||||
|
@ -211,12 +216,17 @@ int Main( int argc, char **argv )
|
|||
|
||||
if ( vm.count( "dry-run" ) == 0 )
|
||||
{
|
||||
//The progress bar should just be enabled when actual file transfers take place
|
||||
pb->SetShowProgressBar(true);
|
||||
drive.Update() ;
|
||||
pb->SetShowProgressBar(false);
|
||||
|
||||
drive.UpdateChangeStamp();
|
||||
drive.SaveState() ;
|
||||
}
|
||||
else
|
||||
drive.DryRun() ;
|
||||
|
||||
|
||||
config.Save() ;
|
||||
Log( "Finished!", log::info ) ;
|
||||
return 0 ;
|
||||
|
|
|
@ -120,8 +120,6 @@ void Drive::Update()
|
|||
{
|
||||
Log( "Synchronizing files", log::info ) ;
|
||||
m_state.Sync( m_syncer, m_options ) ;
|
||||
|
||||
UpdateChangeStamp( ) ;
|
||||
}
|
||||
|
||||
void Drive::DryRun()
|
||||
|
|
|
@ -44,6 +44,7 @@ public :
|
|||
void Update() ;
|
||||
void DryRun() ;
|
||||
void SaveState() ;
|
||||
void UpdateChangeStamp() ;
|
||||
|
||||
struct Error : virtual Exception {} ;
|
||||
|
||||
|
@ -53,8 +54,7 @@ private :
|
|||
void ReadChanges() ;
|
||||
void FromRemote( const Entry& entry ) ;
|
||||
void FromChange( const Entry& entry ) ;
|
||||
void UpdateChangeStamp( ) ;
|
||||
|
||||
|
||||
private :
|
||||
Syncer *m_syncer ;
|
||||
fs::path m_root ;
|
||||
|
|
|
@ -120,9 +120,9 @@ std::string Entry::Name() const
|
|||
return !m_filename.empty() ? m_filename : m_title ;
|
||||
}
|
||||
|
||||
long Entry::DownloadFileBytes() const
|
||||
long Entry::Size() const
|
||||
{
|
||||
return m_downloadFileBytes;
|
||||
return m_size ;
|
||||
}
|
||||
|
||||
} // end of namespace gr
|
||||
|
|
|
@ -61,7 +61,7 @@ public :
|
|||
|
||||
const std::vector<std::string>& ParentHrefs() const ;
|
||||
|
||||
long DownloadFileBytes() const;
|
||||
long Size() const ;
|
||||
|
||||
protected :
|
||||
std::string m_title ;
|
||||
|
@ -82,7 +82,7 @@ protected :
|
|||
|
||||
DateTime m_mtime ;
|
||||
bool m_is_removed ;
|
||||
long m_downloadFileBytes;
|
||||
long m_size ;
|
||||
} ;
|
||||
|
||||
} // end of namespace gr
|
||||
|
|
|
@ -149,7 +149,7 @@ void Resource::AssignIDs( const Entry& remote )
|
|||
m_content = remote.ContentSrc() ;
|
||||
m_is_editable = remote.IsEditable() ;
|
||||
m_etag = remote.ETag() ;
|
||||
m_downloadFileBytes = remote.DownloadFileBytes();
|
||||
m_downloadFileBytes = remote.Size() ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,9 +66,12 @@ void Entry2::Update( const Val& item )
|
|||
m_is_removed = file["labels"]["trashed"].Bool() ;
|
||||
|
||||
if (file.Has("fileSize"))
|
||||
m_downloadFileBytes = file["fileSize"].U64() ;
|
||||
else
|
||||
m_downloadFileBytes = 0;
|
||||
{
|
||||
m_size = file["fileSize"].U64() ;
|
||||
} else
|
||||
{
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
if ( !m_is_dir )
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <string>
|
||||
#include "ResponseLog.hh"
|
||||
#include "util/Types.hh"
|
||||
#include "util/ProgressBar.hh"
|
||||
|
||||
namespace gr {
|
||||
|
||||
|
@ -86,6 +87,8 @@ public :
|
|||
|
||||
virtual std::string Escape( const std::string& str ) = 0 ;
|
||||
virtual std::string Unescape( const std::string& str ) = 0 ;
|
||||
|
||||
virtual void SetProgressBar( ProgressBar* ) = 0;
|
||||
} ;
|
||||
|
||||
} } // end of namespace
|
||||
|
|
|
@ -38,9 +38,6 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -113,11 +110,16 @@ void CurlAgent::SetLog(ResponseLog *log)
|
|||
m_log.reset( log );
|
||||
}
|
||||
|
||||
void CurlAgent::SetProgressBar(ProgressBar *progressbar)
|
||||
{
|
||||
m_pb.reset(progressbar);
|
||||
}
|
||||
|
||||
std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis )
|
||||
{
|
||||
char *str = static_cast<char*>(ptr) ;
|
||||
std::string line( str, str + size*nmemb ) ;
|
||||
|
||||
|
||||
// Check for error (HTTP 400 and above)
|
||||
if ( line.substr( 0, 5 ) == "HTTP/" && line[9] >= '4' )
|
||||
pthis->m_pimpl->error = true;
|
||||
|
@ -127,7 +129,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
|
|||
|
||||
if ( pthis->m_log.get() )
|
||||
pthis->m_log->Write( str, size*nmemb );
|
||||
|
||||
|
||||
static const std::string loc = "Location: " ;
|
||||
std::size_t pos = line.find( loc ) ;
|
||||
if ( pos != line.npos )
|
||||
|
@ -135,7 +137,7 @@ std::size_t CurlAgent::HeaderCallback( void *ptr, size_t size, size_t nmemb, Cur
|
|||
std::size_t end_pos = line.find( "\r\n", pos ) ;
|
||||
pthis->m_pimpl->location = line.substr( loc.size(), end_pos - loc.size() ) ;
|
||||
}
|
||||
|
||||
|
||||
return size*nmemb ;
|
||||
}
|
||||
|
||||
|
@ -146,9 +148,10 @@ std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent
|
|||
if ( pthis->m_log.get() )
|
||||
pthis->m_log->Write( (const char*)ptr, size*nmemb );
|
||||
|
||||
if (pthis->totalDownlaodSize > 0) {
|
||||
if ( pthis->totalDownloadSize > 0 )
|
||||
{
|
||||
pthis->downloadedBytes += (curl_off_t)size*nmemb;
|
||||
CurlAgent::progress_callback(pthis, pthis->totalDownlaodSize, pthis->downloadedBytes, 0L, 0L);
|
||||
CurlAgent::progress_callback(pthis, pthis->totalDownloadSize, pthis->downloadedBytes, 0L, 0L);
|
||||
}
|
||||
|
||||
if ( pthis->m_pimpl->error && pthis->m_pimpl->error_data.size() < 65536 )
|
||||
|
@ -161,101 +164,10 @@ std::size_t CurlAgent::Receive( void* ptr, size_t size, size_t nmemb, CurlAgent
|
|||
}
|
||||
|
||||
|
||||
unsigned short int CurlAgent::DetermineTerminalSize() {
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
return w.ws_col;
|
||||
}
|
||||
|
||||
std::string CurlAgent::CalculateByteSize(curl_off_t bytes, bool withSuffix) {
|
||||
long double KB = bytes / 1024;
|
||||
long double MB = KB / 1024;
|
||||
long double GB = MB / 1024;
|
||||
std::string res;
|
||||
std::string suffix;
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << std::fixed << std::setprecision(2);
|
||||
|
||||
if (GB > 1) {
|
||||
ss << GB;
|
||||
suffix = "GB";
|
||||
}
|
||||
else if (MB > 1) {
|
||||
ss << MB;
|
||||
suffix = "MB";
|
||||
} else {
|
||||
ss << KB;
|
||||
suffix = "KB";
|
||||
}
|
||||
|
||||
res = ss.str() + (withSuffix ? suffix : "");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int CurlAgent::progress_callback(void *ptr, curl_off_t TotalDownloadSize, curl_off_t finishedDownloadSize, curl_off_t TotalToUpload, curl_off_t NowUploaded) {
|
||||
curl_off_t processed = (TotalDownloadSize > TotalToUpload) ? finishedDownloadSize : NowUploaded;
|
||||
curl_off_t total = (TotalDownloadSize > TotalToUpload) ? TotalDownloadSize : TotalToUpload;
|
||||
|
||||
if (total <= 0.0)
|
||||
return 0;
|
||||
|
||||
//libcurl seems to process more bytes then the actual file size :)
|
||||
if (processed > total)
|
||||
processed = total;
|
||||
|
||||
|
||||
int availableSize = CurlAgent::DetermineTerminalSize() - 30; //10 for prefix of percent and 20 for suffix of file size
|
||||
|
||||
int totalDots;
|
||||
|
||||
if (availableSize > 100)
|
||||
totalDots = 100;
|
||||
else if (availableSize < 0)
|
||||
totalDots = 10;
|
||||
else
|
||||
totalDots = availableSize;
|
||||
|
||||
double fraction = (float)processed / total;
|
||||
|
||||
if ((fraction*100) < 100.0)
|
||||
((CurlAgent*)ptr)->hundredpercentDone = false;
|
||||
|
||||
if (!((CurlAgent*)ptr)->hundredpercentDone) {
|
||||
printf("\33[2K\r"); //delete previous output line
|
||||
int dotz = round(fraction * totalDots);
|
||||
|
||||
int count=0;
|
||||
printf(" [%3.0f%%] [", fraction*100);
|
||||
|
||||
for (; count < dotz-1; count++) {
|
||||
printf("=");
|
||||
}
|
||||
|
||||
printf(">");
|
||||
|
||||
for (; count < totalDots-1; count++) {
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("] ");
|
||||
|
||||
printf("%s/%s", CalculateByteSize(processed, false).c_str(), CalculateByteSize(total, true).c_str());
|
||||
|
||||
printf("\r");
|
||||
|
||||
if ((fraction*100) >= 100.0) {
|
||||
((CurlAgent*)ptr)->hundredpercentDone = true;
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
int CurlAgent::progress_callback(void *ptr, curl_off_t totalDownloadSize, curl_off_t finishedDownloadSize, curl_off_t totalToUpload, curl_off_t finishedUploaded)
|
||||
{
|
||||
((CurlAgent*)ptr)->m_pb->PrintProgressBar(totalDownloadSize, finishedDownloadSize, totalToUpload, finishedUploaded);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -276,11 +188,9 @@ long CurlAgent::ExecCurl(
|
|||
|
||||
struct curl_slist *slist = SetHeader( m_pimpl->curl, hdr ) ;
|
||||
|
||||
if (progressBar) {
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback);
|
||||
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
|
||||
|
||||
CURLcode curl_code = ::curl_easy_perform(curl);
|
||||
|
||||
|
@ -324,8 +234,8 @@ long CurlAgent::Request(
|
|||
|
||||
Init() ;
|
||||
CURL *curl = m_pimpl->curl ;
|
||||
progressBar = false;
|
||||
totalDownlaodSize = 0;
|
||||
|
||||
this->totalDownloadSize = downloadFileBytes;
|
||||
|
||||
// set common options
|
||||
::curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str() );
|
||||
|
@ -335,17 +245,6 @@ long CurlAgent::Request(
|
|||
::curl_easy_setopt(curl, CURLOPT_READFUNCTION, &ReadFileCallback ) ;
|
||||
::curl_easy_setopt(curl, CURLOPT_READDATA , in ) ;
|
||||
::curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>( in->Size() ) ) ;
|
||||
|
||||
if (url.compare("https://accounts.google.com/o/oauth2/token"))
|
||||
progressBar = true;
|
||||
else
|
||||
progressBar = false;
|
||||
} else {
|
||||
if (!boost::starts_with(url, "https://www.googleapis.com/")) {
|
||||
progressBar = true;
|
||||
totalDownlaodSize = downloadFileBytes;
|
||||
} else
|
||||
progressBar = false;
|
||||
}
|
||||
|
||||
return ExecCurl( url, dest, hdr ) ;
|
||||
|
|
|
@ -46,6 +46,7 @@ public :
|
|||
|
||||
ResponseLog* GetLog() const ;
|
||||
void SetLog( ResponseLog *log ) ;
|
||||
void SetProgressBar( ProgressBar *progressbar) ;
|
||||
|
||||
long Request(
|
||||
const std::string& method,
|
||||
|
@ -62,13 +63,8 @@ public :
|
|||
|
||||
std::string Escape( const std::string& str ) ;
|
||||
std::string Unescape( const std::string& str ) ;
|
||||
bool hundredpercentDone;
|
||||
long totalDownlaodSize;
|
||||
long downloadedBytes;
|
||||
|
||||
static int progress_callback(void *ptr, curl_off_t TotalDownloadSize, curl_off_t finishedDownloadSize, curl_off_t TotalToUpload, curl_off_t NowUploaded);
|
||||
static std::string CalculateByteSize(curl_off_t bytes, bool withSuffix);
|
||||
static unsigned short int DetermineTerminalSize() ;
|
||||
|
||||
private :
|
||||
static std::size_t HeaderCallback( void *ptr, size_t size, size_t nmemb, CurlAgent *pthis ) ;
|
||||
|
@ -83,14 +79,12 @@ private :
|
|||
|
||||
private :
|
||||
struct Impl ;
|
||||
<<<<<<< 357d7ac833ece9e279242b3608c157a691709dc3
|
||||
std::unique_ptr<Impl> m_pimpl ;
|
||||
std::unique_ptr<ResponseLog> m_log ;
|
||||
=======
|
||||
std::auto_ptr<Impl> m_pimpl ;
|
||||
std::auto_ptr<ResponseLog> m_log ;
|
||||
bool progressBar ;
|
||||
>>>>>>> Progress bar for upload/download of files
|
||||
std::unique_ptr<Impl> m_pimpl ;
|
||||
std::unique_ptr<ResponseLog> m_log ;
|
||||
std::unique_ptr<ProgressBar> m_pb ;
|
||||
|
||||
long totalDownloadSize;
|
||||
long downloadedBytes;
|
||||
} ;
|
||||
|
||||
} } // end of namespace
|
||||
|
|
|
@ -48,6 +48,11 @@ void AuthAgent::SetLog( http::ResponseLog *log )
|
|||
return m_agent->SetLog( log );
|
||||
}
|
||||
|
||||
void AuthAgent::SetProgressBar( ProgressBar *progressbar )
|
||||
{
|
||||
return m_agent->SetProgressBar( progressbar );
|
||||
}
|
||||
|
||||
void AuthAgent::SetUploadSpeed( unsigned kbytes )
|
||||
{
|
||||
m_agent->SetUploadSpeed( kbytes );
|
||||
|
|
|
@ -58,6 +58,8 @@ public :
|
|||
void SetUploadSpeed( unsigned kbytes ) ;
|
||||
void SetDownloadSpeed( unsigned kbytes ) ;
|
||||
|
||||
void SetProgressBar( ProgressBar *progressbar ) ;
|
||||
|
||||
private :
|
||||
http::Header AppendHeader( const http::Header& hdr ) const ;
|
||||
bool CheckRetry( long response ) ;
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
#include "ProgressBar.hh"
|
||||
#include <sys/ioctl.h>
|
||||
#include <math.h>
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace gr
|
||||
{
|
||||
|
||||
ProgressBar::ProgressBar(bool enable_parameter)
|
||||
{
|
||||
this->progressBar_enabled = enable_parameter;
|
||||
}
|
||||
|
||||
ProgressBar::~ProgressBar()
|
||||
{
|
||||
}
|
||||
|
||||
void ProgressBar::SetShowProgressBar(bool showProgressBar)
|
||||
{
|
||||
this->showProgressBar = showProgressBar;
|
||||
}
|
||||
|
||||
unsigned short int ProgressBar::DetermineTerminalSize()
|
||||
{
|
||||
struct winsize w;
|
||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||
|
||||
return w.ws_col;
|
||||
}
|
||||
|
||||
std::string ProgressBar::CalculateByteSize(long bytes)
|
||||
{
|
||||
long double KB = bytes / 1024;
|
||||
long double MB = KB / 1024;
|
||||
long double GB = MB / 1024;
|
||||
std::string res;
|
||||
std::string suffix;
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << std::fixed << std::setprecision(2);
|
||||
|
||||
if (GB > 1)
|
||||
{
|
||||
ss << GB;
|
||||
suffix = "GB";
|
||||
}
|
||||
else if (MB > 1)
|
||||
{
|
||||
ss << MB;
|
||||
suffix = "MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << KB;
|
||||
suffix = "KB";
|
||||
}
|
||||
|
||||
res = ss.str() + suffix;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void ProgressBar::PrintProgressBar(long TotalDownloadSize, long finishedDownloadSize, long TotalToUpload, long NowUploaded)
|
||||
{
|
||||
if (this->showProgressBar && this->progressBar_enabled)
|
||||
{
|
||||
long processed = (TotalDownloadSize > TotalToUpload) ? finishedDownloadSize : NowUploaded;
|
||||
long total = (TotalDownloadSize > TotalToUpload) ? TotalDownloadSize : TotalToUpload;
|
||||
|
||||
if (total <= 0.0)
|
||||
return;
|
||||
|
||||
//libcurl seems to process more bytes then the actual file size :)
|
||||
if (processed > total)
|
||||
processed = total;
|
||||
|
||||
int availableSize = this->DetermineTerminalSize() - 32; //10 for prefix of percent and 22 for suffix of file size
|
||||
|
||||
int totalDots;
|
||||
if (availableSize > 100)
|
||||
totalDots = 100;
|
||||
else if (availableSize < 0)
|
||||
totalDots = 10;
|
||||
else
|
||||
totalDots = availableSize;
|
||||
|
||||
double fraction = (float) processed / total;
|
||||
|
||||
if ((fraction * 100) < 100.0)
|
||||
this->hundredpercentDone = false;
|
||||
|
||||
if (!this->hundredpercentDone)
|
||||
{
|
||||
printf("\33[2K\r"); //delete previous output line
|
||||
|
||||
int dotz = round(fraction * totalDots);
|
||||
int count = 0;
|
||||
|
||||
printf(" [%3.0f%%] [", fraction * 100);
|
||||
|
||||
for (; count < dotz - 1; count++)
|
||||
{
|
||||
printf("=");
|
||||
}
|
||||
|
||||
printf(">");
|
||||
|
||||
for (; count < totalDots - 1; count++)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
printf("] ");
|
||||
printf("%s/%s", this->CalculateByteSize(processed).c_str(), this->CalculateByteSize(total).c_str());
|
||||
printf("\r");
|
||||
|
||||
if ((fraction * 100) >= 100.0)
|
||||
{
|
||||
this->hundredpercentDone = true;
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#include <string>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace gr
|
||||
{
|
||||
|
||||
class ProgressBar
|
||||
{
|
||||
|
||||
public:
|
||||
ProgressBar(bool enable_parameter);
|
||||
virtual ~ProgressBar();
|
||||
|
||||
void PrintProgressBar(long TotalDownloadSize, long finishedDownloadSize, long TotalToUpload, long NowUploaded);
|
||||
void SetShowProgressBar(bool showProgressBar);
|
||||
|
||||
private:
|
||||
static std::string CalculateByteSize(long bytes);
|
||||
static unsigned short int DetermineTerminalSize();
|
||||
|
||||
bool hundredpercentDone = false;
|
||||
bool showProgressBar = false;
|
||||
bool progressBar_enabled = false;
|
||||
};
|
||||
|
||||
}
|
||||
;
|
||||
|
Loading…
Reference in New Issue