Kobold 0.3.3 → 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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +5 -0
  3. data/.rubocop.yml +21 -1
  4. data/.rules/bugs/untestable.md +27 -0
  5. data/.rules/changelog/2026-03/30/01.md +55 -0
  6. data/.rules/changelog/2026-03/30/02.md +27 -0
  7. data/.rules/changelog/2026-03/30/03.md +36 -0
  8. data/.rules/changelog/2026-03/30/04.md +48 -0
  9. data/.rules/changelog/2026-03/30/05.md +19 -0
  10. data/.rules/changelog/2026-03/30/06.md +16 -0
  11. data/.rules/changelog/2026-03/30/07.md +28 -0
  12. data/.rules/changelog/2026-03/30/08.md +29 -0
  13. data/.rules/changelog/2026-03/30/09.md +33 -0
  14. data/.rules/changelog/2026-03/30/10.md +12 -0
  15. data/.rules/changelog/2026-03/30/11.md +47 -0
  16. data/.rules/changelog/2026-03/30/12.md +18 -0
  17. data/.rules/changelog/2026-03/30/13.md +36 -0
  18. data/.rules/changelog/2026-03/30/14.md +13 -0
  19. data/.rules/changelog/2026-03/30/15.md +24 -0
  20. data/.rules/default/rubocop.md +228 -0
  21. data/.rules/docs/kobold_api.md +491 -0
  22. data/README.md +131 -29
  23. data/Rakefile +19 -2
  24. data/exe/kobold +3 -57
  25. data/lib/Kobold/cli/admin_commands.rb +124 -0
  26. data/lib/Kobold/cli/checkout_commands.rb +73 -0
  27. data/lib/Kobold/cli/error_handling.rb +50 -0
  28. data/lib/Kobold/cli/flag_parser.rb +109 -0
  29. data/lib/Kobold/cli/init_commands.rb +108 -0
  30. data/lib/Kobold/cli/lifecycle_commands.rb +116 -0
  31. data/lib/Kobold/cli/list_commands.rb +80 -0
  32. data/lib/Kobold/cli/output.rb +40 -0
  33. data/lib/Kobold/cli/repo_commands.rb +101 -0
  34. data/lib/Kobold/cli/update_commands.rb +71 -0
  35. data/lib/Kobold/cli.rb +120 -0
  36. data/lib/Kobold/config.rb +136 -0
  37. data/lib/Kobold/database.rb +169 -0
  38. data/lib/Kobold/errors.rb +59 -0
  39. data/lib/Kobold/fetch.rb +19 -0
  40. data/lib/Kobold/git_ops.rb +162 -0
  41. data/lib/Kobold/init.rb +17 -13
  42. data/lib/Kobold/invoke.rb +12 -192
  43. data/lib/Kobold/linker.rb +87 -0
  44. data/lib/Kobold/manager/checkout.rb +78 -0
  45. data/lib/Kobold/manager/cleaning.rb +47 -0
  46. data/lib/Kobold/manager/fetching.rb +58 -0
  47. data/lib/Kobold/manager/invoking.rb +67 -0
  48. data/lib/Kobold/manager/lifecycle.rb +133 -0
  49. data/lib/Kobold/manager/registration.rb +32 -0
  50. data/lib/Kobold/manager.rb +140 -0
  51. data/lib/Kobold/repo/worktree_helpers.rb +56 -0
  52. data/lib/Kobold/repo.rb +135 -0
  53. data/lib/Kobold/settings.rb +103 -0
  54. data/lib/Kobold/version.rb +2 -2
  55. data/lib/Kobold.rb +14 -13
  56. data/prototyping/.kobold +19 -24
  57. data/sample-project-ideas/.kobold +19 -27
  58. data/sig/Kobold.rbs +217 -1
  59. metadata +60 -59
  60. data/lib/Kobold/first_time_setup.rb +0 -14
  61. data/lib/Kobold/read_config.rb +0 -15
data/sig/Kobold.rbs CHANGED
@@ -1,4 +1,220 @@
1
1
  module Kobold
2
2
  VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
