kompo 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 824cb5818444206e527f8a70d899c53b922f05a2ee44b1433b9103e2bc00dec9
4
- data.tar.gz: bc82fea90c7f254f3f1e2221cadd4dedb9ec0e0c64ae4a68163e5784a0de35d1
3
+ metadata.gz: 9810a7219117daa1c6a82c2741df55d16acb20a7d59b6dec0609f2f6a68418dd
4
+ data.tar.gz: 0b304b0510ec458f50c75e94528d604f71fa9cc7f5cdbb7386bcf1671495ca02
5
5
  SHA512:
6
- metadata.gz: 164750a94ce03e80d4dbdbd6c88a33ea76e92e5ddcd0a7ee2170aa76e2c24c3471616739a21adcd37724a49a0af93bb3805b73e14446159dc218cb514fb0fc9a
7
- data.tar.gz: 7668b48ea202b6f21dccceb8a67097d1df27b6661295c36b756f9a537c09f5479ed326f86c0374b7bb5fef860d62f54a599c520212798a31b02c03ddb6bc295a
6
+ metadata.gz: d678007c08242abee43dc8dd74a70a425701287336782b87f55e60624fa605ce1d844b345f14f70583e11dbccbcf507aec307b3cdcfc9a1472f5eab356d0c80c
7
+ data.tar.gz: ef31ac68e4ef6e15d1b98b1e71d97faf8385b36c3f75d85c918e970a0f47331845f4b994c1a4a68144ed730ca18331b21794b8c9dd543c881639c71c8042df02
@@ -3,9 +3,7 @@ FROM mcr.microsoft.com/devcontainers/base:ubuntu
3
3
  RUN apt-get update && apt-get install -y clang
4
4
  RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
5
5
  ENV PATH="/root/.cargo/bin:$PATH"
6
- RUN git clone https://github.com/ahogappa0613/kompo-vfs.git && \
6
+ RUN git clone https://github.com/ahogappa/kompo-vfs.git && \
7
7
  cd kompo-vfs && \
8
- sudo /root/.cargo/bin/cargo build --release && \
9
- sudo cp target/release/kompo-cli /usr/local/bin && \
10
- sudo cp target/release/libkompo.a /usr/local/lib
8
+ sudo /root/.cargo/bin/cargo build --release
11
9
 
@@ -13,8 +13,8 @@
13
13
  },
14
14
  "containerEnv": {
15
15
  // "PATH": "/usr/local/cargo/bin:${containerEnv:PATH}",
16
- "KOMPO_CLI": "/usr/local/bin/kompo-cli",
17
- "LIB_KOMPO_DIR": "/usr/local/lib",
16
+ // "KOMPO_CLI": "/usr/local/bin/kompo-cli",
17
+ // "LIB_KOMPO_DIR": "/usr/local/lib",
18
18
  },
19
19
  // Features to add to the dev container. More info: https://containers.dev/features.
20
20
  // "features": {},
