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,222 @@
1
+ require 'gem/release/cmds/base'
2
+ require 'gem/release/data'
3
+ require 'gem/release/files/templates'
4
+
5
+ module Gem
6
+ module Release
7
+ module Cmds
8
+ class Bootstrap < Base
9
+ summary 'Scaffolds a new gem from template files.'
10
+
11
+ # TODO document license
12
+
13
+ description <<~str
14
+ #{summary} Optionally initialize a git repository, set a git remote, and push
15
+ to the remote repository.
16
+
17
+ If no argument is given the current directory name is used as the gem name. If
18
+ one or many arguments are given then these will be used as gem names, and new
19
+ directories will be created accordingly.
20
+
21
+ By default the following files will be created:
22
+
23
+ * `.gitignore`
24
+ * `Gemspec`
25
+ * `[gem-name].gemspec`
26
+ * `LICENSE.md`
27
+ * `lib/[gem]/[name].rb`
28
+ * `lib/[gem]/[name]/version.rb`
29
+
30
+ Templates in the first existing one of these directories will always be used to
31
+ create additional files:
32
+
33
+ * `./.gem-release/default` (local)
34
+ * `~/.gem-release/default` (global)
35
+
36
+ If `--template [group]` is given additional files will be created from the
37
+ first existing one of these directories:
38
+
39
+ * `./.gem-release/[group]` (local)
40
+ * `~/.gem-release/[group]` (global)
41
+
42
+ It is possible to specify several template groups in order to add files from
43
+ several custom template directories.
44
+
45
+ If `--template rspec` is given then additionally the files `.rspec` and
46
+ `spec/spec_helper.rb` will be created, or whatever files exist in a local or
47
+ global directory `.gem-release/templates/rspec`.
48
+
49
+ If `--template travis` is given then additionally the file `.travis.yml` will
50
+ be created, or whatever files exist in a local or global directory
51
+ `.gem-release/templates/travis`.
52
+
53
+ The license added by default is the MIT License. If `--license [name]` is given
54
+ then this license will be added. The only other license file shipped is the
55
+ Mozilla Public License v2.0. Other licenses must be present in the local or
56
+ global directory `.gem-release/licenses`.
57
+ str
58
+
59
+ arg :gem_name, 'name of the gem (optional, will default to the current directory name if not specified)'
60
+
61
+ DEFAULTS = {
62
+ strategy: :glob,
63
+ scaffold: true,
64
+ git: true,
65
+ github: false,
66
+ push: false,
67
+ license: :mit,
68
+ templates: []
69
+ }
70
+
71
+ DESCR = {
72
+ scaffold: 'Scaffold gem files',
73
+ dir: 'Directory to place the gem in (defaults to the given name, or the current working dir)',
74
+ licenses: 'License(s) to add',
75
+ template: 'Template groups to use for scaffolding',
76
+ rspec: 'Use the rspec group (by default adds .rspec and spec/spec_helper.rb)',
77
+ travis: 'Use the rspec group (by default adds .travis.yml)',
78
+ strategy: 'Strategy for collecting files [glob|git] in .gemspec',
79
+ git: 'Initialize a git repo',
80
+ github: 'Initialize a git repo, create on github',
81
+ remote: 'Git remote repository',
82
+ push: 'Push the git repo to github'
83
+ }
84
+
85
+ opt '--[no]-scaffold', DESCR[:scaffold] do |value|
86
+ opts[:scaffold] = value
87
+ end
88
+
89
+ opt '--dir DIR', DESCR[:dir] do |value|
90
+ opts[:dir] = value
91
+ end
92
+
93
+ opt '-t', '--template NAME', DESCR[:template] do |value|
94
+ (opts[:templates] ||= []) << value
95
+ end
96
+
97
+ opt '--rspec', DESCR[:rspec] do |value|
98
+ (opts[:templates] ||= []) << value
99
+ end
100
+
101
+ opt '--travis', DESCR[:travis] do |value|
102
+ (opts[:templates] ||= []) << value
103
+ end
104
+
105
+ opt '-l', '--no-license NAME', DESCR[:license] do |value|
106
+ value ? (opts[:license] ||= []) << value : opts[:license] = []
107
+ end
108
+
109
+ opt '-s', '--strategy NAME', DESCR[:strategy] do |value|
110
+ opts[:strategy] = value
111
+ end
112
+
113
+ opt '--git', DESCR[:git] do |value|
114
+ opts[:git] = value
115
+ end
116
+
117
+ opt '--github', DESCR[:github] do |value|
118
+ opts[:github] = value
119
+ end
120
+
121
+ opt '--remote', DESCR[:remote] do |value|
122
+ opts[:remote] = value
123
+ end
124
+
125
+ opt '--push', DESCR[:push] do |value|
126
+ opts[:push] = value
127
+ end
128
+
129
+ MSGS = {
130
+ scaffold: 'Scaffolding gem %s',
131
+ create: 'Creating %s',
132
+ exists: 'Skipping existing file %s',
133
+ git_init: 'Initializing git repository',
134
+ git_add: 'Adding files',
135
+ git_commit: 'Creating initial commit',
136
+ git_remote: 'Adding git remote %s',
137
+ git_push: 'Pushing to git remote %s',
138
+ unknown_license: 'Unknown license: %s'
139
+ }
140
+
141
+ CMDS = {
142
+ git_init: 'git init',
143
+ git_add: 'git add .',
144
+ git_commit: 'git commit -m "Initial commit"',
145
+ git_remote: 'git remote add %s https://github.com/%s.git',
146
+ git_push: 'git push -u %s master'
147
+ }
148
+
149
+ def run
150
+ in_dirs do
151
+ scaffold if opts[:scaffold]
152
+ init_git if opts[:github] || opts[:git]
153
+ create_repo if opts[:github]
154
+ end
155
+ end
156
+
157
+ private
158
+
159
+ FILES = %w(
160
+ .gitignore
161
+ Gemfile
162
+ gemspec
163
+ main.rb
164
+ version.rb
165
+ )
166
+
167
+ def scaffold
168
+ announce :scaffold, gem.name
169
+ files.each { |file| write(file) }
170
+ end
171
+
172
+ def files
173
+ files = Files::Templates.new(FILES, opts[:templates], data).all
174
+ files << license if opts[:license]
175
+ files.compact
176
+ end
177
+
178
+ def license
179
+ file = Files::Templates.license(opts[:license], data)
180
+ warn :unknown_license, opts[:license] unless file
181
+ file
182
+ end
183
+
184
+ def write(file)
185
+ msg = :create if pretend?
186
+ msg ||= file.write ? :create : :exists
187
+ level = msg == :create ? :info : :warn
188
+ send(level, msg, file.target)
189
+ end
190
+
191
+ def init_git
192
+ cmd :git_init
193
+ cmd :git_add
194
+ cmd :git_commit
195
+ end
196
+
197
+ def create_repo
198
+ cmd :git_remote, remote, "#{github_user_name}/#{gem.name}"
199
+ cmd :git_push, remote if opts[:push]
200
+ end
201
+
202
+ def data
203
+ Data.new(system, gem, opts).data
204
+ end
205
+
206
+ def remote
207
+ opts[:remote] || :origin
208
+ end
209
+
210
+ def opts
211
+ @opts ||= normalize(super)
212
+ end
213
+
214
+ def normalize(opts)
215
+ opts[:templates] << 'rspec' if opts.delete(:rspec)
216
+ opts[:templates] << 'travis' if opts.delete(:travis)
217
+ opts
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,165 @@
1
+ require 'gem/release/cmds/base'
2
+ require 'gem/release/files/version'
3
+
4
+ module Gem
5
+ module Release
6
+ module Cmds
7
+ class Bump < Base
8
+ summary 'Bumps one, several, or all gems in this directory.'
9
+
10
+ description <<~str
11
+ Bumps the version number defined in lib/[gem_name]/version.rb to to a given,
12
+ specific version number, or to the next major, minor, patch, or pre-release
13
+ level.
14
+
15
+ Optionally it pushes to the origin repository. Also, optionally it invokes the
16
+ `gem tag` and/or `gem release` command.
17
+
18
+ If no argument is given the first gemspec's name is assumed as the gem name.
19
+ If one or many arguments are given then these will be used as gem names. If
20
+ `--recurse` is given then all gem names from all gemspecs in this directory or
21
+ any of its subdirectories will be used.
22
+
23
+ The version can be bumped to either one of these targets:
24
+
25
+ ```
26
+ major
27
+ 1.1.1 # Bump to the given, specific version number
28
+ major # Bump to the next major level (e.g. 0.0.1 to 1.0.0)
29
+ minor # Bump to the next minor level (e.g. 0.0.1 to 0.1.0)
30
+ patch # Bump to the next patch level (e.g. 0.0.1 to 0.0.2)
31
+ pre|rc|etc # Bump to the next pre-release level (e.g. 0.0.1 to
32
+ # 0.1.0.pre.1, 1.0.0.pre.1 to 1.0.0.pre.2)
33
+ ```
34
+
35
+ When searching for the version file for a gem named `gem-name`: the following
36
+ paths will be searched relative to the gemspec's directory.
37
+
38
+ * `lib/gem-name/version.rb`
39
+ * `lib/gem/name/version.rb`
40
+ str
41
+
42
+ arg :gem_name, 'name of the gem (optional, will use the directory name, or all gemspecs if --recurse is given)'
43
+
44
+ DESCR = {
45
+ version: 'Target version: next [major|minor|patch|pre|release] or a given version number [x.x.x]',
46
+ commit: 'Perform a commit after incrementing gem version',
47
+ push: 'Push the new commit to the git remote repository',
48
+ remote: 'Git remote to push to (defaults to origin)',
49
+ tag: 'Shortcut for running the `gem tag` command',
50
+ recurse: 'Recurse into directories that contain gemspec files',
51
+ release: 'Shortcut for the `gem release` command'
52
+ }
53
+
54
+ DEFAULTS = {
55
+ commit: true,
56
+ push: true,
57
+ remote: 'origin'
58
+ }
59
+
60
+ opt '-c', '--[no-]commit', DESCR[:commit] do |value|
61
+ opts[:commit] = value
62
+ end
63
+
64
+ opt '-p', '--[no-]push', DESCR[:push] do |value|
65
+ opts[:push] = value
66
+ end
67
+
68
+ opt '--remote REMOTE', DESCR[:remote] do |value|
69
+ opts[:remote] = value
70
+ end
71
+
72
+ opt '-v', '--version VERSION', DESCR[:version] do |value|
73
+ opts[:version] = value
74
+ end
75
+
76
+ opt '-t', '--tag', DESCR[:tag] do |value|
77
+ opts[:tag] = value
78
+ end
79
+
80
+ opt '-r', '--release', DESCR[:release] do |value|
81
+ opts[:release] = value
82
+ end
83
+
84
+ opt '--recurse', DESCR[:recurse] do |value|
85
+ opts[:recurse] = value
86
+ end
87
+
88
+ MSGS = {
89
+ not_found: 'Ignoring %s. Version file %s not found.',
90
+ no_remote: 'Cannot push to missing git remote %s.',
91
+ bump: 'Bumping %s from version %s to %s',
92
+ version: 'Changing version in %s from %s to %s',
93
+ git_add: 'Staging %s',
94
+ git_commit: 'Creating commit',
95
+ git_push: 'Pushing to the %s git repository'
96
+ }
97
+
98
+ CMDS = {
99
+ git_add: 'git add %s',
100
+ git_commit: 'git commit -m "Bump to %s"',
101
+ git_push: 'git push %s'
102
+ }
103
+
104
+ def run
105
+ in_gem_dirs do
106
+ validate
107
+ bump
108
+ commit if opts[:commit]
109
+ push if opts[:commit] && opts[:push]
110
+ reset
111
+ end
112
+ tag if opts[:tag]
113
+ release if opts[:release]
114
+ end
115
+
116
+ private
117
+
118
+ def validate
119
+ abort :not_found, gem.name, version.path unless version.exists?
120
+ abort :no_remote, remote if push? && !git_remotes.include?(remote)
121
+ end
122
+
123
+ def bump
124
+ announce :bump, gem.name, version.from, version.to
125
+ return true if pretend?
126
+ notice :version, version.path, version.from, version.to
127
+ version.bump
128
+ end
129
+
130
+ def commit
131
+ cmd :git_add, version.path
132
+ cmd :git_commit, version.to
133
+ end
134
+
135
+ def push
136
+ cmd :git_push, remote
137
+ end
138
+
139
+ def tag
140
+ Tag.new(context, args, opts).run
141
+ end
142
+
143
+ def release
144
+ Release.new(context, args, except(opts, :tag)).run
145
+ end
146
+
147
+ def reset
148
+ @version = nil
149
+ end
150
+
151
+ def version
152
+ @version ||= Files::Version.new(gem.name, opts[:version])
153
+ end
154
+
155
+ def push?
156
+ opts[:push]
157
+ end
158
+
159
+ def remote
160
+ opts[:remote]
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,85 @@
1
+ require 'gem/release/cmds/base'
2
+ require 'gem/release/data'
3
+ require 'gem/release/files/template'
4
+
5
+ module Gem
6
+ module Release
7
+ module Cmds
8
+ class Gemspec < Base
9
+ summary 'Generates a gemspec.'
10
+
11
+ description <<~str
12
+ #{summary}
13
+
14
+ If no argument is given the current directory name is used as the gem name. If
15
+ one or many arguments are given then these will be used as gem names, and new
16
+ directories will be created accordingly.
17
+
18
+ The generated `gemspec` file will use the `glob` strategy for finding files by
19
+ default. Known strategies are:
20
+
21
+ * `glob` - uses the glob pattern `{bin/*,lib/**/*,[A-Z]*}`
22
+ * `git` - uses the git command `git ls-files app lib`
23
+ str
24
+
25
+ arg :gem_name, 'name of the gem (optional, will default to the current directory name if not specified)'
26
+
27
+ DEFAULTS = {
28
+ strategy: :glob
29
+ }
30
+
31
+ DESCR = {
32
+ dir: 'Directory to place the gem in (defaults to the given name, or the current working dir)',
33
+ license: 'License(s) to list in the gemspec',
34
+ strategy: 'Strategy for collecting files [glob|git] in gemspec'
35
+ }
36
+
37
+ opt '--dir DIR', DESCR[:dir] do |value|
38
+ opts[:dir] = value
39
+ end
40
+
41
+ opt '-l', '--[no]-license[s] NAMES', DESCR[:license] do |value|
42
+ value ? (opts[:license] ||= []) << value : opts[:license] = []
43
+ end
44
+
45
+ opt '-s', '--strategy', DESCR[:strategy] do |value|
46
+ opts[:strategy] = value
47
+ end
48
+
49
+ MSGS = {
50
+ gemspec: 'Generating %s.gemspec',
51
+ create: 'Creating %s',
52
+ exists: 'Skipping %s: already exists'
53
+ }
54
+
55
+ def run
56
+ in_dirs do
57
+ announce :gemspec, gem.name
58
+ generate
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def generate
65
+ msg = :create if pretend?
66
+ msg ||= file.write ? :create : :exists
67
+ level = msg == :create ? :notice : :warn
68
+ send(level, msg, file.target)
69
+ end
70
+
71
+ def file
72
+ templates["#{gem.name}.gemspec"]
73
+ end
74
+
75
+ def templates
76
+ Files::Templates.new(['gemspec'], opts[:template], data)
77
+ end
78
+
79
+ def data
80
+ Data.new(system, gem, opts).data
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end