3
+ FORMAT_VERSION: String
4
+ KOBOLD_DIR: String
5
+
6
+ def self.invoke: (?config_path: String, ?database_name: String) -> Array[Hash[Symbol, untyped]]
7
+ def self.fetch: (?config_path: String, ?database_name: String) -> Array[Hash[Symbol, untyped]]
8
+ def self.init: (?dir: String) -> Hash[Symbol, untyped]
9
+
10
+ class Manager
11
+ attr_reader database: Database
12
+
13
+ def initialize: (?database: String) -> void
14
+
15
+ # Repo Registration
16
+ def register: (String repo, source: String) -> Hash[Symbol, untyped]
17
+ def unregister: (String repo) -> Hash[Symbol, untyped]
18
+
19
+ # Fetch
20
+ def fetch: (String repo) -> Hash[Symbol, untyped]
21
+ def fetch_all: (?config_path: String) -> Array[Hash[Symbol, untyped]]
22
+
23
+ # Checkout
24
+ def checkout: (String repo, ?branch: String?, ?commit: String?, ?label: String?, ?dir: String?) -> Hash[Symbol, untyped]
25
+
26
+ # Branching
27
+ def create_branch: (String repo, name: String, ?from: String, ?dir: String?) -> Hash[Symbol, untyped]
28
+
29
+ # Worktree Management
30
+ def remove_worktree: (String repo, dir: String) -> Hash[Symbol, untyped]
31
+
32
+ # Invoke
33
+ def invoke: (?config_path: String) -> Array[Hash[Symbol, untyped]]
34
+
35
+ # Init
36
+ def init: (?dir: String) -> Hash[Symbol, untyped]
37
+
38
+ # Listing
39
+ def list_repos: () -> Hash[String, Hash[String, String]]
40
+ def list_worktrees: (String repo) -> Array[String]
41
+ def list_branches: (String repo) -> Array[String]
42
+
43
+ # Config Generation
44
+ def generate_config: (path: String, ?dependencies: Array[Hash[Symbol | String, untyped]], ?includes: Array[String]) -> Hash[Symbol, untyped]
45
+
46
+ # Clean
47
+ def clean: (?purge_repos: bool, ?config_path: String?) -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
48
+
49
+ # Add Dependency
50
+ def add: (config_path: String, name: String, repo: String, source: String, ?branch: String?, ?commit: String?, ?label: String?, ?dir: String?) -> Hash[Symbol, untyped]
51
+
52
+ # Remove Dependency
53
+ def remove: (config_path: String, dependency_name: String, ?cleanup: bool) -> Hash[Symbol, untyped]
54
+
55
+ # Update Dependency
56
+ def update: (config_path: String, dependency_name: String) -> Hash[Symbol, untyped]
57
+ def update_all: (?config_path: String) -> Array[Hash[Symbol, untyped]]
58
+
59
+ # Database Lifecycle (class methods)
60
+ def self.create_database: (String name) -> Hash[Symbol, untyped]
61
+ def self.delete_database: (String name) -> Hash[Symbol, untyped]
62
+ def self.list_databases: () -> Array[String]
63
+
64
+ private
65
+
66
+ def build_clone_url: (String source, String repo) -> String
67
+ def resolve_config: (String config_path) -> Config
68
+ def referenced_slugs_from_config: (String config_path) -> Set[String]
69
+ end
70
+
71
+ module Errors
72
+ class RepoNotFound < StandardError
73
+ def initialize: (String slug) -> void
74
+ end
75
+
76
+ class WorktreeExists < StandardError
77
+ def initialize: (String path) -> void
78
+ end
79
+
80
+ class ConfigError < StandardError
81
+ end
82
+
83
+ class DatabaseNotFound < StandardError
84
+ def initialize: (String name) -> void
85
+ end
86
+
87
+ class InvalidFormat < StandardError
88
+ def initialize: (String version, String expected) -> void
89
+ end
90
+
91
+ class CloneError < StandardError
92
+ def initialize: (String url, String message) -> void
93
+ end
94
+
95
+ class FetchError < StandardError
96
+ def initialize: (String slug, String message) -> void
97
+ end
98
+
99
+ class GitError < StandardError
100
+ end
101
+
102
+ class DependencyNotFound < StandardError
103
+ def initialize: (String name) -> void
104
+ end
105
+
106
+ class DatabaseExists < StandardError
107
+ def initialize: (String name) -> void
108
+ end
109
+
110
+ class LinkError < StandardError
111
+ end
112
+ end
113
+
114
+ module GitOps
115
+ def self.clone: (String url, String path) -> untyped
116
+ def self.open: (String path) -> untyped
117
+ def self.create_worktree: (untyped repo, String path, String ref) -> void
118
+ def self.remove_worktree: (untyped repo, String path) -> void
119
+ def self.fetch: (untyped repo, ?label: String) -> void
120
+ def self.resolve_ref: (untyped repo, String ref) -> String
121
+ def self.resolve_branch_head: (untyped repo, String branch) -> String
122
+ end
123
+
124
+ class Config
125
+ REQUIRED_KEYS: Array[String]
126
+ OPTIONAL_KEYS: Array[String]
127
+ ALL_DEP_KEYS: Array[String]
128
+
129
+ attr_reader format_version: String
130
+ attr_reader includes: Array[String]
131
+ attr_reader dependencies: Hash[String, Hash[String, String]]
132
+ attr_reader path: String?
133
+
134
+ def self.read: (String path) -> Config
135
+ def self.write: (String path, Config config) -> void
136
+ def self.generate: (?dependencies: Array[Hash[Symbol | String, untyped]], ?includes: Array[String]) -> Config
137
+ def self.validate: (Hash[String, untyped] data) -> true
138
+
139
+ def initialize: (data: Hash[String, untyped], ?path: String?) -> void
140
+ def to_h: () -> Hash[String, untyped]
141
+ def each_dependency: () { (String, Hash[String, String]) -> void } -> void
142
+ def add_dependency: (String name, Hash[String | Symbol, String?] dep) -> void
143
+ def remove_dependency: (String name) -> Hash[String, String]?
144
+ def dependency?: (String name) -> bool
145
+ def dependency: (String name) -> Hash[String, String]?
146
+ def update_dependency: (String name, String key, String? value) -> void
147
+ end
148
+
149
+ class Database
150
+ REGISTRY_FILE: String
151
+
152
+ attr_reader name: String
153
+
154
+ def self.list_databases: () -> Array[String]
155
+ def self.exists?: (String name) -> bool
156
+ def self.slugify: (String repo_path) -> String
157
+
158
+ def initialize: (?String name) -> void
159
+ def path: () -> String
160
+ def setup: () -> void
161
+ def exists?: () -> bool
162
+ def delete: () -> void
163
+ def register_repo: (String slug, String source_url) -> Hash[String, String]
164
+ def unregister_repo: (String slug) -> void
165
+ def list_repos: () -> Hash[String, Hash[String, String]]
166
+ def repo: (String slug) -> Repo
167
+ def repos_dir: () -> String
168
+ end
169
+
170
+ class Repo
171
+ attr_reader database: Database
172
+ attr_reader slug: String
173
+ attr_reader source_url: String
174
+
175
+ def initialize: (Database database, String slug, String source_url) -> void
176
+ def path: () -> String
177
+ def source_path: () -> String
178
+ def clone: () -> untyped
179
+ def cloned?: () -> bool
180
+ def fetch: () -> void
181
+ def create_worktree: (?branch: String?, ?commit: String?, ?label: String?) -> String
182
+ def remove_worktree: (String identifier) -> void
183
+ def create_branch: (String name, ?from: String) -> String
184
+ def list_worktrees: () -> Array[String]
185
+ def list_branches: () -> Array[String]
186
+ def resolve_branch_head: (String branch) -> String
187
+ def purge: () -> void
188
+ def worktree_path_for: (?branch: String?, ?commit: String?, ?label: String?) -> String
189
+ end
190
+
191
+ module Linker
192
+ def self.link: (String target, String destination) -> String
193
+ def self.unlink: (String destination) -> void
194
+ def self.relink: (String target, String destination) -> String
195
+ def self.valid?: (String destination) -> bool
196
+ end
197
+
198
+ module Settings
199
+ CONFIG_FILE: String
200
+ DEFAULT_SOURCE: String
201
+
202
+ def self.config_path: () -> String
203
+ def self.read: () -> Hash[String, untyped]
204
+ def self.write: (Hash[String, untyped] data) -> void
205
+ def self.get: (String key) -> String?
206
+ def self.set: (String key, String value) -> void
207
+ def self.default_source: () -> String
208
+ def self.default_source=: (String url) -> void
209
+ end
210
+
211
+ class CLI
212
+ COMMANDS: Array[String]
213
+ EXIT_SUCCESS: Integer
214
+ EXIT_ERROR: Integer
215
+ EXIT_USAGE: Integer
216
+
217
+ def initialize: (?Array[String] argv) -> void
218
+ def run: () -> void
219
+ end
4
220
  end
