gem-release 1.0.0 → 2.0.0.dev.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +13 -0
- data/Gemfile.lock +72 -0
- data/{lib/gem_release/templates/LICENSE → MIT-LICENSE.md} +3 -2
- data/README.md +646 -0
- data/README.md.erb +159 -0
- data/TODO.txt +194 -0
- data/lib/gem/release.rb +13 -0
- data/lib/gem/release/cmds.rb +16 -0
- data/lib/gem/release/cmds/base.rb +101 -0
- data/lib/gem/release/cmds/bootstrap.rb +222 -0
- data/lib/gem/release/cmds/bump.rb +165 -0
- data/lib/gem/release/cmds/gemspec.rb +85 -0
- data/lib/gem/release/cmds/release.rb +100 -0
- data/lib/gem/release/cmds/runner.rb +52 -0
- data/lib/gem/release/cmds/tag.rb +93 -0
- data/lib/gem/release/config.rb +42 -0
- data/lib/gem/release/config/env.rb +49 -0
- data/lib/gem/release/config/files.rb +35 -0
- data/lib/gem/release/context.rb +76 -0
- data/lib/gem/release/context/gem.rb +28 -0
- data/lib/gem/release/context/gemspec.rb +41 -0
- data/lib/gem/release/context/paths.rb +87 -0
- data/lib/gem/release/context/system.rb +36 -0
- data/lib/gem/release/data.rb +60 -0
- data/lib/gem/release/files/template.rb +61 -0
- data/lib/gem/release/files/template/context.rb +30 -0
- data/lib/gem/release/files/templates.rb +59 -0
- data/lib/gem/release/files/templates/group.rb +47 -0
- data/lib/gem/release/files/version.rb +68 -0
- data/lib/gem/release/helper.rb +45 -0
- data/lib/gem/release/helper/hash.rb +35 -0
- data/lib/gem/release/helper/string.rb +43 -0
- data/lib/gem/release/support/gem_command.rb +67 -0
- data/lib/gem/release/support/registry.rb +59 -0
- data/lib/gem/release/templates/.gitignore +8 -0
- data/lib/gem/release/templates/Gemfile +3 -0
- data/lib/gem/release/templates/gemspec +19 -0
- data/lib/gem/release/templates/licenses/mit.md +21 -0
- data/lib/gem/release/templates/licenses/mpl-2.md +373 -0
- data/lib/gem/release/templates/main.rb +1 -0
- data/lib/gem/release/templates/rspec/.rspec +3 -0
- data/lib/gem/release/templates/rspec/spec/spec_helper.rb +4 -0
- data/lib/gem/release/templates/travis/.travis.yml +1 -0
- data/lib/gem/release/templates/version.rb +1 -0
- data/lib/gem/release/version.rb +5 -0
- data/lib/gem/release/version/number.rb +102 -0
- data/lib/rubygems/commands/bootstrap_command.rb +4 -93
- data/lib/rubygems/commands/bump_command.rb +4 -110
- data/lib/rubygems/commands/gemspec_command.rb +5 -29
- data/lib/rubygems/commands/release_command.rb +4 -70
- data/lib/rubygems/commands/tag_command.rb +5 -46
- data/lib/rubygems_plugin.rb +8 -2
- metadata +56 -83
- data/lib/core_ext/hash/symbolize_keys.rb +0 -13
- data/lib/core_ext/kernel/silence.rb +0 -18
- data/lib/core_ext/string/camelize.rb +0 -5
- data/lib/gem_release.rb +0 -10
- data/lib/gem_release/command_options.rb +0 -31
- data/lib/gem_release/configuration.rb +0 -33
- data/lib/gem_release/gemspec_template.rb +0 -35
- data/lib/gem_release/helpers.rb +0 -104
- data/lib/gem_release/template.rb +0 -52
- data/lib/gem_release/templates/Gemfile +0 -3
- data/lib/gem_release/templates/README.md +0 -1
- data/lib/gem_release/templates/Rakefile +0 -10
- data/lib/gem_release/templates/gemspec +0 -18
- data/lib/gem_release/templates/gitignore +0 -25
- data/lib/gem_release/templates/test/test_helper.rb +0 -2
- data/lib/gem_release/templates/version.rb +0 -12
- data/lib/gem_release/version.rb +0 -3
- data/lib/gem_release/version_file.rb +0 -115
- data/lib/gem_release/version_template.rb +0 -14
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'gem/release/context/gemspec'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Release
|
5
|
+
class Context
|
6
|
+
class Gem
|
7
|
+
attr_reader :name, :spec
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@spec = Gemspec.new(name)
|
11
|
+
@name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def version
|
15
|
+
spec.version.to_s if spec
|
16
|
+
end
|
17
|
+
|
18
|
+
def filename
|
19
|
+
spec.gem_filename if spec
|
20
|
+
end
|
21
|
+
|
22
|
+
def spec_filename
|
23
|
+
spec.filename if name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Gem
|
2
|
+
module Release
|
3
|
+
class Context
|
4
|
+
class Gemspec < Struct.new(:name)
|
5
|
+
attr_reader :filename
|
6
|
+
|
7
|
+
def initialize(*)
|
8
|
+
super
|
9
|
+
@filename = name && "#{name}.gemspec" || filenames.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def gem_name
|
13
|
+
gemspec.name if gemspec
|
14
|
+
end
|
15
|
+
|
16
|
+
def version
|
17
|
+
gemspec.version.to_s if gemspec
|
18
|
+
end
|
19
|
+
|
20
|
+
def gem_filename
|
21
|
+
gemspec.file_name if gemspec
|
22
|
+
end
|
23
|
+
|
24
|
+
def exists?
|
25
|
+
filename && File.exists?(filename)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def gemspec
|
31
|
+
return @gemspec if instance_variable_defined?(:@gemspec)
|
32
|
+
@gemspec = exists? ? ::Gem::Specification.load(filename) : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
def filenames
|
36
|
+
Dir['*.gemspec'].map { |path| File.basename(path) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Release
|
5
|
+
class Context
|
6
|
+
class Paths < Struct.new(:names, :opts)
|
7
|
+
class Base < Struct.new(:names, :opts)
|
8
|
+
def in_dir(dir, &block)
|
9
|
+
dir == cwd ? yield : Dir.chdir(dir, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def current
|
13
|
+
[[cwd, cwd.basename.to_s]]
|
14
|
+
end
|
15
|
+
|
16
|
+
def cwd
|
17
|
+
@cwd ||= Pathname.pwd
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class ByNames < Base
|
22
|
+
def in_dirs(&block)
|
23
|
+
dirs.each do |dir, name|
|
24
|
+
dir.mkdir unless dir == cwd || dir.exist?
|
25
|
+
in_dir(dir) { yield name }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def dirs
|
32
|
+
names.any? ? dirs_by_names : current
|
33
|
+
end
|
34
|
+
|
35
|
+
def dirs_by_names
|
36
|
+
names.map { |name| [Pathname.new(dir || name).expand_path, name] }
|
37
|
+
end
|
38
|
+
|
39
|
+
def dir
|
40
|
+
opts[:dir]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ByGemspecs < Base
|
45
|
+
def in_dirs(&block)
|
46
|
+
dirs.each do |dir, name|
|
47
|
+
in_dir(dir) { yield name }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def dirs
|
54
|
+
dirs = by_gemspecs if opts[:recurse]
|
55
|
+
dirs ||= by_names if names.any?
|
56
|
+
dirs ||= gemspec
|
57
|
+
dirs || by_gemspecs || current
|
58
|
+
end
|
59
|
+
|
60
|
+
def by_gemspecs
|
61
|
+
paths = gemspecs(true).map { |path| [path.dirname, name_for(path)] }
|
62
|
+
paths unless paths.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def by_names
|
66
|
+
paths = names.map { |arg| by_gemspecs.detect { |_, name| name == arg } }.compact
|
67
|
+
paths unless paths.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
def gemspec
|
71
|
+
path = gemspecs.first
|
72
|
+
[[path.expand_path.dirname, name_for(path)]] if path
|
73
|
+
end
|
74
|
+
|
75
|
+
def name_for(path)
|
76
|
+
path.basename('.gemspec').to_s
|
77
|
+
end
|
78
|
+
|
79
|
+
def gemspecs(recurse = false)
|
80
|
+
pattern = recurse ? '**/*.gemspec' : '*.gemspec'
|
81
|
+
Pathname.glob(pattern).map(&:expand_path).sort
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Gem
|
2
|
+
module Release
|
3
|
+
class Context
|
4
|
+
class System
|
5
|
+
def run(cmd)
|
6
|
+
system(cmd)
|
7
|
+
end
|
8
|
+
|
9
|
+
def gem_cmd(cmd, *args)
|
10
|
+
::Gem::Commands.const_get("#{cmd.to_s.capitalize}Command").new.invoke(*args.flatten)
|
11
|
+
# TODO what's with the return value? maybe add our own abstraction that can check the result?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def git_remotes
|
16
|
+
`git remote`.split("\n")
|
17
|
+
end
|
18
|
+
|
19
|
+
def git_user_name
|
20
|
+
str = `git config --get user.name`.strip
|
21
|
+
str unless str.empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
def git_user_email
|
25
|
+
str = `git config --get user.email`.strip
|
26
|
+
str unless str.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
def github_user_name
|
30
|
+
str = `git config --get github.user`.strip
|
31
|
+
str.empty? ? git_user_name : str
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'gem/release/helper/string'
|
4
|
+
|
5
|
+
module Gem
|
6
|
+
module Release
|
7
|
+
class Data < Struct.new(:system, :gem, :opts)
|
8
|
+
include Helper::String
|
9
|
+
|
10
|
+
def data
|
11
|
+
{
|
12
|
+
gem_name: gem_name,
|
13
|
+
gem_path: gem_name.gsub('-', '/'),
|
14
|
+
module_names: module_names,
|
15
|
+
author: user_name,
|
16
|
+
email: user_email,
|
17
|
+
homepage: homepage,
|
18
|
+
licenses: licenses,
|
19
|
+
summary: '[summary]',
|
20
|
+
description: '[description]',
|
21
|
+
files: files
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def module_names
|
28
|
+
gem_name.split('-').map { |part| camelize(part) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def gem_name
|
32
|
+
gem.name || raise('No gem_name given.')
|
33
|
+
end
|
34
|
+
|
35
|
+
def user_name
|
36
|
+
system.git_user_name || '[your name]'
|
37
|
+
end
|
38
|
+
|
39
|
+
def user_email
|
40
|
+
system.git_user_email || '[your email]'
|
41
|
+
end
|
42
|
+
|
43
|
+
def homepage
|
44
|
+
"https://github.com/#{user_name}/#{gem_name}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def licenses
|
48
|
+
Array(license).join(',').split(',').map(&:upcase)
|
49
|
+
end
|
50
|
+
|
51
|
+
def license
|
52
|
+
opts[:license] if opts[:license]
|
53
|
+
end
|
54
|
+
|
55
|
+
def files
|
56
|
+
STRATEGIES[(opts[:strategy] || :glob).to_sym] || STRATEGIES[:glob]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'gem/release/files/template/context'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Release
|
5
|
+
module Files
|
6
|
+
class Template
|
7
|
+
FILES = {
|
8
|
+
'.gitignore' => '.gitignore',
|
9
|
+
'Gemfile' => 'Gemfile',
|
10
|
+
'gemspec' => '%{gem_name}.gemspec',
|
11
|
+
'license' => 'MIT-LICENSE.md',
|
12
|
+
'main.rb' => 'lib/%{gem_path}.rb',
|
13
|
+
'version.rb' => 'lib/%{gem_path}/version.rb'
|
14
|
+
}
|
15
|
+
|
16
|
+
attr_accessor :source, :target, :data
|
17
|
+
|
18
|
+
def initialize(source, target, data)
|
19
|
+
@source = source
|
20
|
+
@target = (FILES[target] || target) % data
|
21
|
+
@data = data
|
22
|
+
end
|
23
|
+
|
24
|
+
PATH = File.expand_path('../..', __FILE__)
|
25
|
+
|
26
|
+
def filename
|
27
|
+
File.basename(target)
|
28
|
+
end
|
29
|
+
|
30
|
+
def write
|
31
|
+
return false if exists?
|
32
|
+
FileUtils.mkdir_p(File.dirname(target))
|
33
|
+
File.write(target, render)
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def exists?
|
38
|
+
File.exist?(target.to_s)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def render
|
44
|
+
template.result(binding)
|
45
|
+
end
|
46
|
+
|
47
|
+
def template
|
48
|
+
ERB.new(File.read(source))
|
49
|
+
end
|
50
|
+
|
51
|
+
def binding
|
52
|
+
context.instance_eval { binding }
|
53
|
+
end
|
54
|
+
|
55
|
+
def context
|
56
|
+
Context.new(data)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Gem
|
2
|
+
module Release
|
3
|
+
module Files
|
4
|
+
class Template
|
5
|
+
class Context < OpenStruct
|
6
|
+
class Const < Struct.new(:type, :names)
|
7
|
+
def define(&block)
|
8
|
+
lines = build(names) { |name| "#{type} #{name}" }
|
9
|
+
lines << indent(block.call, names.size) if block
|
10
|
+
lines += build(names) { |name| 'end' }.reverse
|
11
|
+
lines.join("\n")
|
12
|
+
end
|
13
|
+
|
14
|
+
def build(names, &block)
|
15
|
+
names.map.with_index { |name, ix| indent(block.call(name), ix) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def indent(str, level)
|
19
|
+
"#{' ' * level}#{str}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def define(type, &block)
|
24
|
+
Const.new(type, module_names).define(&block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Gem
|
2
|
+
module Release
|
3
|
+
module Files
|
4
|
+
class Templates < Struct.new(:files, :groups, :data)
|
5
|
+
BUILTIN = [
|
6
|
+
['./.gem-release/%s'],
|
7
|
+
['~/.gem-release/%s'],
|
8
|
+
['../../templates/', __FILE__],
|
9
|
+
]
|
10
|
+
|
11
|
+
CUSTOM = [
|
12
|
+
['./.gem-release/%s'],
|
13
|
+
['~/.gem-release/%s'],
|
14
|
+
['../../templates/%s', __FILE__],
|
15
|
+
]
|
16
|
+
|
17
|
+
LICENSE = [
|
18
|
+
['./.gem-release/licenses'],
|
19
|
+
['~/.gem-release/licenses'],
|
20
|
+
['../../templates/licenses', __FILE__],
|
21
|
+
]
|
22
|
+
|
23
|
+
def self.license(name, data)
|
24
|
+
file = Templates.new(["#{name}{,.*}"], [], data).license
|
25
|
+
file.target = "LICENSE#{File.extname(file.target)}" if file
|
26
|
+
file
|
27
|
+
end
|
28
|
+
|
29
|
+
def [](filename)
|
30
|
+
all.detect { |file| file.filename == filename }
|
31
|
+
end
|
32
|
+
|
33
|
+
def all
|
34
|
+
all = builtin + custom
|
35
|
+
all.flatten.uniq(&:target)
|
36
|
+
end
|
37
|
+
|
38
|
+
def builtin
|
39
|
+
templates_for(BUILTIN, files)
|
40
|
+
end
|
41
|
+
|
42
|
+
def custom
|
43
|
+
templates_for(CUSTOM, '**/*')
|
44
|
+
end
|
45
|
+
|
46
|
+
def license
|
47
|
+
templates_for(LICENSE, files).first
|
48
|
+
end
|
49
|
+
|
50
|
+
def templates_for(sources, files)
|
51
|
+
all = Group.new(groups, data, sources, files).all
|
52
|
+
all.map { |source, target| Template.new(source, target, data) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
require 'gem/release/files/templates/group'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Gem
|
2
|
+
module Release
|
3
|
+
module Files
|
4
|
+
class Templates
|
5
|
+
class Group
|
6
|
+
attr_reader :groups, :data, :sources, :files
|
7
|
+
|
8
|
+
def initialize(groups, data, sources, files)
|
9
|
+
@groups = [:default] + Array(groups)
|
10
|
+
@data = data
|
11
|
+
@sources = sources
|
12
|
+
@files = Array(files)
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
return [] unless paths.any?
|
17
|
+
all = Dir.glob(pattern, File::FNM_DOTMATCH)
|
18
|
+
all = all.select { |file| File.file?(file) }
|
19
|
+
all.map { |file| [file, relative(file)] }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def pattern
|
25
|
+
"{#{paths.join(',')}}/{#{files.join(',')}}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def relative(file)
|
29
|
+
paths.inject(file) { |file, path| file.sub("#{path}/", '') }
|
30
|
+
end
|
31
|
+
|
32
|
+
def paths
|
33
|
+
@paths ||= groups.map do |group|
|
34
|
+
paths = paths_for(group).map { |path| File.expand_path(*path) }
|
35
|
+
paths.detect { |path| File.exists?(path) }
|
36
|
+
end.compact
|
37
|
+
end
|
38
|
+
|
39
|
+
def paths_for(group)
|
40
|
+
sources.map { |paths| paths.map { |path| path % group } }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|