fue 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +8 -0
- data/CONTRIBUTING.md +3 -3
- data/LICENSE.md +1 -1
- data/README.md +24 -8
- data/bin/fue +30 -6
- data/lib/fue.rb +3 -0
- data/lib/fue/auth.rb +86 -75
- data/lib/fue/finder.rb +92 -23
- data/lib/fue/security.rb +6 -10
- data/lib/fue/shell.rb +14 -0
- data/lib/fue/version.rb +3 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: db5d73f68b7c73685841e8e2cf7a677ebaea651d4d900fba9ed4986ab16a1ca1
|
4
|
+
data.tar.gz: 1493b9161cc0a613349cb02901231bbf58dbb2bfb4df67e0773eba3ff0f845dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06cc2b6d34d6d3b0b04526034d87a8b2d588f1018d346da6fbd895b8c7816845194a62096eb1f158994b076b43ca68be08f40e5acde9be9a5e818f3e5422d7a0
|
7
|
+
data.tar.gz: ce802803afc1595a9eff8ec0bcdbf1ec4a017aa97dc93269c5f5382b870ef6a2eca86576f4cb4a92dc6360d7255292b2dcf933942d1a32af4eb2a5684a4e35ec
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
### 0.3.0 (2020/05/22)
|
2
|
+
|
3
|
+
* [#25](https://github.com/dblock/fue/pull/25): Added `contributors`, find repo contributors' e-mails - [@dblock](https://github.com/dblock).
|
4
|
+
* [#12](https://github.com/dblock/fue/issues/12): Added explicit ruby call to run fue - [@SYNstack](https://github.com/SYNstack).
|
5
|
+
* [#13](https://github.com/dblock/fue/issues/13): Changed shell tests to be OS-neutral - [@SYNstack](https://github.com/SYNstack).
|
6
|
+
* [#16](https://github.com/dblock/fue/issues/16): Setup Windows CI - [@SYNstack](https://github.com/synstack).
|
7
|
+
* [#17](https://github.com/dblock/fue/issues/19): Fix open-ended dependencies in gemspec - [@SYNstack](https://github.com/synstack).
|
8
|
+
|
1
9
|
### 0.2.1 (2018/8/23)
|
2
10
|
|
3
11
|
* [#2](https://github.com/dblock/fue/issues/2): Prompt to authenticate with Github - [@dblock](https://github.com/dblock).
|
data/CONTRIBUTING.md
CHANGED
@@ -4,11 +4,11 @@ This project is work of [many contributors](https://github.com/dblock/fue/graphs
|
|
4
4
|
|
5
5
|
You're encouraged to submit [pull requests](https://github.com/dblock/fue/pulls), [propose features and discuss issues](https://github.com/dblock/fue/issues).
|
6
6
|
|
7
|
-
In the examples below, substitute your
|
7
|
+
In the examples below, substitute your GitHub username for `contributor` in URLs.
|
8
8
|
|
9
9
|
### Fork the Project
|
10
10
|
|
11
|
-
Fork the [project on
|
11
|
+
Fork the [project on GitHub](https://github.com/dblock/fue) and check out your copy.
|
12
12
|
|
13
13
|
```
|
14
14
|
git clone https://github.com/contributor/fue.git
|
@@ -47,7 +47,7 @@ We definitely appreciate pull requests that highlight or reproduce a problem, ev
|
|
47
47
|
|
48
48
|
Implement your feature or bug fix.
|
49
49
|
|
50
|
-
Ruby style is enforced with [Rubocop](https://github.com/bbatsov/rubocop). Run `bundle exec rubocop` and fix any style issues highlighted, auto-correct issues when possible with `bundle exec rubocop -a`. To silence generally
|
50
|
+
Ruby style is enforced with [Rubocop](https://github.com/bbatsov/rubocop). Run `bundle exec rubocop` and fix any style issues highlighted, auto-correct issues when possible with `bundle exec rubocop -a`. To silence generally ignored issues, including line lengths or code complexity metrics, run `bundle exec rubocop --auto-gen-config`.
|
51
51
|
|
52
52
|
Make sure that `bundle exec rake` completes without errors.
|
53
53
|
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -3,8 +3,9 @@ Fue
|
|
3
3
|
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/fue.svg)](https://badge.fury.io/rb/fue)
|
5
5
|
[![Build Status](https://travis-ci.org/dblock/fue.svg)](https://travis-ci.org/dblock/fue)
|
6
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/github/dblock/fue?branch=master&svg=true)](https://ci.appveyor.com/project/dblock/fue)
|
6
7
|
|
7
|
-
Find
|
8
|
+
Find e-mail addresses of a Github users from their commit logs.
|
8
9
|
|
9
10
|
Fue is short for "Finding Unicorn Engineers".
|
10
11
|
|
@@ -16,20 +17,35 @@ Fue is short for "Finding Unicorn Engineers".
|
|
16
17
|
gem install fue
|
17
18
|
```
|
18
19
|
|
20
|
+
### Commands
|
21
|
+
|
19
22
|
#### Find Someone's Email
|
20
23
|
|
21
|
-
The `find` command looks through user's initial
|
24
|
+
The `find` command looks through user's initial repository commits.
|
22
25
|
|
23
26
|
```
|
24
|
-
$ fue find defunkt
|
27
|
+
$ fue --verbose find defunkt
|
25
28
|
|
26
29
|
Chris Wanstrath <chris@ozmm.org>
|
27
30
|
Chris Wanstrath <chris@github.com>
|
28
31
|
```
|
29
32
|
|
33
|
+
#### Find All Repo Contributors' Emails
|
34
|
+
|
35
|
+
The `contributors` command looks through a git log of contributors, then fetches their e-mails.
|
36
|
+
|
37
|
+
```
|
38
|
+
$ fue --verbose contributors defunkt/colored
|
39
|
+
|
40
|
+
defunkt: Chris Wanstrath <chris@ozmm.org>
|
41
|
+
kch: Caio Chassot <kch@users.noreply.github.com>
|
42
|
+
```
|
43
|
+
|
44
|
+
### Options
|
45
|
+
|
30
46
|
#### Specify More Depth
|
31
47
|
|
32
|
-
By default the code looks at 1 commit from the last 10
|
48
|
+
By default the code looks at 1 commit from the last 10 repositories. You can look at more repositories (breadth) and more commits (depth). The maximum value for depth is 100, enforced by Github. Fue will iterate over a number of repositories larger than 100.
|
33
49
|
|
34
50
|
```
|
35
51
|
$ fue find --breadth=100 --depth=5 defunkt
|
@@ -39,7 +55,7 @@ Chris Wanstrath <chris@github.com>
|
|
39
55
|
defunkt <chris@ozmm.org>
|
40
56
|
```
|
41
57
|
|
42
|
-
|
58
|
+
### Get Help
|
43
59
|
|
44
60
|
```
|
45
61
|
fue help
|
@@ -47,7 +63,7 @@ fue help
|
|
47
63
|
|
48
64
|
Displays additional options.
|
49
65
|
|
50
|
-
|
66
|
+
### Access Tokens
|
51
67
|
|
52
68
|
Fue will prompt you for Github credentials and 2FA, if enabled.
|
53
69
|
|
@@ -64,10 +80,10 @@ See [Creating a Personal Access Token for the Command Line](https://help.github.
|
|
64
80
|
|
65
81
|
## Contributing
|
66
82
|
|
67
|
-
There
|
83
|
+
There are [a few feature requests and known issues](https://github.com/dblock/fue/issues). Please contribute! See [CONTRIBUTING](CONTRIBUTING.md).
|
68
84
|
|
69
85
|
## Copyright and License
|
70
86
|
|
71
|
-
Copyright (c) 2018, Daniel Doubrovkine, [Artsy](http://artsy.github.io), with help from [Orta](https://github.com/orta).
|
87
|
+
Copyright (c) 2018-2020, Daniel Doubrovkine, [Artsy](http://artsy.github.io), with help from [Orta](https://github.com/orta).
|
72
88
|
|
73
89
|
This project is licensed under the [MIT License](LICENSE.md).
|
data/bin/fue
CHANGED
@@ -1,29 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require 'gli'
|
3
5
|
require 'fue'
|
4
6
|
|
5
7
|
class App
|
6
8
|
extend GLI::App
|
7
9
|
|
8
|
-
program_desc "Find a
|
10
|
+
program_desc "Find a GitHub user's e-mail address."
|
9
11
|
version Fue::VERSION
|
10
12
|
|
11
13
|
switch %i[v verbose], desc: 'Produce verbose output.', default_value: false
|
12
|
-
flag %i[t token], desc: '
|
13
|
-
flag %i[u username], desc: '
|
14
|
+
flag %i[t token], desc: 'GitHub access token.', default_value: ENV['GITHUB_ACCESS_TOKEN']
|
15
|
+
flag %i[u username], desc: 'GitHub username.', default_value: Fue::Auth.instance.username
|
14
16
|
|
15
17
|
arguments :strict
|
16
18
|
subcommand_option_handling :normal
|
17
19
|
|
18
20
|
pre do |global_options, _command, options, _args|
|
19
21
|
options = global_options.dup
|
20
|
-
token = options.delete(:token) || Fue::Auth.token
|
22
|
+
token = options.delete(:token) || Fue::Auth.instance.token
|
21
23
|
$fue = Fue::Finder.new(token, options)
|
22
24
|
end
|
23
25
|
|
24
26
|
default_command :help
|
25
27
|
|
26
|
-
desc "Find a
|
28
|
+
desc "Find a GitHub user's e-mail address."
|
27
29
|
arg 'username'
|
28
30
|
command :find do |c|
|
29
31
|
c.flag %i[d depth], desc: 'Maximum search depth in each repository.', default_value: 1
|
@@ -37,7 +39,29 @@ class App
|
|
37
39
|
"in the first #{options[:depth].to_i > 1 ? "#{options[:depth]} commits" : 'commit'} " \
|
38
40
|
"of #{options[:breadth]} most recent repositor#{options[:breadth] == 1 ? 'y' : 'ies'} ..."
|
39
41
|
end
|
40
|
-
puts $fue.emails(options.merge(username: username))
|
42
|
+
puts $fue.emails(options.merge(username: username, verbose: global_options[:verbose]))
|
43
|
+
exit_now! nil, 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Find a GitHub repo contributors' e-mail addresses."
|
48
|
+
arg 'repo'
|
49
|
+
command :contributors do |c|
|
50
|
+
c.flag %i[d depth], desc: 'Maximum search depth in each repository for a given user.', default_value: 1
|
51
|
+
c.flag %i[b breadth], desc: 'Maximum number of repositories to search.', default_value: 10
|
52
|
+
c.action do |global_options, options, args|
|
53
|
+
repo = args.first
|
54
|
+
options[:depth] = options[:depth].to_i
|
55
|
+
options[:breadth] = options[:breadth].to_i
|
56
|
+
if global_options[:verbose]
|
57
|
+
puts "Searching for contributors' e-mail addresses in '#{repo}' " \
|
58
|
+
"in the first #{options[:depth].to_i > 1 ? "#{options[:depth]} commits" : 'commit'} " \
|
59
|
+
"of #{options[:breadth]} most recent repositor#{options[:breadth] == 1 ? 'y' : 'ies'} ..."
|
60
|
+
end
|
61
|
+
contributor_emails = $fue.contributors(options.merge(repo: repo, verbose: global_options[:verbose]))
|
62
|
+
contributor_emails.each_pair do |username, emails|
|
63
|
+
puts "#{username}: #{emails.join(', ')}"
|
64
|
+
end
|
41
65
|
exit_now! nil, 0
|
42
66
|
end
|
43
67
|
end
|
data/lib/fue.rb
CHANGED
data/lib/fue/auth.rb
CHANGED
@@ -1,97 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fue
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
stored_token
|
4
|
+
class Auth
|
5
|
+
def self.instance
|
6
|
+
@instance ||= new
|
7
|
+
end
|
8
|
+
|
9
|
+
def token
|
10
|
+
stored_options = { username: username, server: 'github.com', label: 'fue' }
|
11
|
+
stored_token = Fue::Security.get(stored_options)
|
12
|
+
unless stored_token
|
13
|
+
stored_token = github_token
|
14
|
+
Fue::Security.store!(stored_options.merge(password: stored_token))
|
15
|
+
puts 'Token saved to keychain.'
|
13
16
|
end
|
17
|
+
stored_token
|
18
|
+
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
20
|
+
def username
|
21
|
+
@username ||= begin
|
22
|
+
username = get_git_username&.chomp
|
23
|
+
username = get_username if username.nil? || username.empty?
|
24
|
+
username
|
21
25
|
end
|
26
|
+
end
|
22
27
|
|
23
|
-
|
28
|
+
private
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
github_token(get_code)
|
31
|
-
else
|
32
|
-
raise e
|
33
|
-
end
|
34
|
-
rescue Github::Error::UnprocessableEntity => e
|
35
|
-
raise e, 'A fue token already exists! Please revoke all previously-generated fue personal access tokens at https://github.com/settings/tokens.'
|
36
|
-
end
|
30
|
+
def get_git_username
|
31
|
+
Fue::Shell.system!('git config github.user')
|
32
|
+
rescue RuntimeError
|
33
|
+
nil
|
34
|
+
end
|
37
35
|
|
38
|
-
|
39
|
-
|
36
|
+
def github_token(code = nil)
|
37
|
+
github(code).auth.create(scopes: ['public_repo'], note: note).token
|
38
|
+
rescue Github::Error::Unauthorized => e
|
39
|
+
case e.response_headers['X-GitHub-OTP']
|
40
|
+
when /required/
|
41
|
+
github_token(get_code)
|
42
|
+
else
|
43
|
+
raise e
|
40
44
|
end
|
45
|
+
rescue Github::Error::UnprocessableEntity => e
|
46
|
+
raise e, 'A fue token already exists! Please revoke all previously-generated fue personal access tokens at https://github.com/settings/tokens.'
|
47
|
+
end
|
41
48
|
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
def password
|
50
|
+
@password ||= get_password
|
51
|
+
end
|
52
|
+
|
53
|
+
def note
|
54
|
+
"Fui (https://github.com/dblock/fue) on #{Socket.gethostname}"
|
55
|
+
end
|
45
56
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
}
|
57
|
+
def github(code = nil)
|
58
|
+
Github.new do |config|
|
59
|
+
config.basic_auth = [username, password].join(':')
|
60
|
+
if code
|
61
|
+
config.connection_options = {
|
62
|
+
headers: {
|
63
|
+
'X-GitHub-OTP' => code
|
54
64
|
}
|
55
|
-
|
65
|
+
}
|
56
66
|
end
|
57
67
|
end
|
68
|
+
end
|
58
69
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
70
|
+
def get_username
|
71
|
+
print 'Enter GitHub username: '
|
72
|
+
username = $stdin.gets
|
73
|
+
username&.chomp
|
74
|
+
rescue Interrupt => e
|
75
|
+
raise e, 'ctrl + c'
|
76
|
+
end
|
65
77
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
78
|
+
def get_password
|
79
|
+
print "Enter #{username}'s GitHub password (never stored): "
|
80
|
+
get_secure
|
81
|
+
end
|
70
82
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
83
|
+
def get_code
|
84
|
+
print 'Enter GitHub 2FA code: '
|
85
|
+
get_secure
|
86
|
+
end
|
75
87
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
88
|
+
def get_secure
|
89
|
+
current_tty = `stty -g`
|
90
|
+
system 'stty raw -echo -icanon isig' if $CHILD_STATUS.success?
|
91
|
+
input = ''
|
92
|
+
while (char = $stdin.getbyte) && !((char == 13) || (char == 10))
|
93
|
+
if (char == 127) || (char == 8)
|
94
|
+
input[-1, 1] = '' unless input.empty?
|
95
|
+
else
|
96
|
+
$stdout.write '*'
|
97
|
+
input << char.chr
|
87
98
|
end
|
88
|
-
print "\r\n"
|
89
|
-
input
|
90
|
-
rescue Interrupt => e
|
91
|
-
raise e, 'ctrl + c'
|
92
|
-
ensure
|
93
|
-
system "stty #{current_tty}" unless current_tty.empty?
|
94
99
|
end
|
100
|
+
print "\r\n"
|
101
|
+
input
|
102
|
+
rescue Interrupt => e
|
103
|
+
raise e, 'ctrl + c'
|
104
|
+
ensure
|
105
|
+
system "stty #{current_tty}" unless current_tty.empty?
|
95
106
|
end
|
96
107
|
end
|
97
108
|
end
|
data/lib/fue/finder.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fue
|
2
4
|
class Finder
|
3
5
|
attr_reader :token
|
@@ -19,21 +21,18 @@ module Fue
|
|
19
21
|
|
20
22
|
def emails(options = {})
|
21
23
|
query = <<-GRAPHQL
|
22
|
-
query($login: String!, $author_id: ID!, $depth: Int!, $breadth: Int!, $
|
24
|
+
query($login: String!, $author_id: ID!, $depth: Int!, $breadth: Int!, $cursor: String) {
|
23
25
|
user(login: $login) {
|
24
|
-
repositories(last: $breadth, after: $
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
email
|
35
|
-
name
|
36
|
-
}
|
26
|
+
repositories(last: $breadth, after: $cursor, isFork:false, privacy: PUBLIC) {
|
27
|
+
nodes {
|
28
|
+
defaultBranchRef {
|
29
|
+
target {
|
30
|
+
... on Commit {
|
31
|
+
history(first: $depth, author: { id: $author_id }) {
|
32
|
+
nodes {
|
33
|
+
author {
|
34
|
+
email
|
35
|
+
name
|
37
36
|
}
|
38
37
|
}
|
39
38
|
}
|
@@ -41,42 +40,112 @@ module Fue
|
|
41
40
|
}
|
42
41
|
}
|
43
42
|
}
|
43
|
+
pageInfo {
|
44
|
+
startCursor
|
45
|
+
}
|
44
46
|
}
|
45
47
|
}
|
46
48
|
}
|
47
49
|
GRAPHQL
|
48
50
|
|
51
|
+
# max number of repositories to search
|
49
52
|
max_breadth = options[:breadth] || 10
|
50
53
|
|
51
54
|
query_options = {
|
52
55
|
login: options[:username],
|
53
56
|
author_id: author_id(options[:username]),
|
57
|
+
# max number of commits to look into
|
54
58
|
depth: options[:depth] || 1
|
55
59
|
}
|
56
60
|
|
61
|
+
STDOUT.write "Searching for emails for #{options[:username]} ." if options[:verbose]
|
62
|
+
|
57
63
|
emails = Set.new
|
58
64
|
|
59
65
|
loop do
|
60
66
|
query_options[:breadth] = [max_breadth, 100].min
|
61
67
|
response = graphql_client.query(query, query_options)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
next unless branch_ref
|
68
|
-
branch_ref.target.history.nodes.each do |node|
|
69
|
-
emails << "#{node.author.name} <#{node.author.email}>"
|
70
|
-
end
|
68
|
+
repositories = response&.data&.user&.repositories
|
69
|
+
repositories&.nodes&.each do |history|
|
70
|
+
master_history = history.default_branch_ref&.target&.history
|
71
|
+
master_history&.nodes&.each do |node|
|
72
|
+
emails << "#{node.author.name} <#{node.author.email}>"
|
71
73
|
end
|
72
74
|
end
|
75
|
+
query_options[:cursor] = repositories&.page_info&.start_cursor
|
76
|
+
break unless query_options[:cursor]
|
77
|
+
|
73
78
|
max_breadth -= 100
|
74
79
|
break if max_breadth <= 0
|
80
|
+
|
81
|
+
STDOUT.write '.' if options[:verbose]
|
75
82
|
end
|
76
83
|
|
84
|
+
puts " found #{emails.size} email address#{emails.size == 1 ? '' : 'es'}." if options[:verbose]
|
85
|
+
|
77
86
|
emails.to_a
|
78
87
|
end
|
79
88
|
|
89
|
+
def contributors(options = {})
|
90
|
+
query = <<-GRAPHQL
|
91
|
+
query($owner: String!, $name: String!, $cursor: String) {
|
92
|
+
repository(owner: $owner, name: $name) {
|
93
|
+
defaultBranchRef {
|
94
|
+
target {
|
95
|
+
... on Commit {
|
96
|
+
history(first: 100, after: $cursor) {
|
97
|
+
nodes {
|
98
|
+
author {
|
99
|
+
user {
|
100
|
+
login
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
pageInfo {
|
105
|
+
endCursor
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
GRAPHQL
|
114
|
+
|
115
|
+
repo_owner, repo_name = options[:repo].split('/', 2)
|
116
|
+
|
117
|
+
query_options = {
|
118
|
+
owner: repo_owner,
|
119
|
+
name: repo_name
|
120
|
+
}
|
121
|
+
|
122
|
+
logins = Set.new
|
123
|
+
|
124
|
+
STDOUT.write 'Fetching contributors .' if options[:verbose]
|
125
|
+
|
126
|
+
loop do
|
127
|
+
response = graphql_client.query(query, query_options)
|
128
|
+
history = response&.data&.repository&.default_branch_ref&.target&.history
|
129
|
+
history&.nodes&.each do |node|
|
130
|
+
login = node.author.user&.login
|
131
|
+
logins << login if login
|
132
|
+
end
|
133
|
+
query_options[:cursor] = history&.page_info.end_cursor
|
134
|
+
STDOUT.write '.' if options[:verbose]
|
135
|
+
break unless query_options[:cursor]
|
136
|
+
end
|
137
|
+
|
138
|
+
puts " found #{logins.size} contributor#{logins.size == 1 ? '' : 's'}." if options[:verbose]
|
139
|
+
|
140
|
+
Hash[logins.map do |login|
|
141
|
+
begin
|
142
|
+
[login, emails(options.merge(username: login))]
|
143
|
+
rescue StandardError => e
|
144
|
+
warn e.to_s
|
145
|
+
end
|
146
|
+
end.compact]
|
147
|
+
end
|
148
|
+
|
80
149
|
private
|
81
150
|
|
82
151
|
def graphql_client
|
data/lib/fue/security.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fue
|
2
4
|
module Security
|
3
5
|
class << self
|
4
6
|
def store!(options)
|
5
|
-
system!(security('add', options))
|
7
|
+
Fue::Shell.system!(security('add', options))
|
6
8
|
end
|
7
9
|
|
8
10
|
def get(options)
|
9
|
-
system!(security('find', options))
|
11
|
+
Fue::Shell.system!(security('find', options))
|
10
12
|
rescue RuntimeError
|
11
13
|
nil
|
12
14
|
end
|
@@ -31,16 +33,10 @@ module Fue
|
|
31
33
|
def security_path
|
32
34
|
@security_path ||= begin
|
33
35
|
`which security`.chomp
|
34
|
-
|
35
|
-
|
36
|
+
rescue StandardError
|
37
|
+
'security'
|
36
38
|
end
|
37
39
|
end
|
38
|
-
|
39
|
-
def system!(*cmd)
|
40
|
-
stdout, _, status = Open3.capture3(*cmd)
|
41
|
-
raise "failed with exit code #{status}" unless status.success?
|
42
|
-
stdout.slice!(0..-(1 + $INPUT_RECORD_SEPARATOR.size))
|
43
|
-
end
|
44
40
|
end
|
45
41
|
end
|
46
42
|
end
|
data/lib/fue/shell.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fue
|
4
|
+
module Shell
|
5
|
+
class << self
|
6
|
+
def system!(*cmd)
|
7
|
+
stdout, stderr, status = Open3.capture3(*cmd)
|
8
|
+
raise ["exit code #{status}", stderr].compact.join("\n") unless status.success?
|
9
|
+
|
10
|
+
stdout.slice!(0..-(1 + $INPUT_RECORD_SEPARATOR.size))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/fue/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Doubrovkine
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: github_api
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.18.2
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.18.2
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: gli
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.17'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.17'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: graphlient
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- lib/fue/auth.rb
|
69
69
|
- lib/fue/finder.rb
|
70
70
|
- lib/fue/security.rb
|
71
|
+
- lib/fue/shell.rb
|
71
72
|
- lib/fue/version.rb
|
72
73
|
homepage: http://github.com/dblock/fue
|
73
74
|
licenses:
|
@@ -88,9 +89,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
89
|
- !ruby/object:Gem::Version
|
89
90
|
version: 1.3.6
|
90
91
|
requirements: []
|
91
|
-
|
92
|
-
rubygems_version: 2.6.12
|
92
|
+
rubygems_version: 3.1.3
|
93
93
|
signing_key:
|
94
94
|
specification_version: 4
|
95
|
-
summary: Find an e-mail address of a
|
95
|
+
summary: Find an e-mail address of a GitHub user.
|
96
96
|
test_files: []
|