taski 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 260795a6ff4d622bd95b3bfb2668ba6123f17339650ea9371ea54d2210691d98
4
- data.tar.gz: 60d7f97a6c736ed91e50bd2e8e9f48c163f76024e7407c0da96c9d77f4394514
3
+ metadata.gz: d04adfab160e07e101e7d6364796d5607a896010396950ee5d479824bb4c422e
4
+ data.tar.gz: aeb0ea3476853608c0ef77e80e907c79db7ea62c1aaead8a22d8232d7e4c13aa
5
5
  SHA512:
6
- metadata.gz: 71ccbe4131ac8409636071355af2de6cfda0862e21fb012e70b2f2fe60cb3bbc7023d640f9d3dc889f6759e8885a5dba5a1c0d543a6aa05e9299aa9ff401df54
7
- data.tar.gz: a0a291d6fdd8d9ec1a122dbca9d115aa5c36f8008e7812120b0356e218ea895f46b292eab4404404c611c1f1b69e6dc9e4247f18d2cfc7a079b7d1f0ec2716d6
6
+ metadata.gz: b3201ee69bc45ae1e58569bf1a98647ff7e38adabf0d04334805fdbac816468d420b1d460113970e1fc9394e6f9e6ca2fe4c700e0c390b9032366a01690c7762
7
+ data.tar.gz: 81a9796f7234f8f66216b61b7ea676b40614bb8258b8a6d6a0244e5d016319ea1492f7817324e1669a6ede1eeaf3f0ad4d8b71fd210168022838f66047348bff
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 ahogappa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,49 +1,37 @@
1
1
  # Taski
2
2
 
3
3
  **Taski** is a Ruby-based task runner designed for small, composable processing steps.
4
- With Taski, you define tasks and the outputs they depend on. Taski then statically resolves task dependencies and determines the correct execution order.
4
+ In Taski, you define tasks as Ruby classes that expose named values through `define`. Dependencies between tasks are established automatically when one task references the result of another—no need for explicit dependency declarations.
5
5
 
6
- Tasks are executed in a topologically sorted order, ensuring that all dependencies are resolved before a task is run. Reverse execution is also supported, making it easy to clean up intermediate files after a build process.
6
+ Tasks are executed in a topologically sorted order, ensuring that tasks are built only after their inputs are available. Reverse execution is also supported, making it easy to clean up intermediate files or revert changes after a build.
7
7
 
8
8
  > **🚧 Development Status:** Taski is currently under active development and the API may change.
9
9
 
10
10
  > **⚠️ Limitation:** Circular dependencies are **not** supported at this time.
11
11
 
12
+ > **ℹ️ Note:** Taski does **not** infer dependencies from file contents or behavior. Instead, dependencies are implicitly established via references between task definitions.
13
+
12
14
  ### Features
13
15
 
14
- - Simple and declarative task definitions
15
- - Static dependency resolution
16
+ - Define tasks using Ruby classes
17
+ - Implicit dependencies via reference to other task outputs
16
18
  - Topological execution order
17
- - Reverse execution for teardown or cleanup
19
+ - Reverse execution for cleanup
18
20
  - Built entirely in Ruby
19
21
 
20
- ## Installation
21
-
22
- Install the gem and add to the application's Gemfile by executing:
23
-
24
- ```bash
25
- bundle add taski
26
- ```
27
-
28
- If bundler is not being used to manage dependencies, install the gem by executing:
29
-
30
- ```bash
31
- gem install taski
32
- ```
33
-
34
- ## Usage
22
+ ### Example
35
23
 
36
24
  ```ruby
37
25
  class TaskA < Taski::Task
38
- definition :task_a, -> { "Task A" }
26
+ define :task_a_result, -> { "Task A" }
39
27
 
40
28
  def build
41
- task_a
29
+ puts 'Processing...'
42
30
  end
43
31
  end
44
32
 
45
33
  class TaskB < Taski::Task
46
- definition :simple_task, -> { "Task result is #{TaskA.task_a}" }
34
+ define :simple_task, -> { "Task result is #{TaskA.task_a_result}" }
47
35
 
48
36
  def build
49
37
  puts simple_task
@@ -51,9 +39,24 @@ class TaskB < Taski::Task
51
39
  end
52
40
 
53
41
  TaskB.build
42
+ # => Processing...
54
43
  # => Task result is Task A
55
44
  ```
