poet 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,4 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
3
+ - 1.9.2
4
4
  - 1.9.3
5
+ - rbx-18mode
6
+ - jruby
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: jruby
10
+ - rvm: rbx-18mode
data/History.txt CHANGED
@@ -1,5 +1,23 @@
1
1
  master
2
2
 
3
+ 0.5
4
+
5
+ - drop support for Ruby 1.8
6
+
7
+ - edit files under ~/.ssh/config.d/ directly with `poet edit some_ssh_config_file`
8
+
9
+ - use Thor internally for CLI
10
+
11
+ - 'bootstrap' is now a subcommand (use `poet bootstrap` instead of `poet --bootstrap`)
12
+
13
+ - also test against JRuby, Rubinius, and 1.9.2
14
+
15
+ - running verbosely works again
16
+
17
+ - extended help
18
+
19
+ 0.4
20
+
3
21
  - let users organize their config files in directories
4
22
 
5
23
  0.3.1
data/README.md CHANGED
@@ -1,16 +1,26 @@
1
1
  [![Build Status](https://secure.travis-ci.org/awendt/poet.png)](http://travis-ci.org/awendt/poet)
2
2
 
3
- # Wanna split up your `~/.ssh/config` into several files?
3
+ # Split your `ssh_config` into separate files!
4
4
 
5
- 1. `gem install poet`
6
- 2. `poet --bootstrap`
7
- 3. Organize files in `~/.ssh/config.d/ssh_config` any way you want. Just remember to re-run `poet` afterwards.
5
+ ## Getting started
6
+
7
+ $ gem install poet
8
+ $ poet bootstrap
9
+
10
+ This will move your `~/.ssh/config` into `~/.ssh/config.d/` and create an identical `~/.ssh/config`.
11
+ Organize files in `~/.ssh/config.d/` any way you want (just remember to re-run `poet` afterwards).
12
+
13
+ To edit `~/.ssh/config.d/some_file`, run `poet edit some_file`.
14
+ Poet will open your favorite $EDITOR and automatically create a new `~/.ssh/config`
15
+ when you quit the editor.
16
+
17
+ ## Advanced usage
8
18
 
9
19
  Poet won't touch your existing ssh_config.
10
20
  If you want to play with it, pass a different filename to the "-o" option.
11
21
  Or move your existing config out of the way.
12
22
 
13
- Stanzas under `~/.ssh/config.d/` with an extension of .disabled are ignored by Poet.
23
+ Stanzas under `~/.ssh/config.d/` with an extension of .disabled are ignored by default.
14
24
  Every now and then, when you do need it, run `poet --with CONFIG` to explicitly include
15
25
  `CONFIG.disabled` in your generated ssh_config. You can even include several by running several
16
26
  `--with` options or using `--with CONFIG1,CONFIG2`.
data/bin/poet CHANGED
@@ -1,37 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'optparse'
4
3
  require 'poet'
5
4
 
6
- options = {
7
- :ssh_config => ENV['POET_OUTPUT'] || File.expand_path('~/.ssh/config'),
8
- :verbose => false,
9
- :with => [],
10
- :dir => ENV['POET_GLOBDIR'] || File.expand_path('~/.ssh/config.d')
11
- }
12
-
13
- optparse = OptionParser.new do|opts|
14
- opts.on('-h', '--help', 'Display this screen') do
15
- puts opts
16
- exit
17
- end
18
- opts.on('-d', '--dir DIR', '') do |dir|
19
- options[:dir] = File.expand_path(dir)
20
- end
21
- opts.on('-o', '--output FILE', '') do |file|
22
- options[:ssh_config] = file
23
- end
24
- opts.on('-v', '--verbose', 'Be verbose') do
25
- options[:verbose] = true
26
- end
27
- opts.on('--bootstrap [FILE]', '') do |file|
28
- options[:bootstrap] = File.expand_path(file || options[:ssh_config])
29
- end
30
- opts.on('-w', '--with CONFIG', 'Include an otherwise disabled config file') do |file|
31
- options[:with] += file.split(',')
32
- options[:with].each{|file| puts "Including #{file} even if disabled..."}
33
- end
34
- end
35
- optparse.parse!
36
-
37
- Poet.application(options).run
5
+ PoetCLI.start(ARGV)
@@ -8,7 +8,7 @@ Feature: Bootstrapping
8
8
  Host *.amazonaws.com
9
9
  StrictHostKeyChecking no
10
10
  """
11
- When I run `poet --bootstrap --dir ./config.d`
11
+ When I run `poet bootstrap --dir ./config.d`
12
12
  Then the exit status should be 0
13
13
  And a directory named "config.d" should exist
14
14
  And a file named "config.d/ssh_config" should exist
@@ -24,8 +24,8 @@ Feature: Bootstrapping
24
24
  Host *.amazonaws.com
25
25
  StrictHostKeyChecking no
26
26
  """
27
- When I run `poet --bootstrap --dir ./config.d`
27
+ When I run `poet bootstrap --dir ./config.d`
28
28
  Then the exit status should be 0
29
- When I run `poet --bootstrap --dir ./config.d`
30
- Then the output from "poet --bootstrap --dir ./config.d" should contain "You're already good to go"
29
+ When I run `poet bootstrap --dir ./config.d`
30
+ Then the output from "poet bootstrap --dir ./config.d" should contain "You're already good to go"
31
31
  And the exit status should not be 0
@@ -0,0 +1,32 @@
1
+ Feature: Editing files
2
+ Scenario: User wants to edit files quickly
3
+ Given a file named "favorite_editor" with:
4
+ """
5
+ Host vim
6
+ User me
7
+ """
8
+ When I set env variable "EDITOR" to "/bin/cat"
9
+ And I run `poet edit favorite_editor`
10
+ Then the output from "poet edit favorite_editor" should contain "Host vim"
11
+ And the file "ssh_config" should contain "Host vim"
12
+
13
+ Scenario: Show warning when user does not have EDITOR set
14
+ Given a file named "no_editor" with:
15
+ """
16
+ Host none
17
+ User me
18
+ """
19
+ When I set env variable "EDITOR" to ""
20
+ And I run `poet edit no_editor`
21
+ Then the output from "poet edit no_editor" should contain "$EDITOR is empty. Could not determine your favorite editor."
22
+ And the exit status should not be 0
23
+
24
+ Scenario: Do not re-create ssh_config when no file was created
25
+ Given a file named "important" with:
26
+ """
27
+ This is absolutely vital information
28
+ """
29
+ When I set env variable "EDITOR" to "/bin/cat"
30
+ And I run `poet edit missing -o important`
31
+ Then the output from "poet edit missing -o important" should not contain "Found hand-crafted ssh_config"
32
+ And the exit status should be 0
@@ -0,0 +1,3 @@
1
+ When /^I set env variable "(\w+)" to "([^"]*)"$/ do |var, value|
2
+ ENV[var] = value
3
+ end
@@ -0,0 +1,29 @@
1
+ Feature: Seeing more output when running verbosely
2
+ Scenario: Silent by default
3
+ Given a file named "test" with:
4
+ """
5
+ Host te.st
6
+ User me
7
+ """
8
+ When I run `poet`
9
+ Then the output should not contain "Using test"
10
+
11
+ Scenario: User sees which files are included
12
+ Given a directory named "customers"
13
+ And a file named "customers/first" with:
14
+ """
15
+ Host customer1
16
+ User me
17
+ """
18
+ And a file named "customers/second" with:
19
+ """
20
+ Host customer2
21
+ User me
22
+ """
23
+ When I run `poet -v`
24
+ Then the output should contain exactly:
25
+ """
26
+ Using customers/first
27
+ Using customers/second
28
+
29
+ """
data/lib/poet.rb CHANGED
@@ -1,71 +1,87 @@
1
1
  require "poet/version"
