beaver-build 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a00331b274e731341ca50bccc73fa013c5449673ee30a9beea5b0a01259ffac7
4
+ data.tar.gz: 209d69ad346136143bbc4c612f10fd22e04db7eb55b602dd02d189ef48bd6947
5
+ SHA512:
6
+ metadata.gz: 5580ebbb545b2e2a45d05db57827aaacb3bd4fd712f4f45adece1bcf8bc6600c32f207c32de0edb8c90c66286fb827052aef1fe47652f5962af34a502c19c985
7
+ data.tar.gz: 98a08e5c318ad7700b49a5362bd7f891363538f12230db73cac35eec0496a7a54d4345c04345906a97ec398cb9ab8ce095e527c7c96007046227c4839e597ba3
data/lib/FileInfo.rb ADDED
@@ -0,0 +1,51 @@
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 ADDED
@@ -0,0 +1,35 @@
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/beaver.rb ADDED
@@ -0,0 +1,60 @@
1
+ require 'fileutils'
2
+
3
+ # Export functions
4
+ require 'file_change'
5
+ require 'file_exists'
6
+ require 'command'
7
+ require 'alias'
8
+
9
+ class Beaver
10
+ # The location where Beaver caches
11
+ attr_accessor :cache_loc
12
+
13
+ # Initializer should not be used outside of this module
14
+ def initialize
15
+ # Contains all commands
16
+ # [commandName: String => command: Function]
17
+ @commands = Hash.new
18
+ # Contains the main command name
19
+ @mainCommand = nil
20
+ @cache_loc = "./.beaver"
21
+ end
22
+
23
+ # Appends a command to the global beaver
24
+ def __appendCommand(name, func)
25
+ if @commands.size == 0
26
+ @mainCommand = name.to_sym
27
+ end
28
+
29
+ @commands[name.to_sym] = func
30
+ end
31
+
32
+ def __appendCommandCB(name, &func)
33
+ self.__appendCommand(name, func)
34
+ end
35
+
36
+ # Call a command
37
+ def call(cmd)
38
+ _cmd = @commands[cmd.to_sym]
39
+ if _cmd.nil?
40
+ puts "No command called #{cmd} found"
41
+ exit 1
42
+ end
43
+
44
+ _cmd.call
45
+ end
46
+
47
+ # Put this at the end of a file
48
+ def end
49
+ command = ARGV[0] || @mainCommand
50
+ self.call command
51
+ end
52
+
53
+ # Clean beaver
54
+ def clean
55
+ FileUtils.rm_r @cache_loc
56
+ end
57
+ end
58
+
59
+ # Global beaverr object@
60
+ $beaver = Beaver.new
data/lib/command.rb ADDED
@@ -0,0 +1,105 @@
1
+ require 'pathname'
2
+ require 'file_matches'
3
+
4
+ # register a new beaver command
5
+ #
6
+ # - Possible combinations
7
+ # Register a normal command
8
+ # command :name do end
9
+ # Register a command that executes if a source file changed, or the target file does not exist (one target file per source file)
10
+ # command :name, src: "", target_dir: "", target_ext: "", do end
11
+ # Register a command that executes if a source file changed, or the single target file does not exist (multiple sources into one target file)
12
+ # The callback will receive a files variables, which is a string containing all paths, separated by spaces
13
+ # command :name, src: "", target: "" do end
14
+ def command(name, src:nil, target_dir:nil, target_ext:nil, target:nil, &func)
15
+ if !src.nil? && !target_dir.nil? && !target_ext.nil?
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
27
+ end
28
+ end
29
+
30
+ # Register a new beaver command
31
+ def _command(name, &func)
32
+ $beaver.__appendCommand(name, func)
33
+ end
34
+
35
+ # Defines a dependency from source file to target file
36
+ OneWayDependency = Struct.new(:src, :target)
37
+
38
+ # - Example:
39
+ # ```ruby
40
+ # command_oto :command_name, src: "src/**/*.c", target_dir: "build", target_ext: ".o" do |source_file, target_file|
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
+ )
65
+ end
66
+
67
+ for file in files
68
+ should_execute = false
69
+ if file_changed?(file.src)
70
+ # If source file has changed, then the function should be called
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
78
+ end
79
+
80
+ if should_execute
81
+ func.call file.src, file.target
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+
88
+ def _command_mto(name, src:nil, target:nil, &func)
89
+ $beaver.__appendCommandCB name do
90
+ should_execute = false
91
+
92
+ if_any_changed src do |_|
93
+ should_execute = true
94
+ end
95
+
96
+ if !File.file?(target)
97
+ should_execute = true
98
+ end
99
+
100
+ if should_execute
101
+ src_files = get_matches(src)
102
+ func.call src_files.join(" "), target
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,62 @@
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
@@ -0,0 +1,22 @@
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
@@ -0,0 +1,26 @@
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
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beaver-build
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jonas Everaert
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-15 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/FileInfo.rb
20
+ - lib/alias.rb
21
+ - lib/beaver.rb
22
+ - lib/command.rb
23
+ - lib/file_change.rb
24
+ - lib/file_exists.rb
25
+ - lib/file_matches.rb
26
+ homepage: https://github.com/jomy10/beaver
27
+ licenses:
28
+ - MIT
29
+ metadata: {}
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ required_rubygems_version: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ requirements: []
45
+ rubygems_version: 3.3.3
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: Ruby-powered build tool
49
+ test_files: []