metadata CHANGED
@@ -1,86 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Kobold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - CatsAtTheRodeo
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2023-11-10 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: tty-option
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.3.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.3.0
27
- - !ruby/object:Gem::Dependency
28
- name: tty-config
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 0.6.0
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 0.6.0
41
- - !ruby/object:Gem::Dependency
42
- name: inifile
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 3.0.0
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 3.0.0
55
12
  - !ruby/object:Gem::Dependency
56
13
  name: git
57
14
  requirement: !ruby/object:Gem::Requirement
58
15
  requirements:
59
16
  - - "~>"
60
17
  - !ruby/object:Gem::Version
61
- version: 1.18.0
18
+ version: '4.3'
62
19
  type: :runtime
63
20
  prerelease: false
64
21
  version_requirements: !ruby/object:Gem::Requirement
65
22
  requirements:
66
23
  - - "~>"
67
24
  - !ruby/object:Gem::Version
68
- version: 1.18.0
25
+ version: '4.3'
69
26
  - !ruby/object:Gem::Dependency
70
- name: tty-progressbar
27
+ name: toml-rb
71
28
  requirement: !ruby/object:Gem::Requirement
72
29
  requirements:
73
30
  - - "~>"
74
31
  - !ruby/object:Gem::Version
75
- version: 0.18.2
32
+ version: '3.0'
76
33
  type: :runtime
