poepod 0.1.6 → 0.1.7

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: b205fe50c5830d75893fbfa378b81984bf8a2b73fa8d104509fbbf698e0001fc
4
- data.tar.gz: d4e87cef72c92cdcfaadd6bcf5a452bc1a05b13c4927cce10b6c81250ff99c9c
3
+ metadata.gz: 3bc92cfee72702377260c08e2639cf32b789e54be73d3cea7896bde4bf357332
4
+ data.tar.gz: f79c5a7847f8329c2a1c5ef1718c97b7ce18852df727a5d92c2b58244da2a7c0
5
5
  SHA512:
6
- metadata.gz: c32f1ffb23fcf86f8cd1625c1deab4dc3599a0baf7b4ad80618f1e37a23f7b8e815b6065d628bf138f0e8ca9c2c849d1a08c31599737bee85711a6b4cd3e88f0
7
- data.tar.gz: bdc4de92b51c89cfbeb484a119ce829e8a5c0a7768a032f4ec4299b06f2b35724038b13a2093827fbe839c650c0a18902c544ddd85f842e47ab4e633089edb38
6
+ metadata.gz: 92da41a07f4007489ccba2dacd7a0e0eb194042916a3172d6b62a2e246a8d80eb364816ad0a5721157e1da5367071dfa34e5ca80c3e419ee2a81ddc609f17aa0
7
+ data.tar.gz: cd07a158aab095842892fbd8dd34154811be5d64d5bed0af27d3a085974a1955217ab7a1d445975c993ee30ffb57e57b679958d870785d98767babb7e18042f9
data/lib/poepod/cli.rb CHANGED
@@ -1,6 +1,6 @@
1
+ # lib/poepod/cli.rb
1
2
  # frozen_string_literal: true
2
3
 
3
- # lib/poepod/cli.rb
4
4
  require "thor"
5
5
  require_relative "file_processor"
6
6
  require_relative "gem_processor"
@@ -10,7 +10,7 @@ module Poepod
10
10
  class Cli < Thor
11
11
  # Define shared options
12
12
  def self.shared_options
13
- option :exclude, type: :array, default: Poepod::FileProcessor::EXCLUDE_DEFAULT,
13
+ option :exclude, type: :array, default: nil,
14
14
  desc: "List of patterns to exclude"
15
15
  option :config, type: :string, desc: "Path to configuration file"
16
16
  option :include_binary, type: :boolean, default: false, desc: "Include binary files (encoded in MIME format)"
@@ -36,6 +36,7 @@ module Poepod
36
36
 
37
37
  def wrap(gemspec_path)
38
38
  base_dir = options[:base_dir] || File.dirname(gemspec_path)
39
+ output_file = options[:output_file] || File.join(base_dir, "#{File.basename(gemspec_path, ".*")}_wrapped.txt")
39
40
  processor = Poepod::GemProcessor.new(
40
41
  gemspec_path,
41
42
  include_unstaged: options[:include_unstaged],
@@ -43,9 +44,9 @@ module Poepod
43
44
  include_binary: options[:include_binary],
44
45
  include_dot_files: options[:include_dot_files],
45
46
  base_dir: base_dir,
46
- config_file: options[:config]
47
+ config_file: options[:config],
47
48
  )
48
- success, result, unstaged_files = processor.process
49
+ success, result, unstaged_files = processor.process(output_file)
49
50
  if success
50
51
  handle_wrap_result(success, result, unstaged_files)
51
52
  else
@@ -80,9 +81,9 @@ module Poepod
80
81
  include_binary: options[:include_binary],
81
82
  include_dot_files: options[:include_dot_files],
82
83
  exclude: options[:exclude],
83
- base_dir: base_dir
84
+ base_dir: base_dir,
84
85
  )
85
- total_files, copied_files = processor.process
86
+ total_files, copied_files = processor.process(output_path.to_s)
86
87
  print_result(total_files, copied_files, output_path)
87
88
  end
88
89
 
@@ -114,8 +115,7 @@ module Poepod
114
115
  if File.directory?(first_item)
115
116
  "#{File.basename(first_item)}.txt"
116
117
  else
117
- "#{File.basename(first_item,
118
- ".*")}_concat.txt"
118
+ "#{File.basename(first_item, ".*")}_concat.txt"
119
119
  end
120
120
  else
121
121
  "concatenated_output.txt"
@@ -1,3 +1,4 @@
1
+ # lib/poepod/file_processor.rb
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative "processor"
@@ -5,17 +6,13 @@ require_relative "processor"
5
6
  module Poepod
6
7
  # Processes files for concatenation, handling binary and dot files
