gdata-backup 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +53 -0
- data/Rakefile +3 -0
- data/bin/gdata-backup +23 -0
- data/gdata-backup.gemspec +28 -0
- data/lib/gdata/backup.rb +91 -0
- data/lib/gdata/backup/version.rb +9 -0
- data/spec/download_spec.rb +91 -0
- metadata +159 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
gdata-backup
|
2
|
+
============
|
3
|
+
Make a local copy of Google Docs via the command line.
|
4
|
+
|
5
|
+
This program makes it easy to download your Google Docs for backup, e.g. via a cron job.
|
6
|
+
|
7
|
+
Installation
|
8
|
+
============
|
9
|
+
|
10
|
+
```
|
11
|
+
bundle
|
12
|
+
```
|
13
|
+
|
14
|
+
Configuration
|
15
|
+
=============
|
16
|
+
This gem uses the imap-backup gem's command line inetrface to configure the GMail
|
17
|
+
accounts that you want to back up. imap-backup is installed when you run bundle (above).
|
18
|
+
|
19
|
+
```shell
|
20
|
+
$ imap-backup setup
|
21
|
+
```
|
22
|
+
|
23
|
+
See the imap-backup README for fuller instructions.
|
24
|
+
|
25
|
+
Usage
|
26
|
+
=====
|
27
|
+
|
28
|
+
```
|
29
|
+
gdata-backup EMAIL DIRECTORY
|
30
|
+
```
|
31
|
+
|
32
|
+
Alternatives
|
33
|
+
============
|
34
|
+
|
35
|
+
There are various other applications available which download Google Docs:
|
36
|
+
|
37
|
+
* You can download a zipped bundle from the Google Docs web interface,
|
38
|
+
* There are some Open Source,
|
39
|
+
* There are various commercial products.
|
40
|
+
|
41
|
+
Open Source:
|
42
|
+
|
43
|
+
* http://gdocs-backup.com/source
|
44
|
+
* http://gs.fhtino.it/gdocbackup - .net/mono
|
45
|
+
* http://1st-soft.net/gdd/ - greasemonkey
|
46
|
+
|
47
|
+
Commercial:
|
48
|
+
|
49
|
+
* http://www.backupgoo.com/en/index.html
|
50
|
+
* http://www.workflow.ae/Google-Docs-Backup-Utility/
|
51
|
+
* http://www.gladinet.com/
|
52
|
+
* http://www.syncdocs.com/
|
53
|
+
|
data/Rakefile
ADDED
data/bin/gdata-backup
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
root = File.expand_path('../..', __FILE__)
|
4
|
+
$: << File.join(root, 'lib')
|
5
|
+
|
6
|
+
require 'gdata/backup'
|
7
|
+
|
8
|
+
def usage
|
9
|
+
puts <<EOT
|
10
|
+
Usage:
|
11
|
+
$ #{__FILE__} email@gmail.com destination_directory
|
12
|
+
EOT
|
13
|
+
end
|
14
|
+
|
15
|
+
if ARGV.size < 2
|
16
|
+
usage
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
|
20
|
+
@user, @path = ARGV
|
21
|
+
|
22
|
+
Gdata::Backup.new(@user, @path).run
|
23
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
load File.expand_path('lib/gdata/backup/version.rb', File.dirname(__FILE__))
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ['Joe Yates']
|
6
|
+
gem.email = ['joe.g.yates@gmail.com']
|
7
|
+
gem.description = 'Google Drive backup'
|
8
|
+
gem.summary = <<-EOT
|
9
|
+
Backup Google Drive documents as Open Document Format files.
|
10
|
+
EOT
|
11
|
+
gem.homepage = 'https://github.com/joeyates/gdata-backup'
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($\)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^spec/})
|
16
|
+
gem.name = 'gdata-backup'
|
17
|
+
gem.require_paths = ['lib']
|
18
|
+
gem.version = Gdata::Backup::VERSION
|
19
|
+
|
20
|
+
gem.add_runtime_dependency 'gdata'
|
21
|
+
gem.add_runtime_dependency 'imap-backup'
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rake'
|
24
|
+
gem.add_development_dependency 'pry'
|
25
|
+
gem.add_development_dependency 'pry-doc'
|
26
|
+
gem.add_development_dependency 'rspec'
|
27
|
+
end
|
28
|
+
|
data/lib/gdata/backup.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'gdata/client'
|
2
|
+
require 'gdata/http'
|
3
|
+
require 'gdata/auth'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
require 'imap/backup'
|
7
|
+
|
8
|
+
module Gdata
|
9
|
+
class Backup
|
10
|
+
def initialize(account_username, path)
|
11
|
+
@path = path
|
12
|
+
store = Imap::Backup::Configuration::Store.new
|
13
|
+
@config = store.data
|
14
|
+
@account = @config[:accounts].find { |a| a[:username] == account_username }
|
15
|
+
raise 'account unknown' if @account.nil?
|
16
|
+
@log = Logger.new(STDOUT)
|
17
|
+
@log.level = Logger::INFO
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
raise "The supplied path '#{@path}' does not exist" unless File.directory?(@path)
|
22
|
+
documents.each do |document|
|
23
|
+
@log.info document[:file_name]
|
24
|
+
begin
|
25
|
+
response = spreadsheet_client.get(document[:url])
|
26
|
+
rescue => e
|
27
|
+
@log.error "Download of #{document[:file_name]} failed: #{e}"
|
28
|
+
next
|
29
|
+
end
|
30
|
+
File.open(File.join(@path, document[:file_name]), 'wb' ) do |file|
|
31
|
+
file.write response.body
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def documents
|
39
|
+
return @documents if @documents
|
40
|
+
|
41
|
+
doc = doc_list_client.get('https://docs.google.com/feeds/documents/private/full')
|
42
|
+
list = doc.to_xml
|
43
|
+
|
44
|
+
@documents = []
|
45
|
+
list.elements.each( 'entry' ) do | entry |
|
46
|
+
src = entry.elements[ 'content' ].attributes[ 'src' ]
|
47
|
+
title = entry.elements[ 'title' ].text
|
48
|
+
format = download_format( src, title )
|
49
|
+
if format == ''
|
50
|
+
@log.info "Skipping '#{title}'"
|
51
|
+
next
|
52
|
+
end
|
53
|
+
url = src + '&exportFormat=' + format
|
54
|
+
clean_title = title.gsub(/[^a-z0-9\s\-\_]/i, '_')
|
55
|
+
file_name = clean_title + '.' + format
|
56
|
+
@documents << { :file_name => file_name,
|
57
|
+
:url => url }
|
58
|
+
end
|
59
|
+
|
60
|
+
@documents
|
61
|
+
end
|
62
|
+
|
63
|
+
def doc_list_client
|
64
|
+
return @doc_list_client if @doc_list_client
|
65
|
+
@doc_list_client = GData::Client::DocList.new
|
66
|
+
@doc_list_client.clientlogin(@account[:username], @account[:password])
|
67
|
+
@doc_list_client
|
68
|
+
end
|
69
|
+
|
70
|
+
def spreadsheet_client
|
71
|
+
return @spreadsheet_client if @spreadsheet_client
|
72
|
+
@spreadsheet_client = GData::Client::Spreadsheets.new
|
73
|
+
@spreadsheet_client.clientlogin(@account[:username], @account[:password])
|
74
|
+
@spreadsheet_client
|
75
|
+
end
|
76
|
+
|
77
|
+
def download_format( url, title )
|
78
|
+
case
|
79
|
+
when title =~ %r(\.pdf$)
|
80
|
+
''
|
81
|
+
when url =~ %r(feeds/download/presentations)
|
82
|
+
''
|
83
|
+
when url =~ /spreadsheets/
|
84
|
+
'ods'
|
85
|
+
else
|
86
|
+
'odt'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
$: << '../lib'
|
2
|
+
|
3
|
+
require 'gdata/download'
|
4
|
+
require "rexml/document"
|
5
|
+
|
6
|
+
describe Gdata::Download do
|
7
|
+
|
8
|
+
def canned_doc_list_response
|
9
|
+
s = <<EOT
|
10
|
+
<feed xmlns='http://www.w3.org/2005/Atom'>
|
11
|
+
<entry>
|
12
|
+
<title>Doc1</title>
|
13
|
+
<content src='https://docs.google.com/feeds/download/documents/export/Export?id=XXXXXXXX' type='text/html'/>
|
14
|
+
</entry>
|
15
|
+
<entry>
|
16
|
+
<title>Doc2</title>
|
17
|
+
<content src='https://docs.google.com/feeds/download/documents/export/Export?id=YYYYYYYY' type='text/html'/>
|
18
|
+
</entry>
|
19
|
+
</feed>
|
20
|
+
EOT
|
21
|
+
@rexml = REXML::Document.new(s)
|
22
|
+
stub('GData_HTTP_Response', :to_xml => @rexml.root)
|
23
|
+
end
|
24
|
+
|
25
|
+
context '#initialize' do
|
26
|
+
before :each do
|
27
|
+
@config = stub('Imap::Backup::Configuration::Store')
|
28
|
+
Imap::Backup::Configuration::Store.stub!(:new).and_return(@config)
|
29
|
+
@data = {:accounts => [{:username => 'account_username'}]}
|
30
|
+
@config.stub!(:data).and_return(@data)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should load config' do
|
34
|
+
Imap::Backup::Configuration::Store.should_receive(:new).and_return(@config)
|
35
|
+
@config.should_receive(:data).and_return(@data)
|
36
|
+
|
37
|
+
Gdata::Download.new('account_username', '/a/path')
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should fail if the account is not configured' do
|
41
|
+
expect do
|
42
|
+
Gdata::Download.new('unknown_username', '/a/path')
|
43
|
+
end.to raise_error(/unknown/)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
context '#documents' do
|
49
|
+
|
50
|
+
before :each do
|
51
|
+
@data = {:accounts => [{:username => 'jdoe@example.com', :password => 'secret'}]}
|
52
|
+
@config = stub('Imap::Backup::Configuration::Store', :data => @data)
|
53
|
+
Imap::Backup::Configuration::Store.stub!(:new).and_return(@config)
|
54
|
+
@doc_list_client = stub('GData::Client::DocList')
|
55
|
+
@doc_list_client.stub!(:clientlogin => true)
|
56
|
+
GData::Client::DocList.stub!(:new => @doc_list_client)
|
57
|
+
@doc_list_client.stub!(:get).
|
58
|
+
with('https://docs.google.com/feeds/documents/private/full').
|
59
|
+
and_return(canned_doc_list_response)
|
60
|
+
end
|
61
|
+
|
62
|
+
subject { Gdata::Download.new('jdoe@example.com', '/a/path') }
|
63
|
+
|
64
|
+
it 'should log in' do
|
65
|
+
@doc_list_client. should_receive(:clientlogin).
|
66
|
+
with('jdoe@example.com', 'secret').
|
67
|
+
and_return(true)
|
68
|
+
|
69
|
+
subject.documents
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should list documents' do
|
73
|
+
@doc_list_client. should_receive(:get).
|
74
|
+
and_return(canned_doc_list_response)
|
75
|
+
|
76
|
+
subject.documents
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should return document information' do
|
80
|
+
documents = subject.documents
|
81
|
+
|
82
|
+
documents. should == [{:file_name => 'Doc1.odt',
|
83
|
+
:url => 'https://docs.google.com/feeds/download/documents/export/Export?id=XXXXXXXX&exportFormat=odt'},
|
84
|
+
{:file_name => 'Doc2.odt',
|
85
|
+
:url => 'https://docs.google.com/feeds/download/documents/export/Export?id=YYYYYYYY&exportFormat=odt'}]
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gdata-backup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Joe Yates
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: gdata
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: imap-backup
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pry
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: pry-doc
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rspec
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Google Drive backup
|
111
|
+
email:
|
112
|
+
- joe.g.yates@gmail.com
|
113
|
+
executables:
|
114
|
+
- gdata-backup
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .gitignore
|
119
|
+
- Gemfile
|
120
|
+
- README.md
|
121
|
+
- Rakefile
|
122
|
+
- bin/gdata-backup
|
123
|
+
- gdata-backup.gemspec
|
124
|
+
- lib/gdata/backup.rb
|
125
|
+
- lib/gdata/backup/version.rb
|
126
|
+
- spec/download_spec.rb
|
127
|
+
homepage: https://github.com/joeyates/gdata-backup
|
128
|
+
licenses: []
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
hash: -2792609340228659123
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ! '>='
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
hash: -2792609340228659123
|
151
|
+
requirements: []
|
152
|
+
rubyforge_project:
|
153
|
+
rubygems_version: 1.8.23
|
154
|
+
signing_key:
|
155
|
+
specification_version: 3
|
156
|
+
summary: Backup Google Drive documents as Open Document Format files.
|
157
|
+
test_files:
|
158
|
+
- spec/download_spec.rb
|
159
|
+
has_rdoc:
|