77
34
  prerelease: false
78
35
  version_requirements: !ruby/object:Gem::Requirement
79
36
  requirements:
80
37
  - - "~>"
81
38
  - !ruby/object:Gem::Version
82
- version: 0.18.2
83
- description:
39
+ version: '3.0'
40
+ description: Manages Git repositories as packages. Clones repos into a local cache,
41
+ creates Git worktrees for specific branches/commits, and symlinks them into project
42
+ directories.
84
43
  email:
85
44
  - contact@tradam.dev
86
45
  executables:
@@ -88,7 +47,26 @@ executables:
88
47
  extensions: []
89
48
  extra_rdoc_files: []
90
49
  files:
50
+ - ".rspec"
91
51
  - ".rubocop.yml"
52
+ - ".rules/bugs/untestable.md"
53
+ - ".rules/changelog/2026-03/30/01.md"
54
+ - ".rules/changelog/2026-03/30/02.md"
55
+ - ".rules/changelog/2026-03/30/03.md"
56
+ - ".rules/changelog/2026-03/30/04.md"
57
+ - ".rules/changelog/2026-03/30/05.md"
58
+ - ".rules/changelog/2026-03/30/06.md"
59
+ - ".rules/changelog/2026-03/30/07.md"
60
+ - ".rules/changelog/2026-03/30/08.md"
61
+ - ".rules/changelog/2026-03/30/09.md"
62
+ - ".rules/changelog/2026-03/30/10.md"
63
+ - ".rules/changelog/2026-03/30/11.md"
64
+ - ".rules/changelog/2026-03/30/12.md"
65
+ - ".rules/changelog/2026-03/30/13.md"
66
+ - ".rules/changelog/2026-03/30/14.md"
67
+ - ".rules/changelog/2026-03/30/15.md"
68
+ - ".rules/default/rubocop.md"
69
+ - ".rules/docs/kobold_api.md"
92
70
  - CHANGELOG.md
