toys 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 516ab9d472491bb7250ac10e033024dd2e621908836d8e7ccce46d563418d3d3
4
- data.tar.gz: 706e194857b09e1f24f2a360d03ba42259b1782284c80f56299bef3d5dc991b4
3
+ metadata.gz: 1af0f4b8108ed4bf39da40bffa62fd4cc601df712b0b2e0a5a8d7ff9eb7cb160
4
+ data.tar.gz: 6c8f02f7f0e5a84c13e3ef7048febbab744f89fc14ca950221d6c56130eb8fc6
5
5
  SHA512:
6
- metadata.gz: 21ea81146849ffa1549803556ec237af812223b7d3e88ae4f36115ac1ee45ce8795bedbc3b6cbf5168322d557cb85397e89c51195bb8385172ab1bc61b47b24f
7
- data.tar.gz: 0c5ec538c871002c01261cfe662ba732f164fb977ed7906460608517f86c0bc16319ba7da3f7e5294ac8aab7e786a5ab0126dbfe7c5ff50d4815ce3514514c8e
6
+ metadata.gz: 7976bb5dd0d9619f44b6c4e88ef63f417ccf88a72fb2f89aa6d5528eb70270c0dead339419b4339a184f7ef8d7fe7d6a2161f9119a3aa03af425831d54ceed22
7
+ data.tar.gz: 59e8a779fddedfa0b38245d36002b8e5626be6f9740d2e2090c5fe65ef225dd3278461a20d7e3928a6ce9b6a798f943d818cb3916aeda5562f89e1e7fdc7d8f9
@@ -1,5 +1,17 @@
1
1
  # Release History
2
2
 
3
+ ### 0.6.0 / 2018-10-22
4
+
5
+ * FIXED: Build tools cd into the context directory when running.
6
+ * FIXED: Rakefiles are evaluated and tasks are run in the Rakefile's directory.
7
+ * ADDED: Context directory is available in the DSL and the tool runtime.
8
+ * IMPROVED: Rake template searches parent directories for Rakefile.
9
+ * IMPROVED: Rake tasks show the Rakefile path in the long description.
10
+ * IMPROVED: Subtools whose names begin with underscore are no longer listed in help
11
+ screens unless the `--all` flag is given.
12
+ * IMPROVED: Non-runnable namespaces are no longer displayed in recursive subtool
13
+ lists if their children are already displayed.
14
+
3
15
  ### 0.5.0 / 2018-10-07
4
16
 
5
17
  * ADDED: Period and colon are recognized as tool path delimiters.
@@ -1079,13 +1079,13 @@ which can be used to call another tool:
1079
1079
  end
1080
1080
 
1081
1081
  Pass the tool name and arguments as arguments to the run method. It will
1082
- execute, and return a process status object (i.e. 0 for success, and nonzero
1083
- for error). Make sure you handle the exit status. For example, in most cases,
1084
- you should probably exit if the tool you are calling returns a nonzero code.
1082
+ execute, and return a process status code (i.e. 0 for success, and nonzero for
1083
+ error). Make sure you handle the exit status. For example, in most cases, you
1084
+ should probably exit if the tool you are calling returns a nonzero code.
1085
1085
 
