mirror of https://github.com/vitalif/grive2
pull/40/head
commit
ac1763f2c7
|
@ -4,3 +4,13 @@ grive.kdev4
|
|||
.project
|
||||
.cproject
|
||||
build/
|
||||
/CMakeCache.txt
|
||||
CMakeFiles
|
||||
moc_*.cxx*
|
||||
bgrive/ui_MainWindow.h
|
||||
Makefile
|
||||
*.a
|
||||
bgrive/bgrive
|
||||
grive/grive
|
||||
libgrive/btest
|
||||
*.cmake
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "xml/Node.hh"
|
||||
#include "xml/NodeSet.hh"
|
||||
#include "xml/String.hh"
|
||||
#include "xml/TreeBuilder.hh"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/exception/all.hpp>
|
||||
|
@ -252,7 +253,7 @@ void Resource::FromRemoteFile( const Entry& remote, const DateTime& last_sync )
|
|||
void Resource::FromLocal( const DateTime& last_sync )
|
||||
{
|
||||
fs::path path = Path() ;
|
||||
assert( fs::exists( path ) ) ;
|
||||
//assert( fs::exists( path ) ) ;
|
||||
|
||||
// root folder is always in sync
|
||||
if ( !IsRoot() )
|
||||
|
@ -270,8 +271,8 @@ void Resource::FromLocal( const DateTime& last_sync )
|
|||
m_state = ( m_mtime > last_sync ? local_new : remote_deleted ) ;
|
||||
|
||||
m_name = path.filename().string() ;
|
||||
m_kind = fs::is_directory(path) ? "folder" : "file" ;
|
||||
m_md5 = fs::is_directory(path) ? "" : crypt::MD5::Get( path ) ;
|
||||
//m_kind = fs::is_directory(path) ? "folder" : "file" ;
|
||||
m_md5 = IsFolder() ? "" : crypt::MD5::Get( path ) ;
|
||||
}
|
||||
|
||||
assert( m_state != unknown ) ;
|
||||
|
@ -579,23 +580,68 @@ bool Resource::Upload(
|
|||
% xml::Escape(m_name)
|
||||
).str() ;
|
||||
|
||||
http::StringResponse str ;
|
||||
if ( post )
|
||||
http->Post( link, meta, &str, hdr ) ;
|
||||
else
|
||||
http->Put( link, meta, &str, hdr ) ;
|
||||
bool retrying=false;
|
||||
while ( true ) {
|
||||
if ( retrying ) {
|
||||
file.Seek( 0, SEEK_SET );
|
||||
os::Sleep( 5 );
|
||||
}
|
||||
|
||||
http::Header uphdr ;
|
||||
uphdr.Add( "Expect:" ) ;
|
||||
uphdr.Add( "Accept:" ) ;
|
||||
try {
|
||||
http::StringResponse str ;
|
||||
if ( post )
|
||||
http->Post( link, meta, &str, hdr ) ;
|
||||
else
|
||||
http->Put( link, meta, &str, hdr ) ;
|
||||
} catch ( Error &e ) {
|
||||
std::string const *info = boost::get_error_info<xml::TreeBuilder::ExpatApiError>(e);
|
||||
if ( info && (*info == "XML_Parse") ) {
|
||||
Log( "Error parsing pre-upload response XML, retrying whole upload in 5s",
|
||||
log::warning );
|
||||
retrying = true;
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// the content upload URL is in the "Location" HTTP header
|
||||
std::string uplink = http->RedirLocation() ;
|
||||
http::XmlResponse xml ;
|
||||
http::Header uphdr ;
|
||||
uphdr.Add( "Expect:" ) ;
|
||||
uphdr.Add( "Accept:" ) ;
|
||||
|
||||
http->Put( uplink, &file, &xml, uphdr ) ;
|
||||
AssignIDs( Entry( xml.Response() ) ) ;
|
||||
m_mtime = Entry(xml.Response()).MTime();
|
||||
// the content upload URL is in the "Location" HTTP header
|
||||
std::string uplink = http->RedirLocation() ;
|
||||
http::XmlResponse xml ;
|
||||
|
||||
long http_code = 0;
|
||||
try {
|
||||
http_code = http->Put( uplink, &file, &xml, uphdr ) ;
|
||||
} catch ( Error &e ) {
|
||||
std::string const *info = boost::get_error_info<xml::TreeBuilder::ExpatApiError>(e);
|
||||
if ( info && (*info == "XML_Parse") ) {
|
||||
Log( "Error parsing response XML, retrying whole upload in 5s",
|
||||
log::warning );
|
||||
retrying = true;
|
||||
continue;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if ( http_code == 410 || http_code == 412 ) {
|
||||
Log( "request failed with %1%, retrying whole upload in 5s", http_code,
|
||||
log::warning ) ;
|
||||
retrying = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( retrying )
|
||||
Log( "upload succeeded on retry", log::warning );
|
||||
Entry responseEntry = Entry( xml.Response() );
|
||||
AssignIDs( responseEntry ) ;
|
||||
m_mtime = responseEntry.MTime();
|
||||
break;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ void State::FromLocal( const fs::path& p )
|
|||
|
||||
bool State::IsIgnore( const std::string& filename )
|
||||
{
|
||||
return filename[0] == '.' ;
|
||||
return filename == ".grive" || filename == ".grive_state";
|
||||
}
|
||||
|
||||
void State::FromLocal( const fs::path& p, Resource* folder )
|
||||
|
@ -89,19 +89,20 @@ void State::FromLocal( const fs::path& p, Resource* folder )
|
|||
|
||||
else
|
||||
{
|
||||
bool is_dir = fs::is_directory(i->path());
|
||||
// if the Resource object of the child already exists, it should
|
||||
// have been so no need to do anything here
|
||||
Resource *c = folder->FindChild( fname ) ;
|
||||
if ( c == 0 )
|
||||
{
|
||||
c = new Resource( fname, fs::is_directory(i->path()) ? "folder" : "file" ) ;
|
||||
c = new Resource( fname, is_dir ? "folder" : "file" ) ;
|
||||
folder->AddChild( c ) ;
|
||||
m_res.Insert( c ) ;
|
||||
}
|
||||
|
||||
c->FromLocal( m_last_sync ) ;
|
||||
|
||||
if ( fs::is_directory( i->path() ) )
|
||||
if ( is_dir )
|
||||
FromLocal( *i, c ) ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ XmlResponse::XmlResponse() : m_tb( new xml::TreeBuilder )
|
|||
{
|
||||
}
|
||||
|
||||
void XmlResponse::Clear()
|
||||
{
|
||||
m_tb.reset(new xml::TreeBuilder);
|
||||
}
|
||||
|
||||
std::size_t XmlResponse::Write( const char *data, std::size_t count )
|
||||
{
|
||||
m_tb->ParseData( data, count ) ;
|
||||
|
|
|
@ -21,8 +21,10 @@
|
|||
|
||||
#include "http/Error.hh"
|
||||
#include "http/Header.hh"
|
||||
#include "http/XmlResponse.hh"
|
||||
#include "util/log/Log.hh"
|
||||
#include "util/OS.hh"
|
||||
#include "util/File.hh"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
@ -69,8 +71,22 @@ long AuthAgent::Put(
|
|||
Header auth = AppendHeader(hdr) ;
|
||||
|
||||
long response ;
|
||||
while ( CheckRetry(
|
||||
response = m_agent->Put( url, file, dest, AppendHeader(hdr) ) ) ) ;
|
||||
bool keepTrying = true;
|
||||
while ( keepTrying ) {
|
||||
response = m_agent->Put( url, file, dest, auth );
|
||||
keepTrying = CheckRetry( response );
|
||||
if ( keepTrying ) {
|
||||
file->Seek( 0, SEEK_SET );
|
||||
XmlResponse *xmlResponse = dynamic_cast<XmlResponse*>(dest);
|
||||
if( xmlResponse )
|
||||
xmlResponse->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// On 410 Gone or 412 Precondition failed, recovery may be possible so don't
|
||||
// throw an exception
|
||||
if ( response == 410 || response == 412 )
|
||||
return response;
|
||||
|
||||
return CheckHttpResponse(response, url, auth) ;
|
||||
}
|
||||
|
@ -152,6 +168,7 @@ bool AuthAgent::CheckRetry( long response )
|
|||
Log( "resquest failed due to auth token expired: %1%. refreshing token",
|
||||
response, log::warning ) ;
|
||||
|
||||
os::Sleep( 5 ) ;
|
||||
m_auth.Refresh() ;
|
||||
return true ;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "Error.hh"
|
||||
#include "Node.hh"
|
||||
#include "util/log/Log.hh"
|
||||
|
||||
#include <expat.h>
|
||||
|
||||
|
@ -72,8 +73,10 @@ void TreeBuilder::ParseData( const char *data, std::size_t count, bool last )
|
|||
{
|
||||
is_new = false ;
|
||||
|
||||
if ( ::XML_Parse( m_impl->psr, data, count, last ) == 0 )
|
||||
if ( ::XML_Parse( m_impl->psr, data, count, last ) == 0 ) {
|
||||
Log("Error parsing XML: %1%", data, log::error);
|
||||
BOOST_THROW_EXCEPTION( Error() << ExpatApiError("XML_Parse") );
|
||||
}
|
||||
}
|
||||
|
||||
Node TreeBuilder::Parse( const std::string& xml )
|
||||
|
|
Loading…
Reference in New Issue