gitt 2.2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/README.adoc +31 -13
- data/gitt.gemspec +4 -4
- data/lib/gitt/commands/branch.rb +1 -1
- data/lib/gitt/commands/config.rb +5 -7
- data/lib/gitt/commands/log.rb +24 -5
- data/lib/gitt/commands/tag.rb +9 -3
- data/lib/gitt/directable.rb +16 -0
- data/lib/gitt/models/commit.rb +24 -4
- data/lib/gitt/models/person.rb +12 -4
- data/lib/gitt/models/trailer.rb +3 -4
- data/lib/gitt/parsers/attributer.rb +9 -7
- data/lib/gitt/parsers/commit.rb +8 -5
- data/lib/gitt/parsers/person.rb +15 -13
- data/lib/gitt/parsers/tag.rb +3 -3
- data/lib/gitt/parsers/trailer.rb +4 -3
- data/lib/gitt/rspec/shared_contexts/git_repo.rb +1 -1
- data/lib/gitt/rspec/shared_contexts/temp_dir.rb +1 -1
- data/lib/gitt/sanitizers/container.rb +1 -0
- data/lib/gitt/sanitizers/date.rb +3 -1
- data/lib/gitt/sanitizers/email.rb +3 -1
- data/lib/gitt/sanitizers/scissors.rb +3 -1
- data/lib/gitt/sanitizers/statistic.rb +41 -0
- data/lib/gitt/shell.rb +2 -2
- data/lib/gitt.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +10 -11
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a62c7af41ef6056ceb816436a8c80f1d2ee3fd792fbbcadadbc82a2b5eba97d
|
4
|
+
data.tar.gz: bc3d13fbd0296b5ca483f02033446fc79fbbd46617d0fd2b06cf07477ba06d3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df96432454f47a6d4fd57c741949dabd088f61c1a62af03b25fac1860a766b52ecf19e7bd3973b29ee617e1c015588953ba34ca17fd56201f894ec9279819f80
|
7
|
+
data.tar.gz: da01de46bb99ad4c59a328101772184703da241949ba9678dfb19c71c2e616a7fd6ab4d422035592ffe15473d33663e4e07e73fa9dede99c5e06660940d9ecdb
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/README.adoc
CHANGED
@@ -24,7 +24,7 @@ toc::[]
|
|
24
24
|
== Features
|
25
25
|
|
26
26
|
* Wraps a subset of native {git_link} commands with additional enhancements to improve your working experience.
|
27
|
-
* Answers link:https://dry-rb.org/gems/dry-monads[monads] you can
|
27
|
+
* Answers link:https://dry-rb.org/gems/dry-monads[monads] you can link:https://alchemists.io/projects/transactable[pipe] together for more complex workflows.
|
28
28
|
* Provides _optional_ {rspec_link} shared contexts that speed up the testing of your own Git related implementations.
|
29
29
|
|
30
30
|
== Requirements
|
@@ -65,11 +65,13 @@ git.tag? # Answers if local or remote tag exists.
|
|
65
65
|
git.tag_create # Create a new tag.
|
66
66
|
git.tag_last # Answers last tag created.
|
67
67
|
git.tag_local? # Answers if local tag exists?
|
68
|
-
git.tag_parse # Parses and answers a tag record.
|
69
68
|
git.tag_remote? # Answers if remote tag exists?
|
69
|
+
git.tag_show # Answers information about a single tag.
|
70
70
|
git.tagged? # Answers if the repository has any tags.
|
71
|
+
git.tags # Answers all tags.
|
71
72
|
git.tags_push # Pushes local tags to remote git.
|
72
73
|
git.uncommitted # Parses a file and answers an unsaved commit message.
|
74
|
+
|
73
75
|
----
|
74
76
|
|
75
77
|
=== Commands
|
@@ -160,6 +162,9 @@ tag = Gitt::Commands::Tag.new
|
|
160
162
|
# Example: tag.call "--list"
|
161
163
|
stdout, stderr, status = tag.call
|
162
164
|
|
165
|
+
# Creates a new tag.
|
166
|
+
tag.create "0.0.0", "Version 0.0.0"
|
167
|
+
|
163
168
|
# Answers true or false base on whether local and remote tag exist.
|
164
169
|
tag.exist? "0.1.0"
|
165
170
|
|
@@ -175,6 +180,9 @@ tag.push
|
|
175
180
|
# Answers if remote tag exists.
|
176
181
|
tag.remote? "0.1.0"
|
177
182
|
|
183
|
+
# Answers details about a specific tag.
|
184
|
+
tag.show "1.0.0"
|
185
|
+
|
178
186
|
# Answers true or false based on whether repository is tagged.
|
179
187
|
tag.tagged?
|
180
188
|
----
|
@@ -224,21 +232,31 @@ An instance of `Gitt::Models::Tag` is what is answered back to when using `Gitt:
|
|
224
232
|
[source,ruby]
|
225
233
|
----
|
226
234
|
# #<struct Gitt::Models::Tag
|
227
|
-
# author_date="Tue Dec 29 17:33:01 2020 -0700",
|
228
235
|
# author_email="demo@example.com",
|
229
|
-
# author_name="
|
230
|
-
#
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
236
|
+
# author_name="Brooke Kuhlmann",
|
237
|
+
# authored_at="1671892451",
|
238
|
+
# authored_relative_at="1 year ago",
|
239
|
+
# body="A demo body.",
|
240
|
+
# committed_at="1671997684",
|
241
|
+
# committed_relative_at="1 year ago",
|
242
|
+
# committer_email="demo@example.com",
|
243
|
+
# committer_name="Brooke Kuhlmann",
|
244
|
+
# sha="662f32b2846c7bd4f153560478f035197f5279d5",
|
245
|
+
# subject="Version 1.0.0",
|
246
|
+
# version="1.0.0">
|
234
247
|
----
|
235
248
|
|
236
249
|
You get a {struct_link} with the following attributes:
|
237
250
|
|
238
|
-
* `author_date`: Stores author creation date.
|
239
251
|
* `author_email`: Stores author email.
|
240
252
|
* `author_name`: Store author name.
|
253
|
+
* `authored_at`: Stores author creation date.
|
254
|
+
* `authored_relative_at`: Stores author creation date relative to current time.
|
241
255
|
* `body`: Stores body of tag which can be sentences, multiple paragraphs, and/or signature information.
|
256
|
+
* `committer_email`: Stores committer email.
|
257
|
+
* `committer_name`: Store committer name.
|
258
|
+
* `committed_at`: Stores committer creation date.
|
259
|
+
* `committed_relative_at`: Stores committer creation date relative to current time.
|
242
260
|
* `sha`: Stores the commit SHA for which this tag labels
|
243
261
|
* `subject`: Stores the subject.
|
244
262
|
* `version`: Stores the version.
|
@@ -283,12 +301,12 @@ Provides a simple Git repository with a single commit for testing purposes. This
|
|
283
301
|
[source,ruby]
|
284
302
|
----
|
285
303
|
require "gitt/rspec/shared_contexts/git_repo"
|
286
|
-
require "refinements/
|
304
|
+
require "refinements/pathname"
|
287
305
|
|
288
306
|
describe Demo do
|
289
307
|
include_context "with Git repository"
|
290
308
|
|
291
|
-
using Refinements::
|
309
|
+
using Refinements::Pathname
|
292
310
|
|
293
311
|
it "is a demo" do
|
294
312
|
git_repo_dir.change_dir { # Your expectation goes here. }
|
@@ -303,12 +321,12 @@ Provides a temporary directory (i.e. `tmp/rspec`) for creating directories and o
|
|
303
321
|
[source,ruby]
|
304
322
|
----
|
305
323
|
require "gitt/rspec/shared_contexts/temp_dir"
|
306
|
-
require "refinements/
|
324
|
+
require "refinements/pathname"
|
307
325
|
|
308
326
|
describe Demo do
|
309
327
|
include_context "with temporary directory"
|
310
328
|
|
311
|
-
using Refinements::
|
329
|
+
using Refinements::Pathname
|
312
330
|
|
313
331
|
it "is a demo" do
|
314
332
|
temp_dir.change_dir { # Your expectation goes here. }
|
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 = "
|
5
|
+
spec.version = "3.0.0"
|
6
6
|
spec.authors = ["Brooke Kuhlmann"]
|
7
7
|
spec.email = ["brooke@alchemists.io"]
|
8
8
|
spec.homepage = "https://alchemists.io/projects/gitt"
|
@@ -22,10 +22,10 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.signing_key = Gem.default_key_path
|
23
23
|
spec.cert_chain = [Gem.default_cert_path]
|
24
24
|
|
25
|
-
spec.required_ruby_version =
|
26
|
-
spec.add_dependency "core", "~> 0
|
25
|
+
spec.required_ruby_version = "~> 3.3"
|
26
|
+
spec.add_dependency "core", "~> 1.0"
|
27
27
|
spec.add_dependency "dry-monads", "~> 1.6"
|
28
|
-
spec.add_dependency "refinements", "~>
|
28
|
+
spec.add_dependency "refinements", "~> 12.0"
|
29
29
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
30
30
|
|
31
31
|
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
|
data/lib/gitt/commands/branch.rb
CHANGED
data/lib/gitt/commands/config.rb
CHANGED
@@ -13,18 +13,16 @@ module Gitt
|
|
13
13
|
@shell = shell
|
14
14
|
end
|
15
15
|
|
16
|
-
def call(*
|
16
|
+
def call(*) = shell.call("config", *)
|
17
17
|
|
18
|
-
def get
|
19
|
-
call(
|
20
|
-
|
21
|
-
block_given? ? yield(error) : Success(fallback)
|
22
|
-
end
|
18
|
+
def get(key, fallback = Core::EMPTY_STRING, *)
|
19
|
+
call(*, "--get", key).fmap(&:chomp)
|
20
|
+
.or { |error| block_given? ? yield(error) : Success(fallback) }
|
23
21
|
end
|
24
22
|
|
25
23
|
def origin? = !get("remote.origin.url").value_or(Core::EMPTY_STRING).empty?
|
26
24
|
|
27
|
-
def set(key, value, *
|
25
|
+
def set(key, value, *) = call(*, "--add", key, value).fmap { value }
|
28
26
|
|
29
27
|
private
|
30
28
|
|
data/lib/gitt/commands/log.rb
CHANGED
@@ -18,6 +18,8 @@ module Gitt
|
|
18
18
|
committed_relative_at: "%cr",
|
19
19
|
committer_email: "%ce",
|
20
20
|
committer_name: "%cn",
|
21
|
+
encoding: "%e",
|
22
|
+
notes: "%N",
|
21
23
|
raw: "%B",
|
22
24
|
sha: "%H",
|
23
25
|
signature: "%G?",
|
@@ -25,18 +27,18 @@ module Gitt
|
|
25
27
|
trailers: "%(trailers)"
|
26
28
|
}.freeze
|
27
29
|
|
28
|
-
def initialize shell: SHELL, key_map: KEY_MAP, parser: Parsers::Commit
|
30
|
+
def initialize shell: SHELL, key_map: KEY_MAP, parser: Parsers::Commit.new
|
29
31
|
@shell = shell
|
30
32
|
@key_map = key_map
|
31
33
|
@parser = parser
|
32
34
|
end
|
33
35
|
|
34
|
-
def call(*
|
36
|
+
def call(*) = shell.call("log", *)
|
35
37
|
|
36
38
|
def index *arguments
|
37
|
-
arguments.prepend(pretty_format)
|
39
|
+
arguments.prepend("--shortstat", pretty_format)
|
38
40
|
.then { |pretty_format| call(*pretty_format) }
|
39
|
-
.fmap { |content| String(content).scrub("?")
|
41
|
+
.fmap { |content| String(content).scrub("?") }
|
40
42
|
.fmap { |entries| build_records entries }
|
41
43
|
end
|
42
44
|
|
@@ -58,7 +60,24 @@ module Gitt
|
|
58
60
|
.then { |structure| %(--pretty=format:"#{structure}") }
|
59
61
|
end
|
60
62
|
|
61
|
-
def build_records
|
63
|
+
def build_records entries
|
64
|
+
wrap_statistics entries
|
65
|
+
add_empty_statistics entries
|
66
|
+
entries.split("<break/>").map { |entry| parser.call entry }
|
67
|
+
end
|
68
|
+
|
69
|
+
# :reek:UtilityFunction
|
70
|
+
def wrap_statistics entries
|
71
|
+
entries.gsub!(/\d+\sfile.+\d+\s(insertion|deletion).+\n/) do |match|
|
72
|
+
"<statistics>#{match}</statistics><break/>"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# :reek:UtilityFunction
|
77
|
+
def add_empty_statistics entries
|
78
|
+
entries.gsub! %(</trailers>\n"\n"<author_email>),
|
79
|
+
"</trailers>\n<statistics></statistics>\n<author_email>"
|
80
|
+
end
|
62
81
|
end
|
63
82
|
end
|
64
83
|
end
|
data/lib/gitt/commands/tag.rb
CHANGED
@@ -31,7 +31,7 @@ module Gitt
|
|
31
31
|
@parser = parser
|
32
32
|
end
|
33
33
|
|
34
|
-
def call(*
|
34
|
+
def call(*) = shell.call("tag", *)
|
35
35
|
|
36
36
|
def create version, body = Core::EMPTY_STRING, *flags
|
37
37
|
return Failure "Unable to create Git tag without version." unless version
|
@@ -53,9 +53,15 @@ module Gitt
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def last
|
56
|
-
shell.call("describe", "--abbrev=0", "--tags"
|
56
|
+
shell.call("describe", "--abbrev=0", "--tags")
|
57
57
|
.fmap(&:strip)
|
58
|
-
.or
|
58
|
+
.or do |error|
|
59
|
+
if error.match?(/no names found/i)
|
60
|
+
Failure "No tags found."
|
61
|
+
else
|
62
|
+
Failure error.delete_prefix("fatal: ").chomp
|
63
|
+
end
|
64
|
+
end
|
59
65
|
end
|
60
66
|
|
61
67
|
def local? version
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitt
|
4
|
+
# Provides shared behavior for objects that can act like a commit.
|
5
|
+
module Directable
|
6
|
+
def directive? = amend? || fixup? || squash?
|
7
|
+
|
8
|
+
def amend? = subject.match?(/\Aamend!\s/)
|
9
|
+
|
10
|
+
def fixup? = subject.match?(/\Afixup!\s/)
|
11
|
+
|
12
|
+
def squash? = subject.match?(/\Asquash!\s/)
|
13
|
+
|
14
|
+
def prefix = subject[/\A[\w\!]+/]
|
15
|
+
end
|
16
|
+
end
|
data/lib/gitt/models/commit.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "dry/monads"
|
4
|
+
|
3
5
|
module Gitt
|
4
6
|
module Models
|
5
7
|
# Represents commit details.
|
@@ -15,25 +17,43 @@ module Gitt
|
|
15
17
|
:committed_relative_at,
|
16
18
|
:committer_email,
|
17
19
|
:committer_name,
|
20
|
+
:deletions,
|
21
|
+
:encoding,
|
22
|
+
:files_changed,
|
23
|
+
:insertions,
|
18
24
|
:lines,
|
25
|
+
:notes,
|
19
26
|
:raw,
|
20
27
|
:sha,
|
21
28
|
:signature,
|
22
29
|
:subject,
|
23
30
|
:trailers
|
24
31
|
) do
|
32
|
+
include Directable
|
33
|
+
include Dry::Monads[:result]
|
34
|
+
|
25
35
|
def initialize(**)
|
26
36
|
super
|
27
37
|
freeze
|
28
38
|
end
|
29
39
|
|
30
|
-
def
|
40
|
+
def find_trailer key
|
41
|
+
trailers.find { |trailer| trailer.key == key }
|
42
|
+
.then do |trailer|
|
43
|
+
return Success trailer if trailer
|
31
44
|
|
32
|
-
|
45
|
+
Failure "Unable to find trailer for key: #{key.inspect}."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_trailers key
|
50
|
+
trailers.select { |trailer| trailer.key == key }
|
51
|
+
.then { |trailers| Success trailers }
|
52
|
+
end
|
33
53
|
|
34
|
-
def
|
54
|
+
def trailer_value_for(key) = find_trailer(key).fmap(&:value)
|
35
55
|
|
36
|
-
def
|
56
|
+
def trailer_values_for(key) = find_trailers(key).fmap { |trailers| trailers.map(&:value) }
|
37
57
|
end
|
38
58
|
end
|
39
59
|
end
|
data/lib/gitt/models/person.rb
CHANGED
@@ -1,17 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "core"
|
4
|
+
|
3
5
|
module Gitt
|
4
6
|
module Models
|
5
7
|
# Represents a person within a repository.
|
6
|
-
Person =
|
8
|
+
Person = Data.define :name, :delimiter, :email do
|
7
9
|
def self.for(string, parser: Parsers::Person.new) = parser.call string
|
8
10
|
|
9
|
-
def initialize
|
11
|
+
def initialize name: nil, delimiter: " ", email: nil
|
10
12
|
super
|
11
|
-
freeze
|
12
13
|
end
|
13
14
|
|
14
|
-
def to_s
|
15
|
+
def to_s
|
16
|
+
case self
|
17
|
+
in String, String, String then "#{name}#{delimiter}<#{email}>"
|
18
|
+
in String, String, nil then name
|
19
|
+
in nil, String, String then "<#{email}>"
|
20
|
+
else Core::EMPTY_STRING
|
21
|
+
end
|
22
|
+
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
data/lib/gitt/models/trailer.rb
CHANGED
@@ -3,15 +3,14 @@
|
|
3
3
|
module Gitt
|
4
4
|
module Models
|
5
5
|
# Represents commit trailer details.
|
6
|
-
Trailer =
|
6
|
+
Trailer = Data.define :key, :delimiter, :space, :value do
|
7
7
|
def self.for(string, parser: Parsers::Trailer.new) = parser.call string
|
8
8
|
|
9
|
-
def initialize
|
9
|
+
def initialize key:, value:, delimiter: ":", space: " "
|
10
10
|
super
|
11
|
-
freeze
|
12
11
|
end
|
13
12
|
|
14
|
-
def to_s = values.join
|
13
|
+
def to_s = to_h.values.join
|
15
14
|
end
|
16
15
|
end
|
17
16
|
end
|
@@ -6,23 +6,25 @@ module Gitt
|
|
6
6
|
module Parsers
|
7
7
|
# Extracts attributes from XML formatted content.
|
8
8
|
class Attributer
|
9
|
-
def self.with(...) = new(...)
|
10
|
-
|
11
9
|
def initialize keys = Core::EMPTY_ARRAY
|
12
10
|
@keys = keys
|
13
11
|
end
|
14
12
|
|
15
13
|
def call content
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
attributes.merge key => scrub[%r(<#{key}>(?<value>.*?)</#{key}>)m, :value]
|
20
|
-
end
|
14
|
+
build String(content)
|
15
|
+
rescue ArgumentError => error
|
16
|
+
error.message.include?("invalid byte") ? build(content.scrub("?")) : raise
|
21
17
|
end
|
22
18
|
|
23
19
|
private
|
24
20
|
|
25
21
|
attr_reader :keys
|
22
|
+
|
23
|
+
def build content
|
24
|
+
keys.each.with_object({}) do |key, attributes|
|
25
|
+
attributes[key] = content[%r(<#{key}>(?<value>.*?)</#{key}>)m, :value]
|
26
|
+
end
|
27
|
+
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
data/lib/gitt/parsers/commit.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "refinements/
|
3
|
+
require "refinements/hash"
|
4
4
|
|
5
5
|
module Gitt
|
6
6
|
module Parsers
|
7
7
|
# Parses raw commit information to produce a commit record.
|
8
8
|
class Commit
|
9
|
-
using Refinements::
|
9
|
+
using Refinements::Hash
|
10
10
|
|
11
|
-
def
|
12
|
-
|
13
|
-
def initialize attributer: Attributer.with(Commands::Log::KEY_MAP.keys),
|
11
|
+
def initialize attributer: Attributer.new(Commands::Log::KEY_MAP.keys.append(:statistics)),
|
14
12
|
sanitizers: Sanitizers::CONTAINER,
|
15
13
|
model: Models::Commit
|
16
14
|
@attributer = attributer
|
@@ -18,11 +16,14 @@ module Gitt
|
|
18
16
|
@model = model
|
19
17
|
end
|
20
18
|
|
19
|
+
# rubocop:todo Layout/LineLength
|
21
20
|
def call content
|
22
21
|
attributer.call(content)
|
23
22
|
.then { |attributes| process attributes }
|
23
|
+
.then { |attributes| attributes.merge! statistic_sanitizer.call(attributes.delete(:statistics)) }
|
24
24
|
.then { |attributes| model[**attributes] }
|
25
25
|
end
|
26
|
+
# rubocop:enable Layout/LineLength
|
26
27
|
|
27
28
|
private
|
28
29
|
|
@@ -64,6 +65,8 @@ module Gitt
|
|
64
65
|
|
65
66
|
def scissors_sanitizer = sanitizers.fetch :scissors
|
66
67
|
|
68
|
+
def statistic_sanitizer = sanitizers.fetch :statistic
|
69
|
+
|
67
70
|
def signature_sanitizer = sanitizers.fetch :signature
|
68
71
|
|
69
72
|
def trailers_sanitizer = sanitizers.fetch :trailers
|
data/lib/gitt/parsers/person.rb
CHANGED
@@ -2,26 +2,28 @@
|
|
2
2
|
|
3
3
|
module Gitt
|
4
4
|
module Parsers
|
5
|
-
# Parses
|
5
|
+
# Parses trailer to produce a person.
|
6
6
|
class Person
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
(?<delimiter>\s?) # Space delimiter (optional).
|
11
|
-
(?<email><.+>)? # Collaborator email (optional).
|
12
|
-
\Z # End of line.
|
13
|
-
/x
|
14
|
-
|
15
|
-
def initialize model: Models::Person, pattern: PATTERN
|
16
|
-
@pattern = pattern
|
7
|
+
def initialize email_start: "<", email_end: ">", model: Models::Person
|
8
|
+
@email_start = email_start
|
9
|
+
@email_end = email_end
|
17
10
|
@model = model
|
18
11
|
end
|
19
12
|
|
20
|
-
def call
|
13
|
+
def call content
|
14
|
+
if content.start_with? email_start
|
15
|
+
model[email: content.delete_prefix(email_start).delete_suffix(email_end)]
|
16
|
+
else
|
17
|
+
name, email = content.split " #{email_start}"
|
18
|
+
email.delete_suffix! email_end if email
|
19
|
+
|
20
|
+
model[name:, email:]
|
21
|
+
end
|
22
|
+
end
|
21
23
|
|
22
24
|
private
|
23
25
|
|
24
|
-
attr_reader :
|
26
|
+
attr_reader :email_start, :email_end, :model
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
data/lib/gitt/parsers/tag.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "refinements/
|
3
|
+
require "refinements/hash"
|
4
4
|
|
5
5
|
module Gitt
|
6
6
|
module Parsers
|
7
7
|
# Parses raw tag information to produce a tag record.
|
8
8
|
class Tag
|
9
|
-
using Refinements::
|
9
|
+
using Refinements::Hash
|
10
10
|
|
11
|
-
def initialize attributer: Attributer.
|
11
|
+
def initialize attributer: Attributer.new(Commands::Tag::KEY_MAP.keys),
|
12
12
|
sanitizers: Sanitizers::CONTAINER,
|
13
13
|
model: Models::Tag
|
14
14
|
@attributer = attributer
|
data/lib/gitt/parsers/trailer.rb
CHANGED
@@ -12,20 +12,21 @@ module Gitt
|
|
12
12
|
\Z # End of line.
|
13
13
|
/x
|
14
14
|
|
15
|
-
def initialize model: Models::Trailer
|
15
|
+
def initialize pattern: PATTERN, model: Models::Trailer
|
16
16
|
@pattern = pattern
|
17
17
|
@model = model
|
18
|
+
@empty = model[key: nil, value: nil].to_h
|
18
19
|
end
|
19
20
|
|
20
21
|
def call content
|
21
22
|
content.match(pattern)
|
22
|
-
.then { |data| data ? data.named_captures :
|
23
|
+
.then { |data| data ? data.named_captures(symbolize_names: true) : empty }
|
23
24
|
.then { |attributes| model[**attributes] }
|
24
25
|
end
|
25
26
|
|
26
27
|
private
|
27
28
|
|
28
|
-
attr_reader :pattern, :model
|
29
|
+
attr_reader :pattern, :model, :empty
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
data/lib/gitt/sanitizers/date.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitt
|
4
|
+
module Sanitizers
|
5
|
+
# Converts raw text into a statistics hash.
|
6
|
+
class Statistic
|
7
|
+
EMPTY = {files_changed: 0, insertions: 0, deletions: 0}.freeze
|
8
|
+
|
9
|
+
PATTERN = /
|
10
|
+
(?<total>\d+) # Total capture group.
|
11
|
+
\s # Space delimiter.
|
12
|
+
(?<kind>file|insertion|deletion) # Kind capture group.
|
13
|
+
/x
|
14
|
+
|
15
|
+
def initialize empty: EMPTY, pattern: PATTERN
|
16
|
+
@empty = empty
|
17
|
+
@pattern = pattern
|
18
|
+
end
|
19
|
+
|
20
|
+
# :reek:TooManyStatements
|
21
|
+
def call text
|
22
|
+
return empty unless text
|
23
|
+
|
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
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :empty, :pattern
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/gitt/shell.rb
CHANGED
@@ -12,8 +12,8 @@ module Gitt
|
|
12
12
|
@client = client
|
13
13
|
end
|
14
14
|
|
15
|
-
def call(
|
16
|
-
client.capture3("git",
|
15
|
+
def call(*, **)
|
16
|
+
client.capture3("git", *, **).then do |stdout, stderr, status|
|
17
17
|
status.success? ? Success(stdout) : Failure(stderr)
|
18
18
|
end
|
19
19
|
end
|
data/lib/gitt.rb
CHANGED
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:
|
4
|
+
version: 3.0.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:
|
38
|
+
date: 2024-01-01 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: core
|
@@ -43,14 +43,14 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '0
|
46
|
+
version: '1.0'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '0
|
53
|
+
version: '1.0'
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: dry-monads
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,14 +71,14 @@ dependencies:
|
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: '
|
74
|
+
version: '12.0'
|
75
75
|
type: :runtime
|
76
76
|
prerelease: false
|
77
77
|
version_requirements: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
81
|
+
version: '12.0'
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
83
|
name: zeitwerk
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- lib/gitt/commands/config.rb
|
111
111
|
- lib/gitt/commands/log.rb
|
112
112
|
- lib/gitt/commands/tag.rb
|
113
|
+
- lib/gitt/directable.rb
|
113
114
|
- lib/gitt/models/commit.rb
|
114
115
|
- lib/gitt/models/person.rb
|
115
116
|
- lib/gitt/models/tag.rb
|
@@ -130,6 +131,7 @@ files:
|
|
130
131
|
- lib/gitt/sanitizers/paragraphs.rb
|
131
132
|
- lib/gitt/sanitizers/scissors.rb
|
132
133
|
- lib/gitt/sanitizers/signature.rb
|
134
|
+
- lib/gitt/sanitizers/statistic.rb
|
133
135
|
- lib/gitt/sanitizers/trailers.rb
|
134
136
|
- lib/gitt/shell.rb
|
135
137
|
homepage: https://alchemists.io/projects/gitt
|
@@ -149,10 +151,7 @@ require_paths:
|
|
149
151
|
- lib
|
150
152
|
required_ruby_version: !ruby/object:Gem::Requirement
|
151
153
|
requirements:
|
152
|
-
- - "
|
153
|
-
- !ruby/object:Gem::Version
|
154
|
-
version: '3.2'
|
155
|
-
- - "<="
|
154
|
+
- - "~>"
|
156
155
|
- !ruby/object:Gem::Version
|
157
156
|
version: '3.3'
|
158
157
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -161,7 +160,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
160
|
- !ruby/object:Gem::Version
|
162
161
|
version: '0'
|
163
162
|
requirements: []
|
164
|
-
rubygems_version: 3.5.
|
163
|
+
rubygems_version: 3.5.3
|
165
164
|
signing_key:
|
166
165
|
specification_version: 4
|
167
166
|
summary: A monadic Object API for the Git CLI.
|
metadata.gz.sig
CHANGED
Binary file
|