56
45
 
46
+ ## Installation
47
+
48
+ Install the gem and add to the application's Gemfile by executing:
49
+
50
+ ```bash
51
+ bundle add taski
52
+ ```
53
+
54
+ If bundler is not being used to manage dependencies, install the gem by executing:
55
+
56
+ ```bash
57
+ gem install taski
58
+ ```
59
+
57
60
  ## Development
58
61
 
59
62
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,53 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+
4
+ module Taski
5
+ class Utils < FileUtils
6
+ def rm
7
+
8
+ end
9
+
10
+ def rm_f
11
+ end
12
+
13
+ def rm_rf
14
+
15
+ end
16
+
17
+ def cp
18
+
19
+ end
20
+
21
+ def cp_r
22
+
23
+ end
24
+
25
+ def mkdir
26
+
27
+ end
28
+
29
+ def mkdir_p
30
+
31
+ end
32
+
33
+ def mktmpdir
34
+
35
+ end
36
+
37
+ def cmd(command, info = nil, ret = false)
38
+ puts "exec: #{info}" if info
39
+ puts command
40
+
41
+ if ret
42
+ ret = `#{command}`.chomp
43
+ if $?.exited?
44
+ ret
45
+ else
46
+ raise "Failed to execute command: #{command}"
47
+ end
48
+ else
49
+ system command, exception: true
50
+ end
51
+ end
52
+ end
53
+ end
data/lib/taski/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Taski
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/taski.rb CHANGED
@@ -18,138 +18,126 @@ module Taski
18
18
  end
19
19
 
20
20
  class Task
21
- def self.__resolve__
22
- @__resolve__ ||= {}
23
- end
21
+ class << self
22
+ def ref(klass)
23
+ ref = Reference.new(klass)
24
+ throw :unresolved, ref
25
+ end
24
26
 
25
- def self.ref(klass)
26
- ref = Reference.new(klass)
27
- throw :unresolve, ref
28
- end
27
+ def define(name, block, **options)
28
+ @dependencies ||= []
29
+ @definitions ||= {}
29
30
 
30
- def self.definition(name, block, **options)
31
- @dependencies ||= []
32
- @definitions ||= {}
31
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
32
+ def self.#{name}
33
+ __resolve__[__callee__] ||= false
34
+ if __resolve__[__callee__]
35
+ # already resolved
36
+ else
37
+ __resolve__[__callee__] = true
38
+ throw :unresolved, [self, __callee__]
39
+ end
40
+ end
41
+ RUBY
33
42
 
34
- self.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
35
- def self.#{name}
36
- __resolve__[__callee__] ||= false
37
- if __resolve__[__callee__]
38
- # already resolved
39
- else
40
- __resolve__[__callee__] = true
41
- throw :unresolve, [self, __callee__]
43
+ classes = []
44
+ loop do
45
+ klass, task = catch(:unresolved) do
46
+ block.call
47
+ nil
42
48
  end
43
- end
44
- RUBY
45
49
 
46
- classes = []
47
- loop do
48
- klass, task = catch(:unresolve) do
49
- block.call
50
- nil
51
- end
50
+ if klass.nil?
51
+ classes.each do |task_class|
52
+ task_class[:klass].class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
53
+ __resolve__ = {}
54
+ RUBY
55
+ end
52
56
 
53
- if klass.nil?
54
- classes.each do |task_class|
55
- task_class[:klass].class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
56
- __resolve__ = {}
57
- RUBY
57
+ break
58
+ else
59
+ classes << { klass:, task: }
58
60
  end
59
-
60
- break
61
- else
62
- classes << { klass:, task: }
63
61
  end
64
- end
65
-
66
- @dependencies += classes
67
- @definitions[name] = {block:, options:, classes:}
68
- end
69
62
 
70
- def self.build
71
- resolve_dependences.reverse.each do |task_class|
72
- task_class.new.build
63
+ @dependencies += classes
64
+ @definitions[name] = { block:, options:, classes: }
73
65
  end
74
- end
75
-
76
- def self.clean
77
- resolve_dependences.each do |task_class|
78
- task_class.new.clean
79
- end
80
- end
81
66
 