7
8
  class FileProcessor < Processor
8
- EXCLUDE_DEFAULT = [
9
- %r{node_modules/}, %r{.git/}, /.gitignore$/, /.DS_Store$/, /^\..+/
10
- ].freeze
11
-
12
9
  def initialize(
13
- files,
10
+ patterns,
14
11
  output_file,
15
12
  config_file: nil,
16
13
  include_binary: false,
17
14
  include_dot_files: false,
18
- exclude: [],
15
+ exclude: nil,
19
16
  base_dir: nil
20
17
  )
21
18
  super(
@@ -25,20 +22,15 @@ module Poepod
25
22
  exclude: exclude,
26
23
  base_dir: base_dir,
27
24
  )
28
- @files = files
25
+ @patterns = patterns
29
26
  @output_file = output_file
30
27
  end
31
28
 
32
29
  private
33
30
 
34
31
  def collect_files_to_process
35
- @files.flatten.each_with_object([]) do |file, files_to_process|
36
- Dir.glob(file, File::FNM_DOTMATCH).each do |matched_file|
37
- next unless File.file?(matched_file)
38
- next if should_exclude?(matched_file)
39
-
40
- files_to_process << matched_file
41
- end
32
+ @patterns.flatten.each_with_object([]) do |pattern, files_to_process|
33
+ files_to_process.concat(collect_files_from_pattern(pattern))
42
34
  end
43
35
  end
44
36
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # lib/poepod/gem_processor.rb
4
3
  require_relative "processor"
5
4
  require "rubygems/specification"
6
5
  require "git"
