grive2/libgrive/src/drive/State.cc

187 lines
4.0 KiB
C++
Raw Normal View History

2012-05-16 18:35:22 +04:00
/*
grive: an GPL program to sync a local directory with Google Drive
Copyright (C) 2012 Wan Wai Ho
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "State.hh"
2012-05-19 11:41:21 +04:00
#include "Resource.hh"
2012-05-17 20:37:11 +04:00
#include "CommonUri.hh"
2012-05-16 18:35:22 +04:00
#include "util/Crypt.hh"
#include "util/Log.hh"
#include "protocol/Json.hh"
2012-05-16 20:52:17 +04:00
#include <boost/bind.hpp>
2012-05-16 18:35:22 +04:00
2012-05-16 20:52:17 +04:00
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
2012-05-17 20:37:11 +04:00
#include <boost/multi_index/mem_fun.hpp>
2012-05-16 18:35:22 +04:00
2012-05-16 20:52:17 +04:00
#include <fstream>
2012-05-16 18:35:22 +04:00
2012-05-16 20:52:17 +04:00
namespace gr {
struct State::Impl
{
2012-05-19 11:41:21 +04:00
// ResourceSet rs ;
2012-05-19 11:26:55 +04:00
FolderSet folders ;
std::string change_stamp ;
2012-05-17 20:37:11 +04:00
std::vector<Entry> unresolved ;
2012-05-16 20:52:17 +04:00
} ;
State::State( const fs::path& filename ) :
m_impl( new Impl )
{
if ( fs::exists( filename ) )
Read( filename );
}
void State::Read( const fs::path& filename )
{
Trace( "reading %1%", filename ) ;
}
std::string State::ChangeStamp() const
{
return m_impl->change_stamp ;
}
void State::ChangeStamp( const std::string& cs )
{
m_impl->change_stamp = cs ;
}
void State::Sync( const fs::path& p )
{
2012-05-19 11:26:55 +04:00
Sync( p, m_impl->folders.Root() ) ;
2012-05-17 20:37:11 +04:00
}
2012-05-19 11:41:21 +04:00
void State::Sync( const boost::filesystem3::path& p, gr::Resource* folder )
2012-05-17 20:37:11 +04:00
{
2012-05-19 11:26:55 +04:00
assert( folder != 0 ) ;
2012-05-16 20:52:17 +04:00
for ( fs::directory_iterator i( p ) ; i != fs::directory_iterator() ; ++i )
{
if ( fs::is_directory( i->path() ) )
2012-05-17 20:37:11 +04:00
{
2012-05-19 11:41:21 +04:00
Resource *c = new Resource( i->path().filename().string(), "" ) ;
2012-05-17 20:37:11 +04:00
folder->AddChild( c ) ;
2012-05-19 12:18:33 +04:00
m_impl->folders.Insert( c ) ;
2012-05-17 20:37:11 +04:00
Sync( *i, c ) ;
}
2012-05-19 11:41:21 +04:00
// else if ( i->path().filename().string()[0] != '.' )
// m_impl->rs.insert( Resource( i->path() ) ) ;
2012-05-16 18:35:22 +04:00
}
}
2012-05-16 20:52:17 +04:00
void State::Write( const fs::path& filename ) const
{
Json result ;
result.Add( "change_stamp", Json( m_impl->change_stamp ) ) ;
std::ofstream fs( filename.string().c_str() ) ;
fs << result ;
}
2012-05-16 21:20:02 +04:00
void State::SetId( const fs::path& p, const std::string& id )
2012-05-16 18:35:22 +04:00
{
}
2012-05-17 20:37:11 +04:00
void State::OnEntry( const Entry& e )
{
if ( !Update( e ) )
{
2012-05-19 12:18:33 +04:00
Trace( "can't resolve folder %1%", e.Title() ) ;
2012-05-17 20:37:11 +04:00
m_impl->unresolved.push_back( e ) ;
}
}
void State::ResolveEntry()
{
Trace( "trying to resolve %1% entries", m_impl->unresolved.size() ) ;
while ( !m_impl->unresolved.empty() )
{
if ( TryResolveEntry() == 0 )
{
Trace( "cannot make progress" ) ;
break ;
}
}
Trace( "entries left = %1%", m_impl->unresolved.size() ) ;
}
std::size_t State::TryResolveEntry()
{
assert( !m_impl->unresolved.empty() ) ;
std::size_t count = 0 ;
std::vector<Entry>& en = m_impl->unresolved ;
for ( std::vector<Entry>::iterator i = en.begin() ; i != en.end() ; )
{
2012-05-19 12:18:33 +04:00
Trace( "resolving %1%", i->Title() ) ;
2012-05-17 20:37:11 +04:00
if ( Update( *i ) )
{
i = en.erase( i ) ;
count++ ;
}
else
++i ;
}
return count ;
}
bool State::Update( const Entry& e )
{
2012-05-19 11:41:21 +04:00
Resource *parent = m_impl->folders.FindByHref( e.ParentHref() ) ;
2012-05-19 11:26:55 +04:00
if ( parent != 0 )
2012-05-17 20:37:11 +04:00
{
2012-05-19 11:26:55 +04:00
Trace( "found parent of folder %1%: %2%", e.Title(), parent->Title() ) ;
2012-05-17 20:37:11 +04:00
// see if the entry already exist in local
2012-05-19 11:41:21 +04:00
Resource *child = parent->FindChild( e.Title() ) ;
2012-05-17 20:37:11 +04:00
if ( child != 0 )
{
// since we are updating the ID and Href, we need to remove it and re-add it.
2012-05-19 11:26:55 +04:00
m_impl->folders.Update( child, e ) ;
2012-05-17 20:37:11 +04:00
}
// folder entry exist in google drive, but not local.
else
{
2012-05-19 11:41:21 +04:00
child = new Resource( e ) ;
2012-05-19 11:26:55 +04:00
parent->AddChild( child ) ;
2012-05-17 20:37:11 +04:00
}
return true ;
}
else
return false ;
}
2012-05-19 11:41:21 +04:00
Resource* State::FindFolderByHref( const std::string& href )
2012-05-17 20:37:11 +04:00
{
2012-05-19 11:26:55 +04:00
return m_impl->folders.FindByHref( href ) ;
2012-05-17 20:37:11 +04:00
}
2012-05-16 21:20:02 +04:00
2012-05-16 18:35:22 +04:00
} // end of namespace