2
+ require "thor"
2
3
  require "fileutils"
3
4
 
4
- module Poet
5
+ class PoetCLI < Thor
5
6
 
6
7
  MAGIC_LINE = "# Generated by #{File.basename(__FILE__, '.rb')}"
7
8
 
8
- class << self
9
-
10
- def application(options={})
11
- @application ||= Poet::Application.new(options)
9
+ default_task :create
10
+ class_option :dir,
11
+ desc: 'Use specified directory to collect conf files',
12
+ default: ENV['POET_GLOBDIR'] || File.expand_path('~/.ssh/config.d')
13
+ class_option :output,
14
+ desc: 'Generate output in specified file',
15
+ aliases: '-o',
16
+ default: ENV['POET_OUTPUT'] || File.expand_path('~/.ssh/config')
17
+ class_option :with,
18
+ desc: 'Include an otherwise disabled config file',
19
+ aliases: '-w',
20
+ default: ""
21
+ class_option :verbose,
22
+ desc: 'Be verbose',
23
+ aliases: '-v',
24
+ type: :boolean
25
+
26
+ desc "bootstrap [FILE]",
27
+ "Move ~/.ssh/config (or whatever you specified) to ~/.ssh/config.d/ to help you get started"
28
+ def bootstrap(file=nil)
29
+ file ||= File.expand_path(file || options[:output])
30
+ if File.directory?(options[:dir])
31
+ $stderr.puts "You're already good to go."
32
+ Process.exit!(3)
12
33
  end
