poet 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
@@ -1,5 +1,11 @@
1
1
  master
2
2
 
3
+ - options: Use env var POET_OUTPUT in addition to --output and POET_GLOBDIR in addition to --dir
4
+
5
+ - bootstrapping support
6
+
7
+ 0.2
8
+
3
9
  - testing with Aruba
4
10
 
5
11
  - new CLI options --output and --dir
data/README.md CHANGED
@@ -1,9 +1,23 @@
1
- Lost in a long list of host stanzas in your `$HOME/.ssh/config`?
1
+ [![Build Status](https://secure.travis-ci.org/awendt/poet.png)](http://travis-ci.org/awendt/poet)
2
2
 
3
- Fear not -- divide them up into several smaller files under `$HOME/.ssh/config.d/` and run `poet` to concatenate them into a single ssh_config.
3
+ # Wanna split up your `~/.ssh/config` into several files?
4
4
 
5
- `poet` does not overwrite your existing ssh_config. If you want to play with it, move your existing config out of the way.
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.
6
8
 
7
- Stanzas under `$HOME/.ssh/config.d/` with an extension of .disabled are ignored by poet. Every now and then, when you do need it, run `poet --with CONFIG` to explicitly include `CONFIG.disabled` in your generated ssh_config. You can even include several by running several '--with' options or using `--with CONFIG1,CONFIG2`.
9
+ Poet won't touch your existing ssh_config.
10
+ If you want to play with it, pass a different filename to the "-o" option.
11
+ Or move your existing config out of the way.
8
12
 
9
- If you only want an ssh_config from certain files, use `--only CONFIG` or `--only CONFIG1,CONFIG2`.
13
+ Stanzas under `~/.ssh/config.d/` with an extension of .disabled are ignored by Poet.
14
+ Every now and then, when you do need it, run `poet --with CONFIG` to explicitly include
15
+ `CONFIG.disabled` in your generated ssh_config. You can even include several by running several
16
+ `--with` options or using `--with CONFIG1,CONFIG2`.
17
+
18
+ ## Note on Patches/Pull Requests
19
+
20
+ * Fork the project.
21
+ * Make your feature addition or bug fix.
22
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
23
+ * Send me a pull request. Bonus points for topic branches.
data/bin/poet CHANGED
@@ -1,14 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'optparse'
4
-
5
- MAGIC_LINE = "# Generated by #{File.basename(__FILE__)}"
4
+ require 'poet'
6
5
 
7
6
  options = {
8
- :ssh_config => File.expand_path('~/.ssh/config'),
7
+ :ssh_config => ENV['POET_OUTPUT'] || File.expand_path('~/.ssh/config'),
9
8
  :verbose => false,
10
9
  :with => [],
11
- :dir => File.expand_path('~/.ssh/config.d')
10
+ :dir => ENV['POET_GLOBDIR'] || File.expand_path('~/.ssh/config.d')
12
11
  }
13
12
 
14
13
  optparse = OptionParser.new do|opts|
@@ -25,6 +24,9 @@ optparse = OptionParser.new do|opts|
25
24
  opts.on('-v', '--verbose', 'Be verbose') do
26
25
  options[:verbose] = true
27
26
  end
27
+ opts.on('--bootstrap [FILE]', '') do |file|
28
+ options[:bootstrap] = File.expand_path(file || options[:ssh_config])
29
+ end
28
30
  opts.on('-w', '--with CONFIG', 'Include an otherwise disabled config file') do |file|
29
31
  options[:with] += file.split(',')
30
32
  options[:with].each{|file| puts "Including #{file} even if disabled..."}
@@ -32,33 +34,4 @@ optparse = OptionParser.new do|opts|
32
34
  end
33
35
  optparse.parse!
34
36
 
35
- if !File.directory?(options[:dir])
36
- $stderr.puts "#{options[:dir]} does not exist or is not a directory"
37
- Process.exit!(1)
38
- end
39
-
40
- if File.exists?(options[:ssh_config]) && File.new(options[:ssh_config]).gets == "#{MAGIC_LINE}\n"
41
- puts "Found generated ssh_config under #{options[:ssh_config]}. Overwriting..."
42
- elsif File.exists?(options[:ssh_config])
43
- $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."
44
- Process.exit!(2)
45
- end
46
-
47
- files = Dir["#{options[:dir]}/**"].reject do |file|
48
- file =~ /\.disabled$/ && !options[:with].include?("#{File.basename(file, '.disabled')}")
49
- end
50
-
51
- files -= [options[:ssh_config]]
52
-
53
- entries = []
54
-
55
- files.sort.each do |file|
56
- entries << File.read(file)
57
- end
58
-
59
- File.open(options[:ssh_config], 'w', 0600) do |ssh_config|
60
- ssh_config.puts(MAGIC_LINE)
61
- ssh_config.puts("# DO NOT EDIT THIS FILE")
62
- ssh_config.puts("# Create or modify files under #{options[:dir]} instead")
63
- ssh_config.puts(entries.join("\n"))
64
- end
37
+ Poet.application(options).run
@@ -0,0 +1,31 @@
1
+ Feature: Bootstrapping
2
+ Scenario: User wants help to get started
3
+ Given a file named "ssh_config" with:
4
+ """
5
+ Host home
6
+ StrictHostKeyChecking ask
7
+
8
+ Host *.amazonaws.com
9
+ StrictHostKeyChecking no
10
+ """
11
+ When I run `poet --bootstrap --dir ./config.d`
12
+ Then the exit status should be 0
13
+ And a directory named "config.d" should exist
14
+ And a file named "config.d/ssh_config" should exist
15
+ And the file "config.d/ssh_config" should contain "Host home"
16
+ And the file "ssh_config" should contain "# Generated by poet"
17
+
18
+ Scenario: Bootstrapping a second time
19
+ Given a file named "ssh_config" with:
20
+ """
21
+ Host home
22
+ StrictHostKeyChecking ask
23
+
24
+ Host *.amazonaws.com
25
+ StrictHostKeyChecking no
26
+ """
27
+ When I run `poet --bootstrap --dir ./config.d`
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"
31
+ And the exit status should not be 0
@@ -5,6 +5,5 @@ Feature: Correct permissions
5
5
  Host permissio.ns
6
6
  User whatever
7
7
  """
8
- When I run `poet --dir . -o ssh_config`
9
- And I run `ls -la ssh_config`
8
+ When I run `poet`
10
9
  Then the file "ssh_config" should not be world-accessible
@@ -5,7 +5,7 @@ Feature: Running the program
5
5
  Host te.st
6
6
  User me
7
7
  """
8
- When I run `poet --dir . -o ssh_config`
8
+ When I run `poet`
9
9
  Then the exit status should be 0
10
10
  And the file "ssh_config" should contain "Host te.st"
11
11
 
@@ -14,8 +14,8 @@ Feature: Running the program
14
14
  """
15
15
  This is absolutely vital information
16
16
  """
17
- When I run `poet --dir . -o important`
18
- Then the output from "poet --dir . -o important" should contain "Found hand-crafted ssh_config"
17
+ When I run `poet -o important`
18
+ Then the output from "poet -o important" should contain "Found hand-crafted ssh_config"
19
19
  And the exit status should not be 0
20
20
  And the file "important" should contain "This is absolutely vital information"
21
21
 
@@ -25,6 +25,6 @@ Feature: Running the program
25
25
  Host te.st
26
26
  User me
27
27
  """
28
- When I run `poet --dir missing -o ssh_config`
29
- Then the output from "poet --dir missing -o ssh_config" should contain "missing does not exist"
28
+ When I run `poet --dir missing`
29
+ Then the output from "poet --dir missing" should contain "missing does not exist"
30
30
  And the exit status should not be 0
@@ -10,7 +10,7 @@ Feature: Selectively whitelist files
10
10
  Host always
11
11
  User me
12
12
  """
13
- When I run `poet --dir . -o ssh_config`
13
+ When I run `poet`
14
14
  Then the file "ssh_config" should contain "Host always"
15
15
  But the file "ssh_config" should not contain "Host sometimes"
16
16
 
@@ -25,7 +25,7 @@ Feature: Selectively whitelist files
25
25
  Host always
26
26
  User me
27
27
  """
28
- When I run `poet --dir . -o ssh_config -w sometimes`
28
+ When I run `poet -w sometimes`
29
29
  Then the file "ssh_config" should contain "Host always"
30
30
  And the file "ssh_config" should contain "Host sometimes"
31
31
 
@@ -40,6 +40,6 @@ Feature: Selectively whitelist files
40
40
  Host almost_never
41
41
  User me
42
42
  """
43
- When I run `poet --dir . -o ssh_config -w sometimes,almost_never`
43
+ When I run `poet -w sometimes,almost_never`
44
44
  Then the file "ssh_config" should contain "Host almost_never"
45
45
  And the file "ssh_config" should contain "Host sometimes"
@@ -1,3 +1,4 @@
1
1
  Then /^the file "([^"]*)" should not be world-accessible$/ do |filename|
