poepod 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
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