data/.standard.yml ADDED
@@ -0,0 +1,2 @@
1
+ ignore:
2
+ - "samples/**/*"
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.3.0] - 2026-01-24
11
+
12
+ ### Changed
13
+ - Use RTLD_NEXT for single binary creation process [#6](https://github.com/ahogappa/kompo/pull/6)
14
+ - Rewrite kompo with Taski-based parallel task system [#6](https://github.com/ahogappa/kompo/pull/6)
15
+ - Use ruby-build for Ruby installation [#5](https://github.com/ahogappa/kompo/pull/5)
16
+
17
+ ### Added
18
+ - Ability to configure options for Ruby build
19
+
20
+ ### Fixed
21
+ - Fix error messages
data/Gemfile CHANGED
@@ -1,8 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source "https://rubygems.org"
3
+ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in kompo.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.0"
8
+ gem 'rake', '~> 13.0'
9
+ gem 'taski', '~> 0.8.0'
10
+
11
+ group :development, :test do
12
+ gem 'debug'
13
+ gem 'minitest'
14
+ gem 'simplecov', require: false
15
+ gem 'standard'
16
+ end
data/Gemfile.lock CHANGED
@@ -1,20 +1,132 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kompo (0.1.0)
4
+ kompo (0.3.0)
5
+ async
6
+ mini_portile2
7
+ pathspec
5
8
 
6
9
  GEM
7
10
  remote: https://rubygems.org/
8
11
  specs:
9
- rake (13.1.0)
12
+ ast (2.4.3)
13
+ async (2.35.0)
14
+ console (~> 1.29)
15
+ fiber-annotation
16
+ io-event (~> 1.11)
17
+ metrics (~> 0.12)
18
+ traces (~> 0.18)
19
+ console (1.34.2)
20
+ fiber-annotation
21
+ fiber-local (~> 1.1)
22
+ json
23
+ date (3.5.1)
24
+ debug (1.11.1)
25
+ irb (~> 1.10)
26
+ reline (>= 0.3.8)
27
+ docile (1.4.1)
28
+ erb (6.0.1)
29
+ fiber-annotation (0.2.0)
30
+ fiber-local (1.1.0)
31
+ fiber-storage
32
+ fiber-storage (1.0.1)
33
+ io-console (0.8.2)
34
+ io-event (1.14.2)
35
+ irb (1.16.0)
36
+ pp (>= 0.6.0)
37
+ rdoc (>= 4.0.0)
38
+ reline (>= 0.4.2)
39
+ json (2.18.0)
40
+ language_server-protocol (3.17.0.5)
41
+ lint_roller (1.1.0)
42
+ metrics (0.15.0)
43
+ mini_portile2 (2.8.9)
44
+ minitest (6.0.1)
45
+ prism (~> 1.5)
46
+ parallel (1.27.0)
47
+ parser (3.3.10.1)
48
+ ast (~> 2.4.1)
49
+ racc
50
+ pathspec (2.1.0)
51
+ pp (0.6.3)
52
+ prettyprint
53
+ prettyprint (0.2.0)
54
+ prism (1.8.0)
55
+ psych (5.3.1)
56
+ date
57
+ stringio
58
+ racc (1.8.1)
59
+ rainbow (3.1.1)
60
+ rake (13.3.1)
61
+ rdoc (7.0.2)
62
+ erb
63
+ psych (>= 4.0.0)
64
+ tsort
65
+ regexp_parser (2.11.3)
66
+ reline (0.6.3)
67
+ io-console (~> 0.5)
68
+ rubocop (1.82.1)
69
+ json (~> 2.3)
70
+ language_server-protocol (~> 3.17.0.2)
71
+ lint_roller (~> 1.1.0)
72
+ parallel (~> 1.10)
73
+ parser (>= 3.3.0.2)
74
+ rainbow (>= 2.2.2, < 4.0)
75
+ regexp_parser (>= 2.9.3, < 3.0)
76
+ rubocop-ast (>= 1.48.0, < 2.0)
77
+ ruby-progressbar (~> 1.7)
78
+ unicode-display_width (>= 2.4.0, < 4.0)
79
+ rubocop-ast (1.49.0)
80
+ parser (>= 3.3.7.2)
81
+ prism (~> 1.7)
82
+ rubocop-performance (1.26.1)
83
+ lint_roller (~> 1.1)
84
+ rubocop (>= 1.75.0, < 2.0)
85
+ rubocop-ast (>= 1.47.1, < 2.0)
86
+ ruby-progressbar (1.13.0)
87
+ simplecov (0.22.0)
88
+ docile (~> 1.1)
89
+ simplecov-html (~> 0.11)
90
+ simplecov_json_formatter (~> 0.1)
91
+ simplecov-html (0.13.2)
92
+ simplecov_json_formatter (0.1.4)
93
+ standard (1.53.0)
94
+ language_server-protocol (~> 3.17.0.2)
95
+ lint_roller (~> 1.0)
96
+ rubocop (~> 1.82.0)
97
+ standard-custom (~> 1.0.0)
98
+ standard-performance (~> 1.8)
99
+ standard-custom (1.0.2)
100
+ lint_roller (~> 1.0)
101
+ rubocop (~> 1.50)
102
+ standard-performance (1.9.0)
103
+ lint_roller (~> 1.1)
104
+ rubocop-performance (~> 1.26.0)
105
+ stringio (3.2.0)
106
+ taski (0.8.0)
107
+ prism (~> 1.4)
108
+ tsort
109
+ traces (0.18.2)
110
+ tsort (0.2.0)
111
+ unicode-display_width (3.2.0)
112
+ unicode-emoji (~> 4.1)
113
+ unicode-emoji (4.2.0)
10
114
 
11
115
  PLATFORMS
12
116
  aarch64-linux
13
117
  arm64-darwin-23
118
+ arm64-darwin-24
119
+ arm64-darwin-25
120
+ x86_64-linux
14
121
 
15
122
  DEPENDENCIES
123
+ debug
16
124
  kompo!
125
+ minitest
17
126
  rake (~> 13.0)
127
+ simplecov
128
+ standard
129
+ taski (~> 0.8.0)
18
130
 
19
131
  BUNDLED WITH
20
- 2.4.10
132
+ 2.6.9
data/README.md CHANGED
@@ -1,6 +1,31 @@
1
1
  # Kompo
2
2
  A tool to pack Ruby and Ruby scripts in one binary. This tool is still under development.
3
3
 
4
+ ## Concept
5
+
6
+ Kompo makes it dead simple to distribute Ruby applications. Just run one command, and you get a single binary that works anywhere—no Ruby installation required.
7
+
8
+ ```sh
9
+ $ kompo
10
+ $ ./main # That's it!
11
+ ```
12
+
13
+ ### Why Kompo?
14
+
15
+ - **Dead Simple**: One command to build, one file to distribute. No complex configuration, no build scripts, no Docker containers.
16
+
17
+ - **Zero Dependencies for Users**: Your users just download and run. No Ruby, no gems, no environment setup—it just works.
18
+
19
+ - **Full CRuby Compatibility**: Unlike mruby-based solutions, Kompo embeds the official CRuby interpreter. Your existing code, gems, and C extensions work without modification.
20
+
21
+ - **Cross-Platform**: Build binaries for macOS and Linux. (Windows support is planned)
22
+
23
+ - **Batteries Included**: All your gems, including native extensions, are bundled automatically.
24
+
25
+ ### How It Works
26
+
27
+ Kompo uses a Virtual File System (VFS) to embed Ruby source code, gems, and the Ruby interpreter into a single binary. At runtime, the embedded VFS provides transparent access to these files, allowing Ruby to operate as if everything were installed normally on the filesystem.
28
+
4
29
  ## Installation
5
30
  ```sh
6
31
  $ gem install kompo
@@ -9,35 +34,117 @@ $ gem install kompo
9
34
  ## Usage
10
35
 
11
36
  ### prerequisites
12
- Install [komp-vfs](https://github.com/ahogappa0613/kompo-vfs).
37
+ Install [kompo-vfs](https://github.com/ahogappa/kompo-vfs).
13
38
 
14
39
  #### Homebrew
15
40
  ```sh
16
- $ brew tap ahogappa0613/kompo-vfs https://github.com/ahogappa0613/kompo-vfs.git
17
- $ brew install ahogappa0613/kompo-vfs/kompo-vfs
41
+ $ brew tap ahogappa/kompo-vfs https://github.com/ahogappa/kompo-vfs.git
42
+ $ brew install ahogappa/kompo-vfs/kompo-vfs
18
43
  ```
19
44
 
20
45
  ### Building
21
46
  To build komp-vfs, you need to have cargo installation.
22
47
  ```sh
23
- $ git clone https://github.com/ahogappa0613/kompo-vfs.git
48
+ $ git clone https://github.com/ahogappa/kompo-vfs.git
24
49
  $ cd kompo-vfs
25
50
  $ cargo build --release
26
51
  ```
27
- Set environment variables
52
+
53
+ ## Options
54
+
55
+ ```
56
+ Usage: kompo [options] [files...]
57
+
58
+ Options:
59
+ -e, --entrypoint=FILE Entry point file (default: main.rb)
60
+ -o, --output=DIR Output directory for the binary
61
+ --ruby-version=VERSION Ruby version to use (default: current Ruby version)
62
+ --ruby-source=PATH Path to Ruby source tarball or directory
63
+ --no-cache Build Ruby from source, ignoring cache
64
+ --no-stdlib Exclude Ruby standard library from binary
65
+ --local-vfs-path=PATH Path to local kompo-vfs for development
66
+ --clean[=VERSION] Clean cache (current version by default, or specify VERSION, or "all")
67
+ -t, --tree Show task dependency tree and exit
68
+ -h, --help Show help message
69
+
70
+ Files:
71
+ Additional files and directories to include in the binary
72
+ ```
73
+
74
+ ### Option Details
75
+
76
+ | Option | Description |
77
+ |--------|-------------|
78
+ | `-e, --entrypoint` | Specifies the main Ruby file to execute. Defaults to `main.rb`. |
79
+ | `-o, --output` | Directory where the final binary will be placed. Defaults to current directory. |
80
+ | `--ruby-version` | Ruby version to embed. Kompo will build and cache this version. |
81
+ | `--ruby-source` | Use a local Ruby source instead of downloading. Useful for custom Ruby builds. |
82
+ | `--no-cache` | Force a fresh Ruby build, ignoring any cached version. |
83
+ | `--no-stdlib` | Reduce binary size by excluding Ruby standard library. Only use if your app doesn't need stdlib. |
84
+ | `--local-vfs-path` | Use a local kompo-vfs build instead of Homebrew installation. Useful for development. |
85
+ | `--clean` | Remove cached Ruby builds. Use `--clean=all` to remove all versions. |
86
+ | `-t, --tree` | Display the task dependency graph and exit without building. |
87
+
88
+ ### Examples
89
+
28
90
  ```sh
29
- $ KOMPO_CLI=/path/to/kompo-vfs/target/release/kompo-cli
30
- $ LIB_KOMPO_DIR=/path/to/kompo-vfs/target/release
91
+ # Basic usage - pack main.rb and lib/ directory
92
+ $ kompo main.rb lib/
93
+
94
+ # Specify entry point and output directory
95
+ $ kompo -e app.rb -o ./dist src/ config/
96
+
97
+ # Use a specific Ruby version
98
+ $ kompo --ruby-version=3.3.0 main.rb
99
+
100
+ # Development: use local kompo-vfs
101
+ $ kompo --local-vfs-path=/path/to/kompo-vfs main.rb
102
+
103
+ # Clean all cached Ruby builds
104
+ $ kompo --clean=all
31
105
  ```
32
106
 
107
+ ## .kompoignore
108
+
109
+ You can create a `.kompoignore` file in your project root to exclude files from the binary. This file follows the same syntax as `.gitignore`.
110
+
111
+ ### Syntax
112
+
113
+ ```gitignore
114
+ # Comments start with #
115
+ *.log # Ignore all .log files
116
+ tmp/ # Ignore tmp directory
117
+ **/cache/ # Ignore cache directories at any depth
118
+ !important.log # Negate pattern (don't ignore important.log)
119
+ spec/ # Ignore spec directory
120
+ test/ # Ignore test directory
121
+ node_modules/ # Ignore node_modules
122
+ ```
123
+
124
+ ### Supported Patterns
125
+
126
+ | Pattern | Description |
127
+ |---------|-------------|
128
+ | `*.log` | Glob pattern - matches all .log files |
129
+ | `tmp/` | Directory pattern - matches tmp directory and contents |
130
+ | `**/cache/` | Double star - matches cache at any depth |
131
+ | `!file` | Negation - excludes file from ignore list |
132
+ | `/config.yml` | Anchored - matches only at root level |
133
+
134
+ ### Notes
135
+
136
+ - `.kompoignore` only affects project files, not Ruby standard library or gems
137
+ - Patterns are matched against paths relative to the project root
138
+ - Comments and empty lines are ignored
139
+
33
140
  ## examples
34
141
 
35
142
  * hello
36
143
  * simple hello world script.
37
144
  * sinatra_and_sqlite
38
- * sinatra app with sqlite3 with Gemfile.
145
+ * simple sinatra app with sqlite3.
39
146
  * rails
40
- * 🚧
147
+ * simple Rails 7.1 application.
41
148
 
42
149
  ## Development
43
150
 
@@ -45,4 +152,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
45
152
 
46
153
  ## Contributing
47
154
 
48
- Bug reports and pull requests are welcome on GitHub at https://github.com/ahogappa0613/kompo.
155
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ahogappa/kompo.
data/Rakefile CHANGED
@@ -1,4 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- task default: %i[]
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ end
11
+
12
+ require 'standard/rake'
13
+
14
+ task default: %i[test standard]
@@ -0,0 +1,31 @@
1
+ # 現状の仕様のまとめ
2
+
3
+ ## 基本情報
4
+ kompoはワンバイナリにするファイルを作業ディレクトリにコピーします。
5
+ その作業ディレクトリはワンバイナリ化したプログラムが実行した時のルートディレクトリとします。
6
+ このとき作業ディレクトリのパス名やファイル名はプログラムの中に埋め込まれるため注意が必要です。(デフォルトではSecureRandomを使ってランダムなフォルダ名を生成します)
7
+
8
+ ## kompoの制約
9
+ ワンバイナリ化したプログラム内にデータを書き込むことはできません。
10
+ この制約があるため、一部のrubyプロジェクトの場合ファイルや設定を工夫する必要があります。
11
+
12
+ 例えばrailsのデータベースにsqliteを使う場合、デフォルトだとプロジェクトのtmp/以下にデータベースを配置します。
13
+ さらにこのディレクトリにはrailsの起動時に必要なディレクトリやファイルをいくつか書き込みます。
14
+ sampleにあるrailsではあらかじめtmp/以下に起動に必要なディレクトリやファイルを用意し、それをバイナリに含めることで起動時にディレクトリやファイルを作成しなくても良いようにしています。
15
+
16
+ 一方sqliteのデータベースもここに設置されるのですが、これには書き込みがなされるため、tmp/以下に設置することはできません。
17
+ よってconfig/database.ymlを修正して、sqliteのデータベースは実行するマシンの絶対パスに配置するようにします。
18
+
19
+ 簡単なrailsをワンバイナリ化する具体的な方法はsample/rails/sampleのREADME.mdやsample/rails/sample/config/database.ymlを参照してください。
20
+
21
+ ## 拡張ライブラリが含まれる場合
22
+ 拡張ライブラリが含まれるRubyプロジェクトの場合、拡張ライブラリをbuildできる環境が必要です。また環境が整っていても拡張ライブラリによってはうまくワンバイナリ化できない場合があります。
23
+
24
+ kompoは通常、拡張ライブラリを静的リンクするためにmkmf.rbを実行してMakefileを生成、コンパイルしアーカイブファイルを作ります。
25
+ そしてワンバイナリ化したプログラムを作成するときには、そのMakefileに含まれている情報をもとにinclude/やlib/のパスを指定してコンパイルします。
26
+
27
+ しかし、一部独自のbuild方法をとっているものがあり、Makefileから取得する情報が足りなかったりして失敗する可能性があります。
28
+ これに関してはなるべく対応していくつもりですが、完全に対応できるものではないので、拡張ライブラリのbuild方法をパッチするなり、自前でbuildしたものを使ってワンバイナリ化するなどする必要があります。
29
+
30
+ また当然ですが、拡張ライブラリ自体がクロスコンパイルに対応していない場合は、kompoを使ってもクロスコンパイルできません。
31
+
data/exe/kompo CHANGED
@@ -1,20 +1,51 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require_relative '../lib/kompo'
4
4
  require 'optparse'
5
+ require_relative '../lib/kompo'
5
6
 
6
- option = Kompo::Option.default
7
-
8
- Kompo::Tasks.cd_work_dir(option) do |task|
9
- task.clone_ruby_src
10
-
11
- task.fs_cli
12
-
13
- task.make_main_c
14
-
15
- task.packing
16
-
17
- task.copy_to_dest_dir
7
+ args = {}
8
+ opt = OptionParser.new do |o|
9
+ o.banner = 'Usage: kompo [options] [files...]'
10
+ o.separator ''
11
+ o.separator 'Options:'
12
+
13
+ o.on('-e', '--entrypoint=FILE', 'Entry point file (default: main.rb)') { |v| args[:entrypoint] = v }
14
+ o.on('-o', '--output=DIR', 'Output directory for the binary') { |v| args[:output_dir] = File.expand_path(v) }
15
+ o.on('--ruby-version=VERSION', "Ruby version to use (default: #{RUBY_VERSION})") { |v| args[:ruby_version] = v }
16
+ o.on('--ruby-source=PATH', 'Path to Ruby source tarball or directory') do |v|
17
+ args[:ruby_source_path] = File.expand_path(v)
18
+ end
19
+ o.on('--no-cache', 'Build Ruby from source, ignoring cache') { |_v| args[:no_cache] = true }
20
+ o.on('--no-stdlib', 'Exclude Ruby standard library from binary') { |_v| args[:no_stdlib] = true }
21
+ o.on('--local-vfs-path=PATH', 'Path to local kompo-vfs for development') do |v|
22
+ args[:local_kompo_vfs_path] = File.expand_path(v)
23
+ end
24
+ o.on('--clean[=VERSION]', 'Clean cache (current Ruby version by default, or specify VERSION, or "all")') do |v|
25
+ args[:clean_cache] = v.nil? ? RUBY_VERSION : v
26
+ end
27
+ o.on('-t', '--tree', 'Show task dependency tree and exit') do
28
+ puts Kompo::Packing.tree
29
+ exit(0)
30
+ end
31
+ o.on('-v', '--version', 'Show version') do
32
+ puts "kompo #{Kompo::VERSION}"
33
+ exit(0)
34
+ end
35
+ o.on('-h', '--help', 'Show this help message') do
36
+ puts o
37
+ exit(0)
38
+ end
39
+
40
+ o.separator ''
41
+ o.separator 'Files:'
42
+ o.separator ' Additional files and directories to include in the binary'
18
43
  end
44
+ opt.parse!(ARGV)
45
+ args[:files] = ARGV
19
46
 
20
- puts 'info: Finish kompo!'
47
+ if args[:clean_cache]
48
+ Kompo.clean_cache(args[:clean_cache])
49
+ else
50
+ Kompo::Packing.run_and_clean(args:)
51
+ end
data/lib/fs.c.erb ADDED
@@ -0,0 +1,6 @@
1
+ const char FILES[] = {<%= @file_bytes.join(',') %>};
2
+ const int FILES_SIZE = <%= @file_bytes.size %>;
3
+ const unsigned long long FILES_SIZES[] = {<%= @file_sizes.join(',') %>};
4
+ const char PATHS[] = {<%= @paths.join(',') %>};
5
+ const int PATHS_SIZE = <%= @paths.size %>;
6
+ const char WD[] = {<%= context.work_dir.bytes.join(',') %>,0};
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module Kompo
6
+ # Clean the cache for specified Ruby version
7
+ # @param version [String] Ruby version to clean, or "all" to clean all caches
8
+ def self.clean_cache(version)
9
+ kompo_cache = File.expand_path('~/.kompo/cache')
10
+
11
+ unless Dir.exist?(kompo_cache)
12
+ puts "Cache directory does not exist: #{kompo_cache}"
13
+ return
14
+ end
15
+
16
+ if version == 'all'
17
+ clean_all_caches(kompo_cache)
18
+ else
19
+ clean_version_cache(kompo_cache, version)
20
+ end
21
+ end
22
+
23
+ # Clean all caches in the cache directory
24
+ def self.clean_all_caches(kompo_cache)
25
+ entries = Dir.glob(File.join(kompo_cache, '*'))
26
+ if entries.empty?
27
+ puts "No caches found in #{kompo_cache}"
28
+ return
29
+ end
30
+
31
+ entries.each do |entry|
32
+ FileUtils.rm_rf(entry)
33
+ puts "Removed: #{entry}"
34
+ end
35
+
36
+ puts 'All caches cleaned successfully'
37
+ end
38
+ private_class_method :clean_all_caches
39
+
40
+ # Clean cache for a specific Ruby version
41
+ # New structure: ~/.kompo/cache/{version}/ contains all caches for that version
42
+ def self.clean_version_cache(kompo_cache, version)
43
+ version_cache_dir = File.join(kompo_cache, version)
44
+
45
+ unless Dir.exist?(version_cache_dir)
46
+ puts "No cache found for Ruby #{version}"
47
+ return
48
+ end
49
+
50
+ # Validate that version_cache_dir is under kompo_cache to prevent path traversal
51
+ real_kompo_cache = File.realpath(kompo_cache)
52
+ real_version_cache = File.realpath(version_cache_dir)
53
+
54
+ unless real_version_cache.start_with?(real_kompo_cache + File::SEPARATOR) ||
55
+ real_version_cache == real_kompo_cache
56
+ puts 'Error: Invalid cache path detected (possible path traversal)'
57
+ return
58
+ end
59
+
60
+ FileUtils.rm_rf(real_version_cache)
61
+ puts "Removed: #{real_version_cache}"
62
+ puts "Cache for Ruby #{version} cleaned successfully"
63
+ end
64
+ private_class_method :clean_version_cache
65
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathspec'
4
+
5
+ module Kompo
6
+ # Handler for .kompoignore file
7
+ # Uses pathspec gem for gitignore-compatible pattern matching
8
+ class KompoIgnore
9
+ FILENAME = '.kompoignore'
10
+
11
+ def initialize(project_dir)
12
+ @project_dir = project_dir
13
+ @pathspec = load_pathspec
14
+ end
15
+
16
+ # Check if the given relative path should be ignored
17
+ # @param relative_path [String] Path relative to work_dir
18
+ # @return [Boolean] true if the path should be ignored
19
+ def ignore?(relative_path)
20
+ return false unless @pathspec
21
+
22
+ @pathspec.match(relative_path)
23
+ end
24
+
25
+ # Check if .kompoignore file exists and is enabled
26
+ # @return [Boolean] true if .kompoignore file exists
27
+ def enabled?
28
+ !@pathspec.nil?
29
+ end
30
+
31
+ private
32
+
33
+ def load_pathspec
34
+ ignore_file = File.join(@project_dir, FILENAME)
35
+ return nil unless File.exist?(ignore_file)
36
+
37
+ PathSpec.from_filename(ignore_file)
38
+ end
39
+ end
40
+ end