makit 0.0.144 → 0.0.145
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 +4 -4
- data/README.md +41 -41
- data/exe/makit +5 -5
- data/lib/makit/apache.rb +28 -28
- data/lib/makit/auto.rb +48 -48
- data/lib/makit/cli/base.rb +17 -0
- data/lib/makit/cli/build_commands.rb +500 -500
- data/lib/makit/cli/generators/base_generator.rb +74 -74
- data/lib/makit/cli/generators/dotnet_generator.rb +50 -50
- data/lib/makit/cli/generators/generator_factory.rb +49 -49
- data/lib/makit/cli/generators/node_generator.rb +50 -50
- data/lib/makit/cli/generators/ruby_generator.rb +77 -77
- data/lib/makit/cli/generators/rust_generator.rb +50 -50
- data/lib/makit/cli/generators/templates/dotnet_templates.rb +167 -167
- data/lib/makit/cli/generators/templates/node_templates.rb +161 -161
- data/lib/makit/cli/generators/templates/ruby/gemfile.rb +26 -26
- data/lib/makit/cli/generators/templates/ruby/gemspec.rb +41 -40
- data/lib/makit/cli/generators/templates/ruby/main_lib.rb +33 -33
- data/lib/makit/cli/generators/templates/ruby/rakefile.rb +35 -35
- data/lib/makit/cli/generators/templates/ruby/readme.rb +63 -63
- data/lib/makit/cli/generators/templates/ruby/test.rb +39 -39
- data/lib/makit/cli/generators/templates/ruby/test_helper.rb +29 -29
- data/lib/makit/cli/generators/templates/ruby/version.rb +29 -29
- data/lib/makit/cli/generators/templates/rust_templates.rb +128 -128
- data/lib/makit/cli/main.rb +78 -69
- data/lib/makit/cli/pipeline_commands.rb +311 -0
- data/lib/makit/cli/project_commands.rb +868 -868
- data/lib/makit/cli/repository_commands.rb +661 -661
- data/lib/makit/cli/strategy_commands.rb +207 -212
- data/lib/makit/cli/utility_commands.rb +521 -521
- data/lib/makit/commands/factory.rb +359 -359
- data/lib/makit/commands/middleware/base.rb +73 -73
- data/lib/makit/commands/middleware/cache.rb +248 -248
- data/lib/makit/commands/middleware/command_logger.rb +312 -312
- data/lib/makit/commands/middleware/validator.rb +269 -269
- data/lib/makit/commands/request.rb +316 -316
- data/lib/makit/commands/result.rb +323 -323
- data/lib/makit/commands/runner.rb +386 -386
- data/lib/makit/commands/strategies/base.rb +171 -171
- data/lib/makit/commands/strategies/child_process.rb +162 -162
- data/lib/makit/commands/strategies/factory.rb +136 -136
- data/lib/makit/commands/strategies/synchronous.rb +139 -139
- data/lib/makit/commands.rb +50 -50
- data/lib/makit/configuration/dotnet_project.rb +48 -48
- data/lib/makit/configuration/gitlab_helper.rb +61 -58
- data/lib/makit/configuration/project.rb +446 -168
- data/lib/makit/configuration/rakefile_helper.rb +43 -43
- data/lib/makit/configuration/step.rb +34 -34
- data/lib/makit/configuration/timeout.rb +74 -74
- data/lib/makit/configuration.rb +21 -16
- data/lib/makit/content/default_gitignore.rb +7 -7
- data/lib/makit/content/default_gitignore.txt +225 -225
- data/lib/makit/content/default_rakefile.rb +13 -13
- data/lib/makit/content/gem_rakefile.rb +16 -16
- data/lib/makit/context.rb +1 -1
- data/lib/makit/data.rb +49 -49
- data/lib/makit/directories.rb +140 -140
- data/lib/makit/directory.rb +262 -262
- data/lib/makit/docs/files.rb +89 -89
- data/lib/makit/docs/rake.rb +102 -102
- data/lib/makit/dotnet/cli.rb +69 -69
- data/lib/makit/dotnet/project.rb +217 -217
- data/lib/makit/dotnet/solution.rb +38 -38
- data/lib/makit/dotnet/solution_classlib.rb +239 -239
- data/lib/makit/dotnet/solution_console.rb +264 -264
- data/lib/makit/dotnet/solution_maui.rb +354 -354
- data/lib/makit/dotnet/solution_wasm.rb +275 -275
- data/lib/makit/dotnet/solution_wpf.rb +304 -304
- data/lib/makit/dotnet.rb +102 -102
- data/lib/makit/email.rb +90 -90
- data/lib/makit/environment.rb +142 -142
- data/lib/makit/examples/runner.rb +370 -370
- data/lib/makit/exceptions.rb +45 -45
- data/lib/makit/fileinfo.rb +32 -24
- data/lib/makit/files.rb +43 -43
- data/lib/makit/gems.rb +40 -40
- data/lib/makit/git/cli.rb +54 -54
- data/lib/makit/git/repository.rb +266 -90
- data/lib/makit/git.rb +104 -98
- data/lib/makit/gitlab/pipeline.rb +857 -0
- data/lib/makit/gitlab/pipeline_service_impl.rb +1536 -0
- data/lib/makit/gitlab_runner.rb +59 -59
- data/lib/makit/humanize.rb +218 -137
- data/lib/makit/indexer.rb +47 -47
- data/lib/makit/io/filesystem.rb +111 -0
- data/lib/makit/io/filesystem_service_impl.rb +337 -0
- data/lib/makit/logging/configuration.rb +308 -308
- data/lib/makit/logging/format_registry.rb +84 -84
- data/lib/makit/logging/formatters/base.rb +39 -39
- data/lib/makit/logging/formatters/console_formatter.rb +140 -140
- data/lib/makit/logging/formatters/json_formatter.rb +65 -65
- data/lib/makit/logging/formatters/plain_text_formatter.rb +71 -71
- data/lib/makit/logging/formatters/text_formatter.rb +64 -64
- data/lib/makit/logging/log_request.rb +119 -119
- data/lib/makit/logging/logger.rb +199 -199
- data/lib/makit/logging/sinks/base.rb +91 -91
- data/lib/makit/logging/sinks/console.rb +72 -72
- data/lib/makit/logging/sinks/file_sink.rb +92 -92
- data/lib/makit/logging/sinks/structured.rb +123 -123
- data/lib/makit/logging/sinks/unified_file_sink.rb +296 -296
- data/lib/makit/logging.rb +565 -565
- data/lib/makit/markdown.rb +75 -75
- data/lib/makit/mp/basic_object_mp.rb +17 -17
- data/lib/makit/mp/command_mp.rb +13 -13
- data/lib/makit/mp/command_request.mp.rb +17 -17
- data/lib/makit/mp/project_mp.rb +199 -199
- data/lib/makit/mp/string_mp.rb +205 -199
- data/lib/makit/nuget.rb +74 -74
- data/lib/makit/podman/podman.rb +458 -0
- data/lib/makit/podman/podman_service_impl.rb +1081 -0
- data/lib/makit/port.rb +32 -32
- data/lib/makit/process.rb +377 -377
- data/lib/makit/protoc.rb +112 -107
- data/lib/makit/rake/cli.rb +196 -196
- data/lib/makit/rake/trace_controller.rb +174 -174
- data/lib/makit/rake.rb +81 -81
- data/lib/makit/ruby/cli.rb +185 -185
- data/lib/makit/ruby.rb +25 -25
- data/lib/makit/secrets.rb +51 -51
- data/lib/makit/serializer.rb +130 -130
- data/lib/makit/services/builder.rb +186 -186
- data/lib/makit/services/error_handler.rb +226 -226
- data/lib/makit/services/repository_manager.rb +367 -231
- data/lib/makit/services/validator.rb +112 -112
- data/lib/makit/setup/classlib.rb +101 -101
- data/lib/makit/setup/gem.rb +268 -268
- data/lib/makit/setup/pages.rb +11 -11
- data/lib/makit/setup/razorclasslib.rb +101 -101
- data/lib/makit/setup/runner.rb +54 -54
- data/lib/makit/setup.rb +5 -5
- data/lib/makit/show.rb +110 -110
- data/lib/makit/storage.rb +126 -126
- data/lib/makit/symbols.rb +175 -170
- data/lib/makit/task_info.rb +130 -130
- data/lib/makit/tasks/at_exit.rb +15 -15
- data/lib/makit/tasks/build.rb +22 -22
- data/lib/makit/tasks/clean.rb +13 -13
- data/lib/makit/tasks/configure.rb +10 -10
- data/lib/makit/tasks/format.rb +10 -10
- data/lib/makit/tasks/hook_manager.rb +443 -443
- data/lib/makit/tasks/init.rb +49 -49
- data/lib/makit/tasks/integrate.rb +29 -29
- data/lib/makit/tasks/pull_incoming.rb +13 -13
- data/lib/makit/tasks/setup.rb +16 -16
- data/lib/makit/tasks/sync.rb +17 -17
- data/lib/makit/tasks/tag.rb +16 -16
- data/lib/makit/tasks/task_monkey_patch.rb +81 -81
- data/lib/makit/tasks/test.rb +22 -22
- data/lib/makit/tasks/update.rb +18 -18
- data/lib/makit/tasks.rb +20 -20
- data/lib/makit/test_cache.rb +239 -239
- data/lib/makit/tree.rb +37 -37
- data/lib/makit/v1/configuration/project_service_impl.rb +371 -0
- data/lib/makit/v1/git/git_repository_service_impl.rb +295 -0
- data/lib/makit/v1/makit.v1_pb.rb +35 -35
- data/lib/makit/v1/makit.v1_services_pb.rb +27 -27
- data/lib/makit/v1/services/repository_manager_service_impl.rb +572 -0
- data/lib/makit/version.rb +100 -100
- data/lib/makit/version_util.rb +21 -21
- data/lib/makit/wix.rb +95 -95
- data/lib/makit/yaml.rb +29 -29
- data/lib/makit/zip.rb +17 -17
- data/lib/makit copy.rb +44 -44
- data/lib/makit.rb +111 -43
- metadata +61 -36
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../../../generated/makit/v1/configuration/project_service_services_pb"
|
|
4
|
+
require_relative "../../configuration/gitlab_helper"
|
|
5
|
+
require_relative "../../configuration/rakefile_helper"
|
|
6
|
+
require_relative "../../configuration/step"
|
|
7
|
+
|
|
8
|
+
module Makit
|
|
9
|
+
module V1
|
|
10
|
+
module Configuration
|
|
11
|
+
# gRPC service implementation for ProjectService
|
|
12
|
+
# Implements all the RPC methods defined in the protobuf service definition
|
|
13
|
+
class ProjectServiceImpl < ProjectService::Service
|
|
14
|
+
# Load a project from a JSON file
|
|
15
|
+
def load_from_file(request, _unused_call)
|
|
16
|
+
raise ArgumentError, "File does not exist: #{request.path}" unless File.exist?(request.path)
|
|
17
|
+
|
|
18
|
+
content = File.read(request.path)
|
|
19
|
+
data = JSON.parse(content, symbolize_names: true)
|
|
20
|
+
|
|
21
|
+
project = convert_from_json_data(data)
|
|
22
|
+
project
|
|
23
|
+
rescue ArgumentError => e
|
|
24
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
25
|
+
rescue StandardError => e
|
|
26
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Load a project from JSON string
|
|
30
|
+
def load_from_json(request, _unused_call)
|
|
31
|
+
raise ArgumentError, "JSON string cannot be empty" if request.json_string.nil? || request.json_string.strip.empty?
|
|
32
|
+
|
|
33
|
+
data = JSON.parse(request.json_string, symbolize_names: true)
|
|
34
|
+
project = convert_from_json_data(data)
|
|
35
|
+
project
|
|
36
|
+
rescue ArgumentError => e
|
|
37
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Save a project to a specific path as pretty JSON
|
|
43
|
+
def save_to_file(request, _unused_call)
|
|
44
|
+
validate_project_model(request.project)
|
|
45
|
+
raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
|
|
46
|
+
|
|
47
|
+
File.write(request.path, convert_to_json_pretty(request.project))
|
|
48
|
+
Google::Protobuf::Empty.new
|
|
49
|
+
rescue ArgumentError => e
|
|
50
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
51
|
+
rescue StandardError => e
|
|
52
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Save a project to the default .makit.json file
|
|
56
|
+
def save_to_default(request, _unused_call)
|
|
57
|
+
validate_project_model(request.project)
|
|
58
|
+
File.write(".makit.json", convert_to_json_pretty(request.project))
|
|
59
|
+
Google::Protobuf::Empty.new
|
|
60
|
+
rescue ArgumentError => e
|
|
61
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Load the default project from .makit.json or create a new one
|
|
67
|
+
def load_default(request, _unused_call)
|
|
68
|
+
if File.exist?(".makit.json")
|
|
69
|
+
load_from_file(LoadFromFileRequest.new(path: ".makit.json"), nil)
|
|
70
|
+
else
|
|
71
|
+
project = Project.new(
|
|
72
|
+
name: "",
|
|
73
|
+
version: "0.0.0",
|
|
74
|
+
project_type: "",
|
|
75
|
+
authors: "authors",
|
|
76
|
+
description: "description",
|
|
77
|
+
license_expression: "MIT",
|
|
78
|
+
steps: []
|
|
79
|
+
)
|
|
80
|
+
Makit::Logging.default_logger.warn("Project not configured")
|
|
81
|
+
project
|
|
82
|
+
end
|
|
83
|
+
rescue StandardError => e
|
|
84
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Generate GitLab CI YAML from project
|
|
88
|
+
def generate_gitlab_ci(request, _unused_call)
|
|
89
|
+
validate_project_model(request.project)
|
|
90
|
+
raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
|
|
91
|
+
|
|
92
|
+
# Convert protobuf model to Ruby model for GitLab helper
|
|
93
|
+
ruby_model = convert_to_ruby_model(request.project)
|
|
94
|
+
Makit::Configuration::GitLabHelper.to_yaml(ruby_model, request.path)
|
|
95
|
+
Google::Protobuf::Empty.new
|
|
96
|
+
rescue ArgumentError => e
|
|
97
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
98
|
+
rescue StandardError => e
|
|
99
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Generate Rakefile from project
|
|
103
|
+
def generate_rakefile(request, _unused_call)
|
|
104
|
+
validate_project_model(request.project)
|
|
105
|
+
|
|
106
|
+
# Convert protobuf model to Ruby model for Rakefile helper
|
|
107
|
+
ruby_model = convert_to_ruby_model(request.project)
|
|
108
|
+
content = Makit::Configuration::RakefileHelper.generate(ruby_model)
|
|
109
|
+
GenerateRakefileResponse.new(content: content)
|
|
110
|
+
rescue ArgumentError => e
|
|
111
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
112
|
+
rescue StandardError => e
|
|
113
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Write Rakefile to file
|
|
117
|
+
def write_rakefile(request, _unused_call)
|
|
118
|
+
validate_project_model(request.project)
|
|
119
|
+
raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
|
|
120
|
+
|
|
121
|
+
# Convert protobuf model to Ruby model for Rakefile helper
|
|
122
|
+
ruby_model = convert_to_ruby_model(request.project)
|
|
123
|
+
Makit::Configuration::RakefileHelper.write(ruby_model, request.path)
|
|
124
|
+
Google::Protobuf::Empty.new
|
|
125
|
+
rescue ArgumentError => e
|
|
126
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
127
|
+
rescue StandardError => e
|
|
128
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Validate project configuration
|
|
132
|
+
def validate_project(request, _unused_call)
|
|
133
|
+
errors = validate_project_model_errors(request.project)
|
|
134
|
+
ValidateProjectResponse.new(errors: errors)
|
|
135
|
+
rescue StandardError => e
|
|
136
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Merge two project configurations
|
|
140
|
+
def merge_projects(request, _unused_call)
|
|
141
|
+
merged = Project.new(
|
|
142
|
+
git_remote_url: request.override_project.git_remote_url || request.base_project.git_remote_url,
|
|
143
|
+
name: request.override_project.name || request.base_project.name,
|
|
144
|
+
version: request.override_project.version || request.base_project.version,
|
|
145
|
+
project_type: request.override_project.project_type || request.base_project.project_type,
|
|
146
|
+
authors: request.override_project.authors || request.base_project.authors,
|
|
147
|
+
description: request.override_project.description || request.base_project.description,
|
|
148
|
+
license_expression: request.override_project.license_expression || request.base_project.license_expression,
|
|
149
|
+
dotnet_projects: request.override_project.dotnet_projects.any? ? request.override_project.dotnet_projects.to_a : request.base_project.dotnet_projects.to_a,
|
|
150
|
+
steps: request.override_project.steps.any? ? request.override_project.steps.to_a : request.base_project.steps.to_a
|
|
151
|
+
)
|
|
152
|
+
merged
|
|
153
|
+
rescue StandardError => e
|
|
154
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Create a new project with default values
|
|
158
|
+
def create_project(request, _unused_call)
|
|
159
|
+
raise ArgumentError, "Project name cannot be empty" if request.name.nil? || request.name.strip.empty?
|
|
160
|
+
|
|
161
|
+
project = Project.new(
|
|
162
|
+
name: request.name,
|
|
163
|
+
version: request.version || "0.0.0",
|
|
164
|
+
project_type: request.project_type || "gem",
|
|
165
|
+
authors: "authors",
|
|
166
|
+
description: "description",
|
|
167
|
+
license_expression: "MIT",
|
|
168
|
+
steps: []
|
|
169
|
+
)
|
|
170
|
+
project
|
|
171
|
+
rescue ArgumentError => e
|
|
172
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INVALID_ARGUMENT, e.message)
|
|
173
|
+
rescue StandardError => e
|
|
174
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Update project with new values
|
|
178
|
+
def update_project(request, _unused_call)
|
|
179
|
+
updated_project = Project.new(
|
|
180
|
+
git_remote_url: request.project.git_remote_url,
|
|
181
|
+
name: request.project.name,
|
|
182
|
+
version: request.project.version,
|
|
183
|
+
project_type: request.project.project_type,
|
|
184
|
+
authors: request.project.authors,
|
|
185
|
+
description: request.project.description,
|
|
186
|
+
license_expression: request.project.license_expression,
|
|
187
|
+
dotnet_projects: request.project.dotnet_projects.to_a,
|
|
188
|
+
steps: request.project.steps.to_a
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Apply updates
|
|
192
|
+
request.updates.each do |key, value|
|
|
193
|
+
case key.to_sym
|
|
194
|
+
when :name
|
|
195
|
+
updated_project.name = value
|
|
196
|
+
when :version
|
|
197
|
+
updated_project.version = value
|
|
198
|
+
when :project_type
|
|
199
|
+
updated_project.project_type = value
|
|
200
|
+
when :authors
|
|
201
|
+
updated_project.authors = value
|
|
202
|
+
when :description
|
|
203
|
+
updated_project.description = value
|
|
204
|
+
when :license_expression
|
|
205
|
+
updated_project.license_expression = value
|
|
206
|
+
when :git_remote_url
|
|
207
|
+
updated_project.git_remote_url = value
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
updated_project
|
|
212
|
+
rescue StandardError => e
|
|
213
|
+
raise GRPC::BadStatus.new(GRPC::Core::StatusCodes::INTERNAL, e.message)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
private
|
|
217
|
+
|
|
218
|
+
# Validate project model
|
|
219
|
+
def validate_project_model(project)
|
|
220
|
+
errors = validate_project_model_errors(project)
|
|
221
|
+
raise ArgumentError, errors.join(", ") if errors.any?
|
|
222
|
+
errors
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# Validate project model and return errors without raising
|
|
226
|
+
def validate_project_model_errors(project)
|
|
227
|
+
errors = []
|
|
228
|
+
|
|
229
|
+
errors << "Project name cannot be empty" if project.name.nil? || project.name.strip.empty?
|
|
230
|
+
errors << "Project version cannot be empty" if project.version.nil? || project.version.strip.empty?
|
|
231
|
+
errors << "Project type cannot be empty" if project.project_type.nil? || project.project_type.strip.empty?
|
|
232
|
+
|
|
233
|
+
# Validate steps
|
|
234
|
+
project.steps.each_with_index do |step, index|
|
|
235
|
+
errors << "Step #{index} name cannot be empty" if step.name.nil? || step.name.strip.empty?
|
|
236
|
+
errors << "Step #{index} description cannot be empty" if step.description.nil? || step.description.strip.empty?
|
|
237
|
+
errors << "Step #{index} commands cannot be empty" if step.commands.nil? || step.commands.empty?
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
errors
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
# Convert JSON data to Project
|
|
244
|
+
def convert_from_json_data(data)
|
|
245
|
+
project = Project.new(
|
|
246
|
+
git_remote_url: data[:git_remote_url] || "",
|
|
247
|
+
name: data[:name] || "",
|
|
248
|
+
version: data[:version] || "",
|
|
249
|
+
project_type: data[:project_type] || "",
|
|
250
|
+
authors: data[:authors] || "authors",
|
|
251
|
+
description: data[:description] || "description",
|
|
252
|
+
license_expression: data[:license_expression] || "MIT",
|
|
253
|
+
dotnet_projects: data[:dotnet_projects] || []
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# Convert steps
|
|
257
|
+
(data[:steps] || []).each do |step_data|
|
|
258
|
+
step = Step.new(
|
|
259
|
+
name: step_data[:name] || "",
|
|
260
|
+
description: step_data[:description] || "",
|
|
261
|
+
commands: step_data[:commands] || []
|
|
262
|
+
)
|
|
263
|
+
project.steps << step
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
project
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Convert Project to pretty JSON
|
|
270
|
+
def convert_to_json_pretty(project)
|
|
271
|
+
project_data = {
|
|
272
|
+
name: project.name,
|
|
273
|
+
version: project.version,
|
|
274
|
+
project_type: project.project_type,
|
|
275
|
+
authors: project.authors,
|
|
276
|
+
description: project.description,
|
|
277
|
+
license_expression: project.license_expression,
|
|
278
|
+
steps: project.steps.map do |step|
|
|
279
|
+
{
|
|
280
|
+
name: step.name,
|
|
281
|
+
description: step.description,
|
|
282
|
+
commands: step.commands.to_a
|
|
283
|
+
}
|
|
284
|
+
end
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
JSON.pretty_generate(project_data)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Convert Protobuf Project to Ruby model for helper classes
|
|
291
|
+
def convert_to_ruby_model(proto_model)
|
|
292
|
+
# Create a simple Ruby object that mimics the Project interface
|
|
293
|
+
ruby_model = Object.new
|
|
294
|
+
|
|
295
|
+
def ruby_model.name
|
|
296
|
+
@name
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def ruby_model.name=(value)
|
|
300
|
+
@name = value
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def ruby_model.version
|
|
304
|
+
@version
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def ruby_model.version=(value)
|
|
308
|
+
@version = value
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def ruby_model.project_type
|
|
312
|
+
@project_type
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def ruby_model.project_type=(value)
|
|
316
|
+
@project_type = value
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def ruby_model.steps
|
|
320
|
+
@steps ||= []
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def ruby_model.steps=(value)
|
|
324
|
+
@steps = value
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
ruby_model.name = proto_model.name
|
|
328
|
+
ruby_model.version = proto_model.version
|
|
329
|
+
ruby_model.project_type = proto_model.project_type
|
|
330
|
+
|
|
331
|
+
# Convert steps
|
|
332
|
+
ruby_steps = proto_model.steps.map do |proto_step|
|
|
333
|
+
ruby_step = Object.new
|
|
334
|
+
|
|
335
|
+
def ruby_step.name
|
|
336
|
+
@name
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def ruby_step.name=(value)
|
|
340
|
+
@name = value
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def ruby_step.description
|
|
344
|
+
@description
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def ruby_step.description=(value)
|
|
348
|
+
@description = value
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def ruby_step.commands
|
|
352
|
+
@commands ||= []
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def ruby_step.commands=(value)
|
|
356
|
+
@commands = value
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
ruby_step.name = proto_step.name
|
|
360
|
+
ruby_step.description = proto_step.description
|
|
361
|
+
ruby_step.commands = proto_step.commands.to_a
|
|
362
|
+
ruby_step
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
ruby_model.steps = ruby_steps
|
|
366
|
+
ruby_model
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
end
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
5
|
+
module Makit
|
|
6
|
+
module V1
|
|
7
|
+
module Git
|
|
8
|
+
# Implementation of the GitRepositoryService gRPC service
|
|
9
|
+
class GitRepositoryServiceImpl < GitRepositoryService::Service
|
|
10
|
+
# Get current repository state
|
|
11
|
+
def get_repository_state(request, _unused_call)
|
|
12
|
+
# Get the current repository state using direct git commands
|
|
13
|
+
model = GitRepositoryModel.new
|
|
14
|
+
|
|
15
|
+
# Basic repository checks
|
|
16
|
+
model.is_git_repo = Dir.exist?(".git")
|
|
17
|
+
model.is_ci = ENV["CI"] == "true"
|
|
18
|
+
model.is_detached = `git status`.include?("detached")
|
|
19
|
+
model.is_read_only = !model.is_git_repo || model.is_detached
|
|
20
|
+
model.is_clean = `git status --porcelain`.empty?
|
|
21
|
+
|
|
22
|
+
# File information
|
|
23
|
+
model.unstaged_files.concat(`git status --porcelain`.split("\n"))
|
|
24
|
+
model.untracked_files.concat(`git ls-files --others --exclude-standard`.split("\n"))
|
|
25
|
+
model.tracked_file_infos.concat(get_file_infos_proto)
|
|
26
|
+
model.untracked_file_infos.concat(get_untracked_file_infos_proto)
|
|
27
|
+
|
|
28
|
+
# Commit information
|
|
29
|
+
model.branch = `git branch --show-current`.strip
|
|
30
|
+
model.commit_sha = `git rev-parse HEAD`.strip
|
|
31
|
+
model.commit_message = `git log -1 --pretty=%B`.strip
|
|
32
|
+
model.commit_date = `git log -1 --pretty=%cd`.strip
|
|
33
|
+
model.commit_author = `git log -1 --pretty=%an`.strip
|
|
34
|
+
model.commit_email = `git log -1 --pretty=%ae`.strip
|
|
35
|
+
model.remote_url = `git remote get-url origin`.strip
|
|
36
|
+
|
|
37
|
+
model
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Save repository state to file
|
|
41
|
+
def save_repository_state(request, _unused_call)
|
|
42
|
+
raise ArgumentError, "Model cannot be nil" if request.repository.nil?
|
|
43
|
+
raise ArgumentError, "Path cannot be empty" if request.path.nil? || request.path.strip.empty?
|
|
44
|
+
|
|
45
|
+
# Convert protobuf model to JSON and save
|
|
46
|
+
json_data = convert_proto_to_json(request.repository)
|
|
47
|
+
File.write(request.path, JSON.pretty_generate(json_data))
|
|
48
|
+
|
|
49
|
+
Google::Protobuf::Empty.new
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Load repository state from file
|
|
53
|
+
def load_repository_state(request, _unused_call)
|
|
54
|
+
raise ArgumentError, "File does not exist: #{request.path}" unless File.exist?(request.path)
|
|
55
|
+
|
|
56
|
+
content = File.read(request.path)
|
|
57
|
+
json_data = JSON.parse(content, symbolize_names: true)
|
|
58
|
+
convert_json_to_proto(json_data)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Validate repository state
|
|
62
|
+
def validate_repository_state(request, _unused_call)
|
|
63
|
+
errors = []
|
|
64
|
+
|
|
65
|
+
if request.repository.nil?
|
|
66
|
+
errors << "Model cannot be nil"
|
|
67
|
+
else
|
|
68
|
+
# Basic validation
|
|
69
|
+
if request.repository.is_git_repo
|
|
70
|
+
errors << "Branch cannot be empty for git repository" if request.repository.branch.nil? || request.repository.branch.strip.empty?
|
|
71
|
+
errors << "Commit SHA cannot be empty for git repository" if request.repository.commit_sha.nil? || request.repository.commit_sha.strip.empty?
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
ValidateRepositoryStateResponse.new(errors: errors)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Merge two repository states
|
|
79
|
+
def merge_repository_states(request, _unused_call)
|
|
80
|
+
base = request.base_repository
|
|
81
|
+
override = request.override_repository
|
|
82
|
+
|
|
83
|
+
merged = GitRepositoryModel.new
|
|
84
|
+
|
|
85
|
+
# Use override values if present and not empty, otherwise use base values
|
|
86
|
+
merged.is_git_repo = override.is_git_repo || base.is_git_repo
|
|
87
|
+
merged.is_ci = override.is_ci || base.is_ci
|
|
88
|
+
merged.is_detached = override.is_detached || base.is_detached
|
|
89
|
+
merged.is_read_only = override.is_read_only || base.is_read_only
|
|
90
|
+
merged.is_clean = override.is_clean || base.is_clean
|
|
91
|
+
merged.unstaged_files.concat(override.unstaged_files.any? ? override.unstaged_files.to_a : base.unstaged_files.to_a)
|
|
92
|
+
merged.untracked_files.concat(override.untracked_files.any? ? override.untracked_files.to_a : base.untracked_files.to_a)
|
|
93
|
+
merged.tracked_file_infos.concat(override.tracked_file_infos.any? ? override.tracked_file_infos.to_a : base.tracked_file_infos.to_a)
|
|
94
|
+
merged.untracked_file_infos.concat(override.untracked_file_infos.any? ? override.untracked_file_infos.to_a : base.untracked_file_infos.to_a)
|
|
95
|
+
merged.branch = (override.branch && !override.branch.empty?) ? override.branch : base.branch
|
|
96
|
+
merged.commit_sha = (override.commit_sha && !override.commit_sha.empty?) ? override.commit_sha : base.commit_sha
|
|
97
|
+
merged.commit_message = (override.commit_message && !override.commit_message.empty?) ? override.commit_message : base.commit_message
|
|
98
|
+
merged.commit_date = (override.commit_date && !override.commit_date.empty?) ? override.commit_date : base.commit_date
|
|
99
|
+
merged.commit_author = (override.commit_author && !override.commit_author.empty?) ? override.commit_author : base.commit_author
|
|
100
|
+
merged.commit_email = (override.commit_email && !override.commit_email.empty?) ? override.commit_email : base.commit_email
|
|
101
|
+
merged.remote_url = (override.remote_url && !override.remote_url.empty?) ? override.remote_url : base.remote_url
|
|
102
|
+
|
|
103
|
+
merged
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Create a new repository state
|
|
107
|
+
def create_repository_state(request, _unused_call)
|
|
108
|
+
model = GitRepositoryModel.new
|
|
109
|
+
|
|
110
|
+
model.is_git_repo = request.is_git_repo
|
|
111
|
+
model.is_ci = request.is_ci
|
|
112
|
+
model.is_detached = request.is_detached
|
|
113
|
+
model.is_read_only = request.is_read_only
|
|
114
|
+
model.is_clean = request.is_clean
|
|
115
|
+
model.branch = request.branch
|
|
116
|
+
model.commit_sha = request.commit_sha
|
|
117
|
+
model.commit_message = request.commit_message
|
|
118
|
+
model.commit_date = request.commit_date
|
|
119
|
+
model.commit_author = request.commit_author
|
|
120
|
+
model.commit_email = request.commit_email
|
|
121
|
+
model.remote_url = request.remote_url
|
|
122
|
+
|
|
123
|
+
model
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Update repository state
|
|
127
|
+
def update_repository_state(request, _unused_call)
|
|
128
|
+
raise ArgumentError, "Model cannot be nil" if request.repository.nil?
|
|
129
|
+
raise ArgumentError, "Updates cannot be nil" if request.updates.nil?
|
|
130
|
+
|
|
131
|
+
model = GitRepositoryModel.new
|
|
132
|
+
model.is_git_repo = request.repository.is_git_repo
|
|
133
|
+
model.is_ci = request.repository.is_ci
|
|
134
|
+
model.is_detached = request.repository.is_detached
|
|
135
|
+
model.is_read_only = request.repository.is_read_only
|
|
136
|
+
model.is_clean = request.repository.is_clean
|
|
137
|
+
model.unstaged_files.concat(request.repository.unstaged_files.to_a)
|
|
138
|
+
model.untracked_files.concat(request.repository.untracked_files.to_a)
|
|
139
|
+
model.tracked_file_infos.concat(request.repository.tracked_file_infos.to_a)
|
|
140
|
+
model.untracked_file_infos.concat(request.repository.untracked_file_infos.to_a)
|
|
141
|
+
model.branch = request.repository.branch
|
|
142
|
+
model.commit_sha = request.repository.commit_sha
|
|
143
|
+
model.commit_message = request.repository.commit_message
|
|
144
|
+
model.commit_date = request.repository.commit_date
|
|
145
|
+
model.commit_author = request.repository.commit_author
|
|
146
|
+
model.commit_email = request.repository.commit_email
|
|
147
|
+
model.remote_url = request.repository.remote_url
|
|
148
|
+
|
|
149
|
+
# Apply updates
|
|
150
|
+
request.updates.each do |key, value|
|
|
151
|
+
case key.to_sym
|
|
152
|
+
when :is_git_repo
|
|
153
|
+
model.is_git_repo = value == "true"
|
|
154
|
+
when :is_ci
|
|
155
|
+
model.is_ci = value == "true"
|
|
156
|
+
when :is_detached
|
|
157
|
+
model.is_detached = value == "true"
|
|
158
|
+
when :is_read_only
|
|
159
|
+
model.is_read_only = value == "true"
|
|
160
|
+
when :is_clean
|
|
161
|
+
model.is_clean = value == "true"
|
|
162
|
+
when :branch
|
|
163
|
+
model.branch = value
|
|
164
|
+
when :commit_sha
|
|
165
|
+
model.commit_sha = value
|
|
166
|
+
when :commit_message
|
|
167
|
+
model.commit_message = value
|
|
168
|
+
when :commit_date
|
|
169
|
+
model.commit_date = value
|
|
170
|
+
when :commit_author
|
|
171
|
+
model.commit_author = value
|
|
172
|
+
when :commit_email
|
|
173
|
+
model.commit_email = value
|
|
174
|
+
when :remote_url
|
|
175
|
+
model.remote_url = value
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
model
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
|
|
184
|
+
# Get file information for tracked files
|
|
185
|
+
def get_file_infos_proto
|
|
186
|
+
file_infos = []
|
|
187
|
+
file_list = `git ls-files`.split("\n")
|
|
188
|
+
file_list.each do |file|
|
|
189
|
+
file_infos << convert_file_info_to_proto(file)
|
|
190
|
+
rescue StandardError
|
|
191
|
+
next
|
|
192
|
+
end
|
|
193
|
+
file_infos.sort_by { |info| info.mtime.seconds }.reverse!
|
|
194
|
+
file_infos
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Get file information for untracked files
|
|
198
|
+
def get_untracked_file_infos_proto
|
|
199
|
+
file_infos = []
|
|
200
|
+
file_list = `git ls-files --others --exclude-standard`.split("\n")
|
|
201
|
+
file_list.each do |file|
|
|
202
|
+
file_infos << convert_file_info_to_proto(file)
|
|
203
|
+
rescue StandardError
|
|
204
|
+
next
|
|
205
|
+
end
|
|
206
|
+
file_infos.sort_by { |info| info.mtime.seconds }.reverse!
|
|
207
|
+
file_infos
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# Convert file path to protobuf FileInfo
|
|
211
|
+
def convert_file_info_to_proto(file_path)
|
|
212
|
+
timestamp = Google::Protobuf::Timestamp.new
|
|
213
|
+
mtime = File.mtime(file_path)
|
|
214
|
+
timestamp.seconds = mtime.to_i
|
|
215
|
+
timestamp.nanos = mtime.nsec
|
|
216
|
+
|
|
217
|
+
FileInfo.new(
|
|
218
|
+
name: file_path,
|
|
219
|
+
mtime: timestamp,
|
|
220
|
+
size: File.size(file_path)
|
|
221
|
+
)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Convert protobuf model to JSON hash
|
|
225
|
+
def convert_proto_to_json(proto_model)
|
|
226
|
+
{
|
|
227
|
+
is_git_repo: proto_model.is_git_repo,
|
|
228
|
+
is_ci: proto_model.is_ci,
|
|
229
|
+
is_detached: proto_model.is_detached,
|
|
230
|
+
is_read_only: proto_model.is_read_only,
|
|
231
|
+
is_clean: proto_model.is_clean,
|
|
232
|
+
unstaged_files: proto_model.unstaged_files.to_a,
|
|
233
|
+
untracked_files: proto_model.untracked_files.to_a,
|
|
234
|
+
tracked_file_infos: proto_model.tracked_file_infos.map { |info| convert_file_info_to_json(info) },
|
|
235
|
+
untracked_file_infos: proto_model.untracked_file_infos.map { |info| convert_file_info_to_json(info) },
|
|
236
|
+
branch: proto_model.branch,
|
|
237
|
+
commit_sha: proto_model.commit_sha,
|
|
238
|
+
commit_message: proto_model.commit_message,
|
|
239
|
+
commit_date: proto_model.commit_date,
|
|
240
|
+
commit_author: proto_model.commit_author,
|
|
241
|
+
commit_email: proto_model.commit_email,
|
|
242
|
+
remote_url: proto_model.remote_url
|
|
243
|
+
}
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Convert JSON hash to protobuf model
|
|
247
|
+
def convert_json_to_proto(json_data)
|
|
248
|
+
model = GitRepositoryModel.new
|
|
249
|
+
|
|
250
|
+
model.is_git_repo = json_data[:is_git_repo] || false
|
|
251
|
+
model.is_ci = json_data[:is_ci] || false
|
|
252
|
+
model.is_detached = json_data[:is_detached] || false
|
|
253
|
+
model.is_read_only = json_data[:is_read_only] || false
|
|
254
|
+
model.is_clean = json_data[:is_clean] || false
|
|
255
|
+
model.unstaged_files.concat(json_data[:unstaged_files] || [])
|
|
256
|
+
model.untracked_files.concat(json_data[:untracked_files] || [])
|
|
257
|
+
model.tracked_file_infos.concat((json_data[:tracked_file_infos] || []).map { |info| convert_file_info_from_json(info) })
|
|
258
|
+
model.untracked_file_infos.concat((json_data[:untracked_file_infos] || []).map { |info| convert_file_info_from_json(info) })
|
|
259
|
+
model.branch = json_data[:branch] || ""
|
|
260
|
+
model.commit_sha = json_data[:commit_sha] || ""
|
|
261
|
+
model.commit_message = json_data[:commit_message] || ""
|
|
262
|
+
model.commit_date = json_data[:commit_date] || ""
|
|
263
|
+
model.commit_author = json_data[:commit_author] || ""
|
|
264
|
+
model.commit_email = json_data[:commit_email] || ""
|
|
265
|
+
model.remote_url = json_data[:remote_url] || ""
|
|
266
|
+
|
|
267
|
+
model
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Convert protobuf FileInfo to JSON hash
|
|
271
|
+
def convert_file_info_to_json(proto_file_info)
|
|
272
|
+
{
|
|
273
|
+
name: proto_file_info.name,
|
|
274
|
+
mtime: Time.at(proto_file_info.mtime.seconds, proto_file_info.mtime.nanos, :nsec).to_s,
|
|
275
|
+
size: proto_file_info.size
|
|
276
|
+
}
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Convert JSON hash to protobuf FileInfo
|
|
280
|
+
def convert_file_info_from_json(json_file_info)
|
|
281
|
+
timestamp = Google::Protobuf::Timestamp.new
|
|
282
|
+
mtime = Time.parse(json_file_info[:mtime])
|
|
283
|
+
timestamp.seconds = mtime.to_i
|
|
284
|
+
timestamp.nanos = mtime.nsec
|
|
285
|
+
|
|
286
|
+
FileInfo.new(
|
|
287
|
+
name: json_file_info[:name],
|
|
288
|
+
mtime: timestamp,
|
|
289
|
+
size: json_file_info[:size]
|
|
290
|
+
)
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|