gemify 0.3 → 0.4.0
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/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
|