93
71
  - Kobold Notes/.obsidian/app.json
94
72
  - Kobold Notes/.obsidian/appearance.json
@@ -102,10 +80,35 @@ files:
102
80
  - Rakefile
103
81
  - exe/kobold
104
82
  - lib/Kobold.rb
105
- - lib/Kobold/first_time_setup.rb
83
+ - lib/Kobold/cli.rb
84
+ - lib/Kobold/cli/admin_commands.rb
85
+ - lib/Kobold/cli/checkout_commands.rb
86
+ - lib/Kobold/cli/error_handling.rb
87
+ - lib/Kobold/cli/flag_parser.rb
88
+ - lib/Kobold/cli/init_commands.rb
89
+ - lib/Kobold/cli/lifecycle_commands.rb
90
+ - lib/Kobold/cli/list_commands.rb
91
+ - lib/Kobold/cli/output.rb
92
+ - lib/Kobold/cli/repo_commands.rb
93
+ - lib/Kobold/cli/update_commands.rb
94
+ - lib/Kobold/config.rb
95
+ - lib/Kobold/database.rb
96
+ - lib/Kobold/errors.rb
97
+ - lib/Kobold/fetch.rb
98
+ - lib/Kobold/git_ops.rb
106
99
  - lib/Kobold/init.rb
107
100
  - lib/Kobold/invoke.rb
108
- - lib/Kobold/read_config.rb
101
+ - lib/Kobold/linker.rb
102
+ - lib/Kobold/manager.rb
103
+ - lib/Kobold/manager/checkout.rb
104
+ - lib/Kobold/manager/cleaning.rb
105
+ - lib/Kobold/manager/fetching.rb
106
+ - lib/Kobold/manager/invoking.rb
107
+ - lib/Kobold/manager/lifecycle.rb
108
+ - lib/Kobold/manager/registration.rb
109
+ - lib/Kobold/repo.rb
110
+ - lib/Kobold/repo/worktree_helpers.rb
111
+ - lib/Kobold/settings.rb
109
112
  - lib/Kobold/version.rb
110
113
  - prototyping/.gitignore
111
114
  - prototyping/.kobold
@@ -113,12 +116,11 @@ files:
113
116
  - prototyping/main.c
114
117
  - sample-project-ideas/.kobold
115
118
  - sig/Kobold.rbs
116
- homepage:
119
+ homepage: https://github.com/CatsAtTheRodeo/Kobold
117
120
  licenses:
118
121
  - MIT
119
122
  metadata:
120
123
  source_code_uri: https://github.com/CatsAtTheRodeo/Kobold
121
- post_install_message:
122
124
  rdoc_options: []
123
125
  require_paths:
124
126
  - lib
@@ -126,15 +128,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
128
  requirements:
127
129
  - - ">="
128
130
  - !ruby/object:Gem::Version
129
- version: 2.7.2
131
+ version: '3.0'
130
132
  required_rubygems_version: !ruby/object:Gem::Requirement
131
133
  requirements:
132
134
  - - ">="
133
135
  - !ruby/object:Gem::Version
134
136
  version: '0'
135
137
  requirements: []
136
- rubygems_version: 3.3.25
137
- signing_key:
138
+ rubygems_version: 4.0.3
138
139
  specification_version: 4
139
- summary: Version manager for various libraries and projects.
140
+ summary: Git-based package manager for libraries and projects.
140
141
  test_files: []
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "tty-config"
4
- require 'fileutils'
5
- require 'git'
6
-
7
- module Kobold
8
- class << self
9
- def first_time_setup
10
- FileUtils.mkdir_p "#{KOBOLD_DIR}/repo_cache"
11
- end
12
- end
13
- end
14
-
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "tty-config"
4
- #require 'fileutils'
5
-
6
- module Kobold
7
- class << self
8
- def read_config(dir)
9
- config = TTY::Config.new
10
- config.append_path dir
11
- settings = config.read ".kobold", format: :ini
12
- return settings
13
- end
14
- end
15
- end