rulebow 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,153 @@
1
+ module Rulebow
2
+
3
+ # Master system instance.
4
+ #
5
+ # Returns [System]
6
+ #def self.system
7
+ # @system ||= System.new
8
+ #end
9
+
10
+ ##
11
+ #
12
+ class System < Module
13
+
14
+ RULEBOOK_GLOB = "{,.,_}{R,r}ulebook{,.rb}"
15
+
16
+ # Initialize new System instance.
17
+ #
18
+ def initialize(options={})
19
+ extend self
20
+ extend ShellUtils
21
+
22
+ @root = options[:root] || Dir.pwd
23
+ @ignore = options[:ignore] || [] #Ignore.new
24
+
25
+ @rulebook = options[:rulebook]
26
+ @state_file = options[:statefile]
27
+
28
+ @session = OpenStruct.new
29
+
30
+ @scripts = []
31
+ @rules = []
32
+ #@facts = []
33
+
34
+ @digests = {}
35
+ @rulesets = {}
36
+
37
+ import(*rulebook)
38
+ end
39
+
40
+ # Project's root directory. [String]
41
+ attr :root
42
+
43
+ # Session variables. [Hash]
44
+ attr :session
45
+
46
+ # Digests [Hash]
47
+ attr :digests
48
+
49
+ # Rulesets indexed by name. [Hash]
50
+ attr :rulesets
51
+
52
+ # Rulebook file.
53
+ def rulebook
54
+ @rulebook ||= Dir[File.join(root, RULEBOOK_GLOB)].first
55
+ end
56
+
57
+ # State file.
58
+ def state_file
59
+ @state_file ||= rulebook.chomp('.rb') + '.state'
60
+ end
61
+
62
+ #
63
+ #def default(*rulesets)
64
+ # ruleset :default => rulesets
65
+ #end
66
+
67
+ # Rulesets provide a separate space for rules which are only
68
+ # run when the ruleset name is specifically given.
69
+ #
70
+ # Return [Ruleset]
71
+ def ruleset(name_and_chain, &block)
72
+ name, chain = parse_ruleset_name(name_and_chain)
73
+ if @rulesets.key?(name)
74
+ ruleset = @rulesets[name]
75
+ ruleset.update(chain, &block)
76
+ else
77
+ ruleset = Ruleset.new(self, name_and_chain, &block)
78
+ @rulesets[name] = ruleset
79
+ end
80
+ ruleset
81
+ end
82
+
83
+ # Import from another file, or glob of files, relative to project root.
84
+ #
85
+ # TODO: Should importing be relative to the importing file?
86
+ #
87
+ # Returns nothing.
88
+ def import(*globs)
89
+ globs.each do |glob|
90
+ #if File.relative?(glob)
91
+ # dir = Dir.pwd #session.root #File.dirname(caller[0])
92
+ # glob = File.join(dir, glob)
93
+ #end
94
+ Dir[glob].each do |file|
95
+ next unless File.file?(file) # add warning
96
+ next if @scripts.include?(file)
97
+ @scripts << file
98
+ module_eval(File.read(file), file)
99
+ end
100
+ end
101
+ end
102
+
103
+ # Add paths to be ignored in file rules.
104
+ #
105
+ # globs - List of file globs. [Array<String>]
106
+ #
107
+ # Returns [Array<String>]
108
+ def ignore(*globs)
109
+ @ignore.concat(globs) unless globs.empty?
110
+ @ignore
111
+ end
112
+
113
+ # Replace globs in ignore list.
114
+ #
115
+ # globs - List of file globs. [Array<String>]
116
+ #
117
+ # Returns [Array<String>]
118
+ def ignore!(*globs)
119
+ @ignore.replace(globs)
120
+ @ignore
121
+ end
122
+
123
+ #
124
+ def inspect
125
+ "#<Rulebow::System>"
126
+ end
127
+
128
+ # Home directory.
129
+ #
130
+ # Returns [String]
131
+ def home
132
+ @home ||= File.expand_path('~')
133
+ end
134
+
135
+ private
136
+
137
+ # Parse out a ruleset's name from it's ruleset dependencies.
138
+ #
139
+ # Returns [Array]
140
+ def parse_ruleset_name(name)
141
+ if Hash === name
142
+ raise ArgumentError if name.size > 1
143
+ list = [name.values].flatten.map{ |b| b.to_sym }
144
+ name = name.keys.first
145
+ else
146
+ list = []
147
+ end
148
+ return name.to_sym, list
149
+ end
150
+
151
+ end
152
+
153
+ end
@@ -0,0 +1,203 @@
1
+ module Rulebow
2
+
3
+ ##
4
+ # Encapsulates list of file globs to be watched.
5
+ #
6
+ class WatchList
7
+
8
+ #include Enumerable
9
+
10
+ # Initialize new instance of Ignore.
11
+ #
12
+ # Returns nothing.
13
+ def initialize(options={})
14
+ @accept = options[:accept].to_a.flatten
15
+ @ignore = options[:ignore].to_a.flatten
16
+ end
17
+
18
+ # Project's root directory.
19
+ attr :root
20
+
21
+ # Filter a list of files in accordance with the
22
+ # accept and ignore lists.
23
+ #
24
+ def filter(files)
25
+ filter_ignore(filter_accept(files))
26
+ end
27
+
28
+ # Filter a list of files in accordance with the
29
+ # ignore list.
30
+ #
31
+ # files - The list of files. [Array<String>]
32
+ #
33
+ # Returns [Array<String>]
34
+ def filter_accept(files)
35
+ list = []
36
+ files.each do |file|
37
+ hit = @accept.any? do |pattern|
38
+ match?(pattern, file)
39
+ end
40
+ list << file if hit
41
+ end
42
+ list
43
+ end
44
+
45
+ # Filter a list of files in accordance with the
46
+ # ignore list.
47
+ #
48
+ # files - The list of files. [Array<String>]
49
+ #
50
+ # Returns [Array<String>]
51
+ def filter_ignore(files)
52
+ list = []
53
+ files.each do |file|
54
+ hit = @ignore.any? do |pattern|
55
+ match?(pattern, file)
56
+ end
57
+ list << file unless hit
58
+ end
59
+ list
60
+ end
61
+
62
+ #
63
+ #def each
64
+ # to_a.each{ |g| yield g }
65
+ #end
66
+
67
+ #
68
+ #def size
69
+ # to_a.size
70
+ #end
71
+
72
+ #
73
+ #def to_a
74
+ # @list
75
+ #end
76
+
77
+ #
78
+ def accept(*globs)
79
+ @accept.concat(globs.flatten)
80
+ end
81
+
82
+ #
83
+ def accept!(*globs)
84
+ @accept.replace(globs.flatten)
85
+ end
86
+
87
+ #
88
+ def ignore(*globs)
89
+ @ignore.concat(globs.flatten)
90
+ end
91
+
92
+ #
93
+ def ignore!(*globs)
94
+ @ignore.replace(globs.flatten)
95
+ end
96
+
97
+ # Get a current digest.
98
+ #
99
+ # Returns digest. [Hash]
100
+ def digest(root=nil)
101
+ if root
102
+ Dir.chdir(root) do
103
+ read_digest
104
+ end
105
+ else
106
+ read_digest
107
+ end
108
+ end
109
+
110
+ private
111
+
112
+ def read_digest
113
+ dig = {}
114
+ list = filter(Dir.glob('**/*', File::FNM_PATHNAME))
115
+ list.each do |path|
116
+ if File.directory?(path)
117
+ # TODO: how to handle directories as a whole?
118
+ elsif File.exist?(path)
119
+ dig[path] = checksum(path)
120
+ end
121
+ end
122
+ dig
123
+ end
124
+
125
+ # Given a pattern and a file, does the file match the
126
+ # pattern? This code is based on the rules used by
127
+ # git's .gitignore file.
128
+ #
129
+ # TODO: The code is probably not quite right.
130
+ #
131
+ # TODO: Handle regular expressions.
132
+ #
133
+ # Returns [Boolean]
134
+ def match?(pattern, file)
135
+ if Regexp === pattern
136
+ return pattern.match(file) ? true : false
137
+ end
138
+
139
+ if pattern.start_with?('!')
140
+ return !match?(pattern.sub('!','').strip)
141
+ end
142
+
143
+ dir = pattern.end_with?('/')
144
+ pattern = pattern.chomp('/') if dir
145
+
146
+ if pattern.start_with?('/')
147
+ fnmatch?(pattern.sub('/',''), file)
148
+ else
149
+ if dir
150
+ fnmatch?(File.join(pattern, '**', '*'), file) ||
151
+ fnmatch?(pattern, file) && File.directory?(file)
152
+ elsif pattern.include?('/')
153
+ fnmatch?(pattern, file)
154
+ else
155
+ fnmatch?(File.join('**',pattern), file)
156
+ end
157
+ end
158
+ end
159
+
160
+ # Shortcut to `File.fnmatch?` method.
161
+ #
162
+ # Returns [Boolean]
163
+ def fnmatch?(pattern, file, mode=File::FNM_PATHNAME)
164
+ File.fnmatch?(pattern, file, File::FNM_PATHNAME)
165
+ end
166
+
167
+ # Compute the sha1 identifer for a file.
168
+ #
169
+ # file - path to a file
170
+ #
171
+ # Returns [String] SHA1 digest string.
172
+ def checksum(file)
173
+ sha = ::Digest::SHA1.new
174
+ File.open(file, 'r') do |fh|
175
+ fh.each_line do |l|
176
+ sha << l
177
+ end
178
+ end
179
+ sha.hexdigest
180
+ end
181
+
182
+ =begin
183
+ # Load ignore file. Removes blank lines and line starting with `#`.
184
+ #
185
+ # Returns [Array<String>]
186
+ def load_ignore
187
+ f = file
188
+ i = []
189
+ if f && File.exist?(f)
190
+ File.read(f).lines.each do |line|
191
+ glob = line.strip
192
+ next if glob.empty?
193
+ next if glob.start_with?('#')
194
+ i << glob
195
+ end
196
+ end
197
+ i
198
+ end
199
+ =end
200
+
201
+ end
202
+
203
+ end
@@ -0,0 +1,2 @@
1
+ *.html
2
+ *.1
@@ -0,0 +1,50 @@
1
+ ergo(1) -- Ruby rules-based automated build tool
2
+ ===============================================
3
+
4
+ ## SYNOPSIS
5
+
6
+ `ergo`
7
+ `ergo` <bookmark> [<arg>...]<br>
8
+ `ergo` `-R`|`--rules`<br>
9
+ `ergo` `-h`|`--help`<br>
10
+
11
+
12
+ ## DESCRIPTION
13
+
14
+ Ergo is an *autological* build tool, in that it is used to automate
15
+ build procedure via logical rules-based programming. The developer only
16
+ ever needs to run a single command, `ergo`, and the majority of maintenance
17
+ details of a project are handled. Ergo largely replaces the need of more
18
+ traditional task-based build tools, but it does not complete supplant them.
19
+ They reamin a useful complement for one-off manual build procedures.
20
+
21
+
22
+ ## OPTIONS
23
+
24
+ These options act as subcommands:
25
+
26
+ * `-R`, `--rules`:
27
+ Display the described rules defined in the project's ergo script(s).
28
+
29
+ * `-h`, `--help`:
30
+ Display this help message.
31
+
32
+
33
+ ## ISSUES
34
+
35
+ **Ergo** depends on **Ronn** to provide this man-page and command help message.
36
+ Ronn depends on hpricot and rdiscount, extension libraries that are non-trivial
37
+ to install on some systems. A more portable version of this program would be
38
+ welcome.
39
+
40
+
41
+ ## COPYRIGHT
42
+
43
+ Ergo is Copyright (c) 2009 Thomas Sawyer, Rubyworks
44
+
45
+ Ergo is distributed in accordance to the **GPL-3** license.
46
+
47
+
48
+ ## SEE ALSO
49
+
50
+ ronn(1), rake(1)
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rulebow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - trans
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: notify
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: detroit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mast
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: qed
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ae
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Rulebow is an automated build tool with a set-logic based rule system.
84
+ Rulebow is the perfect tool for performing continuous integration during development.
85
+ email:
86
+ - transfire@gmail.com
87
+ executables:
88
+ - bow
89
+ extensions: []
90
+ extra_rdoc_files:
91
+ - LICENSE.txt
92
+ - README.md
93
+ - HISTORY.md
94
+ files:
95
+ - .index
96
+ - .yardopts
97
+ - bin/bow
98
+ - demo/03_runner/01_applying_rules.md
99
+ - demo/applique/ae.rb
100
+ - demo/applique/rulebow.rb
101
+ - demo/overview.md
102
+ - lib/rulebow/cli.rb
103
+ - lib/rulebow/core_ext/boolean.rb
104
+ - lib/rulebow/core_ext/cli.rb
105
+ - lib/rulebow/core_ext/true_class.rb
106
+ - lib/rulebow/core_ext.rb
107
+ - lib/rulebow/digest.rb
108
+ - lib/rulebow/fact.rb
109
+ - lib/rulebow/ignore.rb
110
+ - lib/rulebow/match.rb
111
+ - lib/rulebow/rule.rb
112
+ - lib/rulebow/ruleset.rb
113
+ - lib/rulebow/runner.rb
114
+ - lib/rulebow/shellutils.rb
115
+ - lib/rulebow/system.rb
116
+ - lib/rulebow/watchlist.rb
117
+ - lib/rulebow.rb
118
+ - lib/rulebow.yml
119
+ - man/.gitignore
120
+ - man/ergo.1
121
+ - man/ergo.1.html
122
+ - man/ergo.1.ronn
123
+ - README.md
124
+ - HISTORY.md
125
+ - LICENSE.txt
126
+ homepage: http://rubyworks.github.com/rulebow
127
+ licenses:
128
+ - BSD-2-Clause
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubyforge_project:
146
+ rubygems_version: 2.0.3
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: An autological build tool.
150
+ test_files: []
151
+ has_rdoc: