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 CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ tmp/*
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
- if Nwcopy::Dropbox.available?
11
- Nwcopy::Dropbox.copy data
12
- else
13
- STDERR << NwCopy::Dropbox.unavailable_message
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
- if Nwcopy::Dropbox.available?
19
- if clipboard = Nwcopy::Dropbox.paste
20
- `echo "#{clipboard}" | pbcopy` unless `which pbcopy`.empty?
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.read
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
@@ -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 clipboard
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Nwcopy
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
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.rubyforge_project = "nwcopy"
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
@@ -0,0 +1,3 @@
1
+ require 'nwcopy'
2
+ require 'minitest/spec'
3
+ require 'minitest/mock'
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
- - 4
10
- version: 0.0.4
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-01-31 00:00:00 -06:00
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: nwcopy
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