beaver-build 1.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/beaver.rb +77 -27
- data/lib/command.rb +68 -87
- data/lib/file.rb +115 -0
- data/lib/file_dep.rb +87 -0
- data/lib/file_obj.rb +89 -0
- data/lib/sh.rb +60 -0
- data/lib/util.rb +2 -0
- metadata +23 -9
- data/lib/FileInfo.rb +0 -51
- data/lib/alias.rb +0 -35
- data/lib/file_change.rb +0 -62
- data/lib/file_exists.rb +0 -22
- data/lib/file_matches.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4bb2de97dfff1bc417996a2af8f02142dc621202bbfb9d802d1c3eb10b51c60
|
4
|
+
data.tar.gz: f63c62063efc3b51d105a753f65bd9f6d86df1fb7ae81b0b9a8a1804e4a47650
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ec0602f51e96e4ecd4101ca4116b79811b2b64e5976fd1f22a2c5254b46d9c278a64e711cc0701fd7f50121dd81f3c66c46d9581667106a76901f37469c3cc3
|
7
|
+
data.tar.gz: 9c18afd6a0c36b2fae88d656464b282f517b3401f610e379fea517615fb9e403c26ffed4b6343b65edbe8901944b40a0331bab09de456d3ddd2022ac22bd5c5c
|
data/lib/beaver.rb
CHANGED
@@ -1,38 +1,61 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
|
3
|
-
# Export functions
|
4
|
-
require 'file_change'
|
5
|
-
require 'file_exists'
|
6
|
-
require 'command'
|
7
|
-
require 'alias'
|
8
|
-
|
9
3
|
class Beaver
|
10
|
-
# The location where
|
4
|
+
# The location where beaver stores its info about files, etc
|
11
5
|
attr_accessor :cache_loc
|
12
|
-
|
13
|
-
|
6
|
+
# whether the current terminal supports 256 color support
|
7
|
+
attr_accessor :term_256_color
|
8
|
+
attr_accessor :opts
|
9
|
+
|
10
|
+
# Initialize functon should not be used by build scripts
|
14
11
|
def initialize
|
15
12
|
# Contains all commands
|
16
|
-
#
|
13
|
+
# { CommandName: Symbol => command: Command }
|
17
14
|
@commands = Hash.new
|
18
|
-
#
|
15
|
+
# Name of the main command
|
19
16
|
@mainCommand = nil
|
20
17
|
@cache_loc = "./.beaver"
|
18
|
+
unless Dir.exist? @cache_loc
|
19
|
+
Dir.mkdir @cache_loc
|
20
|
+
end
|
21
|
+
@term_256_color = `echo $TERM`.include? "256color"
|
22
|
+
@opts = []
|
21
23
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
|
25
|
+
def file_cache_file
|
26
|
+
file_loc = File.join(@cache_loc, "files.info")
|
27
|
+
unless File.exist? file_loc
|
28
|
+
FileUtils.touch file_loc
|
27
29
|
end
|
28
|
-
|
29
|
-
@commands[name.to_sym] = func
|
30
|
+
return file_loc
|
30
31
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
|
33
|
+
# Set an option
|
34
|
+
# :e = exit on non-zero exit code of `sh` execution
|
35
|
+
def set(opt)
|
36
|
+
@opts << opt.to_sym
|
37
|
+
end
|
38
|
+
|
39
|
+
# Check if an option is present
|
40
|
+
def has(opt)
|
41
|
+
@opts.include? opt
|
42
|
+
end
|
43
|
+
|
44
|
+
# Remove an option
|
45
|
+
def rm(opt)
|
46
|
+
@opts.delete opt
|
47
|
+
end
|
48
|
+
|
49
|
+
# Append a command to the global beaver object
|
50
|
+
# - cmd: Command
|
51
|
+
def __appendCommand(cmd)
|
52
|
+
if @commands.size == 0
|
53
|
+
@mainCommand = cmd.name
|
54
|
+
end
|
55
|
+
|
56
|
+
@commands[cmd.name] = cmd
|
34
57
|
end
|
35
|
-
|
58
|
+
|
36
59
|
# Call a command
|
37
60
|
def call(cmd)
|
38
61
|
_cmd = @commands[cmd.to_sym]
|
@@ -40,21 +63,48 @@ class Beaver
|
|
40
63
|
puts "No command called #{cmd} found"
|
41
64
|
exit 1
|
42
65
|
end
|
43
|
-
|
66
|
+
|
44
67
|
_cmd.call
|
45
68
|
end
|
46
|
-
|
69
|
+
|
70
|
+
# Run this command when it is called, no matter if its dependencies did not change
|
71
|
+
def must_run cmd
|
72
|
+
cmd = @commands[cmd.to_sym]
|
73
|
+
if cmd.nil?
|
74
|
+
puts "\001b[31mNON-FATAL ERROR\001b[0m: Command #{cmd} does not exist, so `must_run` has not effect"
|
75
|
+
end
|
76
|
+
cmd.overwrite_should_run = true
|
77
|
+
end
|
78
|
+
|
47
79
|
# Put this at the end of a file
|
48
80
|
def end
|
81
|
+
$cache = CacheManager.new # load cache file
|
82
|
+
|
49
83
|
command = ARGV[0] || @mainCommand
|
84
|
+
if command == "--" # passing arguments to be processed by the builld file -> pass "--" as the command to specify the default
|
85
|
+
command = @mainCommand
|
86
|
+
end
|
50
87
|
self.call command
|
88
|
+
|
89
|
+
$cache.save # save cache file
|
51
90
|
end
|
52
|
-
|
53
|
-
# Clean
|
91
|
+
|
92
|
+
# Clean cache
|
54
93
|
def clean
|
55
94
|
FileUtils.rm_r @cache_loc
|
95
|
+
reset_cache
|
56
96
|
end
|
57
97
|
end
|
58
98
|
|
59
|
-
# Global beaver object
|
60
99
|
$beaver = Beaver.new
|
100
|
+
|
101
|
+
# Export functions
|
102
|
+
require 'command'
|
103
|
+
require 'file'
|
104
|
+
require 'file_dep'
|
105
|
+
require 'sh'
|
106
|
+
|
107
|
+
# Call a command
|
108
|
+
def call(cmd)
|
109
|
+
$beaver.call cmd
|
110
|
+
end
|
data/lib/command.rb
CHANGED
@@ -1,105 +1,86 @@
|
|
1
|
-
require '
|
2
|
-
require 'file_matches'
|
1
|
+
require 'file.rb'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
_command_oto name, src:src, target_dir:target_dir, target_ext:target_ext do |src, trg|
|
17
|
-
func.call src, trg
|
18
|
-
end
|
19
|
-
elsif !src.nil? && !target.nil?
|
20
|
-
_command_mto name, src:src, target:target do |files, target|
|
21
|
-
func.call files, target
|
22
|
-
end
|
23
|
-
else
|
24
|
-
_command name do ||
|
25
|
-
func.call
|
26
|
-
end
|
3
|
+
class Command
|
4
|
+
attr_accessor :name
|
5
|
+
attr_accessor :fn
|
6
|
+
attr_accessor :overwrite_should_run
|
7
|
+
|
8
|
+
def initialize(name, file_deps, fn)
|
9
|
+
@name = name
|
10
|
+
# When one of these files changes, the command should rerun
|
11
|
+
# Type: FileDep, or nil
|
12
|
+
@file_deps = file_deps
|
13
|
+
@fn = fn
|
14
|
+
@overwrite_should_run = false
|
27
15
|
end
|
28
|
-
end
|
29
16
|
|
30
|
-
#
|
31
|
-
def
|
32
|
-
|
33
|
-
|
17
|
+
# Execute the command if needed (dependency files changed)
|
18
|
+
def call
|
19
|
+
if self.should_run?
|
20
|
+
self.call_now()
|
21
|
+
end
|
22
|
+
end
|
34
23
|
|
35
|
-
#
|
36
|
-
|
24
|
+
# Force call the command, even if none of the files changed
|
25
|
+
def call_now
|
26
|
+
$file = nil
|
27
|
+
$files = nil
|
37
28
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
# end
|
43
|
-
# ```
|
44
|
-
def _command_oto(name, src: nil, target_dir: nil, target_ext: nil, &func)
|
45
|
-
$beaver.__appendCommandCB name do
|
46
|
-
src_files = get_matches(src)
|
47
|
-
|
48
|
-
abs_cd = File.dirname(File.expand_path($0))
|
49
|
-
|
50
|
-
# Contains all files with (source and target)
|
51
|
-
files = []
|
52
|
-
src_files.each do |srcfile|
|
53
|
-
file_name = File.basename(srcfile, ".*")
|
54
|
-
|
55
|
-
# path of the source file relative to the current directory
|
56
|
-
path_ext = File.dirname(
|
57
|
-
Pathname.new(File.expand_path(srcfile))
|
58
|
-
.relative_path_from(abs_cd)
|
59
|
-
)
|
60
|
-
|
61
|
-
files << OneWayDependency.new(
|
62
|
-
srcfile,
|
63
|
-
File.join(target_dir, path_ext, "#{file_name}#{target_ext}")
|
64
|
-
)
|
29
|
+
if @file_deps.nil?
|
30
|
+
@fn.call()
|
31
|
+
return
|
65
32
|
end
|
66
33
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
should_execute = true
|
72
|
-
elsif !File.file?(file.target)
|
73
|
-
# If the target file does not exist, then the function should be called
|
74
|
-
should_execute = true
|
75
|
-
elsif __beaver_file_changed?
|
76
|
-
# If the beaver config file changed, then the function should be called
|
77
|
-
should_execute = true
|
34
|
+
if @file_deps.type == :each
|
35
|
+
@file_deps.files.each do |file_obj|
|
36
|
+
$file = file_obj
|
37
|
+
@fn.call()
|
78
38
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
39
|
+
else
|
40
|
+
$files = @file_deps.files
|
41
|
+
@fn.call()
|
83
42
|
end
|
84
43
|
end
|
85
|
-
end
|
86
|
-
|
87
44
|
|
88
|
-
|
89
|
-
|
90
|
-
|
45
|
+
# Returns wheter the command should run, meaning if any of the depency
|
46
|
+
# files changed
|
47
|
+
def should_run?
|
48
|
+
return true if @overwrite_should_run
|
91
49
|
|
92
|
-
|
93
|
-
|
50
|
+
if changed? "__BEAVER__CONFIG__", $PROGRAM_NAME
|
51
|
+
# Ruby script itself changed
|
52
|
+
# TODO: does not account for dependencies of the script (probably uncommon though)
|
53
|
+
|
54
|
+
# Clear cache, because the config failed
|
55
|
+
reset_cache
|
56
|
+
|
57
|
+
unless @file_deps.nil?
|
58
|
+
@file_deps.each_file do |file|
|
59
|
+
$cache.files.add(@name, file)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
return true
|
94
64
|
end
|
95
65
|
|
96
|
-
if
|
97
|
-
|
66
|
+
if @file_deps.nil?
|
67
|
+
return true
|
98
68
|
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
69
|
+
|
70
|
+
changed = false
|
71
|
+
@file_deps.each_file do |file|
|
72
|
+
if !changed && (changed? @name, file)
|
73
|
+
changed = true
|
74
|
+
end
|
75
|
+
|
76
|
+
$cache.files.add(@name, file)
|
103
77
|
end
|
78
|
+
|
79
|
+
return changed
|
104
80
|
end
|
105
81
|
end
|
82
|
+
|
83
|
+
def cmd(name, deps = nil, &fn)
|
84
|
+
cmd = Command.new name, deps, fn
|
85
|
+
$beaver.__appendCommand cmd
|
86
|
+
end
|
data/lib/file.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#########
|
2
|
+
# Cache #
|
3
|
+
#########
|
4
|
+
|
5
|
+
require 'msgpack'
|
6
|
+
|
7
|
+
FileInfo = Struct.new(:modified)
|
8
|
+
|
9
|
+
# - file_info: { command => file_name => file_info }
|
10
|
+
Files = Struct.new(:commands) do
|
11
|
+
# returns the modified date of the file, or nil if it is not yet known
|
12
|
+
def modified(cmd, file)
|
13
|
+
files_info = commands[cmd.to_s]
|
14
|
+
if files_info.nil?
|
15
|
+
return nil
|
16
|
+
end
|
17
|
+
fi = files_info[file]
|
18
|
+
if fi.nil?
|
19
|
+
nil
|
20
|
+
else
|
21
|
+
fi.modified
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(cmd, path)
|
26
|
+
files_info = commands[cmd.to_s]
|
27
|
+
if files_info.nil?
|
28
|
+
commands[cmd.to_s] = Hash.new
|
29
|
+
files_info = commands[cmd.to_s]
|
30
|
+
end
|
31
|
+
files_info[path] = FileInfo.new(
|
32
|
+
File.mtime(path).to_i # modified date as unix time stamp
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
MessagePack::DefaultFactory.register_type(
|
38
|
+
0x01,
|
39
|
+
Files,
|
40
|
+
packer: ->(files, packer) {
|
41
|
+
packer.write(files.commands)
|
42
|
+
},
|
43
|
+
unpacker: ->(unpacker) {
|
44
|
+
Files.new(unpacker.read)
|
45
|
+
},
|
46
|
+
recursive: true,
|
47
|
+
)
|
48
|
+
|
49
|
+
MessagePack::DefaultFactory.register_type(
|
50
|
+
0x02,
|
51
|
+
FileInfo,
|
52
|
+
packer: ->(fi, packer) {
|
53
|
+
packer.write(fi.modified)
|
54
|
+
},
|
55
|
+
unpacker: ->(unpacker) {
|
56
|
+
FileInfo.new(unpacker.read)
|
57
|
+
},
|
58
|
+
recursive: true
|
59
|
+
)
|
60
|
+
|
61
|
+
# f = Files.new(Hash.new)
|
62
|
+
# f.add("lib/beaver.rb")
|
63
|
+
# pack = msg = MessagePack.pack(f)
|
64
|
+
# p pack
|
65
|
+
# p MessagePack::unpack(pack)
|
66
|
+
|
67
|
+
class CacheManager
|
68
|
+
attr_accessor :files
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
begin
|
72
|
+
@files = MessagePack::unpack(File.read $beaver.file_cache_file)
|
73
|
+
rescue EOFError
|
74
|
+
@files = Files.new(Hash.new)
|
75
|
+
@files.add("__BEAVER__CONFIG__", $PROGRAM_NAME)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def save
|
80
|
+
packed = MessagePack.pack(@files)
|
81
|
+
unless Dir.exist? $beaver.cache_loc
|
82
|
+
Dir.mkdir $beaver.cache_loc
|
83
|
+
end
|
84
|
+
File.binwrite($beaver.file_cache_file, packed)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
$cache = nil # will be initialized in `$beaver.end`, so that all settings are applied first
|
89
|
+
|
90
|
+
def reset_cache
|
91
|
+
$cache.files = Files.new(Hash.new)
|
92
|
+
$cache.files.add("__BEAVER__CONFIG__", $PROGRAM_NAME)
|
93
|
+
end
|
94
|
+
|
95
|
+
##############
|
96
|
+
# File utils #
|
97
|
+
##############
|
98
|
+
|
99
|
+
# Returns wether a file has changed
|
100
|
+
# Also returns true if no information about file changes is found
|
101
|
+
def changed? cmd_ctx, file
|
102
|
+
cached_modified = $cache.files.modified cmd_ctx, file
|
103
|
+
|
104
|
+
if cached_modified.nil?
|
105
|
+
# probably new file
|
106
|
+
return true
|
107
|
+
end
|
108
|
+
|
109
|
+
last_modified = File.mtime(file).to_i
|
110
|
+
if cached_modified < last_modified
|
111
|
+
return true
|
112
|
+
else
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
end
|
data/lib/file_dep.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'file_obj'
|
2
|
+
|
3
|
+
# File dependencies for commands
|
4
|
+
class FileDep
|
5
|
+
attr_accessor :type
|
6
|
+
|
7
|
+
def initialize(glob, type)
|
8
|
+
# Can be a string like "main.c" or "src/*.c", or an array like
|
9
|
+
# ["src/main.c", "src/lib/*.c"]
|
10
|
+
@glob = glob
|
11
|
+
# :each or :all
|
12
|
+
@type = type
|
13
|
+
# SingleFile, or MultiFile
|
14
|
+
@file_obj = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# Run fn for each file, passing the file name to fn
|
18
|
+
def each_file(&fn)
|
19
|
+
# Check if already a file object collected
|
20
|
+
if !@file_obj.nil?
|
21
|
+
if @type == :each
|
22
|
+
# @file_obj = []SingleFile
|
23
|
+
@file_obj.each do |file_o|
|
24
|
+
fn.call(file_o.path)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
# @file_obj = MultiFiles
|
28
|
+
@file_obj.each do |file|
|
29
|
+
fn.call(file)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
return
|
34
|
+
end
|
35
|
+
|
36
|
+
# Collect the file object
|
37
|
+
|
38
|
+
# initialize files as an empty array. This will contain full paths to
|
39
|
+
# files, which well then be put into @file_obj as either a []SingleFile
|
40
|
+
# or MultiFiles
|
41
|
+
files = []
|
42
|
+
|
43
|
+
globs = nil
|
44
|
+
if @glob.respond_to? :each
|
45
|
+
# array
|
46
|
+
globs = glob
|
47
|
+
else
|
48
|
+
# string
|
49
|
+
globs = [@glob]
|
50
|
+
end
|
51
|
+
|
52
|
+
globs.each do |glob|
|
53
|
+
Dir[glob].each do |file|
|
54
|
+
fn.call(file)
|
55
|
+
files << file
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# set the @file_obj
|
60
|
+
if @type == :each
|
61
|
+
@file_obj = files.map { |file| SingleFile.new file }
|
62
|
+
else
|
63
|
+
@file_obj = MultiFiles.new files
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# retuns the file/files object(s)
|
68
|
+
# will return either []SingleFile or MultiFiles
|
69
|
+
def files
|
70
|
+
if @file_obj.nil?
|
71
|
+
# Collect file_obj first
|
72
|
+
self.each_file { |f| }
|
73
|
+
end
|
74
|
+
|
75
|
+
return @file_obj
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Command will be called for each file
|
80
|
+
def each(dep)
|
81
|
+
return FileDep.new dep, :each
|
82
|
+
end
|
83
|
+
|
84
|
+
# Command will be called for all files at once
|
85
|
+
def all(dep)
|
86
|
+
return FileDep.new dep, :all
|
87
|
+
end
|
data/lib/file_obj.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Global file objects $file and $files
|
2
|
+
|
3
|
+
class SingleFile
|
4
|
+
# Full file path e.g. "src/main.c"
|
5
|
+
attr_accessor :path
|
6
|
+
|
7
|
+
def initialize(path)
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
# the name of the file, without extension
|
12
|
+
def name
|
13
|
+
File.basename(@path, ".*")
|
14
|
+
end
|
15
|
+
|
16
|
+
# the file name and extension
|
17
|
+
def full_name
|
18
|
+
File.basename(@path)
|
19
|
+
end
|
20
|
+
|
21
|
+
# the file extension
|
22
|
+
def ext
|
23
|
+
File.extname(@path)
|
24
|
+
end
|
25
|
+
|
26
|
+
# the directory of the file e.g. if the file is "src/main.c", dir will be
|
27
|
+
# "src"
|
28
|
+
def dir
|
29
|
+
File.dirname(@path)
|
30
|
+
end
|
31
|
+
|
32
|
+
# will return path
|
33
|
+
def to_s
|
34
|
+
@path
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class MultiFiles
|
39
|
+
# an array of file paths
|
40
|
+
attr_accessor :paths
|
41
|
+
|
42
|
+
def initialize(paths)
|
43
|
+
@paths = paths
|
44
|
+
end
|
45
|
+
|
46
|
+
# an array of all file names, without extensions
|
47
|
+
def names
|
48
|
+
@paths.map { |p| File.basename(p, ".*") }
|
49
|
+
end
|
50
|
+
|
51
|
+
# all file names, including their extensions
|
52
|
+
def full_names
|
53
|
+
@paths.map { |p| File.basename(p) }
|
54
|
+
end
|
55
|
+
|
56
|
+
# all file extensions
|
57
|
+
#
|
58
|
+
# For a list of all unique extensions, use `$files.exts.uniq`
|
59
|
+
def exts
|
60
|
+
@paths.map { |p| File.extname(p) }
|
61
|
+
end
|
62
|
+
|
63
|
+
# all directories
|
64
|
+
#
|
65
|
+
# For a list of all unique directories, use `$files.dir.uniq`
|
66
|
+
def dir
|
67
|
+
@paths.map { |p| File.dirname(p) }
|
68
|
+
end
|
69
|
+
|
70
|
+
# loop over each file
|
71
|
+
def each(&f)
|
72
|
+
@paths.each do |p|
|
73
|
+
f.call(p)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# will return a space separated list of files, surrounded with quotes
|
78
|
+
def to_s
|
79
|
+
@paths.inject("") { |list, elem| list + " \"#{elem}\"" }.strip
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
$file = nil
|
84
|
+
$files = nil
|
85
|
+
|
86
|
+
# Shorthand for using `$file` or `$files`
|
87
|
+
# def $f
|
88
|
+
# return $file || $files
|
89
|
+
# end
|
data/lib/sh.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Shell commands
|
2
|
+
|
3
|
+
# Execute shell command
|
4
|
+
def sh(strcmd)
|
5
|
+
unless strcmd.is_a?(SilentCommand) || strcmd.is_a?(SilentAll) then
|
6
|
+
if $beaver.term_256_color
|
7
|
+
puts "\u001b[38;5;246m#{strcmd}\u001b[0m"
|
8
|
+
else
|
9
|
+
puts "\u001b[30;1m#{strcmd}\u001b[0m"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
if strcmd.is_a?(SilentAll) || strcmd.is_a?(SilentOutput)
|
14
|
+
`#{strcmd}`
|
15
|
+
else
|
16
|
+
puts `#{strcmd}`
|
17
|
+
end
|
18
|
+
|
19
|
+
if $beaver.has(:e)
|
20
|
+
if $?.to_i != 0
|
21
|
+
if $?.exitstatus.nil?
|
22
|
+
puts $?
|
23
|
+
end
|
24
|
+
exit($?.exitstatus || -1)
|
25
|
+
end
|
26
|
+
elsif $?.to_i != 0 && $?.exitstatus.nil?
|
27
|
+
puts $?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
SilentCommand = Struct.new(:strcmd) do
|
32
|
+
def to_s
|
33
|
+
strcmd
|
34
|
+
end
|
35
|
+
end
|
36
|
+
SilentAll = Struct.new(:strcmd) do
|
37
|
+
def to_s
|
38
|
+
strcmd
|
39
|
+
end
|
40
|
+
end
|
41
|
+
SilentOutput = Struct.new(:strcmd) do
|
42
|
+
def to_s
|
43
|
+
strcmd
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Do not print the command
|
48
|
+
def silent(strcmd)
|
49
|
+
return SilentCommand.new(strcmd)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Do not print the command, or the output of the command
|
53
|
+
def full_silent(strcmd)
|
54
|
+
return SilentAll.new(strcmd)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Do not print out the output of the command
|
58
|
+
def output_silent(strcmd)
|
59
|
+
return SilentOutput.new(strcmd)
|
60
|
+
end
|
data/lib/util.rb
ADDED
metadata
CHANGED
@@ -1,18 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beaver-build
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Everaert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2023-07-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: msgpack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.6.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.6.0
|
13
27
|
description: |-
|
14
28
|
Beaver is an easy to understand build tool with a lot of capabilities.
|
15
|
-
Documentation and examples on [github](https://github.com/jomy10/beaver)
|
29
|
+
Documentation and examples on [github](https://github.com/jomy10/beaver).
|
16
30
|
email:
|
17
31
|
executables:
|
18
32
|
- beaver
|
@@ -20,13 +34,13 @@ extensions: []
|
|
20
34
|
extra_rdoc_files: []
|
21
35
|
files:
|
22
36
|
- bin/beaver
|
23
|
-
- lib/FileInfo.rb
|
24
|
-
- lib/alias.rb
|
25
37
|
- lib/beaver.rb
|
26
38
|
- lib/command.rb
|
27
|
-
- lib/
|
28
|
-
- lib/
|
29
|
-
- lib/
|
39
|
+
- lib/file.rb
|
40
|
+
- lib/file_dep.rb
|
41
|
+
- lib/file_obj.rb
|
42
|
+
- lib/sh.rb
|
43
|
+
- lib/util.rb
|
30
44
|
homepage: https://github.com/jomy10/beaver
|
31
45
|
licenses:
|
32
46
|
- MIT
|
data/lib/FileInfo.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
# date: last modified
|
5
|
-
FileInfo = Struct.new(:date)
|
6
|
-
|
7
|
-
class FileInfoRW
|
8
|
-
# file_loc = cache file location
|
9
|
-
# file_path = path of the file that represents the cache file
|
10
|
-
def initialize(file_loc, file_path)
|
11
|
-
@file_loc = file_loc
|
12
|
-
@file_path = file_path
|
13
|
-
end
|
14
|
-
|
15
|
-
# Read the info file and write a new one if needed
|
16
|
-
# Report back if the file has changed
|
17
|
-
def file_has_changed?()
|
18
|
-
cache_file = File.open(@file_loc)
|
19
|
-
|
20
|
-
file_info = JSON.parse(cache_file.read, object_class: OpenStruct)
|
21
|
-
last_modified = File.mtime(@file_path).to_i
|
22
|
-
if last_modified > file_info.date
|
23
|
-
json = self._json
|
24
|
-
File.write(@file_loc, json)
|
25
|
-
return true
|
26
|
-
else
|
27
|
-
return false
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Create the cache file
|
32
|
-
def create_cache()
|
33
|
-
json = self._json
|
34
|
-
|
35
|
-
dirnames = File.dirname(@file_loc)
|
36
|
-
unless File.directory?(dirnames)
|
37
|
-
# Directories do not exist, create them
|
38
|
-
FileUtils.mkdir_p(dirnames)
|
39
|
-
end
|
40
|
-
|
41
|
-
File.write(@file_loc, json)
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
# FileInfo as json
|
46
|
-
def _json
|
47
|
-
return FileInfo.new(
|
48
|
-
File.mtime(@file_path).to_i
|
49
|
-
).to_h.to_json
|
50
|
-
end
|
51
|
-
end
|
data/lib/alias.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# Aliases for default ruby commands for easier access by beaver users
|
2
|
-
|
3
|
-
# Execute system command
|
4
|
-
def §(cmd)
|
5
|
-
puts cmd
|
6
|
-
system cmd
|
7
|
-
end
|
8
|
-
|
9
|
-
# Execute system command
|
10
|
-
def sys(cmd)
|
11
|
-
puts cmd
|
12
|
-
system cmd
|
13
|
-
end
|
14
|
-
|
15
|
-
String.prepend(Module.new do
|
16
|
-
# The directory a file resides in
|
17
|
-
def dirname
|
18
|
-
return File.dirname self
|
19
|
-
end
|
20
|
-
|
21
|
-
# Basename of a file
|
22
|
-
def basename
|
23
|
-
return File.basename(self, ".*")
|
24
|
-
end
|
25
|
-
|
26
|
-
# File's basename with extension
|
27
|
-
def basename_ext
|
28
|
-
return File.basenam self
|
29
|
-
end
|
30
|
-
|
31
|
-
# The file's extension
|
32
|
-
def ext
|
33
|
-
return File.extname self
|
34
|
-
end
|
35
|
-
end)
|
data/lib/file_change.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'file_matches'
|
2
|
-
require 'FileInfo'
|
3
|
-
|
4
|
-
# Execute a function if the specified files have changed since last execution
|
5
|
-
# Also executes the function if the config file has changed
|
6
|
-
#
|
7
|
-
# # Parameters
|
8
|
-
# - files: either an array of files (or file patterns), or a file pattern as a string or regexp
|
9
|
-
# - func: the body of the if statement
|
10
|
-
def if_changed(files, &func)
|
11
|
-
matches = get_matches(files)
|
12
|
-
|
13
|
-
# Execute for each match if either no cache exists, or
|
14
|
-
# if the cache indicates a older file version
|
15
|
-
matches.each do |file|
|
16
|
-
if file_changed?(file) || __beaver_file_changed?
|
17
|
-
func.call file
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Executes if any file changed
|
23
|
-
# The callback receives a list of changed files
|
24
|
-
def if_any_changed(files, &func)
|
25
|
-
changed_files = []
|
26
|
-
if_changed files do |file|
|
27
|
-
changed_files << file
|
28
|
-
end
|
29
|
-
|
30
|
-
unless changed_files.empty?
|
31
|
-
func.call changed_files
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# check if a single file has changed
|
36
|
-
# returns true if it has been changed
|
37
|
-
def file_changed?(file)
|
38
|
-
cache_file_loc = "#{$beaver.cache_loc}/#{file}.info"
|
39
|
-
info_rw = FileInfoRW.new(cache_file_loc, file)
|
40
|
-
if !File.file?(cache_file_loc)
|
41
|
-
# File does not exist, so create it and call the function
|
42
|
-
info_rw.create_cache()
|
43
|
-
|
44
|
-
return true
|
45
|
-
else
|
46
|
-
# File exists, so read it
|
47
|
-
if info_rw.file_has_changed?
|
48
|
-
return true
|
49
|
-
else
|
50
|
-
return false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
$__beaver_file = nil
|
56
|
-
def __beaver_file_changed?
|
57
|
-
if $__beaver_file == nil
|
58
|
-
$__beaver_file = file_changed?($0)
|
59
|
-
end
|
60
|
-
|
61
|
-
return $__beaver_file
|
62
|
-
end
|
data/lib/file_exists.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# Executes a function if a file exists, passing in the existing file
|
2
|
-
def if_exists(files, &func)
|
3
|
-
files.each do |file|
|
4
|
-
if File.file?(file)
|
5
|
-
func.call file
|
6
|
-
end
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
# Executes a function if a file does not exists, passing in the non-existing file
|
11
|
-
def if_not_exists(files, &func)
|
12
|
-
files.each do |file|
|
13
|
-
unless File.file?(file)
|
14
|
-
func.call file
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# Executes a function if a file exists, passing in the existing file
|
20
|
-
def unless_exists(files, &func)
|
21
|
-
if_not_exists(files, func)
|
22
|
-
end
|
data/lib/file_matches.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
def get_matches(files)
|
2
|
-
# All file patterns to process
|
3
|
-
patterns_to_process = []
|
4
|
-
|
5
|
-
# Check if array or string
|
6
|
-
if files.respond_to? :each
|
7
|
-
# is an array
|
8
|
-
patterns_to_process = file
|
9
|
-
else
|
10
|
-
patterns_to_process << files
|
11
|
-
end
|
12
|
-
|
13
|
-
# Contains all files that match the expressions
|
14
|
-
matches = nil
|
15
|
-
|
16
|
-
patterns_to_process.each do |pattern|
|
17
|
-
if pattern.is_a?(Regexp)
|
18
|
-
matches = Find.find("./").grep(pattern)
|
19
|
-
else
|
20
|
-
# is a string
|
21
|
-
matches = Dir.glob(pattern)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
return matches
|
26
|
-
end
|