gemify 0.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -1
- data/README.md +34 -51
- data/Rakefile +3 -0
- data/bin/gemify +262 -54
- data/gemify.gemspec +36 -19
- data/lib/gemify.rb +84 -24
- data/lib/gemify/version.rb +3 -0
- data/test/test_gemify.rb +67 -0
- metadata +23 -27
- data/.yardopts +0 -4
- data/lib/gemify/base.rb +0 -67
- data/lib/gemify/cli.rb +0 -157
- data/lib/gemify/manifest.rb +0 -94
- data/lib/trollop.rb +0 -739
- data/spec/spec_helper.rb +0 -2
data/gemify.gemspec
CHANGED
@@ -1,27 +1,44 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push('lib')
|
3
|
+
require "gemify/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |s|
|
4
|
-
s.name
|
5
|
-
s.version
|
6
|
-
|
7
|
-
s.
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.
|
11
|
-
|
12
|
-
s.
|
6
|
+
s.name = "gemify"
|
7
|
+
s.version = Gemify::VERSION.dup
|
8
|
+
s.date = "2011-03-04"
|
9
|
+
s.summary = "Quickly generate gemspecs for your projects"
|
10
|
+
s.email = "judofyr@gmail.com"
|
11
|
+
s.homepage = "http://dojo.rubyforge.org/gemify"
|
12
|
+
s.authors = ['Magnus Holm']
|
13
|
+
|
14
|
+
s.description = <<EOF
|
15
|
+
Gemify is a simple tool which helps you generate gemspecs (which are
|
16
|
+
used for building gems) and verify that your project follows the common
|
17
|
+
and proven way to structure your Ruby packages.
|
18
|
+
EOF
|
19
|
+
|
20
|
+
dependencies = [
|
21
|
+
# Examples:
|
22
|
+
# [:runtime, "rack", "~> 1.1"],
|
23
|
+
# [:development, "rspec", "~> 2.1"],
|
24
|
+
]
|
25
|
+
|
26
|
+
s.files = Dir['**/*']
|
27
|
+
s.test_files = Dir['test/**/*'] + Dir['spec/**/*']
|
28
|
+
s.executables = Dir['bin/*'].map { |f| File.basename(f) }
|
13
29
|
s.require_paths = ["lib"]
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if s.respond_to? :
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if
|
30
|
+
|
31
|
+
|
32
|
+
## Make sure you can build the gem on older versions of RubyGems too:
|
33
|
+
s.rubygems_version = "1.5.1"
|
34
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
35
|
+
s.specification_version = 3 if s.respond_to? :specification_version
|
36
|
+
|
37
|
+
dependencies.each do |type, name, version|
|
38
|
+
if s.respond_to?("add_#{type}_dependency")
|
39
|
+
s.send("add_#{type}_dependency", name, version)
|
23
40
|
else
|
41
|
+
s.add_dependency(name, version)
|
24
42
|
end
|
25
|
-
else
|
26
43
|
end
|
27
44
|
end
|
data/lib/gemify.rb
CHANGED
@@ -1,27 +1,87 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__)
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'rubygems/builder'
|
5
|
-
require 'yaml'
|
6
|
-
require 'open3'
|
7
|
-
|
8
|
-
require 'gemify/base'
|
9
|
-
require 'gemify/manifest'
|
10
|
-
require 'gemify/cli'
|
11
|
-
|
12
1
|
module Gemify
|
13
|
-
|
2
|
+
extend self
|
3
|
+
|
4
|
+
# Asks the user for a correct value of an attribute:
|
5
|
+
#
|
6
|
+
# >> input! "correct\n"
|
7
|
+
# >> ask("Hello", "world")
|
8
|
+
# => "correct"
|
9
|
+
# >> last_output
|
10
|
+
# => "Hello: world? "
|
11
|
+
#
|
12
|
+
# If the user just presses ENTER, use the provided value:
|
13
|
+
#
|
14
|
+
# >> input! "\n"
|
15
|
+
# >> ask("Hello", "world")
|
16
|
+
# => "world"
|
17
|
+
# >> last_output
|
18
|
+
# => "Hello: world? "
|
19
|
+
def ask(attribute, value)
|
20
|
+
col = "#{attribute}:".ljust(20)
|
21
|
+
print "#{col} #{value}? "
|
22
|
+
new_value = $stdin.gets.chomp
|
23
|
+
new_value.empty? ? value : new_value
|
24
|
+
end
|
25
|
+
|
26
|
+
# Asks a question which defaults to false.
|
27
|
+
#
|
28
|
+
# >> input! "Y\n"
|
29
|
+
# >> yes("Well?")
|
30
|
+
# => true
|
31
|
+
# >> last_output
|
32
|
+
# => "[?] Well? (y/[N]) "
|
33
|
+
#
|
34
|
+
# >> input! "\n"
|
35
|
+
# >> yes("Well?")
|
36
|
+
# => false
|
37
|
+
# >> last_output
|
38
|
+
# => "[?] Well? (y/[N]) "
|
39
|
+
def yes(question)
|
40
|
+
print "[?] #{question} (y/[N]) "
|
41
|
+
$stdin.gets[0,1].downcase == "y"
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
#
|
46
|
+
# >> clean_name("Hello Æwesome!")
|
47
|
+
# => "Hellowesome"
|
48
|
+
def clean_name(name)
|
49
|
+
name.gsub(/[^a-zA-Z0-9_-]/, '')
|
50
|
+
end
|
51
|
+
|
52
|
+
# Converts a project name into a namespace:
|
53
|
+
#
|
54
|
+
# >> name_to_namespace('foo_bar-qux')
|
55
|
+
# => "FooBar::Qux"
|
56
|
+
def name_to_namespace(name)
|
57
|
+
name.gsub(/_?([a-zA-Z0-9]+)/) { $1.capitalize }.gsub('-', '::')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Converts a namespace to a library name:
|
61
|
+
#
|
62
|
+
# >> namespace_to_library("FooBar::Qux")
|
63
|
+
# => "foo_bar/qux"
|
64
|
+
# >> namespace_to_library("HTTParty")
|
65
|
+
# => "httparty"
|
66
|
+
def namespace_to_library(namespace)
|
67
|
+
namespace.split("::").map do |part|
|
68
|
+
part.scan(/([A-Z]+[a-z0-9]+)/).join('_').downcase
|
69
|
+
end.join('/')
|
70
|
+
end
|
71
|
+
|
72
|
+
WARNINGS = {}
|
73
|
+
|
74
|
+
def w(type, str)
|
75
|
+
WARNINGS[type] = true
|
76
|
+
puts "- #{str}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def w?(type)
|
80
|
+
WARNINGS[type]
|
81
|
+
end
|
82
|
+
|
83
|
+
def n(str)
|
84
|
+
puts "[+] #{str}"
|
85
|
+
end
|
14
86
|
end
|
15
87
|
|
16
|
-
# Force Gem::Specification to use Gemify::Base instead.
|
17
|
-
Gem::Specification.extend Module.new {
|
18
|
-
def new(*args, &blk)
|
19
|
-
if self == Gem::Specification
|
20
|
-
Gemify::Base.new(*args, &blk)
|
21
|
-
else
|
22
|
-
Gemify.last_specification = super
|
23
|
-
end
|
24
|
-
end
|
25
|
-
}
|
26
|
-
|
27
|
-
Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
|
data/test/test_gemify.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# Poor man's doctest with mocking of input/output.
|
2
|
+
|
3
|
+
require 'gemify'
|
4
|
+
require 'stringio'
|
5
|
+
|
6
|
+
$myinput = StringIO.new
|
7
|
+
$myoutput = StringIO.new
|
8
|
+
$myoutputpos = 0
|
9
|
+
|
10
|
+
code = /^\s+#\s+>> (.*?)$/
|
11
|
+
result = /^\s+#\s+=> (.*?)$/
|
12
|
+
last_code = nil
|
13
|
+
|
14
|
+
passed = 0
|
15
|
+
failed = 0
|
16
|
+
tests = 0
|
17
|
+
lineno = 0
|
18
|
+
|
19
|
+
def run_code(str)
|
20
|
+
$stdin = $myinput
|
21
|
+
$stdout = $myoutput
|
22
|
+
Gemify.instance_eval(str)
|
23
|
+
ensure
|
24
|
+
$stdin = STDIN
|
25
|
+
$stdout = STDOUT
|
26
|
+
end
|
27
|
+
|
28
|
+
def input!(s)
|
29
|
+
$myinput << s
|
30
|
+
$myinput.pos -= s.length
|
31
|
+
end
|
32
|
+
|
33
|
+
def last_output
|
34
|
+
n = $myoutput.pos - $myoutputpos
|
35
|
+
$myoutput.pos = $myoutputpos
|
36
|
+
$myoutputpos += n
|
37
|
+
$myoutput.read(n)
|
38
|
+
end
|
39
|
+
|
40
|
+
File.open(File.dirname(__FILE__) + '/../lib/gemify.rb') do |f|
|
41
|
+
f.each do |line|
|
42
|
+
lineno += 1
|
43
|
+
|
44
|
+
case line
|
45
|
+
when code
|
46
|
+
last_code = run_code($1)
|
47
|
+
when result
|
48
|
+
last_result = run_code($1)
|
49
|
+
tests += 1
|
50
|
+
|
51
|
+
if last_result == last_code
|
52
|
+
passed += 1
|
53
|
+
else
|
54
|
+
failed += 1
|
55
|
+
puts
|
56
|
+
puts "FAIL on Line #{lineno}:"
|
57
|
+
puts " Expected: #{last_result.inspect}"
|
58
|
+
puts " Actual: #{last_code.inspect}"
|
59
|
+
end
|
60
|
+
|
61
|
+
last_code = true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
puts "#{tests} tests, #{passed} passed, #{failed} failed"
|
67
|
+
exit failed.zero?
|
metadata
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gemify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 3
|
8
|
-
version: "0.3"
|
4
|
+
prerelease:
|
5
|
+
version: 0.4.0
|
9
6
|
platform: ruby
|
10
7
|
authors:
|
11
8
|
- Magnus Holm
|
@@ -13,59 +10,58 @@ autorequire:
|
|
13
10
|
bindir: bin
|
14
11
|
cert_chain: []
|
15
12
|
|
16
|
-
date:
|
13
|
+
date: 2011-03-04 00:00:00 +01:00
|
17
14
|
default_executable:
|
18
15
|
dependencies: []
|
19
16
|
|
20
|
-
description:
|
21
|
-
|
22
|
-
|
17
|
+
description: |
|
18
|
+
Gemify is a simple tool which helps you generate gemspecs (which are
|
19
|
+
used for building gems) and verify that your project follows the common
|
20
|
+
and proven way to structure your Ruby packages.
|
23
21
|
|
22
|
+
email: judofyr@gmail.com
|
23
|
+
executables:
|
24
|
+
- gemify
|
24
25
|
extensions: []
|
25
26
|
|
26
27
|
extra_rdoc_files: []
|
27
28
|
|
28
29
|
files:
|
29
|
-
- .yardopts
|
30
|
-
- CHANGELOG
|
31
|
-
- README.md
|
32
30
|
- bin/gemify
|
31
|
+
- CHANGELOG
|
33
32
|
- gemify.gemspec
|
33
|
+
- lib/gemify/version.rb
|
34
34
|
- lib/gemify.rb
|
35
|
-
-
|
36
|
-
-
|
37
|
-
-
|
38
|
-
- lib/trollop.rb
|
39
|
-
- spec/spec_helper.rb
|
35
|
+
- Rakefile
|
36
|
+
- README.md
|
37
|
+
- test/test_gemify.rb
|
40
38
|
has_rdoc: true
|
41
|
-
homepage: http://dojo.rubyforge.org/
|
39
|
+
homepage: http://dojo.rubyforge.org/gemify
|
42
40
|
licenses: []
|
43
41
|
|
44
|
-
post_install_message:
|
42
|
+
post_install_message:
|
45
43
|
rdoc_options: []
|
46
44
|
|
47
45
|
require_paths:
|
48
46
|
- lib
|
49
47
|
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
50
49
|
requirements:
|
51
50
|
- - ">="
|
52
51
|
- !ruby/object:Gem::Version
|
53
|
-
segments:
|
54
|
-
- 0
|
55
52
|
version: "0"
|
56
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
57
55
|
requirements:
|
58
56
|
- - ">="
|
59
57
|
- !ruby/object:Gem::Version
|
60
|
-
segments:
|
61
|
-
- 0
|
62
58
|
version: "0"
|
63
59
|
requirements: []
|
64
60
|
|
65
61
|
rubyforge_project:
|
66
|
-
rubygems_version: 1.
|
62
|
+
rubygems_version: 1.5.1
|
67
63
|
signing_key:
|
68
64
|
specification_version: 3
|
69
|
-
summary:
|
70
|
-
test_files:
|
71
|
-
|
65
|
+
summary: Quickly generate gemspecs for your projects
|
66
|
+
test_files:
|
67
|
+
- test/test_gemify.rb
|
data/.yardopts
DELETED
data/lib/gemify/base.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
module Gemify
|
2
|
-
# A class providing base functions for generating gems. It doesn't know
|
3
|
-
# anything about the filesystem nor using any magic; you have to give it
|
4
|
-
# all the information.
|
5
|
-
#
|
6
|
-
# == Using
|
7
|
-
#
|
8
|
-
# base = Gemify::Base.new(["lib/file.rb", "bin/program"])
|
9
|
-
# base[:version] = 0.9
|
10
|
-
# base.valid? #=> false
|
11
|
-
# base[:summary] = "A short summary"
|
12
|
-
# base.valid? #=> true
|
13
|
-
#
|
14
|
-
# base.build! # Builds the gem
|
15
|
-
class Base < Gem::Specification
|
16
|
-
REQUIRED = [:name, :summary, :version]
|
17
|
-
OPTIONAL = [:author, :email, :homepage, :dependencies]
|
18
|
-
ALL = REQUIRED + OPTIONAL
|
19
|
-
|
20
|
-
def manifest=(type)
|
21
|
-
# do nothing
|
22
|
-
end
|
23
|
-
|
24
|
-
def inspect_files
|
25
|
-
files.empty? ? "(no files)" : @files.join($/)
|
26
|
-
end
|
27
|
-
|
28
|
-
def version=(version)
|
29
|
-
@version = version && super
|
30
|
-
end
|
31
|
-
|
32
|
-
# Returns the content of +setting+
|
33
|
-
def [](setting)
|
34
|
-
val = send(setting) if respond_to?(setting)
|
35
|
-
if setting.to_s == "dependencies"
|
36
|
-
val.empty? ? nil : val.map do |dep|
|
37
|
-
"#{dep.name} #{dep.requirement}"
|
38
|
-
end.join(" & ")
|
39
|
-
else
|
40
|
-
val
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Sets the +setting+ to +value+
|
45
|
-
def []=(setting, value)
|
46
|
-
value = nil if value.is_a?(String) && value.empty?
|
47
|
-
|
48
|
-
if setting.to_s == "dependencies"
|
49
|
-
self.dependencies = []
|
50
|
-
value.each do |dep|
|
51
|
-
name, *reqs = dep.split(",").map { |x| x.strip }
|
52
|
-
add_runtime_dependency(name, *reqs)
|
53
|
-
end
|
54
|
-
else
|
55
|
-
send("#{setting}=", value) if respond_to?("#{setting}=")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def valid?
|
60
|
-
validate
|
61
|
-
rescue Gem::InvalidSpecificationException
|
62
|
-
false
|
63
|
-
else
|
64
|
-
true
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
data/lib/gemify/cli.rb
DELETED
@@ -1,157 +0,0 @@
|
|
1
|
-
require 'readline'
|
2
|
-
|
3
|
-
module Gemify
|
4
|
-
class CLI
|
5
|
-
ACTIONS = {
|
6
|
-
?x => :exit, ?s => :save, ?r => :reload, ?m => :rename, ?l => :list
|
7
|
-
}
|
8
|
-
|
9
|
-
attr_accessor :base, :file
|
10
|
-
|
11
|
-
def initialize(base, file = nil)
|
12
|
-
@base = base
|
13
|
-
@base.mark_version
|
14
|
-
@file = file
|
15
|
-
@saved = !!file
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.load(file = nil)
|
19
|
-
case file
|
20
|
-
when nil
|
21
|
-
new(Base.new)
|
22
|
-
when String
|
23
|
-
new(Base.load(file), file)
|
24
|
-
when Array
|
25
|
-
file.each_with_index do |f, index|
|
26
|
-
puts "#{index + 1}) #{f}"
|
27
|
-
end
|
28
|
-
puts
|
29
|
-
print "> "
|
30
|
-
chosen = file[gets.strip.to_i - 1]
|
31
|
-
|
32
|
-
if chosen.nil?
|
33
|
-
puts "Err. Sure you wrote the right number?"
|
34
|
-
exit
|
35
|
-
end
|
36
|
-
|
37
|
-
load(chosen)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def menu
|
42
|
-
clear
|
43
|
-
puts "Currently editing #{file || "<unnamed>"}#{' - not saved' if !@saved && @file }"
|
44
|
-
puts
|
45
|
-
puts "Which task would you like to invoke?"
|
46
|
-
index = 0
|
47
|
-
Base::ALL.each do |m|
|
48
|
-
print "#{index += 1}) "
|
49
|
-
print base[m].nil? ? "Set " : "Change "
|
50
|
-
print m
|
51
|
-
print " (required)" if Base::REQUIRED.include?(m)
|
52
|
-
print " = #{base[m]}" unless base[m].nil?
|
53
|
-
puts
|
54
|
-
end
|
55
|
-
puts
|
56
|
-
puts "s) Save"
|
57
|
-
puts "r) Reload (discard unsaved changes)"
|
58
|
-
puts "m) Rename"
|
59
|
-
puts "l) List files"
|
60
|
-
puts
|
61
|
-
puts "x) Exit"
|
62
|
-
puts
|
63
|
-
end
|
64
|
-
|
65
|
-
def update_manifest
|
66
|
-
@base.files = Manifest.auto
|
67
|
-
end
|
68
|
-
|
69
|
-
def main
|
70
|
-
update_manifest
|
71
|
-
@result = nil
|
72
|
-
loop do
|
73
|
-
menu
|
74
|
-
|
75
|
-
if @result
|
76
|
-
puts @result
|
77
|
-
@result = nil
|
78
|
-
end
|
79
|
-
|
80
|
-
letter = (choice = gets).downcase[0]
|
81
|
-
int = choice.to_i
|
82
|
-
|
83
|
-
if action = ACTIONS[letter]
|
84
|
-
send(action)
|
85
|
-
next
|
86
|
-
end
|
87
|
-
|
88
|
-
if (1..Base::ALL.length).include? int
|
89
|
-
change(Base::ALL[int - 1])
|
90
|
-
next
|
91
|
-
end
|
92
|
-
|
93
|
-
@result = "Can't find the task named '#{choice}'"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def change(m)
|
98
|
-
if Base.array_attributes.include?(m)
|
99
|
-
puts "Split by ENTER and press ENTER twice when you're done"
|
100
|
-
res = []
|
101
|
-
while !(val = gets.strip).empty?
|
102
|
-
res << val
|
103
|
-
end
|
104
|
-
base[m] = res
|
105
|
-
else
|
106
|
-
base[m] = gets(m.to_s.capitalize)
|
107
|
-
end
|
108
|
-
|
109
|
-
@saved = false
|
110
|
-
@result = "Updated '#{m}'"
|
111
|
-
rescue ArgumentError => e
|
112
|
-
@result = "Error: #{e}"
|
113
|
-
end
|
114
|
-
|
115
|
-
def reload
|
116
|
-
@base = Base.load(file)
|
117
|
-
@result = "Reloaded #{file}"
|
118
|
-
end
|
119
|
-
|
120
|
-
def save
|
121
|
-
@result = "Gemspec is invalid. Can't save." and return unless base.valid?
|
122
|
-
@file ||= "#{@base.name}.gemspec"
|
123
|
-
|
124
|
-
File.open(file, 'w') do |f|
|
125
|
-
f << base.to_ruby
|
126
|
-
@saved = true
|
127
|
-
end
|
128
|
-
|
129
|
-
@result = "#{file} saved!"
|
130
|
-
end
|
131
|
-
|
132
|
-
def rename
|
133
|
-
@result = "Gemspec is invalid. Can't rename." and return unless base.valid?
|
134
|
-
save
|
135
|
-
old_name = @file
|
136
|
-
default = @base.name + '.gemspec'
|
137
|
-
@file = gets("[#{default}]")
|
138
|
-
@file = default if @file.empty?
|
139
|
-
File.rename(old_name, @file)
|
140
|
-
@result = "Renamed #{old_name} to #{@file}"
|
141
|
-
end
|
142
|
-
|
143
|
-
def list
|
144
|
-
puts @base.inspect_files
|
145
|
-
gets "Ok? ", nil
|
146
|
-
end
|
147
|
-
|
148
|
-
def gets(thing = nil, post = ": ")
|
149
|
-
prompt = thing ? "> #{thing}#{post}" : "> "
|
150
|
-
Readline.readline(prompt, true)
|
151
|
-
end
|
152
|
-
|
153
|
-
def clear
|
154
|
-
system("cls") || print("\ec")
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|