cob 0.0.15
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 +7 -0
- data/bin/cob +6 -0
- data/lib/cob.rb +62 -0
- data/lib/credentials.rb +83 -0
- data/lib/git.rb +27 -0
- data/lib/local_cob.rb +15 -0
- data/lib/navigator.rb +64 -0
- data/lib/paginator.rb +74 -0
- data/lib/remote_cob.rb +61 -0
- data/lib/string_refinements.rb +9 -0
- data/lib/version.rb +5 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 698e8f72857d8052c532614332d07903b44e4b4da52a85debfcaf46745a3109d
|
4
|
+
data.tar.gz: c88940d9ac79e2bbdce31572d53ab1bb1b465ab680bd835fd69d34e15ac49161
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3d084dc142c8613fe784d70507705390538a3472271e747212f26699779e8b11656298e03227931be9ad55b0cdf00c52535f7eaf25ff479d8ac1f7a0c922c54b
|
7
|
+
data.tar.gz: 877eb16d44a54f1221d221d6d7e7f3f69347d125be7af500002c0e6093be8bba64212a8a5453bcbd6b2a59f408b7cd9fe2f7f8bfe92bafe5b902ab0b2a1e6cc7
|
data/bin/cob
ADDED
data/lib/cob.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# !/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# _________ ________ __________
|
6
|
+
# \_ ___ \ \_____ \\______ \
|
7
|
+
# / \ \/ / | \| | _/
|
8
|
+
# \ \____/ | \ | \
|
9
|
+
# \______ /\_______ /______ /
|
10
|
+
# \/ \/ \/
|
11
|
+
#
|
12
|
+
# The ULTIMATE "cob" tool with a total of 3 distinct usages.
|
13
|
+
# examples:
|
14
|
+
# $ cob # queries github and gives you a list of issues to pick from
|
15
|
+
# $ cob 2837 # queries github and checks out the matching issue using "cob" style formating
|
16
|
+
# $ cob "my string with #hashes and, other: . punctuations" # instant cob
|
17
|
+
# $ cob some sentence without special characters # instant cob
|
18
|
+
#
|
19
|
+
|
20
|
+
require_relative './git.rb'
|
21
|
+
require_relative './local_cob.rb'
|
22
|
+
require_relative './string_refinements.rb'
|
23
|
+
|
24
|
+
using StringRefinements
|
25
|
+
|
26
|
+
module Cob
|
27
|
+
class << self
|
28
|
+
def run(args)
|
29
|
+
@args = args
|
30
|
+
|
31
|
+
if (@args.length == 1 && !@args[0].all_digits?) || @args.length > 1
|
32
|
+
run_local
|
33
|
+
exit 0
|
34
|
+
end
|
35
|
+
|
36
|
+
run_remote
|
37
|
+
rescue Interrupt
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def run_local
|
44
|
+
LocalCOB.run
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_remote
|
48
|
+
require 'json'
|
49
|
+
require 'fileutils'
|
50
|
+
require 'tty-prompt'
|
51
|
+
require_relative './credentials.rb'
|
52
|
+
require_relative './paginator.rb'
|
53
|
+
require_relative './navigator.rb'
|
54
|
+
require_relative './remote_cob.rb'
|
55
|
+
|
56
|
+
RemoteCOB::Selection.run && exit(0) if @args.empty?
|
57
|
+
RemoteCOB::Fire.run && exit(0) if @args.length == 1
|
58
|
+
rescue Interrupt
|
59
|
+
exit 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/credentials.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# class to handle the credentials
|
5
|
+
#
|
6
|
+
# usage:
|
7
|
+
#
|
8
|
+
# c = Credentials.new
|
9
|
+
# c.username
|
10
|
+
# c.pa_token
|
11
|
+
#
|
12
|
+
class Credentials
|
13
|
+
def initialize
|
14
|
+
@config_file = ENV['GITHUB_CREDENTIALS_FILE'] ||
|
15
|
+
"#{ENV['HOME']}/.cob/github_credentials.json"
|
16
|
+
@config = parse_config
|
17
|
+
end
|
18
|
+
|
19
|
+
def username
|
20
|
+
# USERNAME
|
21
|
+
@config['username'] || prompt_username
|
22
|
+
end
|
23
|
+
|
24
|
+
def pa_token
|
25
|
+
# PA_TOKEN
|
26
|
+
@config['paToken'] || prompt_pa_token
|
27
|
+
end
|
28
|
+
|
29
|
+
def overwrite_config
|
30
|
+
File.write(@config_file, @config.to_json)
|
31
|
+
end
|
32
|
+
|
33
|
+
def prompt_username
|
34
|
+
prompt = TTY::Prompt.new(active_color: :cyan)
|
35
|
+
username = prompt.ask('What is your github username?') do |q|
|
36
|
+
q.required true
|
37
|
+
q.modify :lowercase
|
38
|
+
end
|
39
|
+
|
40
|
+
@config['username'] = username
|
41
|
+
overwrite_config
|
42
|
+
|
43
|
+
username
|
44
|
+
end
|
45
|
+
|
46
|
+
def prompt_pa_token
|
47
|
+
prompt = TTY::Prompt.new(active_color: :cyan)
|
48
|
+
token = prompt.ask('What is your github personal access token? You can get one from here: https://github.com/settings/tokens') do |q|
|
49
|
+
q.required true
|
50
|
+
end
|
51
|
+
|
52
|
+
@config['paToken'] = token
|
53
|
+
overwrite_config
|
54
|
+
|
55
|
+
token
|
56
|
+
end
|
57
|
+
|
58
|
+
def reset_config_file
|
59
|
+
File.write(@config_file, '{}')
|
60
|
+
end
|
61
|
+
|
62
|
+
def ensure_config_file_is_created
|
63
|
+
return if File.exist?(@config_file)
|
64
|
+
|
65
|
+
segments = @config_file.split('/')
|
66
|
+
paths = segments[0..-2]
|
67
|
+
file = segments[-1]
|
68
|
+
dir = paths.join('/')
|
69
|
+
FileUtils.mkdir_p(dir)
|
70
|
+
FileUtils.touch(dir + '/' + file)
|
71
|
+
|
72
|
+
reset_config_file
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def parse_config
|
78
|
+
JSON.parse(File.read(@config_file))
|
79
|
+
rescue StandardError => e
|
80
|
+
puts "Couldn't parse config file. Make sure the JSON is correct:\n#{@config_file}"
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
end
|
data/lib/git.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# this class interfaces with the local `git` command
|
4
|
+
module Git
|
5
|
+
class << self
|
6
|
+
def remote
|
7
|
+
`git config --list | grep remote.origin.url`&.strip&.split(':')&.last
|
8
|
+
end
|
9
|
+
|
10
|
+
def repository
|
11
|
+
remote.split('/').last.chomp('.git')
|
12
|
+
end
|
13
|
+
|
14
|
+
def repository_owner
|
15
|
+
remote.split('/').first
|
16
|
+
end
|
17
|
+
|
18
|
+
def checkout_branch(text)
|
19
|
+
branch = text.downcase.gsub(/[^a-zA-Z0-9#]+/, '_')
|
20
|
+
output = `git checkout -b #{branch} 2>&1`
|
21
|
+
|
22
|
+
if output.match?(/A branch named '#{branch}' already exists/)
|
23
|
+
`git checkout #{branch}`
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/local_cob.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# _ _ ___ ___ ___
|
4
|
+
# | | ___ __ __ _| | / __/ _ \| _ )
|
5
|
+
# | |__/ _ \/ _/ _` | | | (_| (_) | _ \
|
6
|
+
# |____\___/\__\__,_|_| \___\___/|___/
|
7
|
+
#
|
8
|
+
#
|
9
|
+
# This is the original COB
|
10
|
+
#
|
11
|
+
module LocalCOB
|
12
|
+
def self.run
|
13
|
+
Git.checkout_branch(ARGV.join(' '))
|
14
|
+
end
|
15
|
+
end
|
data/lib/navigator.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# this class prompts the user for selection and shows "next..." and "prev..."
|
4
|
+
# when the user can navigate to the next/prev pages.
|
5
|
+
class Navigator
|
6
|
+
def initialize(paginator)
|
7
|
+
@paginator = paginator
|
8
|
+
@active_index = 1
|
9
|
+
end
|
10
|
+
|
11
|
+
def prompt_for_issue_selection
|
12
|
+
prompt = TTY::Prompt.new(active_color: :cyan)
|
13
|
+
|
14
|
+
if @paginator.no_issues?
|
15
|
+
puts 'No issues found.'
|
16
|
+
exit 0
|
17
|
+
end
|
18
|
+
|
19
|
+
@selected_index = prompt.select('Select issue:') do |menu|
|
20
|
+
menu.default @active_index
|
21
|
+
|
22
|
+
items.each.with_index(1) do |item, i|
|
23
|
+
menu.choice item.to_s, i
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
handle_selection
|
28
|
+
end
|
29
|
+
|
30
|
+
def items
|
31
|
+
ii = @paginator.formatted_issues
|
32
|
+
ii = ['prev...'] + ii if show_prev?
|
33
|
+
ii += ['next...'] if show_next?
|
34
|
+
ii
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def show_prev?
|
40
|
+
@paginator.prev?
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_next?
|
44
|
+
@paginator.next?
|
45
|
+
end
|
46
|
+
|
47
|
+
def handle_selection
|
48
|
+
choice = items[@selected_index - 1]
|
49
|
+
|
50
|
+
return choice unless ['next...', 'prev...'].include? choice
|
51
|
+
|
52
|
+
if choice == 'next...'
|
53
|
+
@paginator.inc
|
54
|
+
@active_index = 1
|
55
|
+
end
|
56
|
+
|
57
|
+
if choice == 'prev...'
|
58
|
+
@paginator.dec
|
59
|
+
@active_index = [items.count, 1].max
|
60
|
+
end
|
61
|
+
|
62
|
+
prompt_for_issue_selection
|
63
|
+
end
|
64
|
+
end
|
data/lib/paginator.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# this class fetches and paginates the issues from github.com
|
4
|
+
class Paginator
|
5
|
+
attr_reader :page
|
6
|
+
|
7
|
+
def initialize(credentials)
|
8
|
+
@credentials = credentials
|
9
|
+
@page = 1
|
10
|
+
@cache = {}
|
11
|
+
@next = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def issues
|
15
|
+
@cache[@page] ||= begin
|
16
|
+
issues = fetch_issues
|
17
|
+
@next[@page] = issues.count.positive?
|
18
|
+
issues
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def no_issues?
|
23
|
+
@page == 1 && issues.empty?
|
24
|
+
end
|
25
|
+
|
26
|
+
def next?
|
27
|
+
issues && @next[@page]
|
28
|
+
end
|
29
|
+
|
30
|
+
def prev?
|
31
|
+
@page > 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def format_issue(issue)
|
35
|
+
"#{issue['number']} --- #{issue['title']}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def formatted_issues
|
39
|
+
issues.map { |i| format_issue(i) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def dec
|
43
|
+
@page = [@page - 1, 1].max
|
44
|
+
end
|
45
|
+
|
46
|
+
def inc
|
47
|
+
@page += 1
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def fetch_issues
|
53
|
+
_header, body = http_get_issues.split("\r\n\r\n")
|
54
|
+
data = JSON.parse(body)
|
55
|
+
|
56
|
+
# TODO: move elsewhere
|
57
|
+
if data.is_a?(Hash) && data['message'] == 'Bad credentials'
|
58
|
+
puts 'Your github credentials are wrong.'
|
59
|
+
|
60
|
+
@credentials.reset_config_file
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
|
64
|
+
data.select { |i| i['pull_request'].nil? } # ignore pull requests
|
65
|
+
end
|
66
|
+
|
67
|
+
def http_get_issues
|
68
|
+
uname = @credentials.username
|
69
|
+
token = @credentials.pa_token
|
70
|
+
`curl -sS -i https://api.github.com/repos/#{Git.repository_owner}/#{Git.repository}/issues?page=#{@page} \
|
71
|
+
-u "#{uname}:#{token}" \
|
72
|
+
-H "Content-Type: application/json"`
|
73
|
+
end
|
74
|
+
end
|
data/lib/remote_cob.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# ___ _ ___ ___ ___
|
5
|
+
# | _ \___ _ __ ___| |_ ___ / __/ _ \| _ )
|
6
|
+
# | / -_) ' \/ _ \ _/ -_) | (_| (_) | _ \
|
7
|
+
# |_|_\___|_|_|_\___/\__\___| \___\___/|___/
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# this module contain the remote commands
|
11
|
+
module RemoteCOB
|
12
|
+
def self.ensure_credentials_and_remote
|
13
|
+
Credentials.new.ensure_config_file_is_created
|
14
|
+
|
15
|
+
unless Git.remote
|
16
|
+
puts 'could not find remote git repository'
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
unless Git.repository_owner && Git.repository
|
21
|
+
puts "couldn't retreive repo and owner from remote: #{remote}"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# This is the code for querying github issues and displaying
|
27
|
+
# a select prompt to the user
|
28
|
+
module Selection
|
29
|
+
def self.run
|
30
|
+
RemoteCOB.ensure_credentials_and_remote
|
31
|
+
paginator = Paginator.new(Credentials.new)
|
32
|
+
issue = Navigator.new(paginator).prompt_for_issue_selection
|
33
|
+
Git.checkout_branch(issue)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# This is the code for automatically checking out the matching issue in github
|
38
|
+
module Fire
|
39
|
+
def self.run
|
40
|
+
RemoteCOB.ensure_credentials_and_remote
|
41
|
+
issue_number = ARGV[0].to_i
|
42
|
+
paginator = Paginator.new(Credentials.new)
|
43
|
+
|
44
|
+
while paginator.next?
|
45
|
+
issue = paginator.issues.detect { |i| i['number'] == issue_number }
|
46
|
+
|
47
|
+
if issue
|
48
|
+
Git.checkout_branch(paginator.format_issue(issue))
|
49
|
+
exit 0
|
50
|
+
end
|
51
|
+
|
52
|
+
puts "couldn't find issue on page: #{paginator.page}, fetching next..."
|
53
|
+
|
54
|
+
paginator.inc
|
55
|
+
end
|
56
|
+
|
57
|
+
puts "couldn't find issue on github."
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cob
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.15
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-09-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: fileutils
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-prompt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.19.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.19.0
|
55
|
+
description: Format and checkout your branches
|
56
|
+
email: yan@shiyason.com
|
57
|
+
executables:
|
58
|
+
- cob
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- bin/cob
|
63
|
+
- lib/cob.rb
|
64
|
+
- lib/credentials.rb
|
65
|
+
- lib/git.rb
|
66
|
+
- lib/local_cob.rb
|
67
|
+
- lib/navigator.rb
|
68
|
+
- lib/paginator.rb
|
69
|
+
- lib/remote_cob.rb
|
70
|
+
- lib/string_refinements.rb
|
71
|
+
- lib/version.rb
|
72
|
+
homepage: https://github.com/yanshiyason/cob
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubygems_version: 3.0.3
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: Checkout github branches with style
|
95
|
+
test_files: []
|