gem-release 1.0.0 → 2.0.0.dev.1

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +72 -0
  4. data/{lib/gem_release/templates/LICENSE → MIT-LICENSE.md} +3 -2
  5. data/README.md +646 -0
  6. data/README.md.erb +159 -0
  7. data/TODO.txt +194 -0
  8. data/lib/gem/release.rb +13 -0
  9. data/lib/gem/release/cmds.rb +16 -0
  10. data/lib/gem/release/cmds/base.rb +101 -0
  11. data/lib/gem/release/cmds/bootstrap.rb +222 -0
  12. data/lib/gem/release/cmds/bump.rb +165 -0
  13. data/lib/gem/release/cmds/gemspec.rb +85 -0
  14. data/lib/gem/release/cmds/release.rb +100 -0
  15. data/lib/gem/release/cmds/runner.rb +52 -0
  16. data/lib/gem/release/cmds/tag.rb +93 -0
  17. data/lib/gem/release/config.rb +42 -0
  18. data/lib/gem/release/config/env.rb +49 -0
  19. data/lib/gem/release/config/files.rb +35 -0
  20. data/lib/gem/release/context.rb +76 -0
  21. data/lib/gem/release/context/gem.rb +28 -0
  22. data/lib/gem/release/context/gemspec.rb +41 -0
  23. data/lib/gem/release/context/paths.rb +87 -0
  24. data/lib/gem/release/context/system.rb +36 -0
  25. data/lib/gem/release/data.rb +60 -0
  26. data/lib/gem/release/files/template.rb +61 -0
  27. data/lib/gem/release/files/template/context.rb +30 -0
  28. data/lib/gem/release/files/templates.rb +59 -0
  29. data/lib/gem/release/files/templates/group.rb +47 -0
  30. data/lib/gem/release/files/version.rb +68 -0
  31. data/lib/gem/release/helper.rb +45 -0
  32. data/lib/gem/release/helper/hash.rb +35 -0
  33. data/lib/gem/release/helper/string.rb +43 -0
  34. data/lib/gem/release/support/gem_command.rb +67 -0
  35. data/lib/gem/release/support/registry.rb +59 -0
  36. data/lib/gem/release/templates/.gitignore +8 -0
  37. data/lib/gem/release/templates/Gemfile +3 -0
  38. data/lib/gem/release/templates/gemspec +19 -0
  39. data/lib/gem/release/templates/licenses/mit.md +21 -0
  40. data/lib/gem/release/templates/licenses/mpl-2.md +373 -0
  41. data/lib/gem/release/templates/main.rb +1 -0
  42. data/lib/gem/release/templates/rspec/.rspec +3 -0
  43. data/lib/gem/release/templates/rspec/spec/spec_helper.rb +4 -0
  44. data/lib/gem/release/templates/travis/.travis.yml +1 -0
  45. data/lib/gem/release/templates/version.rb +1 -0
  46. data/lib/gem/release/version.rb +5 -0
  47. data/lib/gem/release/version/number.rb +102 -0
  48. data/lib/rubygems/commands/bootstrap_command.rb +4 -93
  49. data/lib/rubygems/commands/bump_command.rb +4 -110
  50. data/lib/rubygems/commands/gemspec_command.rb +5 -29
  51. data/lib/rubygems/commands/release_command.rb +4 -70
  52. data/lib/rubygems/commands/tag_command.rb +5 -46
  53. data/lib/rubygems_plugin.rb +8 -2
  54. metadata +56 -83
  55. data/lib/core_ext/hash/symbolize_keys.rb +0 -13
  56. data/lib/core_ext/kernel/silence.rb +0 -18
  57. data/lib/core_ext/string/camelize.rb +0 -5
  58. data/lib/gem_release.rb +0 -10
  59. data/lib/gem_release/command_options.rb +0 -31
  60. data/lib/gem_release/configuration.rb +0 -33
  61. data/lib/gem_release/gemspec_template.rb +0 -35
  62. data/lib/gem_release/helpers.rb +0 -104
  63. data/lib/gem_release/template.rb +0 -52
  64. data/lib/gem_release/templates/Gemfile +0 -3
  65. data/lib/gem_release/templates/README.md +0 -1
  66. data/lib/gem_release/templates/Rakefile +0 -10
  67. data/lib/gem_release/templates/gemspec +0 -18
  68. data/lib/gem_release/templates/gitignore +0 -25
  69. data/lib/gem_release/templates/test/test_helper.rb +0 -2
  70. data/lib/gem_release/templates/version.rb +0 -12
  71. data/lib/gem_release/version.rb +0 -3
  72. data/lib/gem_release/version_file.rb +0 -115
  73. 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
+