1086
1086
  You may also use the `exec` mixin [described below](#Executing_Subprocesses) to
1087
1087
  run a tool in a separate process. This is particularly useful if you need to
1088
- capture or manipulate that tool's input or output.
1088
+ capture or manipulate that tool's input or output stream.
1089
1089
 
1090
1090
  ### Helper Methods and Mixins
1091
1091
 
@@ -1572,96 +1572,6 @@ Either a single `.preload.rb` file or a `.preload` directory, or both, may be
1572
1572
  used. If both are present, the `.preload.rb` file is loaded first before the
1573
1573
  `.preload` directory contents.
1574
1574
 
1575
- ### Data Files
1576
-
1577
- If your tools require images, archives, keys, or other such static data, Toys
1578
- provides a convenient place to put data files that can be looked up by tools
1579
- either during definition or runtime.
1580
-
1581
- To use data files, you must define your tools inside a
1582
- [Toys directory](#Toys_Directories). Within the Toys directory, create a
1583
- directory named `.data` and copy your data files there. You may "find" a data
1584
- file using the `find_data` directive in a Toys file, or by calling the
1585
- `find_data` method in a tool. The `find_data` mechanism takes a relative path
1586
- to a file, locates a matching file (or directory) among the data files, and
1587
- returns the full path to that file system object. You may then read the file
1588
- or perform any other operation on it.
1589
-
1590
- For example, take the following directory structure:
1591
-
1592
- (current directory)
1593
- |
1594
- +- .toys/
1595
- |
1596
- +- .data
1597
- | |
1598
- | +- greeting.txt
1599
- | |
1600
- | +- desc/
1601
- | |
1602
- | +- short.txt
1603
- |
1604
- +- greet.rb <-- defines "greet" (and subtools)
1605
-
1606
- The data files in `.toys/.data` are available to any tool in the `.toys`
1607
- directory or any of its subdirectories. For example, suppose we want our
1608
- "greet" tool to use the contents of `greeting.txt`. We can call `find_data` to
1609
- read those contents when the tool is executed:
1610
-
1611
- # greet.rb
1612
- desc "Print a friendly greeting."
1613
- optional_arg :whom, default: "world", desc: "Whom to greet."
1614
- def run
1615
- greeting = IO.read(find_data("greeting.txt")).strip
1616
- puts "#{greeting}, #{whom}!"
1617
- end
1618
-
1619
- You can include directories in the argument to `find_data`. For example, here
1620
- is how to use the `find_data` directive to read the short description from the
1621
- file "desc/short.txt":
1622
-
1623
- # greet.rb
1624
- desc IO.read(find_data("desc/short.txt")).strip
1625
- optional_arg :whom, default: "world", desc: "Whom to greet."
1626
- def run
1627
- greeting = IO.read(find_data("greeting.txt")).strip
1628
- puts "#{greeting}, #{whom}!"
1629
- end
1630
-
1631
- The `find_data` mechanism will return the "closest" file or directory found.
1632
- In the example below, there is a `desc/short.txt` file in the `.data` directory
1633
- at the top level, but there is also a `desc/short.txt` file in the `.data`
1634
- directory under `test`. Tools under the `test` directory will find the more
1635
- specific data file, while other tools will find the more general file.
1636
-
1637
- (current directory)
1638
- |
1639
- +- .toys/
1640
- |
1641
- +- .data
1642
- | |
1643
- | +- greeting.txt
1644
- | |
1645
- | +- desc/
1646
- | |
1647
- | +- short.txt <-- default description for all tools
1648
- |
1649
- +- greet.rb <-- defines "greet" (and subtools)
1650
- |
1651
- +- test/
1652
- |
1653
- +- .data
1654
- | |
1655
- | +- desc/
1656
- | |
1657
- | +- short.txt <-- override description for test tools
1658
- |
1659
- +- unit.rb <-- defines "test unit" (and its subtools)
1660
-
1661
- If, however, you find `greeting.txt` from a tool under `test`, it will still
1662
- find the more general `.toys/.data/greeting.txt` file because there is no
1663
- overriding file under `.toys/test/.data`.
1664
-
1665
1575
  ## Using Third-Party Gems
1666
1576
 
1667
1577
  The Ruby community has developed many resources for building command line
@@ -1814,8 +1724,8 @@ Toys was designed to organize scripts that may be "scoped" to a project or
1814
1724
  directory. Rake is also commonly used for this purpose: you can write a
1815
1725
  "Rakefile" that defines rake tasks scoped to a directory. In many cases, Toys
1816
1726
  can be used as a replacement for Rake. Indeed, the Toys repository itself
1817
- contains a `.toys.rb` file that defines tools for running tests, builds, and so
1818
- forth, instead of a Rakefile.
1727
+ contains a `.toys.rb` file instead of a Rakefile for running tests, builds, and
1728
+ so forth.
1819
1729
 
1820
1730
  This section will explore the differences between Toys and Rake, and describe
1821
1731
  how to use Toys for some of the things traditionally done with Rake.
@@ -1859,7 +1769,7 @@ it focuses on making it easy to define imperative tasks.
1859
1769
  All told, this boils down to the principle of using the best tool for the job.
1860
1770
  There will be times when you need to express file-based dependencies in some of
1861
1771
  your build tasks. Rake will continue to be your friend in those cases. However,
1862
- for high level tasks such as "run my tests", "build my YARD documentation", or
1772
+ for imperative tasks such as "run my tests", "build my YARD documentation", or
1863
1773
  "release my gem", you may find Toys easier to use.
1864
1774
 
1865
1775
  ### Using Toys to Invoke Rake Tasks
@@ -1955,17 +1865,18 @@ can use either or both tools, depending on your needs.
1955
1865
 
1956
1866
  Toys provides a built-in template for minitest, called `:minitest`. It is
1957
1867
  implemented by the template class {Toys::Templates::Minitest}, and it uses the
1958
- minitest gem, which is provided with most recent versions of Ruby. The
1959
- following directive uses the minitest template to create a tool called `test`:
1868
+ [minitest gem](https://rubygems.org/gems/minitest). The following directive
1869
+ uses the minitest template to create a tool called `test`:
1960
1870
 
1961
1871
  expand :minitest, files: ["test/test*.rb"], libs: ["lib", "ext"]
1962
1872
 
1963
1873
  See the {Toys::Templates::Minitest} documentation for details on the various
1964
1874
  options.
1965
1875
 
1966
- If you want to enforce code style using the "rubocop" gem, you can use the
1967
- built-in `:rubocop` template. The following directive uses this template to
1968
- create a tool called `rubocop`:
1876
+ If you want to enforce code style using the
1877
+ [rubocop gem](https://rubygems.org/gems/rubocop), you can use the built-in
1878
+ `:rubocop` template. The following directive uses this template to create a
1879
+ tool called `rubocop`:
1969
1880
 
1970
1881
  expand :rubocop
1971
1882
 
@@ -2020,13 +1931,13 @@ Here's an example for YARD, creating a tool called `yardoc`:
2020
1931
  Let's look at a complete example that combines the techniques above to provide
2021
1932
  all the basic tools for a Ruby gem. It includes:
2022
1933
 
2023
- * A testing tool that can be run with `toys test`
2024
- * Code style checking using Rubocop, run with `toys rubocop`
2025
- * Documentation building using Yardoc, run with `toys yardoc`
2026
- * Gem building, run with `toys build`
2027
- * Gem build and release to Rubygems.org, run with `toys release`
2028
- * A full CI tool, run with `toys ci`, that can be run from your favorite CI
2029
- system. It runs the tests and style checks, and checks (but does not
1934
+ * A testing tool that can be invoked using `toys test`
1935
+ * Code style checking using Rubocop, invoked using `toys rubocop`
1936
+ * Documentation building using Yardoc, invoked using `toys yardoc`
1937
+ * Gem building, invoked using `toys build`
1938
+ * Gem build and release to Rubygems.org, invoked using `toys release`
1939
+ * A full CI tool, invoked using `toys ci`, that can be run from your favorite
1940
+ CI system. It runs the tests and style checks, and checks (but does not
2030
1941
  actually build) the documentation for warnings and completeness.
2031
1942
 
2032
1943
  Below is the full annotated `.toys.rb` file. For many gems, you could drop this
@@ -2211,10 +2122,10 @@ completely disable decreasing the verbosity, disable both `-q` and `--quiet`.
2211
2122
 
2212
2123
  Normally Toys handles parsing command line arguments for you. This makes
2213
2124
  writing tools easier, and also allows Toys to generate documentation
2214
- automatically for flags and arguments. However, occasionally you'll not want
2215
- Toys to perform any parsing, but just to give you the command line arguments
2125
+ automatically for flags and arguments. However, occasionally you'll want Toys
2126
+ not to perform any parsing, but just to give you the command line arguments
2216
2127
  raw. One common case is if your tool turns around and passes its arguments
2217
- verbatim to another subprocess.
2128
+ verbatim to a subprocess.
2218
2129
 
2219
2130
  To disable argument parsing, use the `disable_argument_parsing` directive. This
2220
2131
  directive disables parsing and validation of flags and positional arguments.
@@ -2233,6 +2144,232 @@ Here is an example that wraps calls to git:
2233
2144
  end
2234
2145
  end
2235
2146
 
2147
+ ### Data Files
2148
+
2149
+ If your tools require images, archives, keys, or other such static data, Toys
2150
+ provides a convenient place to put data files that can be looked up by tools
2151
+ either during definition or runtime.
2152
+
2153
+ To use data files, you must define your tools inside a
2154
+ [Toys directory](#Toys_Directories). Within the Toys directory, create a
2155
+ directory named `.data` and copy your data files there.
2156
+
2157
+ You may then "find" a data file by providing the relative path to the file from
2158
+ the `.data` directory. When defining a tool, use the
2159
+ [Toys::DSL::Tool#find_data](https://www.rubydoc.info/gems/toys-core/Toys%2FDSL%2FTool:find_data)
2160
+ directive in a Toys file. Or, at tool execution time, call
2161
+ [Toys::Tool#find_data](https://www.rubydoc.info/gems/toys-core/Toys%2FTool:find_data)
2162
+ (which is a convenience method for getting the tool source object using the
2163
+ `TOOL_SOURCE` key, and calling
2164
+ [Toys::Definition::SourceInfo#find_data](https://www.rubydoc.info/gems/toys-core/Toys%2FDefinition%2FSourceInfo:find_data)
2165
+ on it). In either case, `find_data` locates a matching file (or directory)
2166
+ among the data files, and returns the full path to that file system object. You
2167
+ may then read the file or perform any other operation on it.
2168
+
2169
+ For example, take the following directory structure:
2170
+
2171
+ (current directory)
2172
+ |
2173
+ +- .toys/
2174
+ |
2175
+ +- .data/
2176
+ | |
2177
+ | +- greeting.txt
2178
+ | |
2179
+ | +- desc/
2180
+ | |
2181
+ | +- short.txt
2182
+ |
2183
+ +- greet.rb <-- defines "greet" (and subtools)
2184
+
2185
+ The data files in `.toys/.data` are available to any tool in the `.toys`
2186
+ directory or any of its subdirectories. For example, suppose we want our
2187
+ "greet" tool to use the contents of `greeting.txt`. We can call `find_data` to
2188
+ read those contents when the tool is executed:
2189
+
2190
+ # greet.rb
2191
+ desc "Print a friendly greeting."
2192
+ optional_arg :whom, default: "world", desc: "Whom to greet."
2193
+ def run
2194
+ greeting = IO.read(find_data("greeting.txt")).strip
2195
+ puts "#{greeting}, #{whom}!"
2196
+ end
2197
+
2198
+ You can include directories in the argument to `find_data`. For example, here
2199
+ is how to use the `find_data` directive to read the short description from the
2200
+ file "desc/short.txt":
2201
+
2202
+ # greet.rb
2203
+ desc IO.read(find_data("desc/short.txt")).strip
2204
+ optional_arg :whom, default: "world", desc: "Whom to greet."
2205
+ def run
2206
+ greeting = IO.read(find_data("greeting.txt")).strip
2207
+ puts "#{greeting}, #{whom}!"
2208
+ end
2209
+
2210
+ The `find_data` mechanism will return the "closest" file or directory found.
2211
+ In the example below, there is a `desc/short.txt` file in the `.data` directory
2212
+ at the top level, but there is also a `desc/short.txt` file in the `.data`
2213
+ directory under `test`. Tools under the `test` directory will find the more
2214
+ specific data file, while other tools will find the more general file.
2215
+
2216
+ (current directory)
2217
+ |
2218
+ +- .toys/
2219
+ |
2220
+ +- .data/
2221
+ | |
2222
+ | +- greeting.txt
2223
+ | |
2224
+ | +- desc/
2225
+ | |
2226
+ | +- short.txt <-- default description for all tools
2227
+ |
2228
+ +- greet.rb <-- defines "greet" (and subtools)
2229
+ |
2230
+ +- test/
2231
+ |
2232
+ +- .data/
2233
+ | |
2234
+ | +- desc/
2235
+ | |
2236
+ | +- short.txt <-- override description for test tools
2237
+ |
2238
+ +- unit.rb <-- defines "test unit" (and its subtools)
2239
+
2240
+ If, however, you find `greeting.txt` from a tool under `test`, it will still
2241
+ find the more general `.toys/.data/greeting.txt` file because there is no
2242
+ overriding file under `.toys/test/.data`.
2243
+
2244
+ ### The Context Directory
2245
+
2246
+ The **context directory** for a tool is the directory containing the toplevel
2247
+ `.toys.rb` file or the `.toys` directory within which the tool is defined. It
2248
+ is sometimes useful for tools that expect to be run from a specific working
2249
+ directory.
2250
+
2251
+ For example, suppose you have a Ruby project directory:
2252
+
2253
+ my-project/
2254
+ |
2255
+ +- .toys.rb <-- project tools defined here
2256
+ |
2257
+ +- lib/
2258
+ |
2259
+ +- test/
2260
+ |
2261
+ etc...
2262
+
2263
+ Now suppose you defined a tool that lists the tests:
2264
+
2265
+ tool "list-tests" do
2266
+ def run
2267
+ puts Dir.glob("test/**/*.rb").join("\n")
2268
+ end
2269
+ end
2270
+
2271
+ This tool assumes it will be run from the main project directory (`my-project`
2272
+ in the above case). However, Toys lets you invoke tools even if you are in a
2273
+ subdirectory:
2274
+
2275
+ cd lib
2276
+ toys list-tests # Does not work
2277
+
2278
+ Rake handles this by actually changing the current working directory to the
2279
+ directory containing the active Rakefile. Toys, however, does not change the
2280
+ working directory unless you tell it. You can make the `list-tests` tool work
2281
+ correctly by changing the directory to the context directory (which is the
2282
+ directory containing the `.toys.rb` file, i.e. the `my-project` directory.)
2283
+
2284
+ tool "list-tests" do
2285
+ def run
2286
+ Dir.chdir context_directory do
2287
+ puts Dir.glob("test/**/*.rb").join("\n")
2288
+ end
2289
+ end
2290
+ end
2291
+
2292
+ Note the context directory is different from `__dir__`. It is not necessarily
2293
+ the directory containing the file being executed, but the directory containing
2294
+ the entire toys directory structure. So if your tool definition is inside a
2295
+ `.toys` directory, it will still work:
2296
+
2297
+ my-project/ <-- context_directory still points here
2298
+ |
2299
+ +- .toys/
2300
+ | |
2301
+ | +- list-tests.rb <-- tool defined here
2302
+ |
2303
+ +- lib/
2304
+ |
2305
+ +- test/
2306
+ |
2307
+ etc...
2308
+
2309
+ This behavior is particularly useful for build tools. Indeed, all the build
2310
+ tools described in the section on
2311
+ [Toys as a Rake Replacement](#Toys_as_a_Rake_Replacement) automatically move
2312
+ into the context directory when they execute.
2313
+
2314
+ #### Changing the Context Directory
2315
+
2316
+ It is even possible to modify the context directory, causing tools that use the
2317
+ context directory (such as the standard build tools) to run in a different
2318
+ directory. Here is an example:
2319
+
2320
+ Suppose you have a repository with multiple gems, each in its own directory:
2321
+
2322
+ my-repo/
2323
+ |
2324
+ +- .toys.rb <-- all project tools defined here
2325
+ |
2326
+ +- gem1/
2327
+ | |
2328
+ | +- lib/
2329
+ | |
2330
+ | +- test/
2331
+ |
2332
+ +- gem2/
2333
+ | |
2334
+ | +- lib/
2335
+ | |
2336
+ | +- test/
2337
+ |
2338
+ etc...
2339
+
2340
+ Assuming all the gems use the same set of build tools, it is possible to define
2341
+ those tools once in a single `.toys.rb` file and have it run in a particular
2342
+ gem directory depending on your current location. For example, you can cd into
2343
+ `gem1` or even `gem1/lib` to have the tools run on `gem1`. Because the standard
2344
+ build tools execute within the context directory, you can accomplish this by
2345
+ setting the context directory to the gem directory corresponding to the current
2346
+ location. That is, if the working directory is `my-repo/gem1/lib`, set the
2347
+ context directory to `my-repo/gem1`. Here's what that could look like:
2348
+
2349
+ # .toys.rb content
2350
+
2351
+ require "pathname"
2352
+ base_dir = Pathname.new context_directory
2353
+ cur_dir = Pathname.new Dir.getwd
2354
+
2355
+ # The gem name is the first segment of the relative path from the context
2356
+ # directory to the current directory.
2357
+ relative_path = cur_dir.relative_path_from(base_dir).to_s
2358
+ gem_name = relative_path.split("/").first
2359
+
2360
+ # Only proceed if we're truly in a subdirectory
2361
+ if gem_name && gem_name != "." && gem_name != ".."
2362
+
2363
+ # Now set the context directory to the gem directory.
2364
+ set_context_directory base_dir.join(gem_name).to_s
2365
+
2366
+ # Define the build tools. Each of these uses the custom context directory
2367
+ # set above, and thus runs for the selected gem.
2368
+ expand :minitest
2369
+ expand :gem_build
2370
+ # etc.
2371
+ end
2372
+
2236
2373
  ## Toys Administration Using the System Tools
2237
2374
 
2238
2375
  Toys comes with a few built-in tools, including some that let you administer
@@ -2265,8 +2402,8 @@ A similar effect can of course be obtained simply by `gem install toys`.
2265
2402
 
2266
2403
  ## Writing Your Own CLI Using Toys
2267
2404
 
2268
- Toys is not primarily designed to help you write a custom command-line binary,
2269
- but you can use it in that fashion. Toys is factored into two gems:
2405
+ Although Toys is not primarily designed to help you write a custom command-line
2406
+ binary, you can use it in that way. Toys is factored into two gems:
2270
2407
  **toys-core**, which includes all the underlying machinery for creating
2271
2408
  command-line binaries, and **toys**, which is really just a wrapper that
2272
2409
  provides the `toys` binary itself and its built-in commands and behavior. To
@@ -2284,7 +2421,8 @@ line binary. For example:
2284
2421
  Toys-Core lets you provide an alternate default run method for your own
2285
2422
  command line binary.
2286
2423
  * Toys itself provides several built-in tools, such as `do`, and `system`.
2287
- Toys-Core lets your own command line binary define its own built-in tools.
2424
+ Toys-Core lets you write your own command line binary with its own built-in
2425
+ tools.
2288
2426
  * Toys itself implements a particular search path for user-provided Toys
2289
2427
  files, and looks for specific file and directory names such as `.toys.rb`.
2290
2428
  Toys-Core lets you change the search path, the file/directory names, or
@@ -186,6 +186,7 @@ module Toys
186
186
  list_flags: true,
187
187
  recursive_flags: true,
188
188
  search_flags: true,
189
+ show_all_subtools_flags: true,
189
190
  default_recursive: true,
190
191
  allow_root_args: true,
191
192
  show_source_path: true,
@@ -66,17 +66,17 @@ module Toys
66
66
  include :fileutils
67
67
 
68
68
  to_run do
69
- files = []
70
- patterns = Array(template.paths)
71
- patterns.each do |pattern|
72
- files.concat(::Dir.glob(pattern))
73
- end
74
- files.uniq!
75
-
76
- files.each do |file|
77
- if ::File.exist?(file)
78
- rm_rf(file)
79
- puts "Cleaned: #{file}"
69
+ ::Dir.chdir(context_directory || ::Dir.getwd) do
70
+ files = []
71
+ patterns = Array(template.paths)
72
+ patterns.each do |pattern|
73
+ files.concat(::Dir.glob(pattern))
74
+ end
75
+ files.uniq.each do |file|
76
+ if ::File.exist?(file)
77
+ rm_rf(file)
78
+ puts "Cleaned: #{file}"
79
+ end
80
80
  end
81
81
  end
82
82
  end
@@ -77,7 +77,9 @@ module Toys
77
77
 
78
78
  to_expand do |template|
79
79
  unless template.gem_name
80
- candidates = ::Dir.glob("*.gemspec")
80
+ candidates = ::Dir.chdir(context_directory || ::Dir.getwd) do
81
+ ::Dir.glob("*.gemspec")
82
+ end
81
83
  if candidates.empty?
82
84
  raise ToolDefinitionError, "Could not find a gemspec"
83
85
  end
@@ -90,31 +92,32 @@ module Toys
90
92
 
91
93
  flag :yes, "-y", "--yes", desc: "Do not ask for interactive confirmation"
92
94
 
93
- include :exec
95
+ include :exec, exit_on_nonzero_status: true
94
96
  include :fileutils
95
97
  include :terminal
96
98
 
97
99
  to_run do
98
100
  require "rubygems/package"
99
- configure_exec(exit_on_nonzero_status: true)
100
- gemspec = ::Gem::Specification.load("#{template.gem_name}.gemspec")
101
- version = gemspec.version
102
- gemfile = "#{template.gem_name}-#{version}.gem"
103
- ::Gem::Package.build(gemspec)
104
- mkdir_p("pkg")
105
- mv(gemfile, "pkg")
106
- if template.push_gem
107
- if ::File.directory?(".git") && capture("git status -s").strip != ""
108
- logger.error "Cannot push the gem when there are uncommited changes"
109
- exit(1)
110
- end
111
- exit(1) unless yes || confirm("Release #{gemfile}?", default: true)
112
- exec(["gem", "push", "pkg/#{gemfile}"])
113
- if template.tag
114
- exec(["git", "tag", "v#{version}"])
115
- if template.push_tag
116
- template.push_tag = "origin" if template.push_tag == true
117
- exec(["git", "push", template.push_tag, "v#{version}"])
101
+ ::Dir.chdir(context_directory || ::Dir.getwd) do
102
+ gemspec = ::Gem::Specification.load("#{template.gem_name}.gemspec")
103
+ version = gemspec.version
104
+ gemfile = "#{template.gem_name}-#{version}.gem"
105
+ ::Gem::Package.build(gemspec)
106
+ mkdir_p("pkg")
107
+ mv(gemfile, "pkg")
108
+ if template.push_gem
109
+ if ::File.directory?(".git") && capture("git status -s").strip != ""
110
+ logger.error "Cannot push the gem when there are uncommited changes"
111
+ exit(1)
112
+ end
113
+ exit(1) unless yes || confirm("Release #{gemfile}?", default: true)
114
+ exec(["gem", "push", "pkg/#{gemfile}"])
115
+ if template.tag
116
+ exec(["git", "tag", "v#{version}"])
117
+ if template.push_tag
118
+ template.push_tag = "origin" if template.push_tag == true
119
+ exec(["git", "push", template.push_tag, "v#{version}"])
120
+ end
118
121
  end
119
122
  end
120
123
  end
@@ -109,28 +109,30 @@ module Toys
109
109
  to_run do
110
110
  gem "minitest", *Array(template.gem_version)
111
111
 
112
- ruby_args = []
113
- unless template.libs.empty?
114
- lib_path = template.libs.join(::File::PATH_SEPARATOR)
115
- ruby_args << "-I#{lib_path}"
116
- end
117
- ruby_args << "-w" if warnings
112
+ ::Dir.chdir(context_directory || ::Dir.getwd) do
113
+ ruby_args = []
114
+ unless template.libs.empty?
115
+ lib_path = template.libs.join(::File::PATH_SEPARATOR)
116
+ ruby_args << "-I#{lib_path}"
117
+ end
118
+ ruby_args << "-w" if warnings
118
119
 
119
- if tests.empty?
120
- Array(template.files).each do |pattern|
121
- tests.concat(::Dir.glob(pattern))
120
+ if tests.empty?
121
+ Array(template.files).each do |pattern|
122
+ tests.concat(::Dir.glob(pattern))
123
+ end
124
+ tests.uniq!
122
125
  end
123
- tests.uniq!
124
- end
125
126
 
126
- result = ruby(ruby_args, in: :controller) do |controller|
127
- tests.each do |file|
128
- controller.in.puts("load '#{file}'")
127
+ result = ruby(ruby_args, in: :controller) do |controller|
128
+ tests.each do |file|
129
+ controller.in.puts("load '#{file}'")
130
+ end
131
+ end
132
+ if result.error?
133
+ logger.error("Minitest failed!")
134
+ exit(result.exit_code)
129
135
  end
130
- end
131
- if result.error?
132
- logger.error("Minitest failed!")
133
- exit(result.exit_code)
134
136
  end
135
137
  end
136
138
  end
@@ -50,8 +50,8 @@ module Toys
50
50
  # the rake gem. Defaults to nil, indicating no version requirement.
51
51
  # @param [String] rakefile_path Path to the Rakefile. Defaults to
52
52
  # {DEFAULT_RAKEFILE_PATH}.
53
- # @param [Boolean] only_described Tools are generated only for rake tasks
54
- # with descriptions. Default is false.
53
+ # @param [Boolean] only_described If true, tools are generated only for
54
+ # rake tasks with descriptions. Default is false.
55
55
  # @param [Boolean] use_flags Generated tools use flags instead of
56
56
  # positional arguments to pass arguments to rake tasks. Default is
57
57
  # false.
@@ -74,16 +74,17 @@ module Toys
74
74
  to_expand do |template|
75
75
  gem "rake", *Array(template.gem_version)
76
76
  require "rake"
77
- ::Rake::TaskManager.record_task_metadata = true
78
- rake = ::Rake::Application.new
79
- ::Rake.application = rake
80
- ::Rake.load_rakefile(template.rakefile_path)
77
+ rakefile_path = Templates::Rake.find_rakefile(template.rakefile_path, context_directory)
78
+ raise "Cannot find #{template.rakefile_path}" unless rakefile_path
79
+ context_dir = ::File.dirname(rakefile_path)
80
+ rake = Templates::Rake.prepare_rake(rakefile_path, context_dir)
81
81
  rake.tasks.each do |task|
82
82
  comments = task.full_comment.to_s.split("\n")
83
83
  next if comments.empty? && template.only_described
84
84
  tool(task.name.split(":"), if_defined: :ignore) do
85
85
  unless comments.empty?
86
86
  desc(comments.first)
87
+ comments << "" << "Defined as a Rake task in #{rakefile_path}"
87
88
  long_desc(*comments)
88
89
  end
89
90
  if template.use_flags
@@ -93,14 +94,18 @@ module Toys
93
94
  end
94
95
  to_run do
95
96
  args = task.arg_names.map { |arg| self[arg] }
96
- task.invoke(*args)
97
+ ::Dir.chdir(context_dir) do
98
+ task.invoke(*args)
99
+ end
97
100
  end
98
101
  else
99
102
  task.arg_names.each do |arg|
100
103
  optional_arg(arg)
101
104
  end
102
105
  to_run do
103
- task.invoke(*args)
106
+ ::Dir.chdir(context_dir) do
107
+ task.invoke(*args)
108
+ end
104
109
  end
105
110
  end
106
111
  end
@@ -118,6 +123,34 @@ module Toys
118
123
  end
119
124
  specs
120
125
  end
126
+
127
+ ## @private
128
+ def self.find_rakefile(path, context_dir)
129
+ if path == ::File.absolute_path(path)
130
+ return ::File.file?(path) && ::File.readable?(path) ? path : nil
131
+ end
132
+ dir = ::Dir.getwd
133
+ 50.times do
134
+ rakefile_path = ::File.expand_path(path, dir)
135
+ return rakefile_path if ::File.file?(rakefile_path) && ::File.readable?(rakefile_path)
136
+ break if dir == context_dir
137
+ next_dir = ::File.dirname(dir)
138
+ break if dir == next_dir
139
+ dir = next_dir
140
+ end
141
+ nil
142
+ end
143
+
144
+ ## @private
145
+ def self.prepare_rake(rakefile_path, context_dir)
146
+ ::Rake::TaskManager.record_task_metadata = true
147
+ rake = ::Rake::Application.new
148
+ ::Rake.application = rake
149
+ ::Dir.chdir(context_dir) do
150
+ ::Rake.load_rakefile(rakefile_path)
151
+ end
152
+ rake
153
+ end
121
154
  end
122
155
  end
123
156
  end
@@ -122,23 +122,25 @@ module Toys
122
122
  gem "rdoc", *Array(template.gem_version)
123
123
  require "rdoc"
124
124
 
125
- files = []
126
- patterns = Array(template.files)
127
- patterns = ["lib/**/*.rb"] if patterns.empty?
128
- patterns.each do |pattern|
129
- files.concat(::Dir.glob(pattern))
130
- end
131
- files.uniq!
125
+ ::Dir.chdir(context_directory || ::Dir.getwd) do
126
+ files = []
127
+ patterns = Array(template.files)
128
+ patterns = ["lib/**/*.rb"] if patterns.empty?
129
+ patterns.each do |pattern|
130
+ files.concat(::Dir.glob(pattern))
131
+ end
132
+ files.uniq!
132
133
 
133
- args = template.options.dup
134
- args << "-o" << template.output_dir
135
- args << "--markup" << template.markup if template.markup
136
- args << "--main" << template.main if template.main
137
- args << "--title" << template.title if template.title
138
- args << "-T" << template.template if template.template
139
- args << "-f" << template.generator if template.generator
134
+ args = template.options.dup
135
+ args << "-o" << template.output_dir
136
+ args << "--markup" << template.markup if template.markup
137
+ args << "--main" << template.main if template.main
138
+ args << "--title" << template.title if template.title
139
+ args << "-T" << template.template if template.template
140
+ args << "-f" << template.generator if template.generator
140
141
 
141
- exec_proc(proc { RDoc::RDoc.new.document(args + files) })
142
+ exec_proc(proc { RDoc::RDoc.new.document(args + files) })
143
+ end
142
144
  end
143
145
  end
144
146
  end
@@ -86,12 +86,14 @@ module Toys
86
86
  gem "rubocop", *Array(template.gem_version)
87
87
  require "rubocop"
88
88
 
89
- cli = ::RuboCop::CLI.new
90
- logger.info "Running RuboCop..."
91
- result = cli.run(template.options)
92
- if result.nonzero?
93
- logger.error "RuboCop failed!"
94
- exit(1) if template.fail_on_error
89
+ ::Dir.chdir(context_directory || ::Dir.getwd) do
90
+ cli = ::RuboCop::CLI.new
91
+ logger.info "Running RuboCop..."
92
+ result = cli.run(template.options)
93
+ if result.nonzero?
94
+ logger.error "RuboCop failed!"
95
+ exit(1) if template.fail_on_error
96
+ end
95
97
  end
96
98
  end
97
99
  end
@@ -169,55 +169,57 @@ module Toys
169
169
  gem "yard", *Array(template.gem_version)
170
170
  require "yard"
171
171
 
172
- files = []
173
- patterns = Array(template.files)
174
- patterns = ["lib/**/*.rb"] if patterns.empty?
175
- patterns.each do |pattern|
176
- files.concat(::Dir.glob(pattern))
177
- end
178
- files.uniq!
172
+ ::Dir.chdir(context_directory || ::Dir.getwd) do
173
+ files = []
174
+ patterns = Array(template.files)
175
+ patterns = ["lib/**/*.rb"] if patterns.empty?
176
+ patterns.each do |pattern|
177
+ files.concat(::Dir.glob(pattern))
178
+ end
179
+ files.uniq!
179
180
 
180
- run_options = template.options.dup
181
- stats_options = template.stats_options.dup
182
- stats_options << "--list-undoc" if template.fail_on_undocumented_objects
183
- run_options << "--fail-on-warning" if template.fail_on_warning
184
- run_options << "--no-output" unless generate_output
185
- run_options << "--output-dir" << template.output_dir if template.output_dir
186
- run_options << "--no-public" unless template.show_public
187
- run_options << "--protected" if template.show_protected
188
- run_options << "--private" if template.show_private
189
- run_options << "--no-private" if template.hide_private_tag
190
- run_options << "-r" << template.readme if template.readme
191
- run_options << "-m" << template.markup if template.markup
192
- run_options << "-t" << template.template if template.template
193
- run_options << "-p" << template.template_path if template.template_path
194
- run_options << "-f" << template.format if template.format
195
- unless stats_options.empty?
196
- run_options << "--no-stats"
197
- stats_options << "--use-cache"
198
- end
199
- run_options.concat(files)
181
+ run_options = template.options.dup
182
+ stats_options = template.stats_options.dup
183
+ stats_options << "--list-undoc" if template.fail_on_undocumented_objects
184
+ run_options << "--fail-on-warning" if template.fail_on_warning
185
+ run_options << "--no-output" unless generate_output
186
+ run_options << "--output-dir" << template.output_dir if template.output_dir
187
+ run_options << "--no-public" unless template.show_public
188
+ run_options << "--protected" if template.show_protected
189
+ run_options << "--private" if template.show_private
190
+ run_options << "--no-private" if template.hide_private_tag
191
+ run_options << "-r" << template.readme if template.readme
192
+ run_options << "-m" << template.markup if template.markup
193
+ run_options << "-t" << template.template if template.template
194
+ run_options << "-p" << template.template_path if template.template_path
195
+ run_options << "-f" << template.format if template.format
196
+ unless stats_options.empty?
197
+ run_options << "--no-stats"
198
+ stats_options << "--use-cache"
199
+ end
200
+ run_options.concat(files)
200
201
 
201
- result = exec_proc(proc { ::YARD::CLI::Yardoc.run(*run_options) })
202
- if result.error?
203
- puts("Yardoc encountered errors", :red, :bold) unless verbosity.negative?
204
- exit(1)
205
- end
206
- unless stats_options.empty?
207
- result = exec_proc(proc { ::YARD::CLI::Stats.run(*stats_options) }, out: :capture)
208
- puts result.captured_out
202
+ result = exec_proc(proc { ::YARD::CLI::Yardoc.run(*run_options) })
209
203
  if result.error?
210
204
  puts("Yardoc encountered errors", :red, :bold) unless verbosity.negative?
211
205
  exit(1)
212
206
  end
213
- exit_on_nonzero_status(result)
214
- if template.fail_on_undocumented_objects
215
- if result.captured_out =~ /Undocumented\sObjects:/
216
- unless verbosity.negative?
217
- puts("Yardoc encountered undocumented objects", :red, :bold)
218
- end
207
+ unless stats_options.empty?
208
+ result = exec_proc(proc { ::YARD::CLI::Stats.run(*stats_options) }, out: :capture)
209
+ puts result.captured_out
210
+ if result.error?
211
+ puts("Yardoc encountered errors", :red, :bold) unless verbosity.negative?
219
212
  exit(1)
220
213
  end
214
+ exit_on_nonzero_status(result)
215
+ if template.fail_on_undocumented_objects
216
+ if result.captured_out =~ /Undocumented\sObjects:/
217
+ unless verbosity.negative?
218
+ puts("Yardoc encountered undocumented objects", :red, :bold)
219
+ end
220
+ exit(1)
221
+ end
222
+ end
221
223
  end
222
224
  end
223
225
  end
@@ -34,5 +34,5 @@ module Toys
34
34
  # Current version of the Toys command line binary
35
35
  # @return [String]
36
36
  #
37
- VERSION = "0.5.0"
37
+ VERSION = "0.6.0"
38
38
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-08 00:00:00.000000000 Z
11
+ date: 2018-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: toys-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.0
19
+ version: 0.6.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.0
26
+ version: 0.6.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: highline
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '5.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '12.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '12.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: redcarpet
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,14 @@ dependencies:
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: 0.59.1
117
+ version: 0.59.2
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: 0.59.1
124
+ version: 0.59.2
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: yard
113
127
  requirement: !ruby/object:Gem::Requirement