rypple 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/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ripple.gemspec
4
+ gemspec
data/README ADDED
@@ -0,0 +1 @@
1
+ A tool for integrating some remote file store (e.g. Dropbox) with a static site generator (e.g. jekyll) with some tools to ease remote updating of the site.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,169 @@
1
+ #!/bin/ruby
2
+ require 'rubygems'
3
+ require 'ripple'
4
+
5
+ baseCGI = <<'eos'
6
+ #!/usr/bin/ruby
7
+ gemPath = "%%GEM_PATH"
8
+ configPath = "%%CONFIG_PATH"
9
+ inDir = "%%IN_DIR"
10
+ outDir = "%%OUT_DIR"
11
+
12
+ if !gemPath.empty?
13
+ $:.push(gemPath)
14
+ ENV['GEM_PATH'] = gemPath
15
+ end
16
+
17
+ require 'cgi'
18
+ require 'rubygems'
19
+ require 'ripple'
20
+ require 'jekyll'
21
+
22
+ cgi = CGI.new
23
+
24
+ puts cgi.header
25
+
26
+ puts "<h1>Rippling . . .</h1>"
27
+ if Ripple.sync(configPath)
28
+ puts "<h1>Generating Static Site</h1>"
29
+ puts `%%COMMAND #{inDir} #{outDir}`
30
+ end
31
+ eos
32
+
33
+ updateHTML = <<'eos'
34
+ <html>
35
+ <head>
36
+ <title>Update Site with Ripple!</title>
37
+ </head>
38
+ <body>
39
+ <h1> Throw a stone into the pond..</h1>
40
+ <form action="update.cgi" method="POST">
41
+ <input type="submit" value="Ripple">
42
+ </form>
43
+ </body>
44
+ </html>
45
+ eos
46
+
47
+ htaccess = <<'eos'
48
+ AuthName "Ripple Updater"
49
+ AuthType Basic
50
+ AuthUserFile %%AUTH_FILE
51
+ Require valid-user
52
+ eos
53
+
54
+ configBase = File.join(ENV["HOME"], '.ripple')
55
+ puts "Configuring the Ripple update script for web use."
56
+ puts "Please enter directory for Ripple Configuration. Default:", configBase
57
+ directory = gets.chomp!
58
+
59
+ if !directory.empty?
60
+ configBase = directory
61
+ end
62
+
63
+ conf = Ripple.loadConfiguration(configBase)
64
+ session, client, keys = Ripple.connectToDropbox(configBase)
65
+
66
+ if !conf.nil? and !keys.nil?
67
+ Ripple.cleanup(conf, keys, configBase)
68
+ end
69
+
70
+ baseCGI.gsub!(/%%CONFIG_PATH/, configBase)
71
+
72
+ choice = false
73
+ insert = true
74
+ while !choice do
75
+ puts "Is your web host set up to use ruby gems? (y/N)"
76
+ answer = gets.chomp!.downcase!
77
+ if answer.nil? or answer.empty?
78
+ choice = true
79
+ elsif answer == "n" or answer == "y"
80
+ insert = (answer == "n")
81
+ choice = true
82
+ end
83
+ end
84
+
85
+ if insert
86
+ gemPath = ''
87
+ if ENV.has_key?('GEM_HOME')
88
+ gemPath = ENV['GEM_HOME']
89
+ else
90
+ puts "Please enter search path for the ruby gems."
91
+ gemPath = gets.chomp!
92
+ end
93
+
94
+ baseCGI.gsub!(/%%GEM_PATH/, gemPath)
95
+ end
96
+
97
+ puts "Where should static site files be store?"
98
+ inDir = File.expand_path(gets.chomp!)
99
+
100
+ if !File.exists?(inDir)
101
+ begin
102
+ Dir.mkdir(inDir)
103
+ rescue SystemCallError
104
+ puts "Cannot create", inDir, ", create this directory and run this script again."
105
+ exit
106
+ end
107
+ end
108
+
109
+ baseCGI.gsub!(/%%IN_DIR/, inDir)
110
+
111
+ puts "Where should the static site generator output files?"
112
+ outDir = File.expand_path(gets.chomp!)
113
+
114
+ if !File.exists?(inDir)
115
+ begin
116
+ Dir.mkdir(outDir)
117
+ rescue SystemCallError
118
+ puts "Cannot create output directory", outDir, ", fix this and run this script again."
119
+ exit
120
+ end
121
+ end
122
+
123
+ baseCGI.gsub!(/%%OUT_DIR/, outDir)
124
+
125
+ command = File.join("#{ENV["GEM_HOME"]}", 'bin', 'jekyll')
126
+ if File.exists?(command)
127
+ puts "Please enter any arguments to pass to jekyll"
128
+ args = gets.chomp!
129
+ baseCGI.gsub!(/%%COMMAND/, command + ' ' + args)
130
+ end
131
+
132
+ rippleDir = File.join(inDir, 'ripple')
133
+
134
+ if !File.exists?(rippleDir)
135
+ begin
136
+ Dir.mkdir(rippleDir)
137
+ rescue SystemCallError
138
+ "Cannot create ripple directory."
139
+ end
140
+ end
141
+
142
+ File.open(File.join(rippleDir, 'update.html'), 'w', 0644) { |f| f.puts updateHTML }
143
+
144
+ out = File.join(rippleDir, 'update.cgi')
145
+ File.open(out, 'w', 0755) { |f| f.puts baseCGI }
146
+
147
+ puts "Should I enable basic user authentication for the update script? (Y/n):"
148
+
149
+ answer = gets.chomp!
150
+ if answer.nil? or answer.empty? or answer.downcase! == 'y'
151
+ print "Enter user name for authentication:"
152
+ user = gets.chomp!
153
+ print "Enter password for authentication:"
154
+ chars = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
155
+ salt = chars[rand(chars.size - 1)] + chars[rand(chars.size - 1)]
156
+ pass = gets.chomp!.crypt(salt)
157
+ authFile = File.join(configBase, '.htpasswd')
158
+ File.open(authFile, 'w') { |f| f.puts "#{user}:#{pass}" }
159
+ htaccess.gsub!(/%%AUTH_FILE/, authFile)
160
+ File.open(File.join(rippleDir, '.htaccess'), 'w') { |f| f.puts htaccess }
161
+ end
162
+
163
+ puts "Attempting first update"
164
+
165
+ if Ripple.sync(configBase)
166
+ puts `jekyll #{inDir} #{outDir}`
167
+ else
168
+ puts "Ripple sync failed."
169
+ end
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/ruby
2
+ module Ripple
3
+ require 'fileutils'
4
+ require 'yaml'
5
+ require "rubygems"
6
+ require 'dropbox_sdk'
7
+ require 'pathname'
8
+
9
+ ACCESS_TYPE = :app_folder
10
+ DefaultConfiguration = {
11
+ :destinationDir => './test',
12
+ :dropbox => {
13
+ :sync => ['**'],
14
+ }
15
+ }
16
+
17
+ DropboxKeyFile = "dropbox_session.yaml"
18
+ RippleConfigFile = "ripple.yaml"
19
+
20
+ def Ripple.connectToDropbox(path)
21
+ dropConf = File.join(path, DropboxKeyFile)
22
+ #Load Dropbox API dropboxKeys from file, if applicable.
23
+ if File.exists?(dropConf)
24
+ dropboxKeys = YAML::load(File.read(dropConf))
25
+ else
26
+ puts "A Dropbox API key/secret is required for accessing your sync files."
27
+ puts "You can visit https://www.dropbox.com/developers/apps to generate these."
28
+ puts "Please enter your Dropbox API key"
29
+ dropboxKeys['key'] = gets.chomp!
30
+ puts "Please enter your Dropbox API secret"
31
+ dropboxKeys['secret'] = gets.chomp!
32
+ end
33
+
34
+ session = nil
35
+
36
+ if dropboxKeys.has_key?(:session)
37
+ session = DropboxSession.deserialize(dropboxKeys[:session])
38
+ else
39
+ session = DropboxSession.new(dropboxKeys[:key], dropboxKeys[:secret])
40
+ session.get_request_token
41
+ authorize_url = session.get_authorize_url
42
+ puts "Visit #{authorize_url} to log in to Dropbox. Hit enter when you have done this."
43
+ gets
44
+ session.get_access_token
45
+ end
46
+
47
+ if session.nil?
48
+ return nil, nil, nil
49
+ end
50
+
51
+ if !dropboxKeys.has_key?(:session)
52
+ dropboxKeys[:session] = session.serialize()
53
+ end
54
+
55
+ client = DropboxClient.new(session, ACCESS_TYPE)
56
+
57
+ if client.nil?
58
+ return nil, nil, nil
59
+ else
60
+ return session, client, dropboxKeys
61
+ end
62
+ end
63
+
64
+ def Ripple.loadConfiguration(path)
65
+ conf = Ripple::DefaultConfiguration.dup
66
+
67
+ ripConf = File.join(path, RippleConfigFile)
68
+ # Load configuration and override any values that differ from the default.
69
+ if File.exists?(ripConf)
70
+ loadedConf = YAML::load(File.read(ripConf))
71
+ conf.merge!(loadedConf)
72
+ end
73
+
74
+ conf[:destinationDir] = File.expand_path(conf[:destinationDir])
75
+ if !File.directory?(conf[:destinationDir])
76
+ begin
77
+ Dir.mkdir(conf[:destinationDir])
78
+ rescue SystemCallError
79
+ raise RuntimeError, "Destination doesn't exist and cannot be created."
80
+ end
81
+ end
82
+ return conf
83
+ end
84
+
85
+ def Ripple.cleanup(conf, keys, path)
86
+ dropConfig = File.join(path, DropboxKeyFile)
87
+ File.open(dropConfig, 'w') do|file|
88
+ file.puts keys.to_yaml
89
+ end
90
+
91
+ rippleConf = File.join(path, RippleConfigFile)
92
+ File.open(rippleConf, 'w') do |file|
93
+ file.puts conf.to_yaml
94
+ end
95
+ end
96
+
97
+ # Iterates over dropbox directory, returing paths and state hash for each file
98
+ # oldFileState should be a hash of paths to state hashes, same as return values
99
+ def Ripple.walkDropbox(client, path, fileState, oldFileState)
100
+ #Here we need to actually sync newest files.
101
+ begin
102
+ useState = (!oldFileState.nil? and oldFileState.has_key?(path) and oldFileState[path]["path"] == path)
103
+ oldState = useState ? oldFileState[path]["hash"] : nil
104
+ states = client.metadata(path, 10000, true, oldState)
105
+ rescue DropboxNotModified
106
+ puts "Files have not changed."
107
+ return nil
108
+ end
109
+
110
+ files = { states["path"] => states }
111
+ #State represents a folder
112
+ if states["is_dir"] and states.has_key?("contents")
113
+ states["contents"].each{ |xx|
114
+ if !xx.nil?
115
+ files[xx["path"]] = xx
116
+ end
117
+ useState = (!oldFileState.nil? and oldFileState.has_key?(xx["path"]))
118
+ old = (useState ? oldFileState[xx["path"]]["hash"] : nil)
119
+ subs = Ripple.walkDropbox(client, xx["path"], fileState, old)
120
+ if !subs.nil?
121
+ files.merge!(subs)
122
+ end
123
+ }
124
+ end
125
+
126
+ return files
127
+ end
128
+
129
+ def Ripple.sync(path = "")
130
+ conf = Ripple.loadConfiguration(path)
131
+ begin
132
+ session, client, dropboxKeys = Ripple.connectToDropbox(path)
133
+ rescue DropboxAuthError
134
+ puts "Dropbox authorization failed."
135
+ Ripple.cleanup(conf, dropboxKeys, path)
136
+ return
137
+ rescue NameError
138
+ puts "Destination does not exist."
139
+ Ripple.cleanup(conf, dropboxKeys, path)
140
+ return
141
+ end
142
+
143
+ if session.nil?
144
+ puts "Could not connect to Dropbox."
145
+ Ripple.cleanup(conf, dropboxKeys, path)
146
+ return
147
+ end
148
+
149
+ destDir = conf[:destinationDir]
150
+
151
+ fileState = {}
152
+ oldFileState = dropboxKeys[:files]
153
+ files = Ripple.walkDropbox(client, '/', fileState, oldFileState)
154
+
155
+ if !files.nil?
156
+ files.keys.each { |x|
157
+ file = client.get_file(x)
158
+ File.open(File.join(destDir, x), 'w') {|f| f.puts file}
159
+ }
160
+ end
161
+
162
+ conf[:dropbox][:sync].each { |ii|
163
+ Dir.glob(File.join(destDir, ii)).each { |oo|
164
+ if !File.directory?(oo)
165
+ upName = Pathname.new(oo).relative_path_from(Pathname.new(destDir)).to_s
166
+ upName = File.join("", upName)
167
+ if files.nil? or !files.has_key?(upName)
168
+ up = File.open(oo)
169
+ client.put_file(upName, up, true)
170
+ up.close()
171
+ end
172
+ end
173
+ }
174
+ }
175
+
176
+ dropboxKeys[:files] = Ripple.walkDropbox(client, '/', fileState, {})
177
+ Ripple.cleanup(conf, dropboxKeys, path)
178
+
179
+ return true
180
+ end
181
+ end
@@ -0,0 +1,3 @@
1
+ module Ripple
2
+ VERSION = "0.0.1"
3
+ end
data/lib/ripple.rb ADDED
@@ -0,0 +1 @@
1
+ require 'ripple/base'
Binary file
data/ripple.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "lib/ripple/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rypple"
7
+ s.version = Ripple::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jason Ziglar"]
10
+ s.email = ["jasedit@catexia.com"]
11
+ s.homepage = "https://github.com/jasedit/ripple"
12
+ s.summary = %q{Dropbox interface for jekyll.}
13
+ s.description = %q{A gem providing a Dropbox syncing interface for jekyll, along with a cgi file to update jekyll.}
14
+
15
+ s.add_runtime_dependency "jekyll"
16
+ s.add_runtime_dependency "dropbox-sdk"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
data/ripple.yaml ADDED
@@ -0,0 +1,5 @@
1
+ ---
2
+ :destinationDir: ./test
3
+ :dropbox:
4
+ :sync:
5
+ - "**"
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rypple
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jason Ziglar
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-02-27 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: jekyll
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: dropbox-sdk
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: A gem providing a Dropbox syncing interface for jekyll, along with a cgi file to update jekyll.
49
+ email:
50
+ - jasedit@catexia.com
51
+ executables:
52
+ - rippleInstall.rb
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - Gemfile
59
+ - README
60
+ - Rakefile
61
+ - bin/rippleInstall.rb
62
+ - lib/ripple.rb
63
+ - lib/ripple/base.rb
64
+ - lib/ripple/version.rb
65
+ - pkg/ripple-0.0.1.gem
66
+ - ripple.gemspec
67
+ - ripple.yaml
68
+ homepage: https://github.com/jasedit/ripple
69
+ licenses: []
70
+
71
+ post_install_message:
72
+ rdoc_options: []
73
+
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirements: []
95
+
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.17
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Dropbox interface for jekyll.
101
+ test_files: []
102
+