nake 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +34 -2
- data/TODO.txt +4 -2
- data/bin/nake +63 -5
- data/examples/arguments.rb +12 -0
- data/examples/file.rb +18 -0
- data/examples/flags.rb +15 -0
- data/lib/nake.rb +85 -13
- data/lib/nake/args.rb +52 -0
- data/lib/nake/argv.rb +38 -20
- data/lib/nake/dsl.rb +26 -0
- data/lib/nake/file_task.rb +60 -0
- data/lib/nake/helpers.rb +47 -3
- data/lib/nake/task.rb +37 -6
- data/lib/nake/tasks/bundle.rb +12 -3
- data/lib/nake/tasks/gem.rb +14 -0
- data/lib/nake/tasks/release.rb +2 -2
- data/lib/nake/tasks/rip.rb +28 -20
- data/spec/nake/file_task_spec.rb +0 -0
- data/spec/nake/tasks/bundle_spec.rb +28 -0
- data/tasks.rb +11 -0
- data/tmp/restart.txt +0 -0
- metadata +10 -3
- data/lib/nake/tasks.rb +0 -49
data/README.textile
CHANGED
@@ -2,9 +2,9 @@ h1. About
|
|
2
2
|
|
3
3
|
Nake is light-weight and highly flexible Rake replacement with much better arguments parsing.
|
4
4
|
|
5
|
-
You might be wondering why to write yet another fucking task manager when we have Rake, Thor and others. Well, because all of them
|
5
|
+
You might be wondering why to write yet another fucking task manager when we have Rake, Thor and others. Well, because all of them suck. For example Rake, anyone is actually using its CLI arguments, because it sucks so much, that everyone rather write @ENV=test VERSION=10 rake db:migrate@. It has not just shitty API for defining CLI arguments, but also it is using very weird and totally non-unix syntax like @rake db:migrate[test,10]@. This syntax isn't just non-standard, but also some shells has @[]@ as special characters, so you actually has to escape it.
|
6
6
|
|
7
|
-
Sounds terrible? Well and it's not all! Let's take a look at this "example":http://gist.github.com/263325, as you can see if you have argument path and you let it empty, than it takes environment variable @$PATH@! I contact Jim Weirich
|
7
|
+
Sounds terrible? Well and it's not all! Let's take a look at this "example":http://gist.github.com/263325, as you can see if you have argument path and you let it empty, than it takes environment variable @$PATH@! I contact Jim Weirich so I hope he will remove this awful bug, but hey, it's pretty bad anyway.
|
8
8
|
|
9
9
|
h1. Features
|
10
10
|
|
@@ -20,6 +20,38 @@ h1. Usage
|
|
20
20
|
|
21
21
|
First of all there is a bunch of "examples":github.com/botanicus/nake/tree/master/examples, so you can try them. All these scripts are executable, so just run @./executable/basic.rb -T@ and that's it!
|
22
22
|
|
23
|
+
h1. Documentation
|
24
|
+
|
25
|
+
h2. Tasks
|
26
|
+
|
27
|
+
h3. Options parsing
|
28
|
+
|
29
|
+
h2. File Tasks
|
30
|
+
|
31
|
+
h2. Task Helpers
|
32
|
+
|
33
|
+
h2. Available Tasks
|
34
|
+
|
35
|
+
h3. Built-in Tasks
|
36
|
+
|
37
|
+
- @-T@
|
38
|
+
- @-H@
|
39
|
+
- @-i@
|
40
|
+
|
41
|
+
h3. File @nake/tasks/bundle@
|
42
|
+
|
43
|
+
This file contains only @bundle@ task which will load bundler @--no-cached@
|
44
|
+
|
45
|
+
h3. File @nake/tasks/clean@
|
46
|
+
|
47
|
+
h3. File @nake/tasks/gem@
|
48
|
+
|
49
|
+
h3. File @nake/tasks/release@
|
50
|
+
|
51
|
+
h3. File @nake/tasks/rip@
|
52
|
+
|
53
|
+
h3. File @nake/tasks/spec@
|
54
|
+
|
23
55
|
h1. Links
|
24
56
|
|
25
57
|
* "RDoc.info API Docs":http://rdoc.info/projects/botanicus/nake
|
data/TODO.txt
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
- task#setup (see Desktop/nake-setup.rb)
|
2
|
+
- yardoc
|
3
|
+
- specs
|
1
4
|
- fix interactive task, it doesn't work so far
|
2
5
|
- better argv parsing maybe, task(:spec) do |*paths, options| is fine, but task(:spec) do |path, options| will fail if no path specified ... but actually task(:spec) do |path = "spec", options| might be fine, try it ... BTW task(["-i", "--interactive"]) do |task, *args, options| doesn't work ... putting options as a first argument should solve everything, but it's not very intuitive :/
|
3
|
-
- it might be worthy to steal filelist from Rake
|
4
6
|
- how to solve args inheriting (like if we have task release which depends on task build which takes a gemspec as an argument)
|
5
7
|
- benchmarks against rake
|
6
|
-
- maybe some of: fileutils extensions, multitask, rule
|
8
|
+
- maybe some of: fileutils extensions, multitask, rule (from rake, see http://rake.rubyforge.org/files/doc/rakefile_rdoc.html)
|
7
9
|
- some default tasks like nake/tasks/package, nake/tasks/clean, nake/tasks/yardoc, nake/tasks/spec, nake/tasks/bundle
|
data/bin/nake
CHANGED
@@ -3,13 +3,71 @@
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
4
4
|
|
5
5
|
require "nake"
|
6
|
+
require "nake/args"
|
7
|
+
require "nake/helpers"
|
6
8
|
|
9
|
+
# TODO: what if I want to run:
|
10
|
+
# ./bin/nake -T
|
11
|
+
# ./bin/nake --verbose -T
|
12
|
+
# ./examples/flags.rb --verbose
|
13
|
+
|
14
|
+
# First file in arguments is separator between args for nake and for task
|
15
|
+
# If there is no file in the arguments
|
16
|
+
# co kdyz omezim tasky na list etc a nebudou moct mit --task etc?
|
17
|
+
# nake --verbose list arg1 arg2 --with-something
|
18
|
+
# => zmizi potreba aliasu
|
19
|
+
# => potreba API pro mapovani na -T etc
|
20
|
+
# Nake.args["-T"] = Nake::Task[:tasks]
|
21
|
+
|
22
|
+
# !!!!!! --verbose neni runable task to jen switchuje naky shity, takze -T by melo fungovat tak, ze naplni Nake.parse[:task] s taskem co se ma runnout
|
7
23
|
# First argument has to be path to file with your tasks
|
8
|
-
load ARGV.first
|
9
24
|
|
10
|
-
#
|
25
|
+
# parse arguments
|
26
|
+
begin
|
27
|
+
Nake.parse
|
28
|
+
rescue Exception => exception
|
29
|
+
puts "~ Arguments parsed into #{Nake.parse.inspect.green}"
|
30
|
+
puts "Exception occured during parsing arguments"
|
31
|
+
print_exception_with_backtrace_and_abort(exception)
|
32
|
+
else
|
33
|
+
if Nake.parse[:nake].include?("--debug") # Nake.debug isn't initialized yet
|
34
|
+
puts "~ Arguments parsed into #{Nake.parse.inspect.green}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# load task file
|
39
|
+
if Nake.parse[:file]
|
40
|
+
begin
|
41
|
+
load Nake.parse[:file]
|
42
|
+
rescue Exception => exception
|
43
|
+
print_exception_with_backtrace_and_abort(exception)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
abort "You have to specify a file with tasks"
|
47
|
+
end
|
48
|
+
|
49
|
+
# run arguments
|
50
|
+
# yes, arguments has to run after the task file is loaded
|
51
|
+
begin
|
52
|
+
original_args = Nake.parse.dup
|
53
|
+
Nake.run_args
|
54
|
+
rescue SystemExit => exception
|
55
|
+
exit exception.status
|
56
|
+
rescue Exception => exception
|
57
|
+
puts "~ Arguments parsed into #{Nake.parse.inspect.green}"
|
58
|
+
puts "Exception occured setting nake flags"
|
59
|
+
print_exception_with_backtrace_and_abort(exception)
|
60
|
+
else
|
61
|
+
if Nake.debug && Nake.parse != original_args
|
62
|
+
puts "~ Arguments changed into #{Nake.parse.inspect.green}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# run tasks
|
11
67
|
begin
|
12
|
-
Nake.
|
13
|
-
rescue
|
14
|
-
|
68
|
+
Nake.run_task
|
69
|
+
rescue SystemExit => exception
|
70
|
+
exit exception.status
|
71
|
+
rescue Exception => exception
|
72
|
+
print_exception_with_backtrace_and_abort(exception)
|
15
73
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!./bin/nake
|
2
|
+
|
3
|
+
# Arguments might be considered as a light-weight variant to tasks
|
4
|
+
# There are two ways how you can use tasks:
|
5
|
+
# 1) as a filter, just set a variable --debug
|
6
|
+
# 2) add your own functionality and then use exit
|
7
|
+
# 3) just set the task which will run afterwards
|
8
|
+
Nake.args["-H", "--help"] = lambda { Kernel.abort("This is my customized help!") }
|
9
|
+
Nake.args["-T", "--tasks"] = lambda { Nake.parse[:task].clear.push("tasks") }
|
10
|
+
Nake.args["--debug", "--no-debug"] = lambda { |key, value| Nake.debug = value }
|
11
|
+
|
12
|
+
# TODO: execution order, argument helper + args passing to the proc
|
data/examples/file.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!./bin/nake
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "recho"
|
5
|
+
rescue LoadError
|
6
|
+
raise LoadError, "This task require recho gem!"
|
7
|
+
end
|
8
|
+
|
9
|
+
directory "tmp"
|
10
|
+
directory "tmp/www"
|
11
|
+
|
12
|
+
file("tmp/restart.txt", "tmp") do |path|
|
13
|
+
touch path
|
14
|
+
end
|
15
|
+
|
16
|
+
file "tmp/www/index.html", "tmp/www" do |path|
|
17
|
+
echo("<html>Hello World!</html>") > path
|
18
|
+
end
|
data/examples/flags.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!./bin/nake --verbose
|
2
|
+
|
3
|
+
# This example document how you can change different flags
|
4
|
+
# - specify these flags in shebang
|
5
|
+
# - use API directly
|
6
|
+
# - ./examples/flags --verbose
|
7
|
+
Nake.verbose = false
|
8
|
+
|
9
|
+
task(:setup) do
|
10
|
+
puts "Setting environment ..."
|
11
|
+
end
|
12
|
+
|
13
|
+
task(:build, :setup) do
|
14
|
+
puts "Building ..."
|
15
|
+
end
|
data/lib/nake.rb
CHANGED
@@ -1,27 +1,99 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require "nake/argv"
|
4
3
|
require "nake/task"
|
5
4
|
|
6
5
|
module Nake
|
7
|
-
VERSION ||= "0.0.
|
8
|
-
|
9
|
-
|
6
|
+
VERSION ||= "0.0.5"
|
7
|
+
def self.verbose
|
8
|
+
@@verbose
|
9
|
+
rescue NameError
|
10
|
+
@@verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.verbose=(boolean)
|
14
|
+
@@verbose = boolean
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.debug
|
18
|
+
@@debug
|
19
|
+
rescue NameError
|
20
|
+
@@debug = true
|
21
|
+
end
|
10
22
|
|
11
|
-
def self.
|
12
|
-
|
23
|
+
def self.debug=(boolean)
|
24
|
+
@@debug = boolean
|
25
|
+
end
|
26
|
+
|
27
|
+
# I was drunk so you might found this code not very clear. But it's clear for me and it works.
|
28
|
+
def self.args
|
29
|
+
@@args ||= begin
|
30
|
+
Hash.new.tap do |hash|
|
31
|
+
hash.define_singleton_method(:[]) do |name|
|
32
|
+
names, value = self.find { |names, block| names.include?(name) }
|
33
|
+
return value
|
34
|
+
end
|
35
|
+
|
36
|
+
hash.define_singleton_method(:[]=) do |*names, proc|
|
37
|
+
super(names, proc)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.parse(args = ARGV)
|
44
|
+
@result ||= begin
|
45
|
+
args.inject(Hash.new) do |hash, argument|
|
46
|
+
hash[:nake] ||= Array.new
|
47
|
+
hash[:task] ||= Array.new
|
48
|
+
hash[:file] ||= "tasks.rb" if File.exist?("tasks.rb")
|
49
|
+
if argument.match(/^-/) && hash[:task].empty?
|
50
|
+
hash[:nake].push(argument)
|
51
|
+
elsif File.exist?(argument)
|
52
|
+
hash[:file] = argument
|
53
|
+
else
|
54
|
+
hash[:task].push(argument)
|
55
|
+
end
|
56
|
+
hash
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.run_args
|
62
|
+
# TODO: proceed --debug and --verbose first! ... to by slo tak, ze by se iterovalo pres Nake.args a pokud je to pritomno tak proved
|
63
|
+
Nake.parse[:nake].each do |argument|
|
64
|
+
unless self.args[argument]
|
65
|
+
abort "Unrecognized argument: #{argument}"
|
66
|
+
end
|
67
|
+
name, value = ArgvParser.parse(argument)
|
68
|
+
if name
|
69
|
+
info "Invoking argument #{argument} with #{name} = #{value}"
|
70
|
+
self.args[argument].call(name, value)
|
71
|
+
else
|
72
|
+
info "Invoking argument #{argument} without any arguments"
|
73
|
+
self.args[argument].call
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Run first task
|
79
|
+
#
|
80
|
+
# @raise [TaskNotFound]
|
81
|
+
# @example
|
82
|
+
# Nake.run(["release"])
|
83
|
+
# @since 0.0.1
|
84
|
+
# @author Jakub Stastny
|
85
|
+
def self.run_task
|
86
|
+
name, *args = Nake.parse[:task]
|
13
87
|
task = Task[name]
|
14
|
-
if name
|
15
|
-
raise TaskNotFound, "Task with name #{name} doesn't exist"
|
16
|
-
elsif name.nil? && task.nil?
|
88
|
+
if name.nil?
|
17
89
|
raise TaskNotFound, "You have to specify a task you want to run!"
|
90
|
+
elsif task.nil?
|
91
|
+
raise TaskNotFound, "Task with name #{name} doesn't exist"
|
92
|
+
else
|
93
|
+
task.run(args)
|
18
94
|
end
|
19
|
-
opts = args.extend(ArgvParsingMixin).extract!
|
20
|
-
task.call(args, opts)
|
21
95
|
end
|
22
96
|
end
|
23
97
|
|
24
98
|
require "nake/dsl"
|
25
99
|
require "nake/helpers"
|
26
|
-
require "nake/tasks"
|
27
|
-
require "nake/colors"
|
data/lib/nake/args.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "nake/dsl"
|
4
|
+
|
5
|
+
argument("-H", "--help") do
|
6
|
+
Kernel.abort "Use #{$0} -T for list of all available tasks or -i for interactive session"
|
7
|
+
end
|
8
|
+
|
9
|
+
argument("-T", "--tasks") do |pattern = nil|
|
10
|
+
tasks, options = Task.tasks.select { |name, task| not task.hidden? }.sort.partition { |key, value| not key.match(/^-/) }
|
11
|
+
arguments = Nake.args.sort
|
12
|
+
|
13
|
+
puts "\n#{"===".yellow} #{"Available tasks".magenta} #{"===".yellow}"
|
14
|
+
if tasks.empty?
|
15
|
+
puts "No tasks defined"
|
16
|
+
else
|
17
|
+
tasks.each do |name, task|
|
18
|
+
puts "#{name.green} #{task.dependencies.join(", ")} # #{task.description || "no description yet"}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
puts "\n#{"===".yellow} #{"Available arguments".magenta} #{"===".yellow}"
|
23
|
+
if arguments.empty?
|
24
|
+
puts "No arguments defined"
|
25
|
+
else
|
26
|
+
arguments.each do |names, proc|
|
27
|
+
puts "#{names.join(" or ").green}" # TODO: description
|
28
|
+
end
|
29
|
+
end
|
30
|
+
exit
|
31
|
+
end
|
32
|
+
|
33
|
+
argument("-i", "--interactive") do |task = nil|
|
34
|
+
ARGV.clear # otherwise IRB will parse it
|
35
|
+
|
36
|
+
require "irb"
|
37
|
+
begin
|
38
|
+
require "irb/readline"
|
39
|
+
rescue LoadError
|
40
|
+
warn "Code completion via readline isn't available"
|
41
|
+
end
|
42
|
+
|
43
|
+
if task
|
44
|
+
Task[task].tap { |task| task.call(*args, options) }
|
45
|
+
end
|
46
|
+
|
47
|
+
IRB.start
|
48
|
+
exit!
|
49
|
+
end
|
50
|
+
|
51
|
+
Nake.args["--verbose", "--no-verbose"] = lambda { |key, value| Nake.verbose = value }
|
52
|
+
Nake.args["--debug", "--no-debug"] = lambda { |key, value| Nake.debug = value }
|
data/lib/nake/argv.rb
CHANGED
@@ -1,29 +1,47 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module Nake
|
4
|
-
module
|
5
|
-
def extract!
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
options[
|
10
|
-
|
11
|
-
when /^--([^=]+)$/ # --git-repository
|
12
|
-
options[$1.gsub("-", "_").to_sym] = true
|
13
|
-
self.delete(argument)
|
14
|
-
when /^--([^=]+)=([^,]+)$/ # --controller=post
|
15
|
-
key, value = $1, $2
|
16
|
-
options[key.gsub("-", "_").to_sym] = value.dup
|
17
|
-
self.delete(argument)
|
18
|
-
when /^--([^=]+)=(.+)$/ # --controllers=posts,comments
|
19
|
-
key, value = $1, $2
|
20
|
-
options[key.gsub("-", "_").to_sym] = value.split(",")
|
21
|
-
self.delete(argument)
|
22
|
-
else
|
23
|
-
# just extract options and ignore others
|
4
|
+
module ArgvParser
|
5
|
+
def self.extract!(args)
|
6
|
+
args.dup.inject(Hash.new) do |options, argument|
|
7
|
+
key, value = self.parse(argument)
|
8
|
+
if key
|
9
|
+
options[key] = value
|
10
|
+
args.delete(argument)
|
24
11
|
end
|
25
12
|
options
|
26
13
|
end
|
27
14
|
end
|
15
|
+
|
16
|
+
def self.extract(args)
|
17
|
+
args.inject(Hash.new) do |options, argument|
|
18
|
+
key, value = self.parse(argument)
|
19
|
+
if key
|
20
|
+
options[key] = value
|
21
|
+
end
|
22
|
+
options
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.parse!(argument)
|
27
|
+
self.parse(argument) || raise("Argument #{argument} can't be parsed!")
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.parse(argument)
|
31
|
+
case argument
|
32
|
+
when /^--no-([^=]+)$/ # --no-git-repository
|
33
|
+
return [$1.gsub("-", "_").to_sym, false]
|
34
|
+
when /^--([^=]+)$/ # --git-repository
|
35
|
+
return [$1.gsub("-", "_").to_sym, true]
|
36
|
+
when /^--([^=]+)=([^,]+)$/ # --controller=post
|
37
|
+
key, value = $1, $2
|
38
|
+
return [key.gsub("-", "_").to_sym, value.dup]
|
39
|
+
when /^--([^=]+)=(.+)$/ # --controllers=posts,comments
|
40
|
+
key, value = $1, $2
|
41
|
+
return [key.gsub("-", "_").to_sym, value.split(",")]
|
42
|
+
else
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
end
|
28
46
|
end
|
29
47
|
end
|
data/lib/nake/dsl.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require "nake"
|
3
4
|
require "nake/task"
|
5
|
+
require "nake/file_task"
|
4
6
|
|
5
7
|
class Object
|
6
8
|
include Nake
|
9
|
+
def argument(*names, &block)
|
10
|
+
Nake.args[*names] = block
|
11
|
+
end
|
12
|
+
|
7
13
|
# Rake-style task definition
|
8
14
|
# task(:release, :build) do |task|
|
9
15
|
# # task definition
|
@@ -17,4 +23,24 @@ class Object
|
|
17
23
|
end
|
18
24
|
end
|
19
25
|
end
|
26
|
+
|
27
|
+
def file(path, *dependencies, &block)
|
28
|
+
if block.nil?
|
29
|
+
FileTask.new(path, *dependencies)
|
30
|
+
else
|
31
|
+
FileTask.new(path, *dependencies) do |task|
|
32
|
+
task.define(&block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def directory(path)
|
38
|
+
FileTask.new(path) do |task|
|
39
|
+
task.hidden = true # do not show in list
|
40
|
+
task.description = "Create directory #{path}"
|
41
|
+
task.define do
|
42
|
+
mkdir_p path
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
20
46
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "nake/task"
|
4
|
+
|
5
|
+
module Nake
|
6
|
+
class FileTask < Task
|
7
|
+
alias_method :path, :name
|
8
|
+
# FileTask can depend on tasks, other file tasks or just files.
|
9
|
+
# If a file task depends on a task, this task isn't supposed to change anything what ...
|
10
|
+
# ... if it's changing something, make sure the changing task is actually called before the file tasks are executed
|
11
|
+
# If the task is changing something so the file will be generated in all cases, you should rather to use normal task
|
12
|
+
# If there are some dependencies on files
|
13
|
+
# FileTask.new("www/index.html") do |task|
|
14
|
+
# task.file_dependencies.push(*FileList["images/**/*"])
|
15
|
+
# task.dependencies.push("www") # www task exist
|
16
|
+
# end
|
17
|
+
def call(args = Array.new, options = Hash.new)
|
18
|
+
will_run = true
|
19
|
+
unless self.dependencies.empty?
|
20
|
+
info "Invoking file task #{name}"
|
21
|
+
will_run = self.invoke_dependencies(*args, options)
|
22
|
+
end
|
23
|
+
if will_run && ! self.blocks.empty?
|
24
|
+
note "Executing file task #{name} with arguments #{args.inspect} and options #{options.inspect}"
|
25
|
+
debug "Config #{self.config.inspect}"
|
26
|
+
self.blocks.each do |block|
|
27
|
+
block.call(self.path, *args, options)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
warn "File task #{name} won't be executed"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
# task will be executed just if
|
36
|
+
def will_run?
|
37
|
+
file_tasks = self.dependencies.select { |name| self.class[name] }
|
38
|
+
file_tasks.any? do |path|
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def task_will_run?(path)
|
44
|
+
File.exist?(path) || File.mtime(path) < File.mtime(self.name)
|
45
|
+
end
|
46
|
+
|
47
|
+
# return true if the task need to be executed, false otherwise
|
48
|
+
def invoke_dependencies(*args, options)
|
49
|
+
self.dependencies.each do |name|
|
50
|
+
if task = self.class[name] # first try if there is a task with given name
|
51
|
+
task.call(*args, options) # TODO: what about arguments?
|
52
|
+
elsif File.exist?(name) # if not, then fallback to file
|
53
|
+
task_will_run?(name)
|
54
|
+
else
|
55
|
+
raise TaskNotFound, "Task with name #{name} doesn't exist"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/nake/helpers.rb
CHANGED
@@ -1,21 +1,65 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require "fileutils"
|
4
|
+
require "nake/colors"
|
4
5
|
|
5
6
|
module Nake
|
6
7
|
module TaskHelpers
|
7
8
|
include FileUtils
|
8
|
-
|
9
|
+
def run(*parts)
|
10
|
+
puts parts.join(" ").cyan
|
11
|
+
system(*parts)
|
12
|
+
end
|
9
13
|
|
10
14
|
# return true if process suceeded, false otherwise
|
11
15
|
# sh "ls -a"
|
12
16
|
# sh "ls", "-a"
|
13
17
|
def sh(*parts)
|
14
18
|
puts "#{"$".magenta} #{parts.join(" ").cyan}"
|
15
|
-
|
16
|
-
|
19
|
+
system("sh", "-c", *parts)
|
20
|
+
end
|
21
|
+
|
22
|
+
# zsh "ls .*(.)"
|
23
|
+
def zsh(*parts)
|
24
|
+
puts "#{"%".magenta} #{parts.join(" ").cyan}"
|
25
|
+
system("zsh", "-c", *parts)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module PrintHelpers
|
30
|
+
def info(message)
|
31
|
+
puts "~ #{message}".cyan if Nake.verbose
|
32
|
+
end
|
33
|
+
|
34
|
+
def note(message)
|
35
|
+
puts "~ #{message}".green if Nake.verbose
|
36
|
+
end
|
37
|
+
|
38
|
+
def warn(message)
|
39
|
+
Kernel.warn("~ #{message.yellow}") if Nake.debug
|
40
|
+
end
|
41
|
+
|
42
|
+
def debug(message)
|
43
|
+
STDERR.puts("~ #{message.yellow}") if Nake.debug
|
44
|
+
end
|
45
|
+
|
46
|
+
def error(message)
|
47
|
+
STDERR.puts "~ #{message}".red
|
48
|
+
end
|
49
|
+
|
50
|
+
def abort(message)
|
51
|
+
Kernel.abort "[#{"ERROR".red}] #{message}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def print_exception_and_abort(exception)
|
55
|
+
abort exception.message
|
56
|
+
end
|
57
|
+
|
58
|
+
def print_exception_with_backtrace_and_abort(exception)
|
59
|
+
abort [exception.message, exception.backtrace.join("\n- ")].join("\n")
|
17
60
|
end
|
18
61
|
end
|
19
62
|
end
|
20
63
|
|
21
64
|
Object.send(:include, Nake::TaskHelpers)
|
65
|
+
Object.send(:include, Nake::PrintHelpers)
|
data/lib/nake/task.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require "nake/colors"
|
4
|
+
require "nake/argv"
|
4
5
|
|
5
6
|
module Nake
|
7
|
+
TaskNotFound ||= Class.new(StandardError)
|
8
|
+
ConfigurationError ||= Class.new(StandardError)
|
9
|
+
|
6
10
|
class Task
|
7
11
|
def self.[](name)
|
8
12
|
name = name.to_s
|
@@ -30,7 +34,7 @@ module Nake
|
|
30
34
|
task && task.setup(*dependencies, &block) || super(name, *dependencies, &block)
|
31
35
|
end
|
32
36
|
|
33
|
-
attr_accessor :name, :description, :dependencies, :hidden
|
37
|
+
attr_accessor :name, :description, :dependencies, :hidden, :original_args
|
34
38
|
attr_reader :blocks, :aliases
|
35
39
|
def initialize(name, *dependencies, &block)
|
36
40
|
@aliases, @hidden = Array.new, false
|
@@ -48,8 +52,14 @@ module Nake
|
|
48
52
|
end
|
49
53
|
|
50
54
|
def config
|
51
|
-
@config ||=
|
52
|
-
|
55
|
+
@config ||= begin
|
56
|
+
Hash.new do |hash, key|
|
57
|
+
raise ConfigurationError, "Configuration key #{key} in task #{name} doesn't exist"
|
58
|
+
end.tap do |hash|
|
59
|
+
hash.define_singleton_method(:declare) do |*keys|
|
60
|
+
keys.each { |key| self[key] = nil }
|
61
|
+
end
|
62
|
+
end
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
@@ -67,18 +77,33 @@ module Nake
|
|
67
77
|
@hidden
|
68
78
|
end
|
69
79
|
|
80
|
+
def run(args)
|
81
|
+
self.original_args = args
|
82
|
+
options = ArgvParser.extract!(args)
|
83
|
+
self.call(args, options)
|
84
|
+
end
|
85
|
+
|
70
86
|
# NOTE: the reason why we don't have splat for args is that when we have Task["-T"]
|
71
87
|
# which doesn't have any args and options, we wall just call it without any arguments,
|
72
88
|
# but when we use splat, then we will have to call it at least with Hash.new for options
|
73
89
|
def call(args = Array.new, options = Hash.new)
|
74
90
|
unless self.dependencies.empty?
|
75
|
-
|
91
|
+
info "Invoking task #{name}"
|
76
92
|
self.invoke_dependencies(*args, options)
|
77
93
|
end
|
78
94
|
unless self.blocks.empty?
|
79
|
-
|
95
|
+
note "Executing task #{name} with arguments #{args.inspect} and options #{options.inspect}"
|
96
|
+
debug "Config #{self.config.inspect}"
|
80
97
|
self.blocks.each do |block|
|
81
|
-
|
98
|
+
# we can't use arity, because it returns 0 for lambda { |options = Hash.new| }.arity
|
99
|
+
# if we define method with one optional argument, it will returns -1
|
100
|
+
|
101
|
+
if RUBY_VERSION >= "1.9.2"
|
102
|
+
raise ArgumentError, "Task can't take block arguments" if args.length + 1 > block.parameters.select { |type, name| type.eql?(:req) || type.eql?(:opt) }.length
|
103
|
+
raise ArgumentError, "Task can't take block arguments" if block.parameters.any? { |type, name| type.eql?(:block) }
|
104
|
+
end
|
105
|
+
|
106
|
+
if RUBY_VERSION >= "1.9.2" && block.parameters.empty?
|
82
107
|
block.call
|
83
108
|
else
|
84
109
|
block.call(*args, options)
|
@@ -87,6 +112,12 @@ module Nake
|
|
87
112
|
end
|
88
113
|
end
|
89
114
|
|
115
|
+
def reset!
|
116
|
+
self.dependencies.clear
|
117
|
+
self.blocks.clear
|
118
|
+
self.aliases.clear
|
119
|
+
end
|
120
|
+
|
90
121
|
protected
|
91
122
|
def invoke_dependencies(*args, options)
|
92
123
|
self.dependencies.each do |name|
|
data/lib/nake/tasks/bundle.rb
CHANGED
@@ -1,9 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require "nake/task"
|
4
|
+
|
3
5
|
# NOTE: if you have bundler bundled locally, just
|
4
6
|
# add bundler/lib into $: and this task will work
|
5
|
-
Task.new(:bundle) do |task|
|
7
|
+
Nake::Task.new(:bundle) do |task|
|
6
8
|
task.description = "Install your gems locally from gems/cache via bundler"
|
9
|
+
|
10
|
+
# define bundler method, so we can test it
|
11
|
+
task.define_singleton_method(:bundler) do
|
12
|
+
@bundler ||= Gem::Commands::BundleCommand.new
|
13
|
+
end
|
14
|
+
|
15
|
+
# task definition
|
7
16
|
task.define do |*args, options|
|
8
17
|
require 'rubygems'
|
9
18
|
require 'rubygems/command'
|
@@ -15,7 +24,7 @@ Task.new(:bundle) do |task|
|
|
15
24
|
abort "You have to have bundler installed!"
|
16
25
|
end
|
17
26
|
|
18
|
-
args.push("--cached")
|
19
|
-
|
27
|
+
args.push("--cached") unless options.delete[:cached]
|
28
|
+
self.bundler.invoke(*task.original_args)
|
20
29
|
end
|
21
30
|
end
|
data/lib/nake/tasks/gem.rb
CHANGED
@@ -6,6 +6,12 @@ require "nake/tasks/clean"
|
|
6
6
|
# register gem files for cleaning
|
7
7
|
Task[:clean].config[:files].push(*Dir["*.gem"])
|
8
8
|
|
9
|
+
module Nake::PackageMixin
|
10
|
+
def gem_name
|
11
|
+
"#{Task[:release].config[:name]}-#{Task[:release].config[:version]}.gem"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
9
15
|
# require "nake/tasks/gem"
|
10
16
|
# Task[:build].config[:gemspec] = Dir["*.gemspec"]
|
11
17
|
Task.new(:build) do |task|
|
@@ -13,3 +19,11 @@ Task.new(:build) do |task|
|
|
13
19
|
sh "gem build #{task.config[:gemspec]}"
|
14
20
|
end
|
15
21
|
end
|
22
|
+
|
23
|
+
Task.new(:install, :build) do |task|
|
24
|
+
task.extend(PackageMixin)
|
25
|
+
task.description = "Install"
|
26
|
+
task.define do
|
27
|
+
sh "gem install #{self.gem_name}"
|
28
|
+
end
|
29
|
+
end
|
data/lib/nake/tasks/release.rb
CHANGED
@@ -35,9 +35,9 @@ end
|
|
35
35
|
Task.new("release:gemcutter") do |task|
|
36
36
|
task.description = "Push gem to Gemcutter"
|
37
37
|
task.dependencies = [:clean, :build]
|
38
|
+
task.extend(PackageMixin)
|
38
39
|
task.define do
|
39
|
-
task.config[:gem] = "#{Task[:release].config[:name]}-#{Task[:release].config[:version]}.gem"
|
40
40
|
puts "Pushing to Gemcutter ..."
|
41
|
-
sh "gem push #{
|
41
|
+
sh "gem push #{self.gem_name}"
|
42
42
|
end
|
43
43
|
end
|
data/lib/nake/tasks/rip.rb
CHANGED
@@ -1,25 +1,33 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
commits = Hash.new
|
8
|
-
commits = dependencies.inject(Hash.new) do |hash, path|
|
9
|
-
Dir.chdir(path) do
|
10
|
-
revision = %x(git show | head -1).chomp.sub("commit ", "")
|
11
|
-
hash[File.basename(path)] = revision
|
12
|
-
hash
|
13
|
-
end
|
14
|
-
end
|
15
|
-
template = File.read("deps.rip.rbe")
|
16
|
-
deps_rip = eval("%Q{#{template}}")
|
17
|
-
File.open("deps.rip", "w") do |file|
|
18
|
-
file.puts(deps_rip)
|
19
|
-
end
|
20
|
-
sh "chmod +x deps.rip"
|
21
|
-
sh "git commit deps.rip -m 'Updated deps.rip'"
|
3
|
+
begin
|
4
|
+
require "recho"
|
5
|
+
rescue LoadError
|
6
|
+
raise LoadError, "This task require recho gem!"
|
22
7
|
end
|
23
8
|
|
9
|
+
require "nake/file_task"
|
10
|
+
|
11
|
+
# FileTask["deps.rip"].config[:versions] = {rack: "1.0.1", media_path: "SHA1"}
|
12
|
+
|
24
13
|
# register task
|
25
|
-
Task[:release].dependencies.unshift("deps.rip")
|
14
|
+
#Task[:release].dependencies.unshift("deps.rip")
|
15
|
+
|
16
|
+
# deps.rip.str:
|
17
|
+
##!/usr/bin/env rip install
|
18
|
+
#
|
19
|
+
## Syntax:
|
20
|
+
## repository [tag or commit to install]
|
21
|
+
#git://github.com/botanicus/media-path.git %{media_path}
|
22
|
+
#git://github.com/rack/rack.git %{rack}
|
23
|
+
|
24
|
+
FileTask.new("deps.rip", "deps.rip.str") do |task|
|
25
|
+
task.config[:versions] = Hash.new
|
26
|
+
task.description = "Regenerate deps.rip"
|
27
|
+
task.define do
|
28
|
+
data = File.read("deps.rip.str")
|
29
|
+
dependencies = "%Q{#{data}}" % task.config[:versions]
|
30
|
+
FileUtils.echo("deps.str") > dependencies
|
31
|
+
sh "chmod +x deps.rip"
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative "../../spec_helper"
|
4
|
+
require "nake/tasks/bundle"
|
5
|
+
|
6
|
+
describe "Task bundle" do
|
7
|
+
before(:each) do
|
8
|
+
@task = Nake::Task[:bundle]
|
9
|
+
@bundler = Object.new.define_singleton_method(:invoke) { |*args| args }
|
10
|
+
@task.define_singleton_method(:bundler) { @bundler }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should invoke bundler with --cached by default" do
|
14
|
+
@task.call.should include("--cached")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should invoke bundler without --cached if --no-cached argument is provided" do
|
18
|
+
@task.call(cached: false).should_not include("--cached")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not pass --no-cached argument to bundler" do
|
22
|
+
@task.call(cached: false).should_not include("--no-cached")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should pass all other arguments to bundler" do
|
26
|
+
@task.call("--only", "development").should eql(["--only", "development"])
|
27
|
+
end
|
28
|
+
end
|
data/tasks.rb
CHANGED
@@ -5,7 +5,18 @@ require "nake/tasks/gem"
|
|
5
5
|
require "nake/tasks/spec"
|
6
6
|
require "nake/tasks/release"
|
7
7
|
|
8
|
+
begin
|
9
|
+
load "code-cleaner.nake"
|
10
|
+
rescue LoadError
|
11
|
+
warn "If you want to contribute to nake, you have to install code-cleaner gem and then run ./tasks.rb hooks:whitespace:install to get Git pre-commit hook for removing trailing whitespace and improving code quality in general."
|
12
|
+
end
|
13
|
+
|
8
14
|
Task[:build].config[:gemspec] = "nake.gemspec"
|
9
15
|
Task[:prerelease].config[:gemspec] = "nake.pre.gemspec"
|
10
16
|
Task[:release].config[:name] = "nake"
|
11
17
|
Task[:release].config[:version] = Nake::VERSION
|
18
|
+
|
19
|
+
Nake::Task["hooks:whitespace:install"].tap do |task|
|
20
|
+
task.config[:encoding] = "utf-8"
|
21
|
+
task.config[:whitelist] = '(bin/[^/]+|.+\.(rb|rake|nake|thor|task))$'
|
22
|
+
end
|
data/tmp/restart.txt
ADDED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nake
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jakub \xC5\xA0\xC5\xA5astn\xC3\xBD aka Botanicus"
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain:
|
11
|
-
date: 2009-12-
|
11
|
+
date: 2009-12-29 00:00:00 +01:00
|
12
12
|
default_executable: nake
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
@@ -33,19 +33,24 @@ files:
|
|
33
33
|
- bin/nake
|
34
34
|
- CHANGELOG
|
35
35
|
- examples/args.rb
|
36
|
+
- examples/arguments.rb
|
36
37
|
- examples/basic.rb
|
37
38
|
- examples/complex.rb
|
38
39
|
- examples/configuration.rb
|
39
40
|
- examples/default.rb
|
40
41
|
- examples/default_proc.rb
|
41
42
|
- examples/dependencies.rb
|
43
|
+
- examples/file.rb
|
44
|
+
- examples/flags.rb
|
42
45
|
- examples/helpers.rb
|
43
46
|
- examples/invoking.rb
|
44
47
|
- examples/options.rb
|
45
48
|
- examples/script.rb
|
49
|
+
- lib/nake/args.rb
|
46
50
|
- lib/nake/argv.rb
|
47
51
|
- lib/nake/colors.rb
|
48
52
|
- lib/nake/dsl.rb
|
53
|
+
- lib/nake/file_task.rb
|
49
54
|
- lib/nake/helpers.rb
|
50
55
|
- lib/nake/task.rb
|
51
56
|
- lib/nake/tasks/bundle.rb
|
@@ -54,7 +59,6 @@ files:
|
|
54
59
|
- lib/nake/tasks/release.rb
|
55
60
|
- lib/nake/tasks/rip.rb
|
56
61
|
- lib/nake/tasks/spec.rb
|
57
|
-
- lib/nake/tasks.rb
|
58
62
|
- lib/nake.rb
|
59
63
|
- LICENSE
|
60
64
|
- nake.gemspec
|
@@ -64,13 +68,16 @@ files:
|
|
64
68
|
- spec/nake/argv_spec.rb
|
65
69
|
- spec/nake/colors_spec.rb
|
66
70
|
- spec/nake/dsl_spec.rb
|
71
|
+
- spec/nake/file_task_spec.rb
|
67
72
|
- spec/nake/helpers_spec.rb
|
68
73
|
- spec/nake/task_spec.rb
|
74
|
+
- spec/nake/tasks/bundle_spec.rb
|
69
75
|
- spec/nake/tasks_spec.rb
|
70
76
|
- spec/nake_spec.rb
|
71
77
|
- spec/spec.opts
|
72
78
|
- spec/spec_helper.rb
|
73
79
|
- tasks.rb
|
80
|
+
- tmp/restart.txt
|
74
81
|
- TODO.txt
|
75
82
|
has_rdoc: true
|
76
83
|
homepage: http://github.com/botanicus/nake
|
data/lib/nake/tasks.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require "nake/dsl"
|
4
|
-
|
5
|
-
task(["-H", "--help"]) do
|
6
|
-
abort "\nUse #{$0} -T for list of all available tasks or -i for interactive session"
|
7
|
-
end
|
8
|
-
|
9
|
-
task(["-T", "--tasks"]) do |pattern, options = Hash.new|
|
10
|
-
tasks, options = Task.tasks.select { |name, task| not task.hidden? }.sort.partition { |key, value| not key.match(/^-/) }
|
11
|
-
|
12
|
-
puts "\n#{"===".yellow} #{"Available tasks".magenta} #{"===".yellow}"
|
13
|
-
if tasks.empty?
|
14
|
-
puts "No tasks defined"
|
15
|
-
else
|
16
|
-
tasks.each do |name, task|
|
17
|
-
puts "#{name.green} #{task.dependencies.join(", ")} # #{task.description || "no description yet"}"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
puts "\n#{"===".yellow} #{"Available options".magenta} #{"===".yellow}"
|
22
|
-
if options.empty?
|
23
|
-
puts "No options defined"
|
24
|
-
else
|
25
|
-
options.each do |name, task|
|
26
|
-
puts "#{name.green} #{task.dependencies.join(", ")} # #{task.description || "no description yet"}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# TODO: this doesn't work so far
|
32
|
-
task(["-i", "--interactive"]) do |*args, options|
|
33
|
-
require "irb"
|
34
|
-
begin
|
35
|
-
require "irb/readline"
|
36
|
-
rescue LoadError
|
37
|
-
warn "Code completion via readline isn't available"
|
38
|
-
end
|
39
|
-
|
40
|
-
unless args.empty?
|
41
|
-
task = Task[args.shift]
|
42
|
-
task.call(*args, options)
|
43
|
-
end
|
44
|
-
|
45
|
-
IRB.start
|
46
|
-
end
|
47
|
-
|
48
|
-
Task["-T"].hidden = true
|
49
|
-
Task["-H"].hidden = true
|