gitt 3.8.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72a1ef8d6a3caccc88017da2ee4a6f639c9851c8dc6c9ee2ef8510fe83130718
4
- data.tar.gz: 418b7d5e9ac48472cc9112ec031ab7d10e6ca04e0e1503dbe42b65c9a9c50d6f
3
+ metadata.gz: '089dc63b1472c88edd6c3135f33cf1888ff2e8c2a2c7653ed274fb76b0758bec'
4
+ data.tar.gz: 0e0f51674ebb293d760b5a9c7f07716e8a3d277ca25823a24decb7d57239bc86
5
5
  SHA512:
6
- metadata.gz: 4637a417134c91608e031acc5d10cb4594b3db50253a2b5fdd059ee505dd67f43f34e685f0df656f8fd524449053adebb38e19e882ec1349cc667e2cdf323f53
7
- data.tar.gz: a2f821d2cf5757e6c373855c5695452890589e701def37dde9b892958b8f5708c85e4f232bd4ad30f888c9eb4810e0d31307cb193ca7b9c6d08a9866c9c02797
6
+ metadata.gz: 918247b90b31936c807ad6643c3fdd31f6ba873599c83ce609b64c897ddc9e95bb3b323caa715a03737ed164ceca6be4fc7ea80b56dcb1550425da1d27bc2c29
7
+ data.tar.gz: 458707c1d8fdfa687ca9d3939da56192199e8bfe3ec050285003062e0a2febb62ee8247dc3668faed3755fc8d89f2b7b74ce99f86bf392b7eaa9f7d9701ebf9a
checksums.yaml.gz.sig CHANGED
Binary file
data/gitt.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "gitt"
5
- spec.version = "3.8.0"
5
+ spec.version = "3.9.0"
6
6
  spec.authors = ["Brooke Kuhlmann"]
7
7
  spec.email = ["brooke@alchemists.io"]
8
8
  spec.homepage = "https://alchemists.io/projects/gitt"
@@ -58,8 +58,8 @@ module Gitt
58
58
  attr_reader :shell, :key_map, :parser
59
59
 
60
60
  def pretty_format
61
- key_map.reduce("") { |string, (key, value)| string + "<#{key}>#{value}</#{key}>%n" }
62
- .then { |structure| %(--pretty=format:"#{structure}") }
61
+ key_map.reduce(+"") { |format, (key, value)| format << "<#{key}>#{value}</#{key}>%n" }
62
+ .then { |format| %(--pretty=format:"#{format}") }
63
63
  end
64
64
 
65
65
  def build_records entries
@@ -70,15 +70,16 @@ module Gitt
70
70
 
71
71
  # :reek:UtilityFunction
72
72
  def wrap_statistics entries
73
- entries.gsub!(/\d+\sfile.+\d+\s(insertion|deletion).+\n/) do |match|
74
- "<statistics>#{match}</statistics><break/>"
73
+ entries.gsub!(/\n"\n\s\d+\sfile.+\d+\s(insertion|deletion).+\n/) do |match|
74
+ match.delete_prefix!("\n\"\n").strip!
75
+ "\n<statistics>#{match}</statistics>\n<break/>"
75
76
  end
76
77
  end
77
78
 
78
79
  # :reek:UtilityFunction
79
80
  def add_empty_statistics entries
80
81
  entries.gsub! %(</trailers>\n"\n"<author_email>),
81
- "</trailers>\n<statistics></statistics>\n<author_email>"
82
+ "</trailers>\n<statistics></statistics><break/>\n<author_email>"
82
83
  end
83
84
  end
84
85
  end
@@ -23,6 +23,7 @@ module Gitt
23
23
  sha: "%(objectname)",
24
24
  signature: "%(contents:signature)",
25
25
  subject: "%(subject)",
26
+ trailers: "%(trailers)",
26
27
  version: "%(refname)"
27
28
  }.freeze
28
29
 
@@ -88,7 +89,7 @@ module Gitt
88
89
  attr_reader :shell, :key_map, :parser
89
90
 
90
91
  def pretty_format
91
- key_map.reduce("") { |content, (key, value)| content + "<#{key}>#{value}</#{key}>%n" }
92
+ key_map.reduce(+"") { |format, (key, value)| format << "<#{key}>#{value}</#{key}>%n" }
92
93
  .then { |format| %(--format="#{format}") }
93
94
  end
94
95
 
@@ -32,30 +32,13 @@ module Gitt
32
32
  :trailers
33
33
  ) do
34
34
  include Directable
35
+ include Trailable
35
36
  include Dry::Monads[:result]
36
37
 
37
38
  def initialize(**)
38
39
  super
39
40
  freeze
40
41
  end