@@ -11,7 +10,7 @@ module Poepod
11
10
  def initialize(
12
11
  gemspec_path,
13
12
  include_unstaged: false,
14
- exclude: [],
13
+ exclude: nil,
15
14
  include_binary: false,
16
15
  include_dot_files: false,
17
16
  base_dir: nil,
@@ -28,29 +27,23 @@ module Poepod
28
27
  @include_unstaged = include_unstaged
29
28
  end
30
29
 
31
- def process
30
+ def process(output_file)
32
31
  return error_no_gemspec unless File.exist?(@gemspec_path)
33
32
 
34
33
  spec = load_gemspec
35
34
  return spec unless spec.is_a?(Gem::Specification)
36
35
 
37
- gem_name = spec.name
38
- @output_file = "#{gem_name}_wrapped.txt"
39
36
  unstaged_files = check_unstaged_files
40
37
 
41
- super()
38
+ total_files, copied_files = super(output_file)
42
39
 
43
- [true, @output_file, unstaged_files]
40
+ [true, output_file, unstaged_files]
44
41
  end
45
42
 
46
43
  private
47
44
 
48
45
  def collect_files_to_process
49
- spec = load_gemspec
50
- files_to_include = (spec.files +
51
- spec.test_files +
52
- find_readme_files).uniq
53
-
46
+ files_to_include = find_gemspec_files
54
47
  files_to_include += check_unstaged_files if @include_unstaged
55
48
 
56
49
  files_to_include.sort.uniq.reject do |relative_path|
@@ -60,6 +53,13 @@ module Poepod
60
53
  end
61
54
  end
62
55
 
56
+ def find_gemspec_files
57
+ spec = load_gemspec
58
+ executables = spec.bindir ? collect_files_from_pattern(File.join(@base_dir, spec.bindir, "*")) : []
59
+
60
+ (spec.files + spec.test_files + find_readme_files + executables).uniq
61
+ end
62
+
63
63
  def error_no_gemspec
64
64
  [false, "Error: The specified gemspec file '#{@gemspec_path}' does not exist."]
65
65
  end
@@ -71,10 +71,9 @@ module Poepod
71
71
  end
72
72
 
73
73
  def find_readme_files
74
- Dir.glob(File.join(File.dirname(@gemspec_path), "README*")).map do |path|
75
- Pathname.new(path).relative_path_from(
76
- Pathname.new(File.dirname(@gemspec_path))
77
- ).to_s
74
+ gemspec_dir = Pathname.new(File.dirname(@gemspec_path))
75
+ Dir.glob(gemspec_dir.join("README*")).map do |path|
76
+ Pathname.new(path).relative_path_from(gemspec_dir).to_s
78
77
  end
79
78
  end
80
79
 
@@ -86,7 +85,7 @@ module Poepod
86
85
  modified_files = git.status.changed.keys
87
86
 
88
87
  (untracked_files + modified_files).select do |file|
89
- file.start_with?("lib/", "spec/", "test/")
88
+ file.start_with?("bin/", "exe/", "lib/", "spec/", "test/")
90
89
  end
91
90
  rescue Git::GitExecuteError => e
92
91
  warn "Git error: #{e.message}. Assuming no unstaged files."
@@ -1,3 +1,4 @@
1
+ # lib/poepod/processor.rb
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "yaml"
@@ -8,33 +9,65 @@ require "stringio"
8
9
  module Poepod
9
10
  # Base processor class
10
11
  class Processor
12
+ EXCLUDE_DEFAULT = [
13
+ %r{node_modules/}, %r{.git/}, /.gitignore$/, /.DS_Store$/,
14
+ ].freeze
15
+
11
16
  def initialize(
12
17
  config_file = nil,
13
18
  include_binary: false,
14
19
  include_dot_files: false,
15
- exclude: [],
20
+ exclude: nil,
16
21
  base_dir: nil
17
22
  )
18
23
  @config = load_config(config_file)
19
24
  @include_binary = include_binary
20
25
  @include_dot_files = include_dot_files
21
- @exclude = exclude || []
26
+ @exclude = exclude || EXCLUDE_DEFAULT
22
27
  @base_dir = base_dir
23
28
  @failed_files = []
24
29
  end
25
30
 
26
- def process
31
+ def process(output_file)
27
32
  files_to_process = collect_files_to_process
28
- total_files, copied_files = process_files(files_to_process)
33
+ total_files, copied_files = process_files(files_to_process, output_file)
29
34
  [total_files, copied_files]
30
35
  end
31
36
 
32
37
  private
33
38
 
39
+ def process_files(files, output_file)
40
+ total_files = files.size
41
+ copied_files = 0
42
+
43
+ File.open(output_file, "w", encoding: "utf-8") do |output|
44
+ files.sort.each do |file_path|
45
+ process_file(output, file_path)
46
+ copied_files += 1
47
+ end
48
+ end
49
+
50
+ [total_files, copied_files]
51
+ end
52
+
34
53
  def collect_files_to_process
35
54
  raise NotImplementedError, "Subclasses must implement collect_files_to_process"
36
55
  end
37
56
 
57
+ def collect_files_from_pattern(pattern)
58
+ expanded_pattern = File.expand_path(pattern)
59
+ if File.directory?(expanded_pattern)
60
+ expanded_pattern = File.join(expanded_pattern, "**", "*")
61
+ end
62
+
63
+ Dir.glob(expanded_pattern, File::FNM_DOTMATCH).each_with_object([]) do |file_path, acc|
64
+ next unless File.file?(file_path)
65
+ next if should_exclude?(file_path)
66
+
67
+ acc << file_path
68
+ end
69
+ end
70
+
38
71
  def load_config(config_file)
39
72
  return {} unless config_file && File.exist?(config_file)
40
73
 
@@ -46,33 +79,26 @@ module Poepod
46
79
 
47
80
  File.open(file_path, "rb") do |file|
48
81
  content = file.read(8192) # Read first 8KB for magic byte detection
49
- mime_type = Marcel::MimeType.for(content, name: File.basename(file_path), declared_type: "text/plain")
50
- !mime_type.start_with?("text/") && mime_type != "application/json"
51
- end
52
- end
82
+ mime_type = Marcel::MimeType.for(
83
+ content,
84
+ name: File.basename(file_path),
85
+ declared_type: "text/plain",
86
+ )
53
87
 
54
- def process_files(files)
55
- total_files = files.size
56
- copied_files = 0
57
-
58
- File.open(@output_file, "w", encoding: "utf-8") do |output|
59
- files.sort.each do |file_path|
60
- process_file(output, file_path)
61
- copied_files += 1
62
- end
88
+ !mime_type.start_with?("text/") && mime_type != "application/json"
63
89
  end
64
-
65
- [total_files, copied_files]
66
90
  end
67
91
 
68
92
  def process_file(output = nil, file_path)
69
93
  output ||= StringIO.new
70
94
 
71
95
  relative_path = if @base_dir
72
- Pathname.new(file_path).relative_path_from(Pathname.new(@base_dir)).to_s
73
- else
74
- file_path
75
- end
96
+ Pathname.new(file_path).relative_path_from(@base_dir).to_s
97
+ else
98
+ file_path
99
+ end
100
+
101
+ puts "Adding to bundle: #{relative_path}"
76
102
 
77
103
  output.puts "--- START FILE: #{relative_path} ---"
78
104
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Poepod
4
- VERSION = "0.1.6"
4
+ VERSION = "0.1.7"
5
5
  end
data/poepod.gemspec CHANGED
@@ -18,8 +18,6 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
20
20
 
21
- # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
21
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
22
  `git ls-files -z`.split("\x0").reject do |f|
25
23
  f.match(%r{^(test|spec|features)/})
@@ -25,7 +25,7 @@ RSpec.describe Poepod::Cli do
25
25
  it "concatenates text files and excludes binary and dot files by default" do
26
26
  output_file = File.join(temp_dir, "output.txt")
27
27
  expect do
28
- cli.invoke(:concat, [File.join(temp_dir, "*")], { output_file: output_file })
28
+ cli.invoke(:concat, [text_file], { output_file: output_file })
29
29
  end.to output(/1 files detected\.\n.*1 files have been concatenated/).to_stdout
30
30
  expect(File.exist?(output_file)).to be true
31
31
  content = File.read(output_file)
@@ -36,7 +36,7 @@ RSpec.describe Poepod::Cli do
36
36
  it "includes binary files when specified" do
37
37
  output_file = File.join(temp_dir, "output.txt")
38
38
  expect do
39
- cli.invoke(:concat, [File.join(temp_dir, "*")], { output_file: output_file, include_binary: true })
39
+ cli.invoke(:concat, [text_file, binary_file], { output_file: output_file, include_binary: true })
40
40
  end.to output(/2 files detected\.\n.*2 files have been concatenated/).to_stdout
41
41
  expect(File.exist?(output_file)).to be true
42
42
  content = File.read(output_file)
@@ -47,7 +47,7 @@ RSpec.describe Poepod::Cli do
47
47
  it "includes dot files when specified" do
48
48
  output_file = File.join(temp_dir, "output.txt")
49
49
  expect do
50
- cli.invoke(:concat, [File.join(temp_dir, "*")], { output_file: output_file, include_dot_files: true })
50
+ cli.invoke(:concat, [text_file, dot_file], { output_file: output_file, include_dot_files: true })
51
51
  end.to output(/2 files detected\.\n.*2 files have been concatenated/).to_stdout
52
52
  expect(File.exist?(output_file)).to be true
53
53
  content = File.read(output_file)
@@ -57,9 +57,8 @@ RSpec.describe Poepod::Cli do
57
57
 
58
58
  it "uses the specified base directory for relative paths" do
59
59
  output_file = File.join(temp_dir, "output.txt")
60
- base_dir = File.dirname(text_file)
61
60
  expect do
62
- cli.invoke(:concat, [File.join(temp_dir, "*")], { output_file: output_file, base_dir: base_dir })
61
+ cli.invoke(:concat, [text_file], { output_file: output_file, base_dir: temp_dir })
63
62
  end.to output(/1 files detected\.\n.*1 files have been concatenated/).to_stdout
64
63
  expect(File.exist?(output_file)).to be true
65
64
  content = File.read(output_file)
@@ -95,8 +94,8 @@ RSpec.describe Poepod::Cli do
95
94
  end
96
95
 
97
96
  it "wraps a gem" do
97
+ output_file = File.join(temp_dir, "test_gem_wrapped.txt")
98
98
  expect { cli.wrap(gemspec_file) }.to output(/The gem has been wrapped into/).to_stdout
99
- output_file = File.join(Dir.pwd, "test_gem_wrapped.txt")
100
99
  expect(File.exist?(output_file)).to be true
101
100
  content = File.read(output_file)
102
101
  expect(content).to include("--- START FILE: lib/test_gem.rb ---")
@@ -112,10 +111,10 @@ RSpec.describe Poepod::Cli do
112
111
 
113
112
  it "uses the specified base directory for relative paths" do
114
113
  base_dir = File.dirname(gemspec_file)
114
+ output_file = File.join(base_dir, "test_gem_wrapped.txt")
115
115
  expect do
116
- cli.invoke(:wrap, [gemspec_file], { base_dir: base_dir })
116
+ cli.invoke(:wrap, [gemspec_file], { base_dir: base_dir, output_file: output_file })
117
117
  end.to output(/The gem has been wrapped into/).to_stdout
118
- output_file = File.join(Dir.pwd, "test_gem_wrapped.txt")
119
118
  expect(File.exist?(output_file)).to be true
120
119
  content = File.read(output_file)
121
120
  expect(content).to include("--- START FILE: lib/test_gem.rb ---")
@@ -27,10 +27,10 @@ RSpec.describe Poepod::FileProcessor do
27
27
 
28
28
  describe "#process" do
29
29
  context "with default options" do
30
- let(:processor) { described_class.new([File.join(temp_dir, "*")], output_file.path) }
30
+ let(:processor) { described_class.new([text_file1, text_file2], output_file.path) }
31
31
 
32
32
  it "processes text files and excludes binary and dot files" do
33
- total_files, copied_files = processor.process
33
+ total_files, copied_files = processor.process(output_file.path)
34
34
  expect(total_files).to eq(2)
35
35
  expect(copied_files).to eq(2)
36
36
 
@@ -51,7 +51,7 @@ RSpec.describe Poepod::FileProcessor do
51
51
  let(:processor) { described_class.new([File.join(temp_dir, "*")], output_file.path, include_binary: true) }
52
52
 
53
53
  it "includes binary files" do
54
- total_files, copied_files = processor.process
54
+ total_files, copied_files = processor.process(output_file.path)
55
55
  expect(total_files).to eq(3)
56
56
  expect(copied_files).to eq(3)
57
57
 
@@ -78,7 +78,7 @@ RSpec.describe Poepod::FileProcessor do
78
78
  let(:processor) { described_class.new([File.join(temp_dir, "*")], output_file.path, include_dot_files: true) }
79
79
 
80
80
  it "includes dot files" do
81
- total_files, copied_files = processor.process
81
+ total_files, copied_files = processor.process(output_file.path)
82
82
  expect(total_files).to eq(3)
83
83
  expect(copied_files).to eq(3)
84
84
 
@@ -104,7 +104,7 @@ RSpec.describe Poepod::FileProcessor do
104
104
  end
105
105
 
106
106
  it "includes all files in sorted order" do
107
- total_files, copied_files = processor.process
107
+ total_files, copied_files = processor.process(output_file.path)
108
108
  expect(total_files).to eq(4)
109
109
  expect(copied_files).to eq(4)
110
110
 
@@ -34,6 +34,7 @@ RSpec.describe Poepod::GemProcessor do
34
34
 
35
35
  describe "#process" do
36
36
  let(:processor) { described_class.new(gemspec_file) }
37
+ let(:output_file) { File.join(temp_dir, "test_gem_wrapped.txt") }
37
38
 
38
39
  before do
39
40
  # Mock Git operations
@@ -41,7 +42,7 @@ RSpec.describe Poepod::GemProcessor do
41
42
  end
42
43
 
43
44
  it "processes the gem files, includes README files, and spec files in sorted order" do
44
- success, output_file = processor.process
45
+ success, result, _ = processor.process(output_file)
45
46
  expect(success).to be true
46
47
  expect(File.exist?(output_file)).to be true
47
48
 
@@ -52,7 +53,7 @@ RSpec.describe Poepod::GemProcessor do
52
53
  "README.md",
53
54
  "README.txt",
54
55
  "lib/test_gem.rb",
55
- "spec/test_gem_spec.rb"
56
+ "spec/test_gem_spec.rb",
56
57
  ]
