pair 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
6
+ - ree
7
+ - jruby
8
+ - rbx
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pair (0.0.1)
5
- httparty
4
+ pair (0.0.2)
5
+ httparty (~> 0.8.1)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
@@ -13,18 +13,20 @@ GEM
13
13
  multi_xml
14
14
  multi_json (1.0.3)
15
15
  multi_xml (0.4.1)
16
- rspec (2.3.0)
17
- rspec-core (~> 2.3.0)
18
- rspec-expectations (~> 2.3.0)
19
- rspec-mocks (~> 2.3.0)
20
- rspec-core (2.3.1)
21
- rspec-expectations (2.3.0)
16
+ rake (0.9.2.2)
17
+ rspec (2.7.0)
18
+ rspec-core (~> 2.7.0)
19
+ rspec-expectations (~> 2.7.0)
20
+ rspec-mocks (~> 2.7.0)
21
+ rspec-core (2.7.1)
22
+ rspec-expectations (2.7.0)
22
23
  diff-lcs (~> 1.1.2)
23
- rspec-mocks (2.3.0)
24
+ rspec-mocks (2.7.0)
24
25
 
25
26
  PLATFORMS
26
27
  ruby
27
28
 
28
29
  DEPENDENCIES
29
30
  pair!
30
- rspec (~> 2.3.0)
31
+ rake
32
+ rspec (~> 2.7.0)
@@ -11,15 +11,24 @@ Hosting Users:
11
11
  * Must have a variant of unix installed
12
12
  * Must have tmux installed
13
13
 