41
-
42
- def find_trailer key
43
- trailers.find { |trailer| trailer.key == key }
44
- .then do |trailer|
45
- return Success trailer if trailer
46
-
47
- Failure "Unable to find trailer for key: #{key.inspect}."
48
- end
49
- end
50
-
51
- def find_trailers key
52
- trailers.select { |trailer| trailer.key == key }
53
- .then { |trailers| Success trailers }
54
- end
55
-
56
- def trailer_value_for(key) = find_trailer(key).fmap(&:value)
57
-
58
- def trailer_values_for(key) = find_trailers(key).fmap { |trailers| trailers.map(&:value) }
59
42
  end
60
43
  end
61
44
  end
@@ -16,8 +16,11 @@ module Gitt
16
16
  :sha,
17
17
  :signature,
18
18
  :subject,
19
+ :trailers,
19
20
  :version
20
21
  ) do
22
+ include Trailable
23
+
21
24
  def initialize(**)
22
25
  super
23
26
  freeze
@@ -18,7 +18,7 @@ module Gitt
18
18
 
19
19
  def call content
20
20
  attributer.call(content)
21
- .then { |attributes| process attributes }
21
+ .then { |attributes| mutate attributes }
22
22
  .then { |attributes| model[**attributes] }
23
23
  end
24
24
 
@@ -27,7 +27,7 @@ module Gitt
27
27
  attr_reader :attributer, :sanitizers, :model
28
28
 
29
29
  # :reek:TooManyStatements
30
- def process attributes
30
+ def mutate attributes
31
31
  body, trailers = attributes.values_at :body, :trailers
32
32
  body = scissors_sanitizer.call body
33
33
 
@@ -16,13 +16,16 @@ module Gitt
16
16
  @model = model
17
17
  end
18
18
 
19
+ # :reek:TooManyStatements
19
20
  def call content
20
21
  attributes = attributer.call content
