batcave 0.0.9 → 0.0.11
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/Gemfile +2 -4
- data/Gemfile.lock +13 -3
- data/batcave.gemspec +3 -1
- data/bin/dk +1 -1
- data/lib/batcave/command/github-issue-milestone.rb +97 -0
- data/lib/batcave/command/smart-edit.rb +63 -0
- data/lib/batcave/main.rb +7 -0
- metadata +42 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a25e16c495db47fa2c3282ecca632718045bc953
|
4
|
+
data.tar.gz: b37c25923e024cb02ce42f67cc91f249da7e844b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c39256bb430dd27a3bab682a63a0721ff855ed210336b06b54528d38086b2fc151b384d15c589d66cb85a3c84e70bc14a7223520f18f4cc846b8dcc09f46e483
|
7
|
+
data.tar.gz: 9ce8d3bce04ca99686e88adf9840216a80c391d0ac44d17456d7fafc9e2c3cbb012ca754bdb56f720634eebec016b53e05893d95e71ebb8737b55d17d1019351
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
batcave (0.0.10)
|
5
|
+
cabin
|
6
|
+
clamp
|
7
|
+
stud (>= 0.0.14)
|
8
|
+
|
1
9
|
GEM
|
2
|
-
remote:
|
10
|
+
remote: https://rubygems.org/
|
3
11
|
specs:
|
4
|
-
|
12
|
+
cabin (0.6.1)
|
13
|
+
clamp (0.6.3)
|
14
|
+
stud (0.0.18)
|
5
15
|
|
6
16
|
PLATFORMS
|
7
17
|
ruby
|
8
18
|
|
9
19
|
DEPENDENCIES
|
10
|
-
|
20
|
+
batcave!
|
data/batcave.gemspec
CHANGED
@@ -2,7 +2,7 @@ Gem::Specification.new do |spec|
|
|
2
2
|
files = %x{git ls-files}.split("\n")
|
3
3
|
|
4
4
|
spec.name = "batcave"
|
5
|
-
spec.version = "0.0.
|
5
|
+
spec.version = "0.0.11"
|
6
6
|
spec.summary = "Experiments in tools, boilerplatery, debugging, etc."
|
7
7
|
spec.description = spec.summary
|
8
8
|
spec.add_dependency("clamp")
|
@@ -11,6 +11,8 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.bindir = "bin"
|
12
12
|
spec.executables << "dk"
|
13
13
|
|
14
|
+
spec.add_dependency("stud", ">= 0.0.14")
|
15
|
+
spec.add_dependency("octokit")
|
14
16
|
spec.author = "Jordan Sissel"
|
15
17
|
spec.email = "jls@semicomplete.com"
|
16
18
|
spec.homepage = "https://github.com/jordansissel/batcave"
|
data/bin/dk
CHANGED
@@ -0,0 +1,97 @@
|
|
1
|
+
require "clamp"
|
2
|
+
require "faraday"
|
3
|
+
require "json"
|
4
|
+
require "insist"
|
5
|
+
require "clamp"
|
6
|
+
|
7
|
+
class BatCave::Command::GithubIssueMilestone < Clamp::Command
|
8
|
+
option ["--log-level", "-l"], "LEVEL", "The log level. Default is 'warn'. Can be 'debug', 'info', 'warn', 'error'", :default => "warn" do |val|
|
9
|
+
insist { ["warn", "debug", "info", "error"] }.include?(val.downcase)
|
10
|
+
val.downcase.to_sym
|
11
|
+
end
|
12
|
+
option "--override", :flag, "Override milestone on an issue if one is already set.", :default => false
|
13
|
+
|
14
|
+
parameter "USER/PROJECT", "The user/project repo name on github.", :attribute_name => "repo"
|
15
|
+
parameter "ISSUE", "The issue number. Can be '-' to read issue numbers from stdin.", :attribute_name => :issue_number
|
16
|
+
parameter "MILESTONE", "The milestone to set", :attribute_name => :milestone_name
|
17
|
+
|
18
|
+
def logger
|
19
|
+
@logger ||= Cabin::Channel.get
|
20
|
+
end
|
21
|
+
|
22
|
+
def execute
|
23
|
+
logger.subscribe(STDOUT)
|
24
|
+
logger.level = log_level
|
25
|
+
logger[:repo] = repo
|
26
|
+
logger[:milestone] = milestone_name
|
27
|
+
|
28
|
+
# verify milestone exists
|
29
|
+
milestones = client.milestones(repo)
|
30
|
+
selector = proc { |m| m["title"] == milestone_name }
|
31
|
+
if milestones.none?(&selector)
|
32
|
+
raise "No such milestone '#{milestone_name}' found in #{repo}"
|
33
|
+
end
|
34
|
+
milestone_number = milestones.find(&selector)["number"]
|
35
|
+
|
36
|
+
logger.debug("Found milestone number", :number => milestone_number)
|
37
|
+
|
38
|
+
if issue_number == "-"
|
39
|
+
STDIN.each_line do |issue_number|
|
40
|
+
set_milestone(repo, issue_number.chomp, milestone_number)
|
41
|
+
end
|
42
|
+
else
|
43
|
+
set_milestone(repo, issue_number, milestone_number)
|
44
|
+
end
|
45
|
+
0
|
46
|
+
rescue RuntimeError => e
|
47
|
+
puts "Error: #{e}"
|
48
|
+
1
|
49
|
+
rescue => e
|
50
|
+
if logger.debug?
|
51
|
+
logger.error("An error occurred", :exception => e, :backtrace => e.backtrace)
|
52
|
+
else
|
53
|
+
logger.error("An error occurred", :exception => e)
|
54
|
+
end
|
55
|
+
1
|
56
|
+
end # def execute
|
57
|
+
|
58
|
+
def set_milestone(repo, issue_number, milestone_number)
|
59
|
+
logger[:issue] = issue_number
|
60
|
+
|
61
|
+
# TODO(sissel): Verify issue exists
|
62
|
+
issue = client.issue(repo, issue_number)
|
63
|
+
if issue.milestone
|
64
|
+
if issue.milestone.title == milestone_name
|
65
|
+
logger.debug("Skipping because milestone is already set", :current_milestone => issue.milestone.title)
|
66
|
+
return
|
67
|
+
end
|
68
|
+
if issue.milestone.title != milestone_name
|
69
|
+
if override?
|
70
|
+
logger.info("Milestone already set on issue, but override is given, so I will override it.", :current_milestone => issue.milestone.title)
|
71
|
+
else
|
72
|
+
logger.info("Milestone already set on issue, skipping this issue.", :current_milestone => issue.milestone.title)
|
73
|
+
#raise "Milestone is already set on '#{repo}' issue #{issue_number}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
client.update_issue(repo, issue_number, issue.title, issue.body, :milestone => milestone_number)
|
78
|
+
logger.info("Updated issue milestone successfully", :repo => repo)
|
79
|
+
end # def execute
|
80
|
+
|
81
|
+
def client
|
82
|
+
# This requires you have ~/.netrc setup correctly
|
83
|
+
# I don't know if it works with 2FA
|
84
|
+
require "octokit"
|
85
|
+
@client ||= Octokit::Client.new(:netrc => true).tap do |client|
|
86
|
+
client.login
|
87
|
+
client.auto_paginate = true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def http
|
92
|
+
@http ||= Faraday.new(:url => "https://github.com") do |faraday|
|
93
|
+
faraday.request :url_encoded
|
94
|
+
faraday.adapter Faraday.default_adapter
|
95
|
+
end # http
|
96
|
+
end # def http
|
97
|
+
end # class BatCave::Command::GithubIssueMilestone
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "clamp"
|
2
|
+
require "batcave/namespace"
|
3
|
+
require "stud/temporary"
|
4
|
+
|
5
|
+
class BatCave::Command::SmartEdit < Clamp::Command
|
6
|
+
def execute
|
7
|
+
rspec_failure = /^ *Failure\/Error/
|
8
|
+
rspec_stack_trace = /^ *# (?<path>[^:]+):(?<line>[0-9]+):/
|
9
|
+
text = capture_tmux
|
10
|
+
if text =~ rspec_failure
|
11
|
+
lines = text.split("\n")
|
12
|
+
# first failure/error
|
13
|
+
index = lines.find_index { |l| l =~ rspec_failure }
|
14
|
+
# then find all lines that look like stack traces.
|
15
|
+
traces = []
|
16
|
+
last_line = index
|
17
|
+
lines[index..-1].each_with_index do |line, i|
|
18
|
+
m = rspec_stack_trace.match(line)
|
19
|
+
if m
|
20
|
+
traces << Hash[m.names.zip(m.captures)]
|
21
|
+
elsif traces.count > 0 && line =~ /^ *$/
|
22
|
+
# already found traces, and a blank line means the end of the trace.
|
23
|
+
last_line = i
|
24
|
+
break
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if traces.any?
|
29
|
+
# Find the most-recently modified file.
|
30
|
+
candidate = traces.sort_by { |t| File.stat(t["path"]).mtime }.reverse.first
|
31
|
+
Stud::Temporary.file do |fd|
|
32
|
+
lines[index .. last_line + index].each do |line|
|
33
|
+
fd.puts(line)
|
34
|
+
end
|
35
|
+
fd.flush
|
36
|
+
|
37
|
+
system("tmux split-window -l 7 'cat #{fd.path}; sleep 3000 ' \\; last-pane")
|
38
|
+
system("#{ENV["EDITOR"]} #{candidate["path"]} +#{candidate["line"]}")
|
39
|
+
system("tmux last-pane \\; kill-pane")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
return 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def tmux?
|
48
|
+
return ENV["TMUX"]
|
49
|
+
end
|
50
|
+
|
51
|
+
def screen?
|
52
|
+
return ENV["STY"]
|
53
|
+
end
|
54
|
+
|
55
|
+
def capture_tmux
|
56
|
+
Stud::Temporary.file do |fd|
|
57
|
+
# Capture the current screen plus 50 lines of history
|
58
|
+
system("tmux capture-pane -S -50")
|
59
|
+
system("tmux save-buffer -b 0 #{fd.path}")
|
60
|
+
return fd.read
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/batcave/main.rb
CHANGED
@@ -3,6 +3,8 @@ require "batcave/namespace"
|
|
3
3
|
require "batcave/command/add"
|
4
4
|
require "batcave/command/update"
|
5
5
|
require "batcave/command/test"
|
6
|
+
require "batcave/command/smart-edit"
|
7
|
+
require "batcave/command/github-issue-milestone"
|
6
8
|
require "cabin"
|
7
9
|
|
8
10
|
class BatCave::Main < Clamp::Command
|
@@ -22,4 +24,9 @@ class BatCave::Main < Clamp::Command
|
|
22
24
|
|
23
25
|
# Run a file's tests.
|
24
26
|
subcommand "test", "Run the tests for a given file", BatCave::Command::Test
|
27
|
+
|
28
|
+
# Figure out what file to edit and do it.
|
29
|
+
subcommand "smart-edit", "Scan the screen for a file to edit", BatCave::Command::SmartEdit
|
30
|
+
|
31
|
+
subcommand "github-issue-milestone", "Set a milestone on an issue", BatCave::Command::GithubIssueMilestone
|
25
32
|
end
|
metadata
CHANGED
@@ -1,46 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: batcave
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.11
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jordan Sissel
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-11-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: clamp
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: cabin
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: stud
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.0.14
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.14
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: octokit
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
44
67
|
- !ruby/object:Gem::Version
|
45
68
|
version: '0'
|
46
69
|
description: Experiments in tools, boilerplatery, debugging, etc.
|
@@ -50,7 +73,7 @@ executables:
|
|
50
73
|
extensions: []
|
51
74
|
extra_rdoc_files: []
|
52
75
|
files:
|
53
|
-
- .gitignore
|
76
|
+
- ".gitignore"
|
54
77
|
- Gemfile
|
55
78
|
- Gemfile.lock
|
56
79
|
- Makefile
|
@@ -59,6 +82,8 @@ files:
|
|
59
82
|
- bin/dk
|
60
83
|
- lib/batcave/action/add.rb
|
61
84
|
- lib/batcave/command/add.rb
|
85
|
+
- lib/batcave/command/github-issue-milestone.rb
|
86
|
+
- lib/batcave/command/smart-edit.rb
|
62
87
|
- lib/batcave/command/test.rb
|
63
88
|
- lib/batcave/command/update.rb
|
64
89
|
- lib/batcave/dsl.rb
|
@@ -81,27 +106,25 @@ files:
|
|
81
106
|
- things/user.sh/THING
|
82
107
|
homepage: https://github.com/jordansissel/batcave
|
83
108
|
licenses: []
|
109
|
+
metadata: {}
|
84
110
|
post_install_message:
|
85
111
|
rdoc_options: []
|
86
112
|
require_paths:
|
87
113
|
- lib
|
88
114
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
115
|
requirements:
|
91
|
-
- -
|
116
|
+
- - ">="
|
92
117
|
- !ruby/object:Gem::Version
|
93
118
|
version: '0'
|
94
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
120
|
requirements:
|
97
|
-
- -
|
121
|
+
- - ">="
|
98
122
|
- !ruby/object:Gem::Version
|
99
123
|
version: '0'
|
100
124
|
requirements: []
|
101
125
|
rubyforge_project:
|
102
|
-
rubygems_version:
|
126
|
+
rubygems_version: 2.2.2
|
103
127
|
signing_key:
|
104
|
-
specification_version:
|
128
|
+
specification_version: 4
|
105
129
|
summary: Experiments in tools, boilerplatery, debugging, etc.
|
106
130
|
test_files: []
|
107
|
-
has_rdoc:
|