57
58
  expect(file_order).to eq(expected_order)
58
59
 
@@ -82,7 +83,7 @@ RSpec.describe Poepod::GemProcessor do
82
83
  let(:processor) { described_class.new("non_existent.gemspec") }
83
84
 
84
85
  it "returns an error" do
85
- success, error_message = processor.process
86
+ success, error_message, _ = processor.process(output_file)
86
87
  expect(success).to be false
87
88
  expect(error_message).to include("Error: The specified gemspec file")
88
89
  end
@@ -104,6 +105,7 @@ RSpec.describe Poepod::GemProcessor do
104
105
 
105
106
  context "with include_unstaged option" do
106
107
  let(:processor) { described_class.new(gemspec_file, include_unstaged: true) }
108
+ let(:output_file) { File.join(temp_dir, "test_gem_wrapped.txt") }
107
109
 
108
110
  it "includes unstaged files" do
109
111
  allow(File).to receive(:file?).and_return(true)
@@ -114,7 +116,7 @@ RSpec.describe Poepod::GemProcessor do
114
116
  "spec/test_gem_spec.rb" => "RSpec.describe TestGem do\nend",
115
117
  "README.md" => "# Test Gem\n\nThis is a test gem.",
116
118
  "README.txt" => "Test Gem\n\nThis is a test gem in plain text.",
117
- "lib/unstaged_file.rb" => "Unstaged content"
119
+ "lib/unstaged_file.rb" => "Unstaged content",
118
120
  }
119
121
 
120
122
  # Mock File.read
@@ -136,7 +138,7 @@ RSpec.describe Poepod::GemProcessor do
136
138
  end
137
139
  end
138
140
 
139
- success, output_file, unstaged_files = processor.process
141
+ success, result, unstaged_files = processor.process(output_file)
140
142
  expect(success).to be true
141
143
  expect(unstaged_files).to eq(["lib/unstaged_file.rb"])
142
144
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poepod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-22 00:00:00.000000000 Z
11
+ date: 2024-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git