13
-
34
+ FileUtils.mkdir_p(options[:dir])
35
+ FileUtils.mv(file, options[:dir])
36
+ create
14
37
  end
15
38
 
16
- class Application
17
-
18
- attr_reader :options
19
-
20
- def initialize(options={})
21
- @options = options
39
+ desc "", "Concatenate all host stanzas under ~/.ssh/config.d/ into a single ~/.ssh/config"
40
+ def create
41
+ if !File.directory?(options[:dir])
42
+ $stderr.puts "#{options[:dir]} does not exist or is not a directory"
43
+ Process.exit!(1)
22
44
  end
23
45
 
24
- def bootstrap
25
- if File.directory?(options[:dir])
26
- $stderr.puts "You're already good to go."
27
- Process.exit!(3)
28
- end
29
- FileUtils.mkdir_p(options[:dir])
30
- FileUtils.mv(options[:bootstrap], options[:dir])
46
+ if File.exists?(options[:output]) && File.new(options[:output]).gets == "#{MAGIC_LINE}\n"
47
+ puts "Found generated ssh_config under #{options[:output]}. Overwriting..."
48
+ elsif File.exists?(options[:output])
49
+ $stderr.puts "Found hand-crafted ssh_config under #{options[:output]}. Please move it out of the way or specify a different output file with the -o option."
50
+ Process.exit!(2)
31
51
  end
32
52
 
33
- def run
34
- bootstrap if options.has_key?(:bootstrap)
35
-
36
- if !File.directory?(options[:dir])
37
- $stderr.puts "#{options[:dir]} does not exist or is not a directory"
38
- Process.exit!(1)
39
- end
40
-
41
- if File.exists?(options[:ssh_config]) && File.new(options[:ssh_config]).gets == "#{MAGIC_LINE}\n"
42
- puts "Found generated ssh_config under #{options[:ssh_config]}. Overwriting..."
43
- elsif File.exists?(options[:ssh_config])
44
- $stderr.puts "Found hand-crafted ssh_config under #{options[:ssh_config]}. Please move it out of the way or specify a different output file with the -o option."
45
- Process.exit!(2)
46
- end
53
+ whitelist = options[:with].split(',')
54
+ files = Dir["#{options[:dir]}/**/*"].reject do |file|
55
+ File.directory?(file) || \
56
+ file =~ /\.disabled$/ && !whitelist.include?("#{File.basename(file, '.disabled')}")
57
+ end
47
58
 
48
- files = Dir["#{options[:dir]}/**/*"].reject do |file|
49
- File.directory?(file) || \
50
- file =~ /\.disabled$/ && !options[:with].include?("#{File.basename(file, '.disabled')}")
51
- end
59
+ files -= [options[:output]]
52
60
 
53
- files -= [options[:ssh_config]]
61
+ entries = []
54
62
 
55
- entries = []
63
+ files.sort.each do |file|
64
+ entries << File.read(file)
65
+ $stdout.puts "Using #{file.gsub(/^\.\//, '')}" if options[:verbose]
66
+ end
56
67
 
