poet 0.4 → 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/.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