14
+ == Installation
15
+ Pair is available on {RubyGems}[http://rubygems.org/gems/pair]; the
16
+ easiest way to install it is
17
+
18
+ gem install pair
19
+
14
20
  == Example
15
21
 
16
- === Interactive hosted session
22
+ === Hosting an interactive session
23
+ In interactive mode, participants can interact with the tmux session.
17
24
 
18
- bin/pairmill host -p<github-user>,<github-user>,<github-user>
25
+ pair host -p<github-user>,<github-user>,<github-user>
19
26
 
20
- === Interactive hosted session
27
+ === Hosting a view-only session
28
+ In view mode, participants can see your tmux session but may not
29
+ interact with it.
21
30
 
22
- bin/pairmill host -v<github-user>,<github-user>,<github-user>
31
+ pair host -v<github-user>,<github-user>,<github-user>
23
32
 
24
33
  == Contributing to pair
25
34
 
data/bin/pair CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  $: << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
 
5
- require "pair/command_line"
6
- Pair::CommandLine.run!(ARGV)
5
+ require "pair/cli"
6
+ Pair::Cli.run!(ARGV)
7
7
 
@@ -1,10 +1,9 @@
1
- require 'httparty'
2
- require 'ruby-debug' if ENV["DEBUGGER"] == "true"
1
+ module Pair
2
+ end
3
3
 
4
4
  require "pair/version"
5
+
6
+ require "pair/os"
7
+ require "pair/config"
5
8
  require "pair/api"
6
9
  require "pair/session"
7
-
8
- module Pair
9
- # Your code goes here...
10
- end
@@ -1,60 +1,39 @@
1
- require 'yaml'
1
+ require 'httparty'
2
+ require 'pair/config'
2
3
 
3
4
  module Pair
4
5
  module Api
5
- def create_session(session)
6
- post("/v1/sessions", {
7
- :body => {
8
- :session => {
9
- :name => session.name,
10
- :viewers => session.viewers,
11
- :participants => session.participants,
12
- :tunnel => {
13
- :host_login => session.host_login
14
- }
15
- }
16
- }
17
- })
18
- end
19
-
20
- def join_session(session)
21
- options = { :query => { :name => session.name, :host => session.host, :format => "json" } }
22
- get("/v1/sessions/search.json", options)
23
- end
6
+ include HTTParty
7
+ extend self
24
8
 
25
- def api_token
26
- config[:api_token]
9
+ def setup
10
+ base_uri ENV['BASE_URI'] || 'api.pairmill.com'
11
+ default_params :api_token => Pair.config.api_token
12
+ yield
27
13
  end
28
14
 
29
- def config
30
- @config ||= if File.exists?(config_file)
31
- YAML.load_file(config_file)[base_uri] || setup_config
32
- else
33
- setup_config
15
+ def create_session(session)
16
+ setup do
17
+ post("/v1/sessions", {
18
+ :body => {
19
+ :session => {
20
+ :name => session.name,
21
+ :viewers => session.viewers,
22
+ :participants => session.participants,
23
+ :tunnel => {
24
+ :host_login => session.host_login
25
+ }
26
+ }
27
+ }
28
+ })
34
29
  end
35
30
  end
36
31
 
37
- def config_file
38
- File.expand_path("~/.pair.yml")
39
- end
40
-
41
- def setup_config
42
- config = YAML.load_file(config_file) rescue {}
43
-
44
- print "Please input your API token for #{base_uri}: "
45
- config[base_uri] = {:api_token => $stdin.gets.chomp}
46
-
47
- File.open(config_file, 'w') do |f|
48
- f.write(YAML.dump(config))
32
+ def join_session(session)
33
+ setup do
34
+ options = { :query => { :name => session.name, :host => session.host, :format => "json" } }
35
+ get("/v1/sessions/search.json", options)
49
36
  end
50
-
51
- config[base_uri]
52
37
  end
53
-
54
- include HTTParty
55
- extend self
56
-
57
- base_uri ENV['BASE_URI'] || 'api.pairmill.com'
58
- default_params :api_token => api_token
59
38
  end
60
39
  end
@@ -1,8 +1,9 @@
1
1
  require "pair"
2
+ require 'pair/cli/custom_errors'
2
3
  require "optparse"
3
4
 
4
5
  module Pair
5
- class CommandLine
6
+ class Cli
6
7
  attr_accessor :arguments, :options
7
8
  private :arguments=, :options=
8
9
 
@@ -18,35 +19,44 @@ module Pair
18
19
  def run!
19
20
  case command = arguments.shift
20
21
  when 'host'
21
- require "pair/command_line/host"
22
+ require "pair/cli/host"
22
23
  Host.run!(arguments)
24
+ when 'config'
25
+ require "pair/cli/config"
26
+ Config.run!(arguments)
23
27
  else
24
28
  unknown_command(command)
25
29
  end
30
+ rescue ApiTokenMissingError, EnableSSHError => error
31
+ handle_error error.message, false
26
32
  rescue SystemExit
27
33
  raise
28
34
  rescue
29
- if $-d
35
+ handle_error " Please contact support@pairmill.com, there\n" +
36
+ " was an issue creating your session.", $-d
37
+ end
38
+
39
+ private
40
+ def handle_error message, reraise = true
41
+ if reraise
42
+ raise
43
+ else
30
44
  STDOUT.puts "\n"
31
- STDOUT.puts " Please contact support@pairmill.com, there"
32
- STDOUT.puts " was an issue creating your session."
45
+ STDOUT.puts message
33
46
  STDOUT.puts "\n"
34
- else
35
- raise
36
47
  end
37
48
  end
38
49
 
39
- private
40
50
  def unknown_command(command)
41
51
  puts "Unknown command: #{command}" if command
42
52
 
43
53
  #{$0} join [options]
44
54
  abort %Q[
45
- Usage: #{$0} host [options]
55
+ Usage: #{$0.split("/").last} host [options]
46
56
 
47
57
  You can pass -h to a subcommand to learn more about it.
48
58
 
49
- e.g. #{$0} join -h
59
+ e.g. #{$0.split("/").last} join -h
50
60
  ].gsub(/^ {0,9}/,'')
51
61
  end
52
62
 
@@ -0,0 +1,28 @@
1
+ module Pair
2
+ class Cli
3
+ class Config < self
4
+ def run!
5
+ parse!
6
+
7
+ Pair.config(options)
8
+ end
9
+
10
+ def parse!
11
+ opts = parse do |opts|
12
+ opts.banner = "Usage: #{$0.split("/").last} config" +
13
+ "\n\n" +
14
+ "Options:" +
15
+ "\n"
16
+
17
+ opts.on("--api-token KEY") do |key|
18
+ options[:api_token] = key
19
+ end
20
+
21
+ # opts.on("--enable-ssh") do
22
+ # options[:enable_ssh] = true
23
+ # end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,6 @@
1
+ module Pair
2
+ class Cli
3
+ class ApiTokenMissingError < StandardError; end
4
+ class EnableSSHError < StandardError; end
5
+ end
6
+ end
@@ -1,16 +1,31 @@
1
- require "pair/command_line"
2
-
3
1
  module Pair
4
- class CommandLine
2
+ class Cli
5
3
  class Host < self
6
4
  def run!
7
5
  parse!
8
- Pair::Session.host(options)
6
+
7
+ with_valid_config do
8
+ Pair::Session.host(options)
9
+ end
10
+ end
11
+
12
+ def with_valid_config
13
+ config = Pair.config
14
+
15
+ unless config.api_token
16
+ raise ApiTokenMissingError.new("api-token is required. try --help to understand how")
17
+ end
18
+
19
+ unless config.ssh_enabled?
20
+ raise EnableSSHError.new("ssh is not enabled, turn on ssh daemon to continue")
21
+ end
22
+
23
+ yield
9
24
  end
10
25
 
11
26
  def parse!
12
27
  opts = parse do |opts|
13
- opts.banner = "Usage: #{$0} host [-s SESSION_NAME] [-v PAIR[,PAIR[,...]] [-p PAIR[,PAIR[,...]]" +
28
+ opts.banner = "Usage: #{$0.split("/").last} host [-s SESSION_NAME] [-v PAIR[,PAIR[,...]] [-p PAIR[,PAIR[,...]]" +
14
29
  "\n\n" +
15
30
  "At least one PAIR (of any type must be defined). A PAIR takes the form of a Github username." +
16
31
  "\n\n"+
@@ -0,0 +1,96 @@
1
+ require 'yaml/store'
2
+
3
+ module Pair
4
+ HOST = ENV['HOST'] || "api.pairmill.com"
5
+
6
+ def self.config(options = nil)
7
+ config = Config.new(HOST, STDIN, STDOUT)
8
+ config.update(options) if options
9
+ config
10
+ end
11
+
12
+ class Config
13
+ attr_accessor :host, :input, :output
14
+
15
+ def initialize(host = HOST, input = STDIN, output = STDOUT)
16
+ self.host = host
17
+ self.input = input
18
+ self.output = output
19
+ end
20
+
21
+ # def api_token
22
+ # self[:api_token] ||= begin
23
+ # print "Please input your API token for Pair: "
24
+ # gets.chomp
25
+ # end
26
+ # end
27
+
28
+ def method_missing(method, *args, &block)
29
+ method = method.to_s
30
+
31
+ if method =~ /=$/ # setter
32
+ self[method.gsub(/=$/,'').to_sym] = [*args].first
33
+ else
34
+ self[method.to_sym] || super
35
+ end
36
+ end
37
+
38
+ def api_token
39
+ self[:api_token]
40
+ end
41
+
42
+ def enable_ssh
43
+ self[:enable_ssh]
44
+ end
45
+
46
+ def ssh_enabled?
47
+ if Pair::OS.x?
48
+ `systemsetup -getremotelogin`.match("Remote Login: On")
49
+ end
50
+ end
51
+
52
+ def update(options = {})
53
+ if options.is_a? Hash
54
+ options.each do |k,v|
55
+ config.transaction do
56
+ host_config[k] = v
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ protected
63
+ def [](key)
64
+ config.transaction do
65
+ host_config[key]
66
+ end
67
+ end
68
+
69
+ def []=(key, value)
70
+ config.transaction do
71
+ host_config[key] = value
72
+ end
73
+ end
74
+
75
+ # Must be called within a config transaction
76
+ def host_config
77
+ config[host] ||= {}
78
+ end
79
+
80
+ def config
81
+ @config ||= YAML::Store.new(config_file)
82
+ end
83
+
84
+ def config_file
85
+ File.join(ENV['HOME'], ".pair.yml")
86
+ end
87
+
88
+ def print(*args)
89
+ output.print(*args)
90
+ end
91
+
92
+ def gets(*args)
93
+ input.gets(*args)
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,13 @@
1
+ require 'rbconfig'
2
+
3
+ module Pair
4
+ module OS
5
+ def linux?
6
+ !RbConfig::CONFIG['target_os'].match("linux").nil?
7
+ end
8
+
9
+ def self.x?
10
+ !RbConfig::CONFIG['target_os'].match("darwin").nil?
11
+ end
12
+ end
13
+ end
@@ -9,8 +9,8 @@ module Pair
9
9
  attr_accessor :attach_command
10
10
  attr_accessor :key_file_path
11
11
 
12
- def initialize(member_keys = {}, attach_command)
13
- self.member_keys = member_keys
12
+ def initialize(member_keys, attach_command)
13
+ self.member_keys = member_keys || {}
14
14
  self.attach_command = attach_command
15
15
  self.key_file_path = File.expand_path("~/.ssh/authorized_keys")
16
16
  end
@@ -1,3 +1,3 @@
1
1
  module Pair
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -17,5 +17,6 @@ Gem::Specification.new do |gem|
17
17
 
18
18
  gem.add_dependency("httparty", "~> 0.8.1")
19
19
 
20
- gem.add_development_dependency("rspec", "~> 2.3.0")
20
+ gem.add_development_dependency("rake")
21
+ gem.add_development_dependency("rspec", "~> 2.7.0")
21
22
  end
@@ -0,0 +1,64 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require 'pair/config'
4
+
5
+ describe Pair::Config do
6
+ let(:stdin) { StringIO.new }
7
+ let(:stdout) { StringIO.new }
8
+ let(:host) { "api.domain.com" }
9
+
10
+ let(:config) { described_class.new(host, stdin, stdout) }
11
+
12
+ before do
13
+ config_hash = {}
14
+ YAML::Store.stub!(:new => config_hash)
15
+ def config_hash.transaction
16
+ yield
17
+ end
18
+ end
19
+
20
+ context "for different hosts" do
21
+ it "has a different set of configs for each host" do
22
+ host1, host2 = "api.domain.com", "api.beta.domain.com"
23
+ config1 = described_class.new(host1)
24
+ config2 = described_class.new(host2)
25
+ config3 = described_class.new(host1)
26
+
27
+ config1.a_setting = "setting 1"
28
+ config2.a_setting = "setting 2"
29
+
30
+ config1.a_setting.should == "setting 1"
31
+ config3.a_setting.should == "setting 1"
32
+ config2.a_setting.should == "setting 2"
33
+ end
34
+ end
35
+
36
+ describe '#api_token' do
37
+ # context "when none is saved" do
38
+ # it "prompts for key to be entered" do
39
+ # response = "abc123"
40
+ # stdin << "#{response}\n"
41
+ # stdin.rewind
42
+ #
43
+ # config.api_token.should == response
44
+ #
45
+ # stdout.rewind
46
+ # stdout.read.should == "Please input your API token for Pair: "
47
+ # end
48
+ #
49
+ # it "saves the key" do
50
+ # stdin.should_receive(:gets).once.and_return("abc123\n")
51
+ # config.api_token
52
+ # config.api_token
53
+ # end
54
+ # end
55
+
56
+ context "when one is already saved" do
57
+ it "returns the saved value" do
58
+ api_token = "abc123"
59
+ config.api_token = api_token
60
+ config.api_token.should == api_token
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
2
 
3
+ require 'pair/session/authorized_keys_file'
3
4
  require 'fileutils'
4
5
 
5
6
  describe Pair::Session::AuthorizedKeysFile do
@@ -2,14 +2,17 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
4
  require 'rspec'
5
- require 'json'
6
5
  require 'fixture_helper'
7
- require 'pair'
6
+
7
+ require 'pair/config'
8
8
 
9
9
  # Requires supporting files with custom matchers and macros, etc,
10
10
  # in ./support/ and its subdirectories.
11
11
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
12
 
13
13
  RSpec.configure do |config|
14
-
14
+ config.before do
15
+ # Never ask for API token in tests
16
+ Pair.stub!(:config => stub(:api_token => "xxxx"))
17
+ end
15
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pair
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,12 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-11-27 00:00:00.000000000Z
13
+ date: 2011-12-08 00:00:00.000000000 -06:00
14
+ default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: httparty
17
- requirement: &70298620262940 !ruby/object:Gem::Requirement
18
+ requirement: &2157594700 !ruby/object:Gem::Requirement
18
19
  none: false
19
20
  requirements:
20
21
  - - ~>
@@ -22,18 +23,29 @@ dependencies:
22
23
  version: 0.8.1
23
24
  type: :runtime
24
25
  prerelease: false
25
- version_requirements: *70298620262940
26
+ version_requirements: *2157594700
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: &2157594280 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *2157594280
26
38
  - !ruby/object:Gem::Dependency
27
39
  name: rspec
28
- requirement: &70298620258860 !ruby/object:Gem::Requirement
40
+ requirement: &2157593740 !ruby/object:Gem::Requirement
29
41
  none: false
30
42
  requirements:
31
43
  - - ~>
32
44
  - !ruby/object:Gem::Version
33
- version: 2.3.0
45
+ version: 2.7.0
34
46
  type: :development
35
47
  prerelease: false
36
- version_requirements: *70298620258860
48
+ version_requirements: *2157593740
37
49
  description: Effortless remote pairing
38
50
  email:
39
51
  - me@bjeanes.com
@@ -46,6 +58,7 @@ files:
46
58
  - .gitignore
47
59
  - .rspec
48
60
  - .rvmrc
61
+ - .travis.yml
49
62
  - Gemfile
50
63
  - Gemfile.lock
51
64
  - README.rdoc
@@ -53,8 +66,12 @@ files:
53
66
  - bin/pair
54
67
  - lib/pair.rb
55
68
  - lib/pair/api.rb
56
- - lib/pair/command_line.rb
57
- - lib/pair/command_line/host.rb
69
+ - lib/pair/cli.rb
70
+ - lib/pair/cli/config.rb
71
+ - lib/pair/cli/custom_errors.rb
72
+ - lib/pair/cli/host.rb
73
+ - lib/pair/config.rb
74
+ - lib/pair/os.rb
58
75
  - lib/pair/session.rb
59
76
  - lib/pair/session/authorized_keys_file.rb
60
77
  - lib/pair/session/hosted_session.rb
@@ -66,8 +83,10 @@ files:
66
83
  - spec/fixtures/api_hosted_session.yml
67
84
  - spec/fixtures/api_joined_session.yml
68
85
  - spec/fixtures/user_keys.yml
86
+ - spec/pair/config_spec.rb
69
87
  - spec/pair/session/authorized_keys_file_spec.rb
70
88
  - spec/spec_helper.rb
89
+ has_rdoc: true
71
90
  homepage: http://www.pairmill.com
72
91
  licenses: []
73
92
  post_install_message:
@@ -88,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
107
  version: '0'
89
108
  requirements: []
90
109
  rubyforge_project:
91
- rubygems_version: 1.8.10
110
+ rubygems_version: 1.6.2
92
111
  signing_key:
93
112
  specification_version: 3
94
113
  summary: Pair with remote programmers with a single command.
@@ -97,5 +116,6 @@ test_files:
97
116
  - spec/fixtures/api_hosted_session.yml
98
117
  - spec/fixtures/api_joined_session.yml
99
118
  - spec/fixtures/user_keys.yml
119
+ - spec/pair/config_spec.rb
100
120
  - spec/pair/session/authorized_keys_file_spec.rb
101
121
  - spec/spec_helper.rb