fire 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.index +53 -0
- data/.yardopts +10 -0
- data/HISTORY.md +33 -0
- data/LICENSE.txt +29 -0
- data/README.md +217 -0
- data/bin/autofire +5 -0
- data/bin/fire +5 -0
- data/demo/03_runner/01_applying_rules.md +51 -0
- data/demo/03_runner/02_resolve_prerequisites.md +95 -0
- data/demo/applique/ae.rb +1 -0
- data/demo/applique/fire.rb +1 -0
- data/demo/applique/rules.rb +5 -0
- data/demo/overview.md +14 -0
- data/lib/fire.rb +3 -0
- data/lib/fire.yml +53 -0
- data/lib/fire/cli.rb +64 -0
- data/lib/fire/core_ext.rb +4 -0
- data/lib/fire/core_ext/boolean.rb +10 -0
- data/lib/fire/core_ext/cli.rb +56 -0
- data/lib/fire/core_ext/true_class.rb +58 -0
- data/lib/fire/digest.rb +112 -0
- data/lib/fire/dsl.rb +34 -0
- data/lib/fire/match.rb +26 -0
- data/lib/fire/rule.rb +103 -0
- data/lib/fire/rulefile.rb +12 -0
- data/lib/fire/runner.rb +76 -0
- data/lib/fire/session.rb +268 -0
- data/lib/fire/shellutils.rb +77 -0
- data/lib/fire/state.rb +91 -0
- data/lib/fire/system.rb +244 -0
- data/lib/fire/task.rb +71 -0
- data/man/fire.1 +47 -0
- data/man/fire.1.html +130 -0
- data/man/fire.1.ronn +52 -0
- metadata +135 -0
data/demo/applique/ae.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ae'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'fire'
|
data/demo/overview.md
ADDED
data/lib/fire.rb
ADDED
data/lib/fire.yml
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
---
|
2
|
+
revision: 2013
|
3
|
+
type: ruby
|
4
|
+
sources:
|
5
|
+
- var
|
6
|
+
authors:
|
7
|
+
- name: Trans
|
8
|
+
email: transfire@gmail.com
|
9
|
+
organizations:
|
10
|
+
- name: Rubyworks
|
11
|
+
requirements:
|
12
|
+
- name: notify
|
13
|
+
- groups:
|
14
|
+
- build
|
15
|
+
development: true
|
16
|
+
name: detroit
|
17
|
+
- groups:
|
18
|
+
- build
|
19
|
+
development: true
|
20
|
+
name: mast
|
21
|
+
conflicts: []
|
22
|
+
alternatives: []
|
23
|
+
resources:
|
24
|
+
- type: home
|
25
|
+
uri: http://rubyworks.github.com/fire
|
26
|
+
label: Homepage
|
27
|
+
- type: code
|
28
|
+
uri: http://github.com/rubyworks/fire
|
29
|
+
label: Source Code
|
30
|
+
- type: bugs
|
31
|
+
uri: http://github.com/rubyworks/fire/issues
|
32
|
+
label: Issue Tracker
|
33
|
+
repositories:
|
34
|
+
- name: upstream
|
35
|
+
scm: git
|
36
|
+
uri: git://github.com/rubyworks/fire.git
|
37
|
+
categories: []
|
38
|
+
copyrights:
|
39
|
+
- holder: Rubyworks
|
40
|
+
year: '2010'
|
41
|
+
license: BSD-2-Clause
|
42
|
+
customs: []
|
43
|
+
paths:
|
44
|
+
lib:
|
45
|
+
- lib
|
46
|
+
created: '2010-07-05'
|
47
|
+
summary: The best build tool, logically!
|
48
|
+
title: Fire
|
49
|
+
version: 0.2.0
|
50
|
+
name: fire
|
51
|
+
description: ! "Fire is a continuous integration build tool with a slick set logic
|
52
|
+
\nstate/rules system."
|
53
|
+
date: '2013-02-12'
|
data/lib/fire/cli.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'fire/core_ext'
|
2
|
+
require 'fire/session'
|
3
|
+
|
4
|
+
module Fire
|
5
|
+
|
6
|
+
# Fire's command line interface.
|
7
|
+
#
|
8
|
+
class CLI
|
9
|
+
|
10
|
+
# Fire her up!
|
11
|
+
def self.run(argv=ARGV)
|
12
|
+
new(argv).run
|
13
|
+
end
|
14
|
+
|
15
|
+
# Fire her up in autorun mode!
|
16
|
+
def self.autorun(argv=ARGV)
|
17
|
+
new(argv).autorun
|
18
|
+
end
|
19
|
+
|
20
|
+
# Initialize new instance of Fire::CLI.
|
21
|
+
def initialize(argv=ARGV)
|
22
|
+
@argv = argv
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns session instance. [Session]
|
26
|
+
def session
|
27
|
+
@session ||= Session.new(:watch=>@watch)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Fire her up!
|
31
|
+
def run
|
32
|
+
args = cli_parse
|
33
|
+
session.run(args)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Fire her up in autorun mode!
|
37
|
+
def autorun
|
38
|
+
args = cli_parse
|
39
|
+
session.autorun(args)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Parse command line arguments with just the prettiest
|
43
|
+
# little CLI parser there ever was.
|
44
|
+
def cli_parse
|
45
|
+
cli @argv,
|
46
|
+
"-T" => method(:list_tasks),
|
47
|
+
"-w" => method(:watch)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Print out a list of availabe manual triggers.
|
51
|
+
def list_tasks
|
52
|
+
puts "(#{session.root})"
|
53
|
+
puts session.task_sheet
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
|
57
|
+
# Set the watch wait period.
|
58
|
+
def watch(seconds)
|
59
|
+
@watch = seconds
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Kernel
|
2
|
+
private
|
3
|
+
#
|
4
|
+
# CLI is based on Clap library
|
5
|
+
# Copyright (c) 2010 Michel Martens
|
6
|
+
#
|
7
|
+
def cli(*args)
|
8
|
+
opts = (Hash === args.last ? args.pop : nil)
|
9
|
+
argv = args.first || ARGV.dup
|
10
|
+
args = []
|
11
|
+
|
12
|
+
#raise ArgumentError unless opts
|
13
|
+
|
14
|
+
# Split option aliases.
|
15
|
+
opts = opts.inject({}) do |h,(k,v)|
|
16
|
+
k.to_s.split(/\s+/).each{|o| h[o]=v}; h
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convert single dash flags into multiple flags.
|
20
|
+
argv = argv.inject([]) do |a, v|
|
21
|
+
if v[0,1] == '-' && v[1,1] != '-'
|
22
|
+
a.concat(v[1..-1].chars.map{|c| "-#{c}"})
|
23
|
+
else
|
24
|
+
a << v
|
25
|
+
end
|
26
|
+
a
|
27
|
+
end
|
28
|
+
|
29
|
+
while argv.any?
|
30
|
+
item = argv.shift
|
31
|
+
flag = opts[item]
|
32
|
+
|
33
|
+
if flag
|
34
|
+
# Work around lambda semantics in 1.8.7.
|
35
|
+
arity = [flag.arity, 0].max
|
36
|
+
|
37
|
+
# Raise if there are not enough parameters
|
38
|
+
# available for the flag.
|
39
|
+
if argv.size < arity
|
40
|
+
raise ArgumentError
|
41
|
+
end
|
42
|
+
|
43
|
+
# Call the lambda with N items from argv,
|
44
|
+
# where N is the lambda's arity.
|
45
|
+
flag.call(*argv.shift(arity))
|
46
|
+
else
|
47
|
+
|
48
|
+
# Collect the items that don't correspond to
|
49
|
+
# flags.
|
50
|
+
args << item
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
args
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# We are going to try doing it this way. If i proves a problem
|
2
|
+
# we'll make a special class.
|
3
|
+
#
|
4
|
+
class TrueClass
|
5
|
+
def empty?
|
6
|
+
false
|
7
|
+
end
|
8
|
+
|
9
|
+
def &(other)
|
10
|
+
other
|
11
|
+
end
|
12
|
+
|
13
|
+
def |(other)
|
14
|
+
other
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
=begin
|
19
|
+
class TrueArray < Array
|
20
|
+
|
21
|
+
def each; end
|
22
|
+
|
23
|
+
def size
|
24
|
+
1 # ?
|
25
|
+
end
|
26
|
+
|
27
|
+
def empty?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def &(other)
|
32
|
+
other.dup
|
33
|
+
end
|
34
|
+
|
35
|
+
def |(other)
|
36
|
+
other.dup
|
37
|
+
end
|
38
|
+
|
39
|
+
## If this would have worked we would not have had
|
40
|
+
## to override Array.
|
41
|
+
#def coerce(other)
|
42
|
+
# return self, other
|
43
|
+
#end
|
44
|
+
end
|
45
|
+
=end
|
46
|
+
|
47
|
+
class Array
|
48
|
+
alias and_without_t :&
|
49
|
+
alias or_without_t :|
|
50
|
+
|
51
|
+
def |(other)
|
52
|
+
TrueClass === other ? dup : or_without_t(other)
|
53
|
+
end
|
54
|
+
|
55
|
+
def &(other)
|
56
|
+
TrueClass === other ? dup : and_without_t(other)
|
57
|
+
end
|
58
|
+
end
|
data/lib/fire/digest.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Fire
|
5
|
+
|
6
|
+
#
|
7
|
+
#
|
8
|
+
class Digest
|
9
|
+
|
10
|
+
#
|
11
|
+
DEFAULT_FILE = ".fire/digest"
|
12
|
+
|
13
|
+
#
|
14
|
+
attr :file
|
15
|
+
|
16
|
+
#
|
17
|
+
attr :current
|
18
|
+
|
19
|
+
#
|
20
|
+
attr :saved
|
21
|
+
|
22
|
+
#
|
23
|
+
attr :ignore
|
24
|
+
|
25
|
+
#
|
26
|
+
def initialize(options={})
|
27
|
+
@file = options[:file] || DEFAULT_FILE
|
28
|
+
@ignore = options[:ignore] || []
|
29
|
+
|
30
|
+
@current = {}
|
31
|
+
@saved = {}
|
32
|
+
|
33
|
+
read
|
34
|
+
refresh
|
35
|
+
end
|
36
|
+
|
37
|
+
# Load saved digest.
|
38
|
+
def read
|
39
|
+
return unless File.exist?(file)
|
40
|
+
File.read(file).lines.each do |line|
|
41
|
+
if md = /^(\w+)\s+(.*?)$/.match(line)
|
42
|
+
@saved[md[2]] = md[1]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
=begin
|
48
|
+
# Gather current digest for all files.
|
49
|
+
#
|
50
|
+
# Returns nothing.
|
51
|
+
def refresh
|
52
|
+
Dir['**/*'].each do |path|
|
53
|
+
if File.directory?(path)
|
54
|
+
# how to handle directories as a whole?
|
55
|
+
elsif File.exist?(path)
|
56
|
+
id = checksum(path)
|
57
|
+
@current[path] = id
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
=end
|
62
|
+
|
63
|
+
# Gather current digest for all files.
|
64
|
+
#
|
65
|
+
# Returns nothing.
|
66
|
+
def refresh
|
67
|
+
list = Dir['**/*']
|
68
|
+
list = list.reject{ |path| ignore.any?{ |ig| /^#{ig}/ =~ path } }
|
69
|
+
list.each do |path|
|
70
|
+
if File.directory?(path)
|
71
|
+
# how to handle directories as a whole?
|
72
|
+
elsif File.exist?(path)
|
73
|
+
id = checksum(path)
|
74
|
+
@current[path] = id
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Save current digest.
|
80
|
+
def save
|
81
|
+
dir = File.dirname(file)
|
82
|
+
FileUtils.mkdir(dir) unless File.directory?(dir)
|
83
|
+
File.open(file, 'w'){ |f| f << to_s }
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns [String] digest file format.
|
87
|
+
def to_s
|
88
|
+
s = ""
|
89
|
+
current.each do |path, id|
|
90
|
+
s << "#{id} #{path}\n"
|
91
|
+
end
|
92
|
+
s
|
93
|
+
end
|
94
|
+
|
95
|
+
# Compute the sha1 identifer for a file.
|
96
|
+
#
|
97
|
+
# file - path to a file
|
98
|
+
#
|
99
|
+
# Returns [String] SHA1 digest string.
|
100
|
+
def checksum(file)
|
101
|
+
sha = ::Digest::SHA1.new
|
102
|
+
File.open(file, 'r') do |fh|
|
103
|
+
fh.each_line do |l|
|
104
|
+
sha << l
|
105
|
+
end
|
106
|
+
end
|
107
|
+
sha.hexdigest
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
data/lib/fire/dsl.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Fire
|
2
|
+
|
3
|
+
p "HERE!!!!!!!"
|
4
|
+
|
5
|
+
#
|
6
|
+
module DSL
|
7
|
+
|
8
|
+
def state(name, &condition)
|
9
|
+
Fire.system.state(name, &condition)
|
10
|
+
end
|
11
|
+
|
12
|
+
def rule(logic, &procedure)
|
13
|
+
Fire.system.rule(logic, &procedure)
|
14
|
+
end
|
15
|
+
|
16
|
+
#def file(pattern, &procedure)
|
17
|
+
# Fire.system.file(pattern, &procedure)
|
18
|
+
#end
|
19
|
+
|
20
|
+
def trip(state)
|
21
|
+
Fire.system.trip(state)
|
22
|
+
end
|
23
|
+
|
24
|
+
def desc(description)
|
25
|
+
Fire.system.desc(description)
|
26
|
+
end
|
27
|
+
|
28
|
+
def task(name_and_logic, &procedure)
|
29
|
+
Fire.system.task(name_and_logic, &procedure)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/fire/match.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Fire
|
2
|
+
|
3
|
+
# Match is a subclass of a string that also stores the
|
4
|
+
# MatchData then matched against it in a Regexp comparison.
|
5
|
+
#
|
6
|
+
class Match < String
|
7
|
+
# Initialize a new instance of Match.
|
8
|
+
#
|
9
|
+
# string - The string. [String]
|
10
|
+
# matchdata - The match data. [MatchData]
|
11
|
+
#
|
12
|
+
def intialize(string, matchdata)
|
13
|
+
replace(string)
|
14
|
+
@matchdata = matchdata
|
15
|
+
end
|
16
|
+
|
17
|
+
# The match data that resulted from
|
18
|
+
# a successful Regexp against the string.
|
19
|
+
#
|
20
|
+
# Returns [MatchData]
|
21
|
+
def matchdata
|
22
|
+
@matchdata
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|