57
- files.sort.each do |file|
58
- entries << File.read(file)
59
- end
68
+ File.open(options[:output], 'w', 0600) do |ssh_config|
69
+ ssh_config.puts(MAGIC_LINE)
70
+ ssh_config.puts("# DO NOT EDIT THIS FILE")
71
+ ssh_config.puts("# Create or modify files under #{options[:dir]} instead")
72
+ ssh_config.puts(entries.join("\n"))
73
+ end
74
+ end
60
75
 
61
- File.open(options[:ssh_config], 'w', 0600) do |ssh_config|
62
- ssh_config.puts(MAGIC_LINE)
63
- ssh_config.puts("# DO NOT EDIT THIS FILE")
64
- ssh_config.puts("# Create or modify files under #{options[:dir]} instead")
65
- ssh_config.puts(entries.join("\n"))
66
- end
76
+ desc "edit FILE", "Open FILE under ~/.ssh/config.d/ in your favorite $EDITOR"
77
+ def edit(file)
78
+ if ENV['EDITOR'].to_s.empty?
79
+ $stderr.puts "$EDITOR is empty. Could not determine your favorite editor."
80
+ Process.exit!(4)
67
81
  end
68
-
82
+ filepath = File.join(options[:dir], file)
83
+ system("#{ENV['EDITOR']} #{filepath}")
84
+ create if File.exists?(filepath)
69
85
  end
70
86
 
71
87
  end
data/lib/poet/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Poet
2
- VERSION = "0.4"
2
+ VERSION = "0.5"
3
3
  end
data/poet.gemspec CHANGED
@@ -22,4 +22,5 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "cucumber"
23
23
  s.add_development_dependency "aruba"
24
24
  s.add_development_dependency "rake"
25
+ s.add_runtime_dependency "thor"
25
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poet
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: '0.5'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-27 00:00:00.000000000 Z
12
+ date: 2013-02-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cucumber
16
- requirement: &70266493053500 !ruby/object:Gem::Requirement
16
+ requirement: &70099056296460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70266493053500
24
+ version_requirements: *70099056296460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: aruba
27
- requirement: &70266493053040 !ruby/object:Gem::Requirement
27
+ requirement: &70099056296020 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70266493053040
35
+ version_requirements: *70099056296020
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70266493052600 !ruby/object:Gem::Requirement
38
+ requirement: &70099056295560 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,18 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70266493052600
46
+ version_requirements: *70099056295560
47
+ - !ruby/object:Gem::Dependency
48
+ name: thor
49
+ requirement: &70099056311480 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70099056311480
47
58
  description: Split your longish ~/.ssh/config into files in ~/.ssh/config.d/ and let
48
59
  poet join them for you.
49
60
  email:
@@ -62,11 +73,14 @@ files:
62
73
  - Rakefile
63
74
  - bin/poet
64
75
  - features/bootstrapping.feature
76
+ - features/editing_files.feature
65
77
  - features/permissions.feature
66
78
  - features/running.feature
67
79
  - features/selective_files.feature
80
+ - features/step_definitions/editor_steps.rb
68
81
  - features/step_definitions/permissions_steps.rb
69
82
  - features/support/env.rb
83
+ - features/verbose.feature
70
84
  - lib/poet.rb
71
85
  - lib/poet/version.rb
72
86
  - poet.gemspec
@@ -84,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
98
  version: '0'
85
99
  segments:
86
100
  - 0
87
- hash: -4363712381040709860
101
+ hash: -3487840776745573411
88
102
  required_rubygems_version: !ruby/object:Gem::Requirement
89
103
  none: false
90
104
  requirements:
@@ -93,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
107
  version: '0'
94
108
  segments:
95
109
  - 0
96
- hash: -4363712381040709860
110
+ hash: -3487840776745573411
97
111
  requirements: []
98
112
  rubyforge_project: poet
99
113
  rubygems_version: 1.8.11
@@ -102,8 +116,11 @@ specification_version: 3
102
116
  summary: Poet concatenates stanzas
103
117
  test_files:
104
118
  - features/bootstrapping.feature
119
+ - features/editing_files.feature
105
120
  - features/permissions.feature
106
121
  - features/running.feature
107
122
  - features/selective_files.feature
123
+ - features/step_definitions/editor_steps.rb
108
124
  - features/step_definitions/permissions_steps.rb
109
125
  - features/support/env.rb
126
+ - features/verbose.feature