21
- attributes.transform_with! author_email: email_sanitizer,
22
- authored_at: date_sanitizer,
23
- committed_at: date_sanitizer,
24
- committer_email: email_sanitizer,
25
- version: version_serializer
22
+ body, trailers = attributes.values_at :body, :trailers
23
+ sanitize attributes
24
+
25
+ attributes[:body] = (
26
+ trailers ? body.sub(/\n??#{Regexp.escape trailers}\n??/, "") : body
27
+ ).to_s.chomp
28
+
26
29
  model[**attributes]
27
30
  end
28
31
 
@@ -30,10 +33,21 @@ module Gitt
30
33
 
31
34
  attr_reader :attributer, :sanitizers, :model
32
35
 
36
+ def sanitize attributes
37
+ attributes.transform_with! author_email: email_sanitizer,
38
+ authored_at: date_sanitizer,
39
+ committed_at: date_sanitizer,
40
+ committer_email: email_sanitizer,
41
+ trailers: trailers_sanitizer,
42
+ version: version_serializer
43
+ end
44
+
33
45
  def date_sanitizer = sanitizers.fetch :date
34
46
 
35
47
  def email_sanitizer = sanitizers.fetch :email
36
48
 
49
+ def trailers_sanitizer = sanitizers.fetch :trailers
50
+
37
51
  def version_serializer = sanitizers.fetch :version
38
52
  end
39
53
  end
@@ -4,7 +4,6 @@ require "core"
4
4
 
5
5
  module Gitt
6
6
  # Primary object/wrapper for processing all Git related commands.
7
- # :reek:TooManyMethods
8
7
  class Repository
9
8
  COMMANDS = {
10
9
  branch: Commands::Branch,
@@ -34,6 +33,11 @@ module Gitt
34
33
 
35
34
  def get(...) = commands.fetch(:config).get(...)
36
35
 
36
+ def inspect
37
+ "#<#{self.class}:#{object_id} @shell=#{shell.inspect} " \
38
+ "@commands=#{commands.values.map(&:class).inspect}>"
39
+ end
40
+
37
41
  def log(...) = commands.fetch(__method__).call(...)
38
42
 
39
43
  def origin? = commands.fetch(:config).origin?
@@ -6,7 +6,7 @@ module Gitt
6
6
  date: Date,
7
7
  email: Email,
8
8
  lines: Lines,
9
- paragraphs: Paragraphs,
9
+ paragraphs: Paragraphs.new,
10
10
  scissors: Scissors,
11
11
  signature: Signature,
12
12
  statistic: Statistic.new,
@@ -1,9 +1,53 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "core"
4
+ require "refinements/array"
5
+ require "strscan"
4
6
 
5
7
  module Gitt
6
8
  module Sanitizers
7
- Paragraphs = -> text { text ? text.split("\n\n").map(&:chomp) : Core::EMPTY_ARRAY }
9
+ # Detects and parses paragraphs (including code blocks).
10
+ class Paragraphs
11
+ using Refinements::Array
12
+
13
+ PATTERN = /
14
+ ( # Condition start.
15
+ (?:\..*?\n)? # Optional ASCII Doc label.
16
+ (?:\[.*\]\n)? # Optional ASCII Doc directive.
17
+ [-_=+\.\*]{4} # ASCII Doc block start.
18
+ [\s\S]*? # Lazy block content of any character.
19
+ [-_=+\.\*]{4} # ASCII Doc block end.
20
+ | # Or.
21
+ ``` # Markdown start.
22
+ [\s\S]*? # Lazy block content of any character.
23
+ ``` # Markdown end.
24
+ ) # Condition end.
25
+ /mx
26
+
27
+ def initialize pattern: PATTERN, client: StringScanner
28
+ @pattern = pattern
29
+ @client = client
30
+ end
31
+
32
+ def call(text) = scan(client.new(text.to_s))
33
+
34
+ private
35
+
36
+ attr_reader :pattern, :client
37
+
38
+ # :reek:FeatureEnvy
39
+ def scan scanner, collection = []
40
+ until scanner.eos?
41
+ match = scanner.scan_until pattern
42
+
43
+ break collection << scanner.string[scanner.rest].tap(&:strip!).split("\n\n") unless match
44
+
45
+ collection << scanner.pre_match.strip
46
+ collection << scanner.captures
47
+ end
48
+
49
+ collection.tap(&:flatten!).tap(&:compress!)
50
+ end
51
+ end
8
52
  end
9
53
  end
@@ -12,24 +12,25 @@ module Gitt
12
12
  (?<kind>file|insertion|deletion) # Kind capture group.
13
13
  /x
14
14
 
15
+ def self.update_stats attributes, kind, total
16
+ case kind
17
+ when "file" then attributes[:files_changed] = total
18
+ when "insertion" then attributes[:insertions] = total
19
+ when "deletion" then attributes[:deletions] = total
20
+ else fail StandardError, "Invalid kind: #{kind.inspect}."
21
+ end
22
+ end
23
+
15
24
  def initialize empty: EMPTY, pattern: PATTERN
16
25
  @empty = empty
17
26
  @pattern = pattern
18
27
  end
19
28
 
20
- # :reek:TooManyStatements
21
29
  def call text
22
30
  return empty unless text
23
31
 
24
- text.scan(pattern).each.with_object(empty.dup) do |(number, kind), stats|
25
- total = number.to_i
26
-
27
- case kind
28
- when "file" then stats[:files_changed] = total
29
- when "insertion" then stats[:insertions] = total
30
- when "deletion" then stats[:deletions] = total
31
- # :nocov:
32
- end
32
+ text.scan(pattern).each.with_object(empty.dup) do |(number, kind), aggregate|
33
+ self.class.update_stats aggregate, kind, number.to_i
33
34
  end
34
35
  end
35
36
 
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitt
4
+ # Provides shared behavior for objects that have trailers.
5
+ module Trailable
6
+ def find_trailer key
7
+ trailers.find { |trailer| trailer.key == key }
8
+ .then do |trailer|
9
+ return Success trailer if trailer
10
+
11
+ Failure "Unable to find trailer for key: #{key.inspect}."
12
+ end
13
+ end
14
+
15
+ def find_trailers key
16
+ trailers.select { |trailer| trailer.key == key }
17
+ .then { |trailers| Success trailers }
18
+ end
19
+
20
+ def trailer_value_for(key) = find_trailer(key).fmap(&:value)
21
+
22
+ def trailer_values_for(key) = find_trailers(key).fmap { |trailers| trailers.map(&:value) }
23
+ end
24
+ end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitt
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.0
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -35,7 +35,7 @@ cert_chain:
35
35
  3n5C8/6Zh9DYTkpcwPSuIfAga6wf4nXc9m6JAw8AuMLaiWN/r/2s4zJsUHYERJEu
36
36
  gZGm4JqtuSg8pYjPeIJxS960owq+SfuC+jxqmRA54BisFCv/0VOJi7tiJVY=
37
37
  -----END CERTIFICATE-----
38
- date: 2024-09-01 00:00:00.000000000 Z
38
+ date: 2024-09-07 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: core
@@ -135,6 +135,7 @@ files:
135
135
  - lib/gitt/sanitizers/trailers.rb
136
136
  - lib/gitt/sanitizers/version.rb
137
137
  - lib/gitt/shell.rb
138
+ - lib/gitt/trailable.rb
138
139
  homepage: https://alchemists.io/projects/gitt
139
140
  licenses:
140
141
  - Hippocratic-2.1
metadata.gz.sig CHANGED
Binary file