rakit 0.1.4 → 0.1.6
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/exe/rakit +104 -0
- data/lib/generated/data_pb.rb +1 -2
- data/lib/generated/rakit.azure_pb.rb +26 -0
- data/lib/generated/{example_pb.rb → rakit.example_pb.rb} +4 -3
- data/lib/generated/rakit.file_pb.rb +22 -0
- data/lib/generated/rakit.shell_pb.rb +22 -0
- data/lib/generated/rakit.static_web_server_pb.rb +20 -0
- data/lib/generated/rakit.word_count_pb.rb +22 -0
- data/lib/rakit/azure/dev_ops.rb +1 -1
- data/lib/rakit/cli/file.rb +163 -0
- data/lib/rakit/cli/word_count.rb +131 -0
- data/lib/rakit/file.rb +181 -0
- data/lib/rakit/gem.rb +87 -14
- data/lib/rakit/git.rb +10 -4
- data/lib/rakit/hugo.rb +43 -0
- data/lib/rakit/protobuf.rb +11 -9
- data/lib/rakit/shell.rb +1 -1
- data/lib/rakit/static_web_server.rb +226 -0
- data/lib/rakit/word_count.rb +122 -0
- data/lib/rakit.rb +5 -2
- metadata +25 -9
- data/lib/generated/azure.devops_pb.rb +0 -25
- data/lib/generated/shell_pb.rb +0 -22
- data/lib/rakit/data.rb +0 -173
data/lib/rakit/file.rb
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "generated/rakit.file_pb"
|
|
5
|
+
|
|
6
|
+
module Rakit
|
|
7
|
+
# Protobuf-first file operations (list directory, copy file). See specs/005-file-ops/contracts/ruby-api.md.
|
|
8
|
+
module File
|
|
9
|
+
class << self
|
|
10
|
+
# @param request [Rakit::File::ListRequest]
|
|
11
|
+
# @return [Rakit::File::ListResult]
|
|
12
|
+
def list(request)
|
|
13
|
+
dir_path = normalize_path(request.directory.to_s)
|
|
14
|
+
if dir_path.nil?
|
|
15
|
+
return error_list_result("Empty or invalid directory path", 1)
|
|
16
|
+
end
|
|
17
|
+
unless ::File.exist?(dir_path)
|
|
18
|
+
return error_list_result("Directory does not exist: #{dir_path}", 1)
|
|
19
|
+
end
|
|
20
|
+
unless ::File.directory?(dir_path)
|
|
21
|
+
return error_list_result("Not a directory: #{dir_path}", 1)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
include_hidden = request.include_hidden
|
|
25
|
+
follow_symlinks = request.config&.follow_symlinks == true
|
|
26
|
+
entries = request.recursive ? list_entries_recursive(dir_path, include_hidden, follow_symlinks) : list_entries_one_dir(dir_path, include_hidden, follow_symlinks)
|
|
27
|
+
|
|
28
|
+
ListResult.new(
|
|
29
|
+
success: true,
|
|
30
|
+
message: "",
|
|
31
|
+
entries: entries,
|
|
32
|
+
exit_code: 0,
|
|
33
|
+
stderr: ""
|
|
34
|
+
)
|
|
35
|
+
rescue => e
|
|
36
|
+
error_list_result("#{e.message}", 1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @param request [Rakit::File::CopyRequest]
|
|
40
|
+
# @return [Rakit::File::CopyResult]
|
|
41
|
+
def copy(request)
|
|
42
|
+
config = request.config || FileConfig.new
|
|
43
|
+
src = normalize_path(request.source.to_s)
|
|
44
|
+
dest_raw = normalize_path(request.destination.to_s)
|
|
45
|
+
|
|
46
|
+
if src.nil? || dest_raw.nil?
|
|
47
|
+
return error_copy_result(request.source.to_s, request.destination.to_s, "Empty or invalid path", 1)
|
|
48
|
+
end
|
|
49
|
+
unless ::File.exist?(src)
|
|
50
|
+
return error_copy_result(src, dest_raw, "Source does not exist: #{src}", 1)
|
|
51
|
+
end
|
|
52
|
+
if ::File.directory?(src)
|
|
53
|
+
return error_copy_result(src, dest_raw, "Source is a directory (MVP: file only)", 1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
dest_path = resolve_copy_destination(src, dest_raw)
|
|
57
|
+
parent = ::File.dirname(dest_path)
|
|
58
|
+
|
|
59
|
+
unless ::File.directory?(parent)
|
|
60
|
+
if config.create_directories
|
|
61
|
+
FileUtils.mkdir_p(parent)
|
|
62
|
+
else
|
|
63
|
+
return error_copy_result(src, dest_path, "Parent directory does not exist: #{parent}", 1)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
if ::File.file?(dest_path) && !config.overwrite
|
|
68
|
+
return error_copy_result(src, dest_path, "Destination file exists (use overwrite to replace)", 1)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
bytes = perform_copy(src, dest_path, config)
|
|
72
|
+
CopyResult.new(
|
|
73
|
+
success: true,
|
|
74
|
+
message: "",
|
|
75
|
+
source: src,
|
|
76
|
+
destination: dest_path,
|
|
77
|
+
exit_code: 0,
|
|
78
|
+
stderr: "",
|
|
79
|
+
bytes_copied: bytes || 0
|
|
80
|
+
)
|
|
81
|
+
rescue => e
|
|
82
|
+
error_copy_result(request.source.to_s, request.destination.to_s, e.message, 1)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
# T004: Path normalization. Returns expanded absolute path or nil if nil/empty.
|
|
88
|
+
def normalize_path(path, base_dir = nil)
|
|
89
|
+
return nil if path.nil?
|
|
90
|
+
s = path.to_s.strip
|
|
91
|
+
return nil if s.empty?
|
|
92
|
+
base = base_dir || Dir.pwd
|
|
93
|
+
::File.expand_path(s, base)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def error_list_result(message, exit_code)
|
|
97
|
+
ListResult.new(success: false, message: message, entries: [], exit_code: exit_code, stderr: message)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def error_copy_result(source, destination, message, exit_code)
|
|
101
|
+
CopyResult.new(success: false, message: message, source: source.to_s, destination: destination.to_s, exit_code: exit_code, stderr: message)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# T005: List entries for one directory; sort by name; filter hidden; best-effort metadata.
|
|
105
|
+
def list_entries_one_dir(dir_path, include_hidden, follow_symlinks)
|
|
106
|
+
names = Dir.children(dir_path)
|
|
107
|
+
names.reject! { |n| n.start_with?(".") } unless include_hidden
|
|
108
|
+
names.sort!
|
|
109
|
+
names.map { |name| file_entry_for(::File.join(dir_path, name), name, follow_symlinks) }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def file_entry_for(abs_path, name, follow_symlinks)
|
|
113
|
+
stat = follow_symlinks ? (::File.stat(abs_path) rescue nil) : (::File.lstat(abs_path) rescue nil)
|
|
114
|
+
is_symlink = ::File.symlink?(abs_path)
|
|
115
|
+
is_dir = stat ? stat.directory? : false
|
|
116
|
+
size_bytes = (stat && stat.file?) ? (stat.size rescue 0) : 0
|
|
117
|
+
modified_unix_ms = stat ? (stat.mtime.to_f * 1000).to_i : 0
|
|
118
|
+
FileEntry.new(
|
|
119
|
+
path: abs_path,
|
|
120
|
+
name: name,
|
|
121
|
+
is_directory: is_dir,
|
|
122
|
+
is_symlink: is_symlink,
|
|
123
|
+
size_bytes: size_bytes,
|
|
124
|
+
modified_unix_ms: modified_unix_ms
|
|
125
|
+
)
|
|
126
|
+
rescue
|
|
127
|
+
FileEntry.new(path: abs_path, name: name, is_directory: false, is_symlink: false, size_bytes: 0, modified_unix_ms: 0)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# T006: Depth-first recursive list; children at each level sorted by name.
|
|
131
|
+
def list_entries_recursive(dir_path, include_hidden, follow_symlinks)
|
|
132
|
+
entries = list_entries_one_dir(dir_path, include_hidden, follow_symlinks)
|
|
133
|
+
result = []
|
|
134
|
+
entries.each do |entry|
|
|
135
|
+
result << entry
|
|
136
|
+
if entry.is_directory
|
|
137
|
+
result.concat(list_entries_recursive(entry.path, include_hidden, follow_symlinks))
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
result
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Resolve destination: if existing directory, copy into it with basename(source); else file path.
|
|
144
|
+
def resolve_copy_destination(source, destination)
|
|
145
|
+
return ::File.join(destination, ::File.basename(source)) if ::File.exist?(destination) && ::File.directory?(destination)
|
|
146
|
+
destination
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# T007: Atomic copy where possible (temp then rename); respect follow_symlinks for source.
|
|
150
|
+
def perform_copy(source, dest_path, config)
|
|
151
|
+
if !config.follow_symlinks && ::File.symlink?(source)
|
|
152
|
+
# Copy symlink itself: create new symlink with same target
|
|
153
|
+
target = ::File.readlink(source)
|
|
154
|
+
::File.delete(dest_path) if ::File.exist?(dest_path)
|
|
155
|
+
::File.symlink(target, dest_path)
|
|
156
|
+
return 0 # best-effort bytes
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
content = ::File.binread(source)
|
|
160
|
+
dest_dir = ::File.dirname(dest_path)
|
|
161
|
+
temp_path = ::File.join(dest_dir, ".rakit_copy_#{Process.pid}_#{object_id}_#{::File.basename(dest_path)}")
|
|
162
|
+
bytes = nil
|
|
163
|
+
begin
|
|
164
|
+
::File.write(temp_path, content)
|
|
165
|
+
bytes = content.bytesize
|
|
166
|
+
::File.rename(temp_path, dest_path)
|
|
167
|
+
rescue Errno::EXDEV, Errno::EPERM
|
|
168
|
+
# Cross-filesystem or rename not allowed: fall back to overwrite
|
|
169
|
+
::File.write(dest_path, content)
|
|
170
|
+
bytes = content.bytesize
|
|
171
|
+
::File.delete(temp_path) if ::File.exist?(temp_path)
|
|
172
|
+
ensure
|
|
173
|
+
::File.delete(temp_path) if ::File.exist?(temp_path)
|
|
174
|
+
end
|
|
175
|
+
bytes
|
|
176
|
+
rescue => e
|
|
177
|
+
raise "Failed to copy: #{e.message}"
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
data/lib/rakit/gem.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "fileutils"
|
|
4
|
+
require "json"
|
|
5
|
+
require "open3"
|
|
4
6
|
require "rubygems/package"
|
|
5
7
|
|
|
6
8
|
module Rakit
|
|
@@ -11,29 +13,29 @@ module Rakit
|
|
|
11
13
|
FileUtils.mkdir_p(out_dir)
|
|
12
14
|
gem_file = ::Gem::Package.build(spec)
|
|
13
15
|
FileUtils.mv(gem_file, out_dir)
|
|
14
|
-
File.join(out_dir, gem_file)
|
|
16
|
+
::File.join(out_dir, gem_file)
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
# Publish the gem to rubygems.org. Loads the gemspec from gemspec_path and
|
|
18
20
|
# expects the .gem file in dirname(gemspec_path)/artifacts/. Run package first.
|
|
19
21
|
def self.publish(gemspec_path)
|
|
20
|
-
path = File.expand_path(gemspec_path)
|
|
22
|
+
path = ::File.expand_path(gemspec_path)
|
|
21
23
|
spec = ::Gem::Specification.load(path)
|
|
22
|
-
out_dir = File.join(File.dirname(path), "artifacts")
|
|
23
|
-
gem_path = File.join(out_dir, "#{spec.full_name}.gem")
|
|
24
|
+
out_dir = ::File.join(::File.dirname(path), "artifacts")
|
|
25
|
+
gem_path = ::File.join(out_dir, "#{spec.full_name}.gem")
|
|
24
26
|
push(gem_path)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
# Bump the last digit of the version in the gemspec file (e.g. "0.1.0" -> "0.1.1").
|
|
28
30
|
# Writes the file in place. Returns the new version string.
|
|
29
31
|
def self.bump(gemspec_path)
|
|
30
|
-
content = File.read(gemspec_path)
|
|
32
|
+
content = ::File.read(gemspec_path)
|
|
31
33
|
content.sub!(/^(\s*s\.version\s*=\s*["'])([\d.]+)(["'])/) do
|
|
32
34
|
segs = Regexp.last_match(2).split(".")
|
|
33
35
|
segs[-1] = (segs[-1].to_i + 1).to_s
|
|
34
36
|
"#{Regexp.last_match(1)}#{segs.join(".")}#{Regexp.last_match(3)}"
|
|
35
37
|
end or raise "No s.version line found in #{gemspec_path}"
|
|
36
|
-
File.write(gemspec_path, content)
|
|
38
|
+
::File.write(gemspec_path, content)
|
|
37
39
|
content[/s\.version\s*=\s*["']([^"']+)["']/, 1]
|
|
38
40
|
end
|
|
39
41
|
|
|
@@ -41,12 +43,11 @@ module Rakit
|
|
|
41
43
|
# published, warns and returns without pushing. Raises if the file is missing
|
|
42
44
|
# or if gem push fails.
|
|
43
45
|
def self.push(gem_path)
|
|
44
|
-
raise "Gem not found: #{gem_path}. Run rake package first." unless File.file?(gem_path)
|
|
46
|
+
raise "Gem not found: #{gem_path}. Run rake package first." unless ::File.file?(gem_path)
|
|
45
47
|
|
|
46
|
-
base = File.basename(gem_path, ".gem")
|
|
47
|
-
|
|
48
|
-
version
|
|
49
|
-
name = parts.join("-")
|
|
48
|
+
base = ::File.basename(gem_path, ".gem")
|
|
49
|
+
name, version = parse_gem_basename(base)
|
|
50
|
+
raise "Could not parse name/version from #{base}.gem" unless name && version
|
|
50
51
|
|
|
51
52
|
if version_published?(name, version)
|
|
52
53
|
warn "publish: Version #{version} of #{name} is already published on rubygems.org. Skipping push. Bump the version in the gemspec to publish again."
|
|
@@ -57,14 +58,86 @@ module Rakit
|
|
|
57
58
|
raise "gem push failed" unless success
|
|
58
59
|
end
|
|
59
60
|
|
|
61
|
+
# Parse "name-version" basename (no .gem) into [name, version].
|
|
62
|
+
# Version is the last hyphen-separated segment that looks like a version (e.g. 0.1.5).
|
|
63
|
+
def self.parse_gem_basename(base)
|
|
64
|
+
# Match name (may contain hyphens) and version (digits and dots, optional pre-release suffix).
|
|
65
|
+
m = base.match(/\A(.+)-(\d+(?:\.\d+)*(?:\.\w+)?)\z/)
|
|
66
|
+
m ? [m[1], m[2]] : nil
|
|
67
|
+
end
|
|
68
|
+
|
|
60
69
|
def self.version_published?(name, version)
|
|
70
|
+
begin
|
|
71
|
+
return true if version_published_gem_list?(name, version)
|
|
72
|
+
rescue StandardError
|
|
73
|
+
# try API fallbacks
|
|
74
|
+
end
|
|
75
|
+
begin
|
|
76
|
+
return true if version_published_v2?(name, version)
|
|
77
|
+
rescue StandardError
|
|
78
|
+
# try v1 fallback
|
|
79
|
+
end
|
|
80
|
+
begin
|
|
81
|
+
return true if version_published_v1?(name, version)
|
|
82
|
+
rescue StandardError
|
|
83
|
+
nil
|
|
84
|
+
end
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Run `gem list NAME --remote` and check if version appears in the output.
|
|
89
|
+
def self.version_published_gem_list?(name, version)
|
|
90
|
+
out, err, status = Open3.capture3("gem", "list", name, "--remote")
|
|
91
|
+
return false unless status.success?
|
|
92
|
+
# Output format: "name (1.0.0, 0.9.0)" or "name (1.0.0)"
|
|
93
|
+
combined = "#{out}#{err}"
|
|
94
|
+
combined.each_line do |line|
|
|
95
|
+
next unless line.include?(name)
|
|
96
|
+
if line =~ /\s*#{Regexp.escape(name)}\s*\((.*)\)/
|
|
97
|
+
versions = Regexp.last_match(1).split(",").map(&:strip)
|
|
98
|
+
return true if versions.include?(version)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
false
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# GET /api/v2/rubygems/{name}/versions/{version}.json (follows redirects)
|
|
105
|
+
def self.version_published_v2?(name, version)
|
|
61
106
|
require "net/http"
|
|
62
107
|
require "uri"
|
|
63
108
|
uri = URI("https://rubygems.org/api/v2/rubygems/#{URI::DEFAULT_PARSER.escape(name)}/versions/#{URI::DEFAULT_PARSER.escape(version)}.json")
|
|
64
|
-
response =
|
|
109
|
+
response = http_get_following_redirects(uri)
|
|
65
110
|
response.is_a?(Net::HTTPSuccess)
|
|
66
|
-
|
|
67
|
-
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# GET /api/v1/versions/{name}.json and check if version is in the list
|
|
114
|
+
def self.version_published_v1?(name, version)
|
|
115
|
+
require "net/http"
|
|
116
|
+
require "json"
|
|
117
|
+
require "uri"
|
|
118
|
+
uri = URI("https://rubygems.org/api/v1/versions/#{URI::DEFAULT_PARSER.escape(name)}.json")
|
|
119
|
+
response = http_get_following_redirects(uri)
|
|
120
|
+
return false unless response.is_a?(Net::HTTPSuccess)
|
|
121
|
+
list = JSON.parse(response.body)
|
|
122
|
+
list.is_a?(Array) && list.any? { |h| h["number"] == version }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def self.http_get_following_redirects(uri, limit: 5)
|
|
126
|
+
raise ArgumentError, "redirect limit exceeded" if limit <= 0
|
|
127
|
+
require "net/http"
|
|
128
|
+
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", open_timeout: 10, read_timeout: 10) do |http|
|
|
129
|
+
request = Net::HTTP::Get.new(uri)
|
|
130
|
+
request["User-Agent"] = "rakit (https://rubygems.org/gems/rakit)"
|
|
131
|
+
http.request(request)
|
|
132
|
+
end
|
|
133
|
+
case response
|
|
134
|
+
when Net::HTTPRedirection
|
|
135
|
+
location = response["location"]
|
|
136
|
+
next_uri = location.match?(/\Ahttps?:\/\//) ? URI(location) : URI.join(uri, location)
|
|
137
|
+
http_get_following_redirects(next_uri, limit: limit - 1)
|
|
138
|
+
else
|
|
139
|
+
response
|
|
140
|
+
end
|
|
68
141
|
end
|
|
69
142
|
end
|
|
70
143
|
end
|
data/lib/rakit/git.rb
CHANGED
|
@@ -4,12 +4,18 @@ module Rakit
|
|
|
4
4
|
module Git
|
|
5
5
|
# Sync the current directory with the remote (git pull, then git push).
|
|
6
6
|
# Runs from Dir.pwd. Raises if not a git repo or if pull/push fails.
|
|
7
|
+
# If the current branch has no remote tracking branch, pull and push are skipped (no error).
|
|
7
8
|
def self.sync(dir = nil)
|
|
8
9
|
require_relative "shell"
|
|
9
|
-
target = dir ? File.expand_path(dir) : Dir.pwd
|
|
10
|
-
raise "Not a git repository: #{target}" unless File.directory?(File.join(target, ".git"))
|
|
10
|
+
target = dir ? ::File.expand_path(dir) : Dir.pwd
|
|
11
|
+
raise "Not a git repository: #{target}" unless ::File.directory?(::File.join(target, ".git"))
|
|
11
12
|
|
|
12
13
|
Dir.chdir(target) do
|
|
14
|
+
check = Rakit::Shell.run("git rev-parse --abbrev-ref @{u}")
|
|
15
|
+
if check.exit_status != 0
|
|
16
|
+
# No upstream configured for current branch; skip sync
|
|
17
|
+
return
|
|
18
|
+
end
|
|
13
19
|
result = Rakit::Shell.run("git pull")
|
|
14
20
|
raise "git pull failed" unless result.exit_status == 0
|
|
15
21
|
result = Rakit::Shell.run("git push")
|
|
@@ -22,8 +28,8 @@ module Rakit
|
|
|
22
28
|
# Raises if not a git repo or if add fails.
|
|
23
29
|
def self.integrate(commit_message = nil, dir = nil)
|
|
24
30
|
require_relative "shell"
|
|
25
|
-
target = dir ? File.expand_path(dir) : Dir.pwd
|
|
26
|
-
raise "Not a git repository: #{target}" unless File.directory?(File.join(target, ".git"))
|
|
31
|
+
target = dir ? ::File.expand_path(dir) : Dir.pwd
|
|
32
|
+
raise "Not a git repository: #{target}" unless ::File.directory?(::File.join(target, ".git"))
|
|
27
33
|
|
|
28
34
|
message = commit_message || "Integrate"
|
|
29
35
|
Dir.chdir(target) do
|
data/lib/rakit/hugo.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
5
|
+
module Rakit
|
|
6
|
+
# Build Hugo static sites from source. Used by publish_docs and tests.
|
|
7
|
+
# Contract: specs/008-hugo-docs-site/contracts/ruby-api.md
|
|
8
|
+
module Hugo
|
|
9
|
+
class << self
|
|
10
|
+
attr_accessor :hugo_path
|
|
11
|
+
|
|
12
|
+
def hugo_path
|
|
13
|
+
@hugo_path ||= "hugo"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# @param site_dir [String] path to Hugo source (must exist and be a directory)
|
|
17
|
+
# @param out_dir [String] path for build output
|
|
18
|
+
# @return [true] on success
|
|
19
|
+
# @return [false] on failure (Hugo not found, build failed, or invalid site_dir)
|
|
20
|
+
def build(site_dir:, out_dir:)
|
|
21
|
+
site_dir = ::File.expand_path(site_dir)
|
|
22
|
+
out_dir = ::File.expand_path(out_dir)
|
|
23
|
+
return false unless ::File.directory?(site_dir)
|
|
24
|
+
return false if ::File.file?(site_dir)
|
|
25
|
+
|
|
26
|
+
FileUtils.mkdir_p(out_dir)
|
|
27
|
+
success = system(hugo_path, "-s", site_dir, "-d", out_dir, out: $stdout, err: $stderr)
|
|
28
|
+
return false unless success
|
|
29
|
+
return false unless ::File.directory?(out_dir) && (Dir.entries(out_dir) - %w[. ..]).any?
|
|
30
|
+
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param site_dir [String] path to check
|
|
35
|
+
# @return [Boolean] true if config.toml or config.yaml exists under site_dir
|
|
36
|
+
def valid_site?(site_dir)
|
|
37
|
+
dir = ::File.expand_path(site_dir)
|
|
38
|
+
return false unless ::File.directory?(dir)
|
|
39
|
+
::File.file?(::File.join(dir, "config.toml")) || ::File.file?(::File.join(dir, "config.yaml"))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
data/lib/rakit/protobuf.rb
CHANGED
|
@@ -5,19 +5,21 @@ require "fileutils"
|
|
|
5
5
|
module Rakit
|
|
6
6
|
module Protobuf
|
|
7
7
|
# Generate Ruby from .proto files.
|
|
8
|
-
# proto_dir: directory containing .proto files (and -I root)
|
|
9
|
-
# ruby_out: directory for generated *_pb.rb files
|
|
8
|
+
# proto_dir: directory containing .proto files (and -I root); may be relative to base_dir
|
|
9
|
+
# ruby_out: directory for generated *_pb.rb files; may be relative to base_dir
|
|
10
|
+
# base_dir: directory used to expand relative proto_dir and ruby_out (default: Dir.pwd)
|
|
10
11
|
# protoc: executable name/path (default: "protoc")
|
|
11
12
|
# Returns ruby_out if generation ran, nil if no proto files found.
|
|
12
|
-
def self.generate(proto_dir:, ruby_out:, protoc: "protoc")
|
|
13
|
+
def self.generate(proto_dir:, ruby_out:, base_dir: Dir.pwd, protoc: "protoc")
|
|
14
|
+
expanded_proto_dir = File.expand_path(proto_dir, base_dir)
|
|
15
|
+
expanded_ruby_out = File.expand_path(ruby_out, base_dir)
|
|
13
16
|
# output, in grey, " generating code from .proto files..."
|
|
14
17
|
puts "\e[30m generating code from .proto files...\e[0m"
|
|
15
|
-
expanded_proto_dir = File.expand_path(proto_dir)
|
|
16
18
|
proto_files = Dir[File.join(expanded_proto_dir, "**", "*.proto")]
|
|
17
19
|
return nil if proto_files.empty?
|
|
18
20
|
|
|
19
|
-
FileUtils.mkdir_p(
|
|
20
|
-
args = ["-I", expanded_proto_dir, "--ruby_out=#{
|
|
21
|
+
FileUtils.mkdir_p(expanded_ruby_out)
|
|
22
|
+
args = ["-I", expanded_proto_dir, "--ruby_out=#{expanded_ruby_out}", *proto_files]
|
|
21
23
|
system(protoc, *args) or raise "protoc failed"
|
|
22
24
|
|
|
23
25
|
# output a green checkmark and the command that was run
|
|
@@ -25,14 +27,14 @@ module Rakit
|
|
|
25
27
|
# output that the files were generated
|
|
26
28
|
#puts " Generated #{proto_files.size} files in #{ruby_out}"
|
|
27
29
|
# output the files that were generated (all files in the ruby_out directory), once per line
|
|
28
|
-
ruby_out_files = Dir[File.join(
|
|
30
|
+
ruby_out_files = Dir[File.join(expanded_ruby_out, "**", "*_pb.rb")]
|
|
29
31
|
ruby_out_files.each do |file|
|
|
30
32
|
# output, in grey, " #{File.basename(file)}"
|
|
31
33
|
puts "\e[30m #{File.basename(file)}\e[0m"
|
|
32
34
|
end
|
|
33
35
|
# output the number of files that were generated
|
|
34
|
-
#puts " Generated #{ruby_out_files.size} files in #{
|
|
35
|
-
|
|
36
|
+
#puts " Generated #{ruby_out_files.size} files in #{expanded_ruby_out}"
|
|
37
|
+
expanded_ruby_out
|
|
36
38
|
end
|
|
37
39
|
end
|
|
38
40
|
end
|