2
+ step "I run `ls -la ssh_config`"
2
3
  step %Q(the output from "ls -la #{filename}" should contain "-rw-------")
3
4
  end
@@ -1,3 +1,5 @@
1
1
  ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
2
+ ENV['POET_OUTPUT'] = 'ssh_config'
3
+ ENV['POET_GLOBDIR'] = '.'
2
4
 
3
5
  require 'aruba/cucumber'
@@ -1 +1,69 @@
1
1
  require "poet/version"
2
+
3
+ module Poet
4
+
5
+ MAGIC_LINE = "# Generated by #{File.basename(__FILE__, '.rb')}"
6
+
7
+ class << self
8
+
9
+ def application(options={})
10
+ @application ||= Poet::Application.new(options)
11
+ end
12
+
13
+ end
14
+
15
+ class Application
16
+
17
+ attr_reader :options
18
+
19
+ def initialize(options={})
20
+ @options = options
21
+ end
22
+
23
+ def bootstrap
24
+ if File.directory?(options[:dir])
25
+ $stderr.puts "You're already good to go."
26
+ Process.exit!(3)
27
+ end
28
+ FileUtils.mkdir_p(options[:dir])
29
+ FileUtils.mv(options[:bootstrap], options[:dir])
30
+ end
31
+
32
+ def run
33
+ bootstrap if options.has_key?(:bootstrap)
34
+
35
+ if !File.directory?(options[:dir])
36
+ $stderr.puts "#{options[:dir]} does not exist or is not a directory"
37
+ Process.exit!(1)
38
+ end
39
+
40
+ if File.exists?(options[:ssh_config]) && File.new(options[:ssh_config]).gets == "#{MAGIC_LINE}\n"
41
+ puts "Found generated ssh_config under #{options[:ssh_config]}. Overwriting..."
42
+ elsif File.exists?(options[:ssh_config])
43
+ $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."
44
+ Process.exit!(2)
45
+ end
46
+
47
+ files = Dir["#{options[:dir]}/**"].reject do |file|
48
+ file =~ /\.disabled$/ && !options[:with].include?("#{File.basename(file, '.disabled')}")
49
+ end
50
+
51
+ files -= [options[:ssh_config]]
52
+
53
+ entries = []
54
+
55
+ files.sort.each do |file|
56
+ entries << File.read(file)
57
+ end
58
+
59
+ File.open(options[:ssh_config], 'w', 0600) do |ssh_config|
60
+ ssh_config.puts(MAGIC_LINE)
61
+ ssh_config.puts("# DO NOT EDIT THIS FILE")
62
+ ssh_config.puts("# Create or modify files under #{options[:dir]} instead")
63
+ ssh_config.puts(entries.join("\n"))
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -1,3 +1,3 @@
1
1
  module Poet