82
- def exec_command(command, info = nil, ret = false)
83
- puts "exec: #{info}" if info
84
- puts command
85
-
86
- if ret
87
- ret = `#{command}`.chomp
88
- if $?.exited?
89
- ret
90
- else
91
- raise "Failed to execute command: #{command}"
67
+ def build
68
+ resolve_dependencies.reverse.each do |task_class|
69
+ task_class.new.build
92
70
  end
93
- else
94
- system command, exception: true
95
71
  end
96
- end
97
-
98
- def self.refresh
99
- # TODO
100
- end
101
-
102
- private
103
72
 
104
- def self.resolve(queue, resolved)
105
- @dependencies.each do |task|
106
- if task[:klass].is_a?(Reference)
107
- task_class = task[:klass].deref
73
+ def clean
74
+ resolve_dependencies.each do |task_class|
75
+ task_class.new.clean
108
76
  end
77
+ end
109
78
 
110
- # increase priority
111
- if resolved.include?(task[:klass])
112
- resolved.delete(task[:klass])
113
- end
114
- queue << task[:klass]
79
+ def refresh
80
+ # TODO
115
81
  end
116
82
 
117
- # override
118
- self.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
119
- def self.ref(klass)
120
- Object.const_get(klass)
83
+ def resolve(queue, resolved)
84
+ @dependencies.each do |task|
85
+ if task[:klass].is_a?(Reference)
86
+ task[:klass].deref
87
+ else
88
+ task[:klass]
89
+ end => task_class
90
+
91
+ # increase priority
92
+ if resolved.include?(task_class)
93
+ resolved.delete(task_class)
94
+ end
95
+ queue << task_class
121
96
  end
122
- RUBY
123
97
 
124
- @definitions.each do |name, (block, options)|
125
98
  # override
126
- self.class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
127
- def self.#{name}
128
- @__#{name} ||= @definitions[:#{name}][:block].call
99
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
100
+ def self.ref(klass)
101
+ Object.const_get(klass)
129
102
  end
130
103
  RUBY
131
104
 
132
- self.define_method(name) do
133
- unless instance_variable_defined?("@__#{name}")
134
- instance_variable_set("@__#{name}", self.class.send(name))
105
+ @definitions.each do |name, (_block, _options)|
106
+ # override
107
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
108
+ def self.#{name}
109
+ @__#{name} ||= @definitions[:#{name}][:block].call
110
+ end
111
+ RUBY
112
+
113
+ define_method(name) do
114
+ unless instance_variable_defined?("@__#{name}")
115
+ instance_variable_set("@__#{name}", self.class.send(name))
116
+ end
117
+ instance_variable_get("@__#{name}")
135
118
  end
136
- instance_variable_get("@__#{name}")
137
119
  end
138
- end
139
120
 
140
- self
141
- end
121
+ self
122
+ end
142
123
 
143
- def self.resolve_dependences
144
- queue = [self]
145
- resolved = []
124
+ private
146
125
 
147
- while queue.any?
148
- resolved << task_class = queue.shift
149
- task_class.resolve(queue, resolved)
126
+ def __resolve__
127
+ @__resolve__ ||= {}
150
128
  end
151
129
 
152
- resolved
130
+ def resolve_dependencies
131
+ queue = [self]
132
+ resolved = []
133
+
134
+ while queue.any?
135
+ resolved << task_class = queue.shift
136
+ task_class.resolve(queue, resolved)
137
+ end
138
+
139
+ resolved
140
+ end
153
141
  end
154
142
  end
155
143
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taski
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ahogappa
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-05-18 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: Taski is a Ruby-based task runner currently under development. It allows
13
13
  you to define small, composable tasks along with the outputs they depend on. Taski
@@ -21,9 +21,11 @@ executables: []
21
21
  extensions: []
22
22
  extra_rdoc_files: []
23
23
  files:
24
+ - LICENSE
24
25
  - README.md
25
26
  - Rakefile
26
27
  - lib/taski.rb
28
+ - lib/taski/utils.rb
27
29
  - lib/taski/version.rb
28
30
  - sig/taski.rbs
29
31
  homepage: https://github.com/ahogappa/taski
@@ -46,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
48
  - !ruby/object:Gem::Version
47
49
  version: '0'
48
50
  requirements: []
49
- rubygems_version: 3.6.7
51
+ rubygems_version: 3.6.2
50
52
  specification_version: 4
51
53
  summary: A simple yet powerful Ruby task runner with static dependency resolution
52
54
  (in development).