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.
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