2
- VERSION = "0.2"
2
+ VERSION = "0.3"
3
3
  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.2'
4
+ version: '0.3'
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-04-04 00:00:00.000000000 Z
12
+ date: 2012-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cucumber
16
- requirement: &70193940334220 !ruby/object:Gem::Requirement
16
+ requirement: &70282917431800 !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: *70193940334220
24
+ version_requirements: *70282917431800
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: aruba
27
- requirement: &70193940333780 !ruby/object:Gem::Requirement
27
+ requirement: &70282917431300 !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: *70193940333780
35
+ version_requirements: *70282917431300
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &70193940333300 !ruby/object:Gem::Requirement
38
+ requirement: &70282917430840 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70193940333300
46
+ version_requirements: *70282917430840
47
47
  description: Split your longish ~/.ssh/config into files in ~/.ssh/config.d/ and let
48
48
  poet join them for you.
49
49
  email:
@@ -54,12 +54,14 @@ extensions: []
54
54
  extra_rdoc_files: []
55
55
  files:
56
56
  - .gitignore
57
+ - .travis.yml
57
58
  - Gemfile
58
59
  - History.txt
59
60
  - MIT-LICENSE
60
61
  - README.md
61
62
  - Rakefile
62
63
  - bin/poet
64
+ - features/bootstrapping.feature
63
65
  - features/permissions.feature
64
66
  - features/running.feature
65
67
  - features/selective_files.feature
@@ -82,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
84
  version: '0'
83
85
  segments:
84
86
  - 0
85
- hash: 3681220582875752418
87
+ hash: 62288698588282443
86
88
  required_rubygems_version: !ruby/object:Gem::Requirement
87
89
  none: false
88
90
  requirements:
@@ -91,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
93
  version: '0'
92
94
  segments:
93
95
  - 0
94
- hash: 3681220582875752418
96
+ hash: 62288698588282443
95
97
  requirements: []
96
98
  rubyforge_project: poet
97
99
  rubygems_version: 1.8.11
@@ -99,6 +101,7 @@ signing_key:
99
101
  specification_version: 3
100
102
  summary: Poet concatenates stanzas
101
103
  test_files:
104
+ - features/bootstrapping.feature
102
105
  - features/permissions.feature
103
106
  - features/running.feature
104
107
  - features/selective_files.feature