repofetch 0.4.4 → 0.5.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 +4 -4
- data/CONTRIBUTING.md +9 -7
- data/Gemfile.lock +14 -11
- data/README.md +1 -1
- data/RELEASE_NOTES +25 -3
- data/lib/repofetch/bitbucketcloud/stats.rb +64 -0
- data/lib/repofetch/bitbucketcloud.rb +14 -63
- data/lib/repofetch/cli.rb +1 -3
- data/lib/repofetch/github.rb +8 -9
- data/lib/repofetch/gitlab.rb +11 -11
- data/lib/repofetch/plugin.rb +180 -0
- data/lib/repofetch/stat.rb +60 -0
- data/lib/repofetch/timespan_stat.rb +16 -0
- data/lib/repofetch/util.rb +34 -3
- data/lib/repofetch.rb +47 -199
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d212500ad7536eede542d6a5c1e8e0f7cd6de302dd6508c6c279896100004b37
|
4
|
+
data.tar.gz: b8a63cc0c47c808f937b27041e508dbec59fee6934d6adaf2e1e4e94cbf73be5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fffca813b8f21cdae1229dc8d506ff1fba2d50db37252b1403d20a327a276991567aa46e78dcd52a999d290951162886e7ad6366b930054d7553cf5516eecf92
|
7
|
+
data.tar.gz: 788d2d7d46db0e2ed455e170ffaa52a5b392cb87815eb09f906a92e0523d51dc81a2d8f279d850757071046ade142a29e3811734b53931ba1f63691d089746c7
|
data/CONTRIBUTING.md
CHANGED
@@ -62,14 +62,15 @@ The following requirements assume you are *not* manually implementing a plugin's
|
|
62
62
|
`to_s` method, and you are inheriting from `Repofetch::Plugin`.
|
63
63
|
|
64
64
|
- `ascii` should return a string for the ASCII art
|
65
|
-
- `header` should return the header text that will be above the `---` separator on the right side.
|
65
|
+
- `header` should return the header text or an array of header text that will be above the `---` separator on the right side.
|
66
66
|
- `stats` should return an array of values that implement `to_s`. These will be
|
67
67
|
the stats displayed to the right of the ASCII art. You can use`Repofetch::Stat` and
|
68
68
|
`Repofetch::TimespanStat` to create a pretty stat.
|
69
69
|
|
70
|
-
|
70
|
+
### Optional Plugin Instance Methods
|
71
71
|
|
72
72
|
- `theme` can return an instance of `Repofetch::Theme` to use a different color scheme.
|
73
|
+
- `primary_color` will set the color for the header and stat labels.
|
73
74
|
|
74
75
|
### Authoring ASCII Art
|
75
76
|
|
@@ -113,15 +114,16 @@ class MyCoolPlugin < Repofetch::Plugin
|
|
113
114
|
end
|
114
115
|
|
115
116
|
def header
|
116
|
-
# NOTE:
|
117
|
-
|
117
|
+
# NOTE: The inherited header_joiner method will make the final header "My Plugin @ Me"
|
118
|
+
# You can override this method to use a different joiner, or override formatted_header
|
119
|
+
# for more control.
|
120
|
+
['My Plugin', 'Me']
|
118
121
|
end
|
119
122
|
|
120
123
|
def stats
|
121
|
-
# if theme is not passed, the stat will not be styled
|
122
124
|
[
|
123
|
-
Repofetch::Stat.new('git repo detected', @detected_from_git, emoji: '📂'
|
124
|
-
Repofetch::Stat.new('args passed', @arg_count
|
125
|
+
Repofetch::Stat.new('git repo detected', @detected_from_git, emoji: '📂'),
|
126
|
+
Repofetch::Stat.new('args passed', @arg_count)
|
125
127
|
]
|
126
128
|
end
|
127
129
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
repofetch (0.
|
4
|
+
repofetch (0.5.0)
|
5
5
|
actionview (~> 7.0, >= 7.0.4)
|
6
6
|
dotenv (~> 2.8)
|
7
7
|
faraday-retry (~> 2.0)
|
@@ -12,13 +12,13 @@ PATH
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
14
14
|
specs:
|
15
|
-
actionview (7.0.4)
|
16
|
-
activesupport (= 7.0.4)
|
15
|
+
actionview (7.0.4.1)
|
16
|
+
activesupport (= 7.0.4.1)
|
17
17
|
builder (~> 3.1)
|
18
18
|
erubi (~> 1.4)
|
19
19
|
rails-dom-testing (~> 2.0)
|
20
20
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
21
|
-
activesupport (7.0.4)
|
21
|
+
activesupport (7.0.4.1)
|
22
22
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
23
23
|
i18n (>= 1.6, < 2)
|
24
24
|
minitest (>= 5.1)
|
@@ -35,7 +35,7 @@ GEM
|
|
35
35
|
docile (1.4.0)
|
36
36
|
dotenv (2.8.1)
|
37
37
|
erubi (1.12.0)
|
38
|
-
faraday (2.7.
|
38
|
+
faraday (2.7.4)
|
39
39
|
faraday-net_http (>= 2.0, < 3.1)
|
40
40
|
ruby2_keywords (>= 0.0.4)
|
41
41
|
faraday-net_http (3.0.2)
|
@@ -58,7 +58,7 @@ GEM
|
|
58
58
|
faraday (>= 1, < 3)
|
59
59
|
sawyer (~> 0.9)
|
60
60
|
os (1.1.4)
|
61
|
-
overcommit (0.
|
61
|
+
overcommit (0.60.0)
|
62
62
|
childprocess (>= 0.6.3, < 5)
|
63
63
|
iniparse (~> 1.4)
|
64
64
|
rexml (~> 3.2)
|
@@ -70,12 +70,12 @@ GEM
|
|
70
70
|
rails-dom-testing (2.0.3)
|
71
71
|
activesupport (>= 4.2.0)
|
72
72
|
nokogiri (>= 1.6)
|
73
|
-
rails-html-sanitizer (1.
|
73
|
+
rails-html-sanitizer (1.5.0)
|
74
74
|
loofah (~> 2.19, >= 2.19.1)
|
75
75
|
rainbow (3.1.1)
|
76
76
|
rake (13.0.6)
|
77
77
|
rchardet (1.8.0)
|
78
|
-
regexp_parser (2.6.
|
78
|
+
regexp_parser (2.6.2)
|
79
79
|
rexml (3.2.5)
|
80
80
|
rspec (3.12.0)
|
81
81
|
rspec-core (~> 3.12.0)
|
@@ -86,7 +86,7 @@ GEM
|
|
86
86
|
rspec-expectations (3.12.2)
|
87
87
|
diff-lcs (>= 1.2.0, < 2.0)
|
88
88
|
rspec-support (~> 3.12.0)
|
89
|
-
rspec-mocks (3.12.
|
89
|
+
rspec-mocks (3.12.3)
|
90
90
|
diff-lcs (>= 1.2.0, < 2.0)
|
91
91
|
rspec-support (~> 3.12.0)
|
92
92
|
rspec-snapshot (2.0.1)
|
@@ -105,10 +105,13 @@ GEM
|
|
105
105
|
unicode-display_width (>= 2.4.0, < 3.0)
|
106
106
|
rubocop-ast (1.24.1)
|
107
107
|
parser (>= 3.1.1.0)
|
108
|
+
rubocop-capybara (2.17.0)
|
109
|
+
rubocop (~> 1.41)
|
108
110
|
rubocop-rake (0.6.0)
|
109
111
|
rubocop (~> 1.0)
|
110
|
-
rubocop-rspec (2.
|
112
|
+
rubocop-rspec (2.18.1)
|
111
113
|
rubocop (~> 1.33)
|
114
|
+
rubocop-capybara (~> 2.17)
|
112
115
|
ruby-progressbar (1.11.0)
|
113
116
|
ruby2_keywords (0.0.5)
|
114
117
|
sawyer (0.9.2)
|
@@ -149,4 +152,4 @@ DEPENDENCIES
|
|
149
152
|
yard (~> 0.9.28)
|
150
153
|
|
151
154
|
BUNDLED WITH
|
152
|
-
2.4.
|
155
|
+
2.4.4
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
[](./CREDITS.md)
|
5
5
|

|
6
6
|
[](https://github.com/spenserblack/repofetch/actions/workflows/github-code-scanning/codeql)
|
7
|
-
[](https://codecov.io/gh/spenserblack/repofetch)
|
8
8
|
|
9
9
|
Fetch details about your remote repository.
|
10
10
|
|
data/RELEASE_NOTES
CHANGED
@@ -1,6 +1,28 @@
|
|
1
|
-
|
1
|
+
0.5.0
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
- `Stat#format(theme)` to create styled stats
|
6
|
+
- `Stat#style_label` to style the label without mutating the original `Stat` instance
|
7
|
+
- `Plugin#matches_path?` and `Plugin#from_path` to allow plugins to initialize from paths, not
|
8
|
+
just git repositories
|
9
|
+
|
10
|
+
## Changed
|
11
|
+
|
12
|
+
- Bitbucket Cloud header to be bold and blue
|
13
|
+
- `Stat#style_label!` to accept one or more styles as parameters
|
14
|
+
- `Plugin#matches_repo?` to return `false` instead of raising an error when it is not overridden
|
2
15
|
|
3
16
|
## Fixed
|
4
17
|
|
5
|
-
-
|
6
|
-
|
18
|
+
- length of separator to match *visual* length of header
|
19
|
+
|
20
|
+
## Potentially Breaking for 3rd-party Plugins
|
21
|
+
|
22
|
+
### Changed
|
23
|
+
|
24
|
+
- `Repofetch::Util` to be a module
|
25
|
+
- `clean_s` to be called `remove_format_params`
|
26
|
+
- Moved `default_remote` and `default_remote_url` to be in `Repofetch::Util`
|
27
|
+
- `Stat#to_s` to return an unstyled value
|
28
|
+
- Header text and stats will now automatically be bold and use the value returned by `Plugin#primary_color`
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'repofetch'
|
4
|
+
|
5
|
+
class Repofetch
|
6
|
+
class BitbucketCloud < Repofetch::Plugin
|
7
|
+
# Methods to get Bitbucket Cloud stats.
|
8
|
+
module Stats
|
9
|
+
protected
|
10
|
+
|
11
|
+
def repo_data
|
12
|
+
@repo_data ||= agent.call(:get, "repositories/#{@repo_identifier}").data
|
13
|
+
end
|
14
|
+
|
15
|
+
def clone_urls
|
16
|
+
@clone_urls ||= repo_data['links']['clone'].to_h { |clone| [clone['name'].to_sym, clone['href']] }
|
17
|
+
end
|
18
|
+
|
19
|
+
def http_clone_url
|
20
|
+
Repofetch::Stat.new('HTTP(S)', clone_urls[:https], emoji: '🌐')
|
21
|
+
end
|
22
|
+
|
23
|
+
def ssh_clone_url
|
24
|
+
Repofetch::Stat.new('SSH', clone_urls[:ssh], emoji: '🔑')
|
25
|
+
end
|
26
|
+
|
27
|
+
def watchers
|
28
|
+
@watcher_data ||= agent.call(:get, "repositories/#{@repo_identifier}/watchers").data
|
29
|
+
Repofetch::Stat.new('subscribers', @watcher_data['size'], emoji: '👀')
|
30
|
+
end
|
31
|
+
|
32
|
+
def forks
|
33
|
+
@fork_data ||= agent.call(:get, "repositories/#{@repo_identifier}/forks").data
|
34
|
+
Repofetch::Stat.new('forks', @fork_data['size'], emoji: '🔱')
|
35
|
+
end
|
36
|
+
|
37
|
+
def created
|
38
|
+
Repofetch::TimespanStat.new('created', repo_data['created_on'], emoji: '🐣')
|
39
|
+
end
|
40
|
+
|
41
|
+
def updated
|
42
|
+
Repofetch::TimespanStat.new('updated', repo_data['updated_on'], emoji: '📤')
|
43
|
+
end
|
44
|
+
|
45
|
+
def size
|
46
|
+
# NOTE: Size is in bytes
|
47
|
+
# TODO: Move this somewhere else instead of using a copy-paste
|
48
|
+
byte_size = number_to_human_size(repo_data['size'] || 0, precision: 2, significant: false,
|
49
|
+
strip_insignificant_zeros: false)
|
50
|
+
Repofetch::Stat.new('size', byte_size, emoji: '💽')
|
51
|
+
end
|
52
|
+
|
53
|
+
def issues
|
54
|
+
@issue_data ||= agent.call(:get, "repositories/#{@repo_identifier}/issues").data
|
55
|
+
Repofetch::Stat.new('issues', @issue_data['size'], emoji: '❗')
|
56
|
+
end
|
57
|
+
|
58
|
+
def pull_requests
|
59
|
+
@pull_request_data ||= agent.call(:get, "repositories/#{@repo_identifier}/pullrequests").data
|
60
|
+
Repofetch::Stat.new('pull requests', @pull_request_data['size'], emoji: '🔀')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -2,14 +2,19 @@
|
|
2
2
|
|
3
3
|
require 'action_view'
|
4
4
|
require 'optparse'
|
5
|
-
require 'repofetch'
|
5
|
+
require 'repofetch/bitbucketcloud/stats'
|
6
6
|
require 'repofetch/exceptions'
|
7
|
+
require 'repofetch/plugin'
|
8
|
+
require 'repofetch/util'
|
7
9
|
require 'sawyer'
|
8
10
|
|
9
11
|
class Repofetch
|
10
12
|
# Adds support for Bitbucket repositories.
|
11
13
|
class BitbucketCloud < Repofetch::Plugin
|
12
14
|
include ActionView::Helpers::NumberHelper
|
15
|
+
include Repofetch::BitbucketCloud::Stats
|
16
|
+
include Repofetch::Util
|
17
|
+
extend Repofetch::Util
|
13
18
|
|
14
19
|
HTTP_REMOTE_REGEX = %r{https?://bitbucket\.org/(?<owner>[\w._-]+)/(?<repo>[\w._-]+)}.freeze
|
15
20
|
SSH_REMOTE_REGEX = %r{git@bitbucket\.org:(?<owner>[\w._-]+)/(?<repo>[\w._-]+)}.freeze
|
@@ -24,13 +29,15 @@ class Repofetch
|
|
24
29
|
end
|
25
30
|
|
26
31
|
def header
|
27
|
-
"#{repo_data['owner']['display_name']}/#{repo_data['name']}
|
32
|
+
["#{repo_data['owner']['display_name']}/#{repo_data['name']}", 'Bitbucket']
|
28
33
|
end
|
29
34
|
|
30
|
-
def
|
31
|
-
|
35
|
+
def primary_color
|
36
|
+
:blue
|
37
|
+
end
|
32
38
|
|
33
|
-
|
39
|
+
def stats
|
40
|
+
[http_clone_url, ssh_clone_url, watchers, forks, created, updated, size, issues, pull_requests]
|
34
41
|
end
|
35
42
|
|
36
43
|
def ascii
|
@@ -49,8 +56,7 @@ class Repofetch
|
|
49
56
|
|
50
57
|
# Detects that the repository is a Bitbucket repository.
|
51
58
|
def self.matches_repo?(git)
|
52
|
-
|
53
|
-
matches_remote?(default_remote&.url)
|
59
|
+
matches_remote?(default_remote_url(git))
|
54
60
|
end
|
55
61
|
|
56
62
|
# Detects that the remote URL is for a Bitbucket Cloud repository.
|
@@ -60,8 +66,7 @@ class Repofetch
|
|
60
66
|
|
61
67
|
# Gets the owner and repository from a GitHub local repository.
|
62
68
|
def self.repo_identifiers(git)
|
63
|
-
|
64
|
-
remote_identifiers(default_remote&.url)
|
69
|
+
remote_identifiers(default_remote_url(git))
|
65
70
|
end
|
66
71
|
|
67
72
|
# Gets the owner and repository from a GitHub remote URL.
|
@@ -98,60 +103,6 @@ class Repofetch
|
|
98
103
|
|
99
104
|
new(args[0])
|
100
105
|
end
|
101
|
-
|
102
|
-
protected
|
103
|
-
|
104
|
-
def repo_data
|
105
|
-
@repo_data ||= agent.call(:get, "repositories/#{@repo_identifier}").data
|
106
|
-
end
|
107
|
-
|
108
|
-
def clone_urls
|
109
|
-
@clone_urls ||= repo_data['links']['clone'].to_h { |clone| [clone['name'].to_sym, clone['href']] }
|
110
|
-
end
|
111
|
-
|
112
|
-
def http_clone_url
|
113
|
-
Repofetch::Stat.new('HTTP(S)', clone_urls[:https], emoji: '🌐')
|
114
|
-
end
|
115
|
-
|
116
|
-
def ssh_clone_url
|
117
|
-
Repofetch::Stat.new('SSH', clone_urls[:ssh], emoji: '🔑')
|
118
|
-
end
|
119
|
-
|
120
|
-
def watchers
|
121
|
-
@watcher_data ||= agent.call(:get, "repositories/#{@repo_identifier}/watchers").data
|
122
|
-
Repofetch::Stat.new('subscribers', @watcher_data['size'], emoji: '👀')
|
123
|
-
end
|
124
|
-
|
125
|
-
def forks
|
126
|
-
@fork_data ||= agent.call(:get, "repositories/#{@repo_identifier}/forks").data
|
127
|
-
Repofetch::Stat.new('forks', @fork_data['size'], emoji: '🔱')
|
128
|
-
end
|
129
|
-
|
130
|
-
def created
|
131
|
-
Repofetch::TimespanStat.new('created', repo_data['created_on'], emoji: '🐣')
|
132
|
-
end
|
133
|
-
|
134
|
-
def updated
|
135
|
-
Repofetch::TimespanStat.new('updated', repo_data['updated_on'], emoji: '📤')
|
136
|
-
end
|
137
|
-
|
138
|
-
def size
|
139
|
-
# NOTE: Size is in bytes
|
140
|
-
# TODO: Move this somewhere else instead of using a copy-paste
|
141
|
-
byte_size = number_to_human_size(repo_data['size'] || 0, precision: 2, significant: false,
|
142
|
-
strip_insignificant_zeros: false)
|
143
|
-
Repofetch::Stat.new('size', byte_size, emoji: '💽')
|
144
|
-
end
|
145
|
-
|
146
|
-
def issues
|
147
|
-
@issue_data ||= agent.call(:get, "repositories/#{@repo_identifier}/issues").data
|
148
|
-
Repofetch::Stat.new('issues', @issue_data['size'], emoji: '❗')
|
149
|
-
end
|
150
|
-
|
151
|
-
def pull_requests
|
152
|
-
@pull_request_data ||= agent.call(:get, "repositories/#{@repo_identifier}/pullrequests").data
|
153
|
-
Repofetch::Stat.new('pull requests', @pull_request_data['size'], emoji: '🔀')
|
154
|
-
end
|
155
106
|
end
|
156
107
|
end
|
157
108
|
|
data/lib/repofetch/cli.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'git'
|
4
3
|
require 'optparse'
|
5
4
|
require 'repofetch'
|
6
5
|
require 'repofetch/config'
|
@@ -56,8 +55,7 @@ class Repofetch
|
|
56
55
|
def new_plugin
|
57
56
|
return @plugin.from_args(@args) unless @plugin.nil?
|
58
57
|
|
59
|
-
|
60
|
-
Repofetch.get_plugin(git, @args)
|
58
|
+
Repofetch.get_plugin(@repository_path, @args)
|
61
59
|
end
|
62
60
|
|
63
61
|
private
|
data/lib/repofetch/github.rb
CHANGED
@@ -3,13 +3,16 @@
|
|
3
3
|
require 'action_view'
|
4
4
|
require 'octokit'
|
5
5
|
require 'optparse'
|
6
|
-
require 'repofetch'
|
7
6
|
require 'repofetch/exceptions'
|
7
|
+
require 'repofetch/plugin'
|
8
|
+
require 'repofetch/util'
|
8
9
|
|
9
10
|
class Repofetch
|
10
11
|
# Adds support for GitHub repositories.
|
11
12
|
class Github < Repofetch::Plugin
|
12
13
|
include ActionView::Helpers::NumberHelper
|
14
|
+
include Repofetch::Util
|
15
|
+
extend Repofetch::Util
|
13
16
|
|
14
17
|
HTTP_REMOTE_REGEX = %r{https?://github\.com/(?<owner>[\w.-]+)/(?<repository>[\w.-]+)}.freeze
|
15
18
|
SSH_REMOTE_REGEX = %r{git@github\.com:(?<owner>[\w.-]+)/(?<repository>[\w.-]+)}.freeze
|
@@ -31,15 +34,12 @@ class Repofetch
|
|
31
34
|
end
|
32
35
|
|
33
36
|
def stats
|
34
|
-
|
35
|
-
pull_requests]
|
36
|
-
stats.each { |stat| stat.style_label!(:bold) }
|
37
|
+
[http_clone_url, ssh_clone_url, stargazers, subscribers, forks, created, updated, size, issues, pull_requests]
|
37
38
|
end
|
38
39
|
|
39
40
|
# Detects that the repository is a GitHub repository.
|
40
41
|
def self.matches_repo?(git)
|
41
|
-
|
42
|
-
matches_remote?(default_remote&.url)
|
42
|
+
matches_remote?(default_remote_url(git))
|
43
43
|
end
|
44
44
|
|
45
45
|
# Detects that the remote URL is for a GitHub repository.
|
@@ -49,8 +49,7 @@ class Repofetch
|
|
49
49
|
|
50
50
|
# Gets the owner and repository from a GitHub local repository.
|
51
51
|
def self.repo_identifiers(git)
|
52
|
-
|
53
|
-
remote_identifiers(default_remote&.url)
|
52
|
+
remote_identifiers(default_remote_url(git))
|
54
53
|
end
|
55
54
|
|
56
55
|
# Gets the owner and repository from a GitHub remote URL.
|
@@ -93,7 +92,7 @@ class Repofetch
|
|
93
92
|
end
|
94
93
|
|
95
94
|
def header
|
96
|
-
"#{
|
95
|
+
["#{owner}/#{repository}", 'GitHub']
|
97
96
|
end
|
98
97
|
|
99
98
|
def ascii
|
data/lib/repofetch/gitlab.rb
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'cgi'
|
4
|
-
require 'repofetch'
|
5
4
|
require 'repofetch/exceptions'
|
5
|
+
require 'repofetch/plugin'
|
6
|
+
require 'repofetch/util'
|
6
7
|
require 'sawyer'
|
7
8
|
|
8
9
|
class Repofetch
|
9
10
|
# Adds support for GitLab repositories.
|
10
11
|
class Gitlab < Repofetch::Plugin
|
12
|
+
include Repofetch::Util
|
13
|
+
extend Repofetch::Util
|
14
|
+
|
11
15
|
HTTP_REMOTE_REGEX = %r{https?://gitlab\.com/(?<path>[\w.-][\w.\-/]+)}.freeze
|
12
16
|
SSH_REMOTE_REGEX = %r{git@gitlab\.com:(?<path>[\w.-][\w.\-/]+)}.freeze
|
13
17
|
ASCII = File.read(File.expand_path('gitlab/ASCII', __dir__))
|
@@ -22,11 +26,11 @@ class Repofetch
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def header
|
25
|
-
|
29
|
+
[repo_data['name_with_namespace'], 'GitLab']
|
26
30
|
end
|
27
31
|
|
28
|
-
def
|
29
|
-
|
32
|
+
def primary_color
|
33
|
+
:red
|
30
34
|
end
|
31
35
|
|
32
36
|
def stats
|
@@ -35,7 +39,7 @@ class Repofetch
|
|
35
39
|
# NOTE: Stats that require authentication
|
36
40
|
stats << open_issues unless token.nil?
|
37
41
|
|
38
|
-
stats
|
42
|
+
stats
|
39
43
|
end
|
40
44
|
|
41
45
|
def ascii
|
@@ -87,9 +91,7 @@ class Repofetch
|
|
87
91
|
|
88
92
|
# Gets the path (+owner/subproject/repo+) of the repository.
|
89
93
|
def self.repo_identifier(git)
|
90
|
-
|
91
|
-
url = default_remote&.url
|
92
|
-
remote_identifier(url)
|
94
|
+
remote_identifier(default_remote_url(git))
|
93
95
|
end
|
94
96
|
|
95
97
|
# Gets the path (+owner/subproject/repo+) of the repository.
|
@@ -105,9 +107,7 @@ class Repofetch
|
|
105
107
|
|
106
108
|
# Detects that the repository is a GitHub repository.
|
107
109
|
def self.matches_repo?(git)
|
108
|
-
|
109
|
-
url = default_remote&.url
|
110
|
-
matches_remote?(url)
|
110
|
+
matches_remote?(default_remote_url(git))
|
111
111
|
end
|
112
112
|
|
113
113
|
# Detects that the remote URL is for a GitHub repository.
|
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'repofetch'
|
4
|
+
require 'repofetch/util'
|
5
|
+
require 'repofetch/stat'
|
6
|
+
|
7
|
+
class Repofetch
|
8
|
+
# @abstract Subclass to create a plugin.
|
9
|
+
class Plugin
|
10
|
+
include Repofetch::Util
|
11
|
+
|
12
|
+
# Plugin intializer arguments should come from the +from_git+ or +from_args+
|
13
|
+
# class methods.
|
14
|
+
def initialize(*) end
|
15
|
+
|
16
|
+
# Registers this plugin class for repofetch.
|
17
|
+
def self.register
|
18
|
+
Repofetch.register_plugin(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Tries to replace another plugin. An example use case might be if this plugin
|
22
|
+
# extends another registered plugin.
|
23
|
+
#
|
24
|
+
# @param [Plugin] old The plugin to replace
|
25
|
+
def self.replace_or_register(old)
|
26
|
+
Repofetch.replace_or_register_plugin(old, self)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @abstract Detects that this plugin should be used. Should be overridden by subclasses.
|
30
|
+
#
|
31
|
+
# An example implementation is checking if +Repofetch.default_remote_url+ matches
|
32
|
+
# a regular expression.
|
33
|
+
#
|
34
|
+
# @param [Git::Base] _git The Git repository object
|
35
|
+
def self.matches_repo?(_git)
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
# @abstract Detects that this plugin should be used. Should be overridden by subclasses.
|
40
|
+
#
|
41
|
+
# This is intended to be more generic than +matches_repo?+, and support any path.
|
42
|
+
#
|
43
|
+
# An example implementation is checking if an expected file exists in this path.
|
44
|
+
# @param [String] _path The path to check
|
45
|
+
def self.matches_path?(_path)
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
# @abstract This should use a git instance and call +Plugin.new+.
|
50
|
+
#
|
51
|
+
# @param [Git::Base] _git The Git repository object to use when calling +Plugin.new+.
|
52
|
+
# @param [Array] _args The arguments to process.
|
53
|
+
#
|
54
|
+
# @return [Plugin]
|
55
|
+
def self.from_git(_git, _args)
|
56
|
+
raise NoMethodError, 'from_git must be overridden by the plugin subclass'
|
57
|
+
end
|
58
|
+
|
59
|
+
# @abstract This should use a path and call +Plugin.new+.
|
60
|
+
#
|
61
|
+
# @param [String] _path The path to use when calling +Plugin.new+.
|
62
|
+
# @param [Array] _args The arguments to process.
|
63
|
+
#
|
64
|
+
# @return [Plugin]
|
65
|
+
def self.from_path(_path, _args)
|
66
|
+
raise NoMethodError, 'from_path must be overridden by the plugin subclass'
|
67
|
+
end
|
68
|
+
|
69
|
+
# @abstract This will receive an array of strings (e.g. +ARGV+) and call +Plugin.new+.
|
70
|
+
#
|
71
|
+
# @param [Array] _args The arguments to process.
|
72
|
+
#
|
73
|
+
# @return [Plugin]
|
74
|
+
def self.from_args(_args)
|
75
|
+
raise NoMethodError, 'from_args must be overridden by the plugin subclass'
|
76
|
+
end
|
77
|
+
|
78
|
+
# Gets the plugin's theme. Override to use a theme besides the default.
|
79
|
+
def theme
|
80
|
+
Repofetch::DEFAULT_THEME
|
81
|
+
end
|
82
|
+
|
83
|
+
# @abstract The ASCII to be printed alongside the stats.
|
84
|
+
#
|
85
|
+
# This should be overridden by the plugin subclass.
|
86
|
+
# Should be within the bounds 40x20 (width x height).
|
87
|
+
def ascii
|
88
|
+
raise NoMethodError, 'ascii must be overridden by the plugin subclass'
|
89
|
+
end
|
90
|
+
|
91
|
+
# @abstract The header to show for the plugin.
|
92
|
+
#
|
93
|
+
# This should be overridden by the plugin subclass.
|
94
|
+
#
|
95
|
+
# If an array is returned, it will be joined by +header_joiner+.
|
96
|
+
#
|
97
|
+
# @return [String, Array<String>]
|
98
|
+
def header
|
99
|
+
raise NoMethodError, 'header must be overridden by the plugin subclass'
|
100
|
+
end
|
101
|
+
|
102
|
+
# A string to join header text.
|
103
|
+
#
|
104
|
+
# Override to use a different string.
|
105
|
+
# @return [String]
|
106
|
+
def header_joiner
|
107
|
+
' @ '
|
108
|
+
end
|
109
|
+
|
110
|
+
# Creates the separator that appears underneath the header
|
111
|
+
def separator
|
112
|
+
return '-' * header.length unless header.is_a?(Array)
|
113
|
+
|
114
|
+
header_length = header.map(&:length).sum + ((header.length - 1) * header_joiner.length)
|
115
|
+
|
116
|
+
'-' * header_length
|
117
|
+
end
|
118
|
+
|
119
|
+
def to_s
|
120
|
+
zipped_lines.map do |ascii_line, stat_line|
|
121
|
+
cleaned_ascii = remove_format_params(ascii_line)
|
122
|
+
styled_ascii = (ascii_line % theme.to_h) + theme.style(:reset)
|
123
|
+
aligned_stat_line = "#{' ' * (MAX_ASCII_WIDTH + 5)}#{stat_line}"
|
124
|
+
"#{styled_ascii}#{aligned_stat_line.slice(cleaned_ascii.length..)}\n"
|
125
|
+
end.join
|
126
|
+
end
|
127
|
+
|
128
|
+
# @abstract An array of stats that will be displayed to the right of the ASCII art.
|
129
|
+
#
|
130
|
+
# @return [Array<Stat>]
|
131
|
+
def stats
|
132
|
+
[]
|
133
|
+
end
|
134
|
+
|
135
|
+
# The primary color to use for the header and stats.
|
136
|
+
#
|
137
|
+
# Override to use a different color from the theme.
|
138
|
+
# @see Repofetch::Theme
|
139
|
+
#
|
140
|
+
# @return [Symbol]
|
141
|
+
def primary_color
|
142
|
+
:default
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the header, formatted with the primary color and bold, and joined with the header joiner.
|
146
|
+
#
|
147
|
+
# @return [String]
|
148
|
+
def formatted_header
|
149
|
+
(header.is_a?(Array) ? header : [header]).map { |h| apply_styles(h, :bold, primary_color) }.join(header_joiner)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Makes an array of stat lines, including the header and separator.
|
153
|
+
def stat_lines
|
154
|
+
styled_stats = stats.map do |stat|
|
155
|
+
next stat unless stat.is_a?(Repofetch::Stat)
|
156
|
+
|
157
|
+
stat.style_label(:bold, primary_color).format(theme)
|
158
|
+
end
|
159
|
+
[formatted_header, separator, *styled_stats]
|
160
|
+
end
|
161
|
+
|
162
|
+
# Zips ASCII lines with stat lines.
|
163
|
+
#
|
164
|
+
# If there are more of one than the other, than the zip will be padded with empty strings.
|
165
|
+
def zipped_lines
|
166
|
+
ascii_lines = ascii.lines.map(&:chomp)
|
167
|
+
if ascii_lines.length > stat_lines.length
|
168
|
+
ascii_lines.zip(stat_lines)
|
169
|
+
else
|
170
|
+
stat_lines.zip(ascii_lines).map(&:reverse)
|
171
|
+
end.map { |ascii, stat| [ascii.to_s, stat.to_s] }
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def apply_styles(str, *styles)
|
177
|
+
styles.inject(str) { |style, s| theme.format(s, style) }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Repofetch
|
4
|
+
# Base class for stats.
|
5
|
+
class Stat
|
6
|
+
attr_reader :label, :value, :emoji
|
7
|
+
attr_writer :theme
|
8
|
+
|
9
|
+
# Creates a stat
|
10
|
+
#
|
11
|
+
# @param [String] label The label of the stat
|
12
|
+
# @param value The value of the stat
|
13
|
+
# @param [String] emoji An optional emoji for the stat
|
14
|
+
def initialize(label, value, emoji: nil)
|
15
|
+
@label = label
|
16
|
+
@value = value
|
17
|
+
@emoji = emoji
|
18
|
+
@label_styles = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def format(theme = nil)
|
22
|
+
return to_s if theme.nil?
|
23
|
+
|
24
|
+
emoji = @emoji
|
25
|
+
emoji = nil unless Repofetch.config.nil? || Repofetch.config.emojis?
|
26
|
+
styled_label = @label_styles.inject(@label) { |label, style| theme.format(style, label) }
|
27
|
+
"#{emoji}#{styled_label}: #{format_value}"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Formats the value of the stat
|
31
|
+
#
|
32
|
+
# Simply calls +to_s+, but can be overridden by subclasses.
|
33
|
+
def format_value
|
34
|
+
@value.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
emoji = @emoji
|
39
|
+
emoji = nil unless Repofetch.config.nil? || Repofetch.config.emojis?
|
40
|
+
"#{emoji}#{@label}: #{@value}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Adds one or more styles for the label
|
44
|
+
#
|
45
|
+
# @param [Symbol] style The theme's style to add
|
46
|
+
# @param [Symbol] styles Additional styles to add
|
47
|
+
def style_label!(style, *styles)
|
48
|
+
@label_styles << style
|
49
|
+
@label_styles.concat(styles)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Adds one or more styles for the label, returning a new stat
|
53
|
+
#
|
54
|
+
# @param [Symbol] style The theme's style to add
|
55
|
+
# @return [Stat] A new stat with the style added
|
56
|
+
def style_label(style, *styles)
|
57
|
+
dup.tap { |stat| stat.style_label!(style, *styles) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'repofetch/stat'
|
4
|
+
|
5
|
+
class Repofetch
|
6
|
+
# Timespan stat for "x units ago" stats.
|
7
|
+
class TimespanStat < Stat
|
8
|
+
include ActionView::Helpers::DateHelper
|
9
|
+
|
10
|
+
# Formats the value as "x units ago".
|
11
|
+
def format_value(now = nil)
|
12
|
+
now = Time.now if now.nil?
|
13
|
+
"#{distance_of_time_in_words(@value, now)} ago"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/repofetch/util.rb
CHANGED
@@ -2,10 +2,41 @@
|
|
2
2
|
|
3
3
|
class Repofetch
|
4
4
|
# Provides uncategorized utilities.
|
5
|
-
|
6
|
-
#
|
7
|
-
def
|
5
|
+
module Util
|
6
|
+
# Converts a format string into a plain string (e.g. +"%{green}OK"+ -> +"OK"+)
|
7
|
+
def remove_format_params(str)
|
8
8
|
str.gsub(/%{[\w\d]+?}/, '')
|
9
9
|
end
|
10
|
+
|
11
|
+
# Removes ANSI escape sequences from +str+.
|
12
|
+
def clean_ansi(str)
|
13
|
+
str.gsub("\e", '').gsub(/\[\d+(;\d+)*m/, '')
|
14
|
+
end
|
15
|
+
|
16
|
+
# Gets the name of the default remote to use.
|
17
|
+
#
|
18
|
+
# Will try to pick "origin", but if that is not found then it will
|
19
|
+
# pick the first one found, or nil if there aren't any available.
|
20
|
+
#
|
21
|
+
# @param [Git::Base] git The repository instance.
|
22
|
+
#
|
23
|
+
# @return [Git::Remote]
|
24
|
+
def default_remote(git)
|
25
|
+
remotes = git.remotes
|
26
|
+
found_remote = remotes.find { |remote| remote.name == 'origin' }
|
27
|
+
found_remote = remotes[0] if found_remote.nil?
|
28
|
+
found_remote
|
29
|
+
end
|
30
|
+
|
31
|
+
# Just wrapper around +default_remote+ since this is likely the most common
|
32
|
+
# use case (and it's easier than referencing the +Git::Remote+ docs to ensure
|
33
|
+
# correct usage in each plugin).
|
34
|
+
#
|
35
|
+
# @param [Git::Base] git The repository instance.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
def default_remote_url(git)
|
39
|
+
default_remote(git)&.url
|
40
|
+
end
|
10
41
|
end
|
11
42
|
end
|
data/lib/repofetch.rb
CHANGED
@@ -5,6 +5,9 @@ require 'git'
|
|
5
5
|
require 'repofetch/config'
|
6
6
|
require 'repofetch/env'
|
7
7
|
require 'repofetch/exceptions'
|
8
|
+
require 'repofetch/plugin'
|
9
|
+
require 'repofetch/stat'
|
10
|
+
require 'repofetch/timespan_stat'
|
8
11
|
require 'repofetch/theme'
|
9
12
|
require 'repofetch/util'
|
10
13
|
|
@@ -56,230 +59,75 @@ class Repofetch
|
|
56
59
|
# Raises a +Repofetch::NoPluginsError+ if no plugins are found.
|
57
60
|
# Raises a +Repofetch::TooManyPluginsError+ if more than one plugin is found.
|
58
61
|
#
|
59
|
-
# @param [
|
62
|
+
# @param [String] path The path to check.
|
60
63
|
# @param [Array<String>] args The arguments passed to the program.
|
61
64
|
#
|
62
65
|
# @raise [NoPluginsError] If no plugins were selected.
|
63
66
|
# @raise [TooManyPluginsError] If more than one plugin was selected.
|
64
67
|
#
|
65
68
|
# @return [Plugin] A plugin to use.
|
66
|
-
def self.get_plugin(
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
raise NoPluginsError if available_plugins.empty?
|
69
|
+
def self.get_plugin(path, args)
|
70
|
+
path_plugin = get_plugin_for_path(path)
|
71
|
+
repo_plugin = get_plugin_for_repo(path)
|
72
|
+
|
73
|
+
raise TooManyPluginsError if path_plugin && repo_plugin
|
74
|
+
|
75
|
+
raise NoPluginsError if path_plugin.nil? && repo_plugin.nil?
|
74
76
|
|
75
|
-
|
77
|
+
return path_plugin.from_path(path, args) unless path_plugin.nil?
|
76
78
|
|
77
|
-
|
79
|
+
git = Git.open(path)
|
80
|
+
repo_plugin.from_git(git, args)
|
78
81
|
end
|
79
82
|
|
80
|
-
# Gets the
|
83
|
+
# Gets the plugins that matches the given path.
|
81
84
|
#
|
82
|
-
#
|
83
|
-
# pick the first one found, or nil if there aren't any available.
|
85
|
+
# @param [String] path The path to check.
|
84
86
|
#
|
85
|
-
# @
|
86
|
-
|
87
|
-
|
88
|
-
def self.default_remote(git)
|
89
|
-
remotes = git.remotes
|
90
|
-
found_remote = remotes.find { |remote| remote.name == 'origin' }
|
91
|
-
found_remote = remotes[0] if found_remote.nil?
|
92
|
-
found_remote
|
87
|
+
# @return [Array<Plugin>] The plugins that match the path.
|
88
|
+
def self.get_plugins_for_path(path)
|
89
|
+
@plugins.filter { |plugin_class| plugin_class.matches_path?(path) }
|
93
90
|
end
|
94
91
|
|
95
|
-
#
|
96
|
-
# use case (and it's easier than referencing the +Git::Remote+ docs to ensure
|
97
|
-
# correct usage in each plugin).
|
92
|
+
# Gets a single plugin that matches the given path.
|
98
93
|
#
|
99
|
-
# @param [String] path The path to
|
94
|
+
# @param [String] path The path to check.
|
100
95
|
#
|
101
|
-
# @return [
|
102
|
-
def self.
|
103
|
-
|
104
|
-
end
|
105
|
-
|
106
|
-
# @abstract Subclass to create a plugin.
|
107
|
-
class Plugin
|
108
|
-
# Plugin intializer arguments should come from the +from_git+ or +from_args+
|
109
|
-
# class methods.
|
110
|
-
def initialize(*) end
|
111
|
-
|
112
|
-
# Registers this plugin class for repofetch.
|
113
|
-
def self.register
|
114
|
-
Repofetch.register_plugin(self)
|
115
|
-
end
|
116
|
-
|
117
|
-
# Tries to replace another plugin. An example use case might be if this plugin
|
118
|
-
# extends another registered plugin.
|
119
|
-
#
|
120
|
-
# @param [Plugin] old The plugin to replace
|
121
|
-
def self.replace_or_register(old)
|
122
|
-
Repofetch.replace_or_register_plugin(old, self)
|
123
|
-
end
|
124
|
-
|
125
|
-
# @abstract Detects that this plugin should be used. Should be overridden by subclasses.
|
126
|
-
#
|
127
|
-
# An example implementation is checking if +Repofetch.default_remote_url+ matches
|
128
|
-
# a regular expression.
|
129
|
-
#
|
130
|
-
# @param [Git::Base] _git The Git repository object
|
131
|
-
def self.matches_repo?(_git)
|
132
|
-
raise NoMethodError, 'matches_repo? must be overridden by the plugin subclass'
|
133
|
-
end
|
96
|
+
# @return [Plugin, nil] The plugin that matches the path.
|
97
|
+
def self.get_plugin_for_path(path)
|
98
|
+
plugins = get_plugins_for_path(path)
|
134
99
|
|
135
|
-
|
136
|
-
#
|
137
|
-
# @param [Git::Base] _git The Git repository object to use when calling +Plugin.new+.
|
138
|
-
# @param [Array] _args The arguments to process.
|
139
|
-
#
|
140
|
-
# @return [Plugin]
|
141
|
-
def self.from_git(_git, _args)
|
142
|
-
raise NoMethodError, 'from_git must be overridden by the plugin subclass'
|
143
|
-
end
|
144
|
-
|
145
|
-
# @abstract This will receive an array of strings (e.g. +ARGV+) and call +Plugin.new+.
|
146
|
-
#
|
147
|
-
# @param [Array] _args The arguments to process.
|
148
|
-
#
|
149
|
-
# @return [Plugin]
|
150
|
-
def self.from_args(_args)
|
151
|
-
raise NoMethodError, 'from_args must be overridden by the plugin subclass'
|
152
|
-
end
|
153
|
-
|
154
|
-
# Gets the plugin's theme. Override to use a theme besides the default.
|
155
|
-
def theme
|
156
|
-
Repofetch::DEFAULT_THEME
|
157
|
-
end
|
158
|
-
|
159
|
-
# @abstract The ASCII to be printed alongside the stats.
|
160
|
-
#
|
161
|
-
# This should be overridden by the plugin subclass.
|
162
|
-
# Should be within the bounds 40x20 (width x height).
|
163
|
-
def ascii
|
164
|
-
raise NoMethodError, 'ascii must be overridden by the plugin subclass'
|
165
|
-
end
|
166
|
-
|
167
|
-
# @abstract The header to show for the plugin.
|
168
|
-
#
|
169
|
-
# This should be overridden by the plugin subclass.
|
170
|
-
# For example, "foo/bar @ GitHub".
|
171
|
-
def header
|
172
|
-
raise NoMethodError, 'header must be overridden by the plugin subclass'
|
173
|
-
end
|
100
|
+
raise TooManyPluginsError if plugins.length > 1
|
174
101
|
|
175
|
-
|
176
|
-
def separator
|
177
|
-
'-' * Repofetch::Util.clean_s(header).length
|
178
|
-
end
|
179
|
-
|
180
|
-
def to_s
|
181
|
-
zipped_lines.map do |ascii_line, stat_line|
|
182
|
-
cleaned_ascii = Repofetch::Util.clean_s(ascii_line)
|
183
|
-
styled_ascii = (ascii_line % theme.to_h) + theme.style(:reset)
|
184
|
-
aligned_stat_line = "#{' ' * (MAX_ASCII_WIDTH + 5)}#{stat_line}"
|
185
|
-
"#{styled_ascii}#{aligned_stat_line.slice(cleaned_ascii.length..)}\n"
|
186
|
-
end.join
|
187
|
-
end
|
188
|
-
|
189
|
-
# @abstract An array of stats that will be displayed to the right of the ASCII art.
|
190
|
-
#
|
191
|
-
# @return [Array<Stat>]
|
192
|
-
def stats
|
193
|
-
[]
|
194
|
-
end
|
195
|
-
|
196
|
-
# Adds +theme+ to the stats, mutating those stats.
|
197
|
-
#
|
198
|
-
# @return [Array<Stat>]
|
199
|
-
def theme_stats!
|
200
|
-
stats.each do |stat|
|
201
|
-
stat.theme = theme if stat.respond_to?(:theme=)
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
# Makes an array of stat lines, including the header and separator.
|
206
|
-
#
|
207
|
-
# Mutates +stats+ to add the +theme+.
|
208
|
-
def stat_lines!
|
209
|
-
[header, separator, *theme_stats!.map(&:to_s)]
|
210
|
-
end
|
211
|
-
|
212
|
-
# Zips ASCII lines with stat lines.
|
213
|
-
#
|
214
|
-
# If there are more of one than the other, than the zip will be padded with empty strings.
|
215
|
-
def zipped_lines
|
216
|
-
ascii_lines = ascii.lines.map(&:chomp)
|
217
|
-
stat_lines = stat_lines!
|
218
|
-
if ascii_lines.length > stat_lines.length
|
219
|
-
ascii_lines.zip(stat_lines)
|
220
|
-
else
|
221
|
-
stat_lines.zip(ascii_lines).map(&:reverse)
|
222
|
-
end.map { |ascii, stat| [ascii.to_s, stat.to_s] }
|
223
|
-
end
|
102
|
+
plugins[0]
|
224
103
|
end
|
225
104
|
|
226
|
-
#
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
def initialize(label, value, emoji: nil)
|
237
|
-
@label = label
|
238
|
-
@value = value
|
239
|
-
@emoji = emoji
|
240
|
-
@label_styles = []
|
241
|
-
end
|
242
|
-
|
243
|
-
def to_s
|
244
|
-
emoji = @emoji
|
245
|
-
emoji = nil unless Repofetch.config.nil? || Repofetch.config.emojis?
|
246
|
-
"#{emoji}#{format_label}: #{format_value}"
|
247
|
-
end
|
248
|
-
|
249
|
-
# Adds a style for the label
|
250
|
-
#
|
251
|
-
# @param [Symbol] style The theme's style to add
|
252
|
-
def style_label!(style)
|
253
|
-
@label_styles << style
|
254
|
-
end
|
255
|
-
|
256
|
-
# Formats the label, including styles.
|
257
|
-
#
|
258
|
-
# @return [String]
|
259
|
-
def format_label
|
260
|
-
return @label if @theme.nil?
|
261
|
-
|
262
|
-
@label_styles.inject(@label) { |label, style| @theme.format(style, label) }
|
105
|
+
# Gets the plugins that matches the given repository.
|
106
|
+
#
|
107
|
+
# @param [String] path The repository to check.
|
108
|
+
#
|
109
|
+
# @return [Array<Plugin>] The plugins that match the repository.
|
110
|
+
def self.get_plugins_for_repo(path)
|
111
|
+
begin
|
112
|
+
git = Git.open(path)
|
113
|
+
rescue ArgumentError
|
114
|
+
return []
|
263
115
|
end
|
264
116
|
|
265
|
-
|
266
|
-
#
|
267
|
-
# This simply converts the value to a string, but can be overridden but
|
268
|
-
# subclasses to affect +to_s+.
|
269
|
-
def format_value
|
270
|
-
@value.to_s
|
271
|
-
end
|
117
|
+
@plugins.filter { |plugin_class| plugin_class.matches_repo?(git) }
|
272
118
|
end
|
273
119
|
|
274
|
-
#
|
275
|
-
|
276
|
-
|
120
|
+
# Gets a single plugin that matches the given repository.
|
121
|
+
#
|
122
|
+
# @param [String] path The repository to check.
|
123
|
+
#
|
124
|
+
# @return [Plugin, nil] The plugin that matches the repository.
|
125
|
+
def self.get_plugin_for_repo(path)
|
126
|
+
plugins = get_plugins_for_repo(path)
|
277
127
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
"#{distance_of_time_in_words(@value, now)} ago"
|
282
|
-
end
|
128
|
+
raise TooManyPluginsError if plugins.length > 1
|
129
|
+
|
130
|
+
plugins[0]
|
283
131
|
end
|
284
132
|
|
285
133
|
def self.clear_plugins
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: repofetch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Spenser Black
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -298,6 +298,7 @@ files:
|
|
298
298
|
- lib/repofetch/DEFAULT_CONFIG
|
299
299
|
- lib/repofetch/bitbucketcloud.rb
|
300
300
|
- lib/repofetch/bitbucketcloud/ASCII
|
301
|
+
- lib/repofetch/bitbucketcloud/stats.rb
|
301
302
|
- lib/repofetch/cli.rb
|
302
303
|
- lib/repofetch/config.rb
|
303
304
|
- lib/repofetch/env.rb
|
@@ -306,7 +307,10 @@ files:
|
|
306
307
|
- lib/repofetch/github/ASCII
|
307
308
|
- lib/repofetch/gitlab.rb
|
308
309
|
- lib/repofetch/gitlab/ASCII
|
310
|
+
- lib/repofetch/plugin.rb
|
311
|
+
- lib/repofetch/stat.rb
|
309
312
|
- lib/repofetch/theme.rb
|
313
|
+
- lib/repofetch/timespan_stat.rb
|
310
314
|
- lib/repofetch/util.rb
|
311
315
|
homepage: https://github.com/spenserblack/repofetch
|
312
316
|
licenses:
|