Skip to content

Instantly share code, notes, and snippets.

@KainokiKaede
Forked from freekrai/DropboxSync.py
Last active August 29, 2015 14:03

Revisions

  1. KainokiKaede revised this gist Jul 3, 2014. 1 changed file with 4 additions and 1 deletion.
    5 changes: 4 additions & 1 deletion DropboxSync.py
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,7 @@
    import sys
    import pickle
    import console
    import editor

    import dropboxlogin # this code can be found here https://gist.github.com/4034526

    @@ -188,4 +189,6 @@ def savestate(state):
    savestate(state)

    print '\nSync complete'


    print '\nReloading editor'
    editor.open_file(editor.get_path().split('Documents/', 1)[1])
  2. Roger Stringer revised this gist Dec 1, 2012. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions DropboxSync.py
    Original file line number Diff line number Diff line change
    @@ -3,8 +3,6 @@
    import pickle
    import console

    # I moved 'dropboxlogin' into a sub folder so it doesn't clutter my main folder
    sys.path += [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')]
    import dropboxlogin # this code can be found here https://gist.github.com/4034526

    STATE_FILE = '.dropbox_state'
  3. @wrenoud wrenoud revised this gist Nov 10, 2012. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions DropboxSync.py
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@

    # I moved 'dropboxlogin' into a sub folder so it doesn't clutter my main folder
    sys.path += [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')]
    import dropboxlogin
    import dropboxlogin # this code can be found here https://gist.github.com/4034526

    STATE_FILE = '.dropbox_state'

    @@ -190,4 +190,4 @@ def savestate(state):
    savestate(state)

    print '\nSync complete'


  4. @wrenoud wrenoud revised this gist Nov 10, 2012. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions DropboxSync.py
    Original file line number Diff line number Diff line change
    @@ -1,12 +1,10 @@
    import os
    import sys
    sys.path += [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')]

    import pickle
    from glob import glob

    import console

    # I moved 'dropboxlogin' into a sub folder so it doesn't clutter my main folder
    sys.path += [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')]
    import dropboxlogin

    STATE_FILE = '.dropbox_state'
  5. @wrenoud wrenoud revised this gist Nov 10, 2012. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions DropboxSync.py
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,7 @@
    import os
    import sys
    sys.path += [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib')]

    import pickle
    from glob import glob

    @@ -153,9 +156,9 @@ def savestate(state):
    client = dropboxlogin.get_client()
    print '\nLoading local state'
    # lets see if we can unpickle
    if os.path.exists(STATE_FILE):
    try:
    state = loadstate()
    else:
    except:
    print '\nCannot find state file. ***Making new local state***'
    # Aaaah, we have nothing, probably first run
    state = dropbox_state()
  6. @wrenoud wrenoud created this gist Nov 10, 2012.
    192 changes: 192 additions & 0 deletions DropboxSync.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,192 @@
    import os
    import pickle
    from glob import glob

    import console

    import dropboxlogin

    STATE_FILE = '.dropbox_state'

    class dropbox_state:
    def __init__(self):
    self.cursor = None
    self.local_files = {}
    self.remote_files = {}

    # use ignore_path to prevent download of recently uploaded files
    def execute_delta(self, client, ignore_path = None):
    delta = client.delta(self.cursor)
    self.cursor = delta['cursor']

    for entry in delta['entries']:
    path = entry[0][1:]
    meta = entry[1]

    # this skips the path if we just uploaded it
    if path != ignore_path:
    if meta != None:
    path = meta['path'][1:] # caps sensitive
    if meta['is_dir']:
    print '\n\tMaking Directory:',path
    self.makedir_local(path)
    elif path not in self.remote_files:
    print '\n\tNot in local'
    self.download(client, path)
    elif meta['rev'] != self.remote_files[path]['rev']:
    print '\n\tOutdated revision'
    self.download(client, path)
    # remove file or directory
    else:
    if os.path.isdir(path):
    print '\n\tRemoving Directory:', path
    os.removedirs(path)
    elif os.path.isfile(path):
    print '\n\tRemoving File:', path
    os.remove(path)

    del self.local_files[path]
    del self.remote_files[path]
    else:
    pass # file already doesn't exist localy

    # makes dirs if necessary, downloads, and adds to local state data
    def download(self, client, path):
    print '\tDownloading:', path
    # TODO: what if there is a folder there...?
    head, tail = os.path.split(path)
    # make the folder if it doesn't exist yet
    if not os.path.exists(head) and head != '':
    os.makedirs(head)
    #open file to write
    local = open(path,'w')
    remote, meta = client.get_file_and_metadata(os.path.join('/',path))
    local.write(remote.read())
    #clean up
    remote.close()
    local.close()
    # add to local repository
    self.local_files[path] = {'modified': os.path.getmtime(path)}
    self.remote_files[path] = meta

    def upload(self, client, path):
    print '\tUploading:', path
    local = open(path,'r')
    meta = client.put_file(os.path.join('/',path), local, True)
    local.close()

    self.local_files[path] = {'modified': os.path.getmtime(path)}
    self.remote_files[path] = meta

    # clean out the delta for the file upload
    self.execute_delta(client, ignore_path=meta['path'])

    def delete(self, client, path):
    print '\tFile deleted locally. Deleting on Dropbox:',path
    try:
    client.file_delete(path)
    except:
    # file was probably already deleted
    print '\tFile already removed from Dropbox'

    del self.local_files[path]
    del self.remote_files[path]

    # safely makes local dir
    def makedir_local(self,path):
    if not os.path.exists(path): # no need to make a dir that exists
    os.makedirs(path)
    elif os.path.isfile(path): # if there is a file there ditch it
    os.remove(path)
    del self.files[path]

    os.makedir(path)

    # recursively list files on dropbox
    def _listfiles(self, client, path = '/'):
    meta = client.metadata(path)
    filelist = []

    for item in meta['contents']:
    if item['is_dir']:
    filelist += self._listfiles(client,item['path'])
    else:
    filelist.append(item['path'])
    return filelist

    def download_all(self, client, path = '/'):
    filelist = self._listfiles(client)
    for file in filelist:
    self.download(client, file[1:]) # trim root slash

    def check_state(self, client, path):
    # lets see if we've seen it before
    if path not in self.local_files:
    # upload it!
    self.upload(client, path)
    elif os.path.getmtime(path) > self.local_files[path]['modified']:
    # newer file than last sync
    self.upload(client, path)
    else:
    pass # looks like everything is good

    def loadstate():
    fyle = open(STATE_FILE,'r')
    state = pickle.load(fyle)
    fyle.close()

    return state

    def savestate(state):
    fyle = open(STATE_FILE,'w')
    pickle.dump(state,fyle)
    fyle.close()

    if __name__ == '__main__':
    console.show_activity()

    print """
    ****************************************
    * Dropbox File Syncronization *
    ****************************************"""

    client = dropboxlogin.get_client()
    print '\nLoading local state'
    # lets see if we can unpickle
    if os.path.exists(STATE_FILE):
    state = loadstate()
    else:
    print '\nCannot find state file. ***Making new local state***'
    # Aaaah, we have nothing, probably first run
    state = dropbox_state()

    print '\nDownloading everything from Dropbox'
    # no way to check what we have locally is newer, gratuitous dl
    state.download_all(client)

    print '\nUpdating state from Dropbox'
    state.execute_delta(client)


    print '\nChecking for new or updated local files'
    # back to business, lets see if there is anything new or changed localy
    filelist = []
    for root, dirnames, filenames in os.walk('.'):
    for filename in filenames:
    if filename != STATE_FILE:
    filelist.append( os.path.join(root, filename)[2:])

    for file in filelist:
    state.check_state(client,file)

    print '\nChecking for deleted local files'
    old_list = state.local_files.keys()
    for file in old_list:
    if file not in filelist:
    state.delete(client, file)

    print '\nSaving local state'
    savestate(state)

    print '\nSync complete'