rulebow 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: