nwcopy 0.0.4 → 0.0.5
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 +1 -0
- data/Gemfile.lock +21 -0
- data/lib/nwcopy.rb +28 -13
- data/lib/nwcopy/client.rb +82 -0
- data/lib/nwcopy/dropbox.rb +8 -4
- data/lib/nwcopy/gist.rb +50 -0
- data/lib/nwcopy/version.rb +1 -1
- data/nwcopy.gemspec +1 -2
- data/test/test_dropbox.rb +85 -0
- data/test/test_gist.rb +75 -0
- data/test/test_helper.rb +3 -0
- metadata +28 -11
data/.gitignore
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
nwcopy (0.0.4)
|
5
|
+
sinatra
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
rack (1.2.1)
|
11
|
+
sinatra (1.1.2)
|
12
|
+
rack (~> 1.1)
|
13
|
+
tilt (~> 1.2)
|
14
|
+
tilt (1.2.2)
|
15
|
+
|
16
|
+
PLATFORMS
|
17
|
+
ruby
|
18
|
+
|
19
|
+
DEPENDENCIES
|
20
|
+
nwcopy!
|
21
|
+
sinatra
|
data/lib/nwcopy.rb
CHANGED
@@ -2,39 +2,54 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
2
2
|
$:.include?(File.dirname(__FILE__)) ||
|
3
3
|
$:.include?(File.expand_path(File.dirname(__FILE__)))
|
4
4
|
|
5
|
+
require 'nwcopy/client'
|
5
6
|
require 'nwcopy/dropbox'
|
7
|
+
require 'nwcopy/gist'
|
6
8
|
|
7
9
|
module Nwcopy
|
10
|
+
|
11
|
+
def self.plugins
|
12
|
+
[Nwcopy::Client, Nwcopy::Dropbox, Nwcopy::Gist]
|
13
|
+
end
|
14
|
+
|
8
15
|
def self.copy
|
9
16
|
data = read_data
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
17
|
+
unavailable = []
|
18
|
+
plugins.each do |plugin|
|
19
|
+
if plugin.available?
|
20
|
+
return plugin.copy data
|
21
|
+
else
|
22
|
+
unavailable << plugin.unavailable_message
|
23
|
+
end
|
14
24
|
end
|
25
|
+
STDERR << unavailable.join("\n")
|
15
26
|
end
|
16
27
|
|
17
28
|
def self.paste
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
clipboard
|
29
|
+
unavailable = []
|
30
|
+
plugins.each do |plugin|
|
31
|
+
if plugin.available?
|
32
|
+
if clipboard = plugin.paste
|
33
|
+
`echo "#{clipboard}" | pbcopy` unless `which pbcopy`.empty?
|
34
|
+
return clipboard
|
35
|
+
end
|
36
|
+
else
|
37
|
+
unavailable << plugin.unavailable_message
|
22
38
|
end
|
23
|
-
else
|
24
|
-
STDERR << NwCopy::Dropbox.unavailable_message
|
25
39
|
end
|
40
|
+
STDERR << unavailable.join("\n")
|
26
41
|
end
|
27
42
|
|
28
43
|
private
|
29
44
|
def self.read_data
|
30
45
|
if ARGF.file == STDIN
|
31
|
-
STDIN.read_nonblock(1) + STDIN.read
|
46
|
+
StringIO.new(STDIN.read_nonblock(1) + STDIN.read)
|
32
47
|
else
|
33
|
-
ARGF
|
48
|
+
ARGF
|
34
49
|
end
|
35
50
|
rescue IO::WaitReadable => e
|
36
51
|
unless `which pbpaste`.empty?
|
37
|
-
`pbpaste`
|
52
|
+
StringIO.new(`pbpaste`)
|
38
53
|
else
|
39
54
|
STDERR << 'Nothing to do!'
|
40
55
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'net/http/post/multipart'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Nwcopy
|
6
|
+
class Client
|
7
|
+
class << self
|
8
|
+
attr_writer :gist
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.unavailable_message
|
12
|
+
"nwcopy is not configured. Go to nwcopy.heroku.com. Then set $NWCOPY_CREDS."
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.available?
|
16
|
+
ENV['NWCOPY_CREDS']
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.time
|
20
|
+
Time.now
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.copy data
|
24
|
+
if data.respond_to? :filename
|
25
|
+
filename = data.filename
|
26
|
+
else
|
27
|
+
filename = nil
|
28
|
+
@tmpfile = Tempfile.new 'nwcopy'
|
29
|
+
@tmpfile.write(data.read)
|
30
|
+
@tmpfile.close
|
31
|
+
data = File.open @tmpfile.path
|
32
|
+
end
|
33
|
+
|
34
|
+
io = UploadIO.new(data, nil, filename)
|
35
|
+
|
36
|
+
url = URI.parse("#{base_url}/copy")
|
37
|
+
req = Net::HTTP::Post::Multipart.new url.path, 'data' => io
|
38
|
+
res = start req, url
|
39
|
+
|
40
|
+
res.body
|
41
|
+
ensure
|
42
|
+
@tmpfile.unlink if @tmpfile
|
43
|
+
@tmpfile = nil
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def self.paste
|
48
|
+
url = URI.parse("#{base_url}/paste")
|
49
|
+
|
50
|
+
req = Net::HTTP::Get.new(url.path)
|
51
|
+
res = start req, url
|
52
|
+
|
53
|
+
file = res['Location'] ? res['Location'].split('/').last : nil
|
54
|
+
|
55
|
+
if file && !File.exists?(file)
|
56
|
+
File.open file, 'w+' do |f|
|
57
|
+
f << res.body
|
58
|
+
end
|
59
|
+
"Pasted to #{file}"
|
60
|
+
else
|
61
|
+
res.body
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
def self.start req, url
|
67
|
+
req.basic_auth *credentials
|
68
|
+
Net::HTTP.start(url.host, url.port) do |http|
|
69
|
+
http.request req
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.base_url
|
74
|
+
ENV['NWCOPY_TEST'] == 'true' ? 'http://localhost:3000' : 'http://nwcopy.heroku.com'
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.credentials
|
78
|
+
ENV['NWCOPY_CREDS'].split(':')
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
data/lib/nwcopy/dropbox.rb
CHANGED
@@ -2,6 +2,10 @@ require 'digest/sha1'
|
|
2
2
|
|
3
3
|
module Nwcopy
|
4
4
|
class Dropbox
|
5
|
+
class << self
|
6
|
+
attr_accessor :dropbox_base
|
7
|
+
end
|
8
|
+
|
5
9
|
def self.unavailable_message
|
6
10
|
"Dropbox was not found at #{nwcopy_dir}. Get it at http://getdropbox.com/"
|
7
11
|
end
|
@@ -10,14 +14,14 @@ module Nwcopy
|
|
10
14
|
return false unless File.exists? dropbox_dir
|
11
15
|
|
12
16
|
unless File.exists? nwcopy_dir
|
13
|
-
STDERR << "Creating nwcopy directory at #{nwcopy_dir}"
|
14
17
|
Dir.mkdir nwcopy_dir
|
15
18
|
end
|
16
19
|
|
17
20
|
File.exists? nwcopy_dir
|
18
21
|
end
|
19
22
|
|
20
|
-
def self.copy
|
23
|
+
def self.copy io
|
24
|
+
clipboard = io.read
|
21
25
|
digest = Digest::SHA1.hexdigest clipboard
|
22
26
|
nwcopy_file = File.join nwcopy_dir, digest
|
23
27
|
File.open(nwcopy_file, 'w+') do |f|
|
@@ -28,7 +32,7 @@ module Nwcopy
|
|
28
32
|
|
29
33
|
# Used to determine which plugin has the newest file.
|
30
34
|
def self.time
|
31
|
-
latest_file.mtime
|
35
|
+
latest_file ? latest_file.mtime : nil
|
32
36
|
end
|
33
37
|
|
34
38
|
def self.paste
|
@@ -50,7 +54,7 @@ module Nwcopy
|
|
50
54
|
end
|
51
55
|
|
52
56
|
def self.dropbox_dir
|
53
|
-
File.expand_path '~/Dropbox'
|
57
|
+
File.expand_path(dropbox_base || '~/Dropbox')
|
54
58
|
end
|
55
59
|
|
56
60
|
def self.nwcopy_dir
|
data/lib/nwcopy/gist.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'gist'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'digest/sha1'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module Nwcopy
|
7
|
+
class Gist
|
8
|
+
class << self
|
9
|
+
attr_writer :gist
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.unavailable_message
|
13
|
+
"Github is not configured. Cannot use Gist."
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.available?
|
17
|
+
!gist.send(:auth).empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.time
|
21
|
+
Time.parse(latest_gist["created_at"])
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.copy io
|
25
|
+
clipboard = io.read
|
26
|
+
digest = Digest::SHA1.hexdigest clipboard
|
27
|
+
filename = io.respond_to?(:filename) ? io.filename : digest
|
28
|
+
gist.write [{:filename => filename, :input => clipboard}], false
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.paste
|
32
|
+
gist.read latest_gist["repo"]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def self.latest_gist
|
37
|
+
gist.list["gists"].sort{|x, y| Time.parse(y["created_at"]) <=> Time.parse(x["created_at"])}.first
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.gist
|
41
|
+
@gist || ::Gist
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module ::Gist
|
47
|
+
def self.list
|
48
|
+
JSON.parse open("http://gist.github.com/api/v1/json/gists/#{config('github.user')}").read
|
49
|
+
end
|
50
|
+
end
|
data/lib/nwcopy/version.rb
CHANGED
data/nwcopy.gemspec
CHANGED
@@ -12,8 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = %q{network copy & paste.}
|
13
13
|
s.description = %q{Uses your Dropbox folder to facilitate copy and pasting between machines. More awesomesauce to come.}
|
14
14
|
|
15
|
-
s.
|
16
|
-
|
15
|
+
s.add_dependency 'sinatra'
|
17
16
|
s.files = `git ls-files`.split("\n")
|
18
17
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
describe Nwcopy::Dropbox do
|
5
|
+
before do
|
6
|
+
@dropbox = Nwcopy::Dropbox
|
7
|
+
@base = File.expand_path(File.join(File.dirname(__FILE__), '..', 'tmp', 'Dropbox'))
|
8
|
+
@nwcopy_base = File.join(@base, 'nwcopy')
|
9
|
+
@dropbox.dropbox_base = @base
|
10
|
+
end
|
11
|
+
|
12
|
+
describe :with_dropbox do
|
13
|
+
before do
|
14
|
+
@dropbox.dropbox_base = @base
|
15
|
+
FileUtils.mkdir_p @base
|
16
|
+
@available = @dropbox.available?
|
17
|
+
end
|
18
|
+
|
19
|
+
describe :available? do
|
20
|
+
|
21
|
+
it "should respond positively" do
|
22
|
+
@available.must_equal true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should create an nwcopy directory" do
|
26
|
+
File.exists?(@nwcopy_base).must_equal true
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe :time do
|
32
|
+
before do
|
33
|
+
@testfile = File.join(@nwcopy_base, 'foobar')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return nil when no files exist" do
|
37
|
+
@dropbox.time.must_be_nil
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return the time when files exist" do
|
41
|
+
FileUtils.touch(@testfile)
|
42
|
+
@dropbox.time.must_equal File.new(@testfile).mtime
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe :copy do
|
47
|
+
before do
|
48
|
+
@data = "Bad artists copy. Good artists steal."
|
49
|
+
@file = @dropbox.copy StringIO.new(@data)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should exist" do
|
53
|
+
File.exists?(@file).must_equal true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should have the same data" do
|
57
|
+
File.new(@file).read.must_equal @data
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe :paste do
|
62
|
+
before do
|
63
|
+
@data = "Copy from one, it's plagiarism; copy from two, it's research."
|
64
|
+
@file = @dropbox.copy StringIO.new(@data)
|
65
|
+
@pasted = @dropbox.paste
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should match the original data" do
|
69
|
+
@data.must_equal @pasted
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
after do
|
74
|
+
FileUtils.rm_rf @base
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe :without_dropbox do
|
79
|
+
describe :available? do
|
80
|
+
it "should respond negatively" do
|
81
|
+
@dropbox.available?.must_equal false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/test/test_gist.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
describe Nwcopy::Gist do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@gist = Nwcopy::Gist
|
7
|
+
@gists = {"gists" => [
|
8
|
+
{"public" => true,"created_at" => "2010/11/11 15:20:55 -0800","owner" => "j05h","files" => ["distance.rb"],
|
9
|
+
"description" => "Haversine formula in ruby", "repo" => "673425"},
|
10
|
+
{"public" => true,"created_at" => "2010/09/28 12:26:29 -0700","owner" => "j05h","files" => ["random_string.rb"],
|
11
|
+
"description" => nil, "repo" => "601616"},
|
12
|
+
{"public" => true,"created_at" => "2010/07/09 15:01:22 -0700","owner" => "j05h","files" => ["gistfile1.rb"],
|
13
|
+
"description" => nil,"repo" => "470131"}]}
|
14
|
+
end
|
15
|
+
|
16
|
+
describe :with_github do
|
17
|
+
before do
|
18
|
+
@mock = MiniTest::Mock.new
|
19
|
+
@mock.expect :auth, {"foo" => "bar"}
|
20
|
+
@gist.gist = @mock
|
21
|
+
end
|
22
|
+
|
23
|
+
describe :available do
|
24
|
+
it 'should be' do
|
25
|
+
@gist.available?.must_equal true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe :time do
|
30
|
+
before do
|
31
|
+
@mock.expect :list, @gists
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should return the latest time" do
|
35
|
+
@gist.time.must_equal Time.parse(@gists["gists"].first["created_at"])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe :copy do
|
40
|
+
before do
|
41
|
+
@mock.expect :write, "someurl", [String, true]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return a url response" do
|
45
|
+
@gist.copy(StringIO.new("To all good things an end must come.")).must_equal "someurl"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe :paste do
|
50
|
+
before do
|
51
|
+
@mock.expect :list, @gists
|
52
|
+
@mock.expect :read, "Wassup?", [@gists["gists"].first["repo"]]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should return appropriate data" do
|
56
|
+
@gist.paste.must_equal "Wassup?"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
describe :without_github do
|
63
|
+
before do
|
64
|
+
@mock = MiniTest::Mock.new
|
65
|
+
@mock.expect :auth, {}
|
66
|
+
@gist.gist = @mock
|
67
|
+
end
|
68
|
+
|
69
|
+
describe :available do
|
70
|
+
it 'should not be' do
|
71
|
+
@gist.available?.must_equal false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nwcopy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 23
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
8
|
+
- 5
|
9
|
+
version: 0.0.5
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Josh Kleinpeter
|
@@ -15,10 +14,22 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-
|
17
|
+
date: 2011-02-05 00:00:00 -06:00
|
19
18
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: sinatra
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
version: "0"
|
31
|
+
type: :runtime
|
32
|
+
version_requirements: *id001
|
22
33
|
description: Uses your Dropbox folder to facilitate copy and pasting between machines. More awesomesauce to come.
|
23
34
|
email:
|
24
35
|
- josh@kleinpeter.org
|
@@ -32,14 +43,20 @@ extra_rdoc_files: []
|
|
32
43
|
files:
|
33
44
|
- .gitignore
|
34
45
|
- Gemfile
|
46
|
+
- Gemfile.lock
|
35
47
|
- README.rdoc
|
36
48
|
- Rakefile
|
37
49
|
- bin/nwcopy
|
38
50
|
- bin/nwpaste
|
39
51
|
- lib/nwcopy.rb
|
52
|
+
- lib/nwcopy/client.rb
|
40
53
|
- lib/nwcopy/dropbox.rb
|
54
|
+
- lib/nwcopy/gist.rb
|
41
55
|
- lib/nwcopy/version.rb
|
42
56
|
- nwcopy.gemspec
|
57
|
+
- test/test_dropbox.rb
|
58
|
+
- test/test_gist.rb
|
59
|
+
- test/test_helper.rb
|
43
60
|
has_rdoc: true
|
44
61
|
homepage: ""
|
45
62
|
licenses: []
|
@@ -54,7 +71,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
54
71
|
requirements:
|
55
72
|
- - ">="
|
56
73
|
- !ruby/object:Gem::Version
|
57
|
-
hash: 3
|
58
74
|
segments:
|
59
75
|
- 0
|
60
76
|
version: "0"
|
@@ -63,16 +79,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
79
|
requirements:
|
64
80
|
- - ">="
|
65
81
|
- !ruby/object:Gem::Version
|
66
|
-
hash: 3
|
67
82
|
segments:
|
68
83
|
- 0
|
69
84
|
version: "0"
|
70
85
|
requirements: []
|
71
86
|
|
72
|
-
rubyforge_project:
|
87
|
+
rubyforge_project:
|
73
88
|
rubygems_version: 1.3.7
|
74
89
|
signing_key:
|
75
90
|
specification_version: 3
|
76
91
|
summary: network copy & paste.
|
77
|
-
test_files:
|
78
|
-
|
92
|
+
test_files:
|
93
|
+
- test/test_dropbox.rb
|
94
|
+
- test/test_gist.rb
|
95
|
+
- test/test_helper.rb
|