pltt 0.1.0.beta
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/.agignore +1 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +106 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +66 -0
- data/LICENSE.txt +21 -0
- data/README.md +91 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/pltt +15 -0
- data/lib/pltt.rb +6 -0
- data/lib/pltt/actions/base.rb +105 -0
- data/lib/pltt/actions/create.rb +27 -0
- data/lib/pltt/actions/edit.rb +14 -0
- data/lib/pltt/actions/list.rb +20 -0
- data/lib/pltt/actions/resume.rb +20 -0
- data/lib/pltt/actions/start.rb +34 -0
- data/lib/pltt/actions/status.rb +19 -0
- data/lib/pltt/actions/stop.rb +44 -0
- data/lib/pltt/colorize.rb +93 -0
- data/lib/pltt/entry.rb +99 -0
- data/lib/pltt/gitlab_wrapper.rb +40 -0
- data/lib/pltt/runner.rb +66 -0
- data/lib/pltt/version.rb +3 -0
- data/pltt.gemspec +32 -0
- metadata +197 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e8327a3f012b1d7e9e6587751232ba29b60bc1a7c9ec2b368c0b8ef162c129f6
|
|
4
|
+
data.tar.gz: fc6b8868a2c388151f4fbfc77bf0b6b7d034faefeab45bf950b41d0cf16a5c3f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: c6e09108e751a25fb217d43c5a40c704a6409f0239e75c1735f02d489ca2846eb2c758cb3df8d95dbcb6007e83aec2a579b05b0007ee421a4c0588c96039f233
|
|
7
|
+
data.tar.gz: 5fe58994e0787ca17f4c3162436b22634cb9a3094c379d362ee100ae1d0ab51007948470ec4a765189b82798f232f09839656483004b8c3b2cdb0d7f533d47c8
|
data/.agignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
vendor
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.5
|
|
3
|
+
Style/GuardClause:
|
|
4
|
+
MinBodyLength: 1
|
|
5
|
+
Enabled: false
|
|
6
|
+
Style/AndOr:
|
|
7
|
+
EnforcedStyle: conditionals
|
|
8
|
+
Style/PercentLiteralDelimiters:
|
|
9
|
+
PreferredDelimiters: {}
|
|
10
|
+
Style/Alias:
|
|
11
|
+
Enabled: false
|
|
12
|
+
Style/Documentation:
|
|
13
|
+
Enabled: false
|
|
14
|
+
Style/PercentLiteralDelimiters:
|
|
15
|
+
Enabled: false
|
|
16
|
+
Lint/UnusedMethodArgument:
|
|
17
|
+
Enabled: false
|
|
18
|
+
Metrics/ModuleLength:
|
|
19
|
+
Enabled: false
|
|
20
|
+
Style/StringLiterals:
|
|
21
|
+
Enabled: false
|
|
22
|
+
Style/IfUnlessModifier:
|
|
23
|
+
Enabled: false
|
|
24
|
+
Metrics/MethodLength:
|
|
25
|
+
Enabled: false
|
|
26
|
+
Metrics/LineLength:
|
|
27
|
+
Max: 150
|
|
28
|
+
Metrics/AbcSize:
|
|
29
|
+
Enabled: false
|
|
30
|
+
Metrics/ClassLength:
|
|
31
|
+
Enabled: false
|
|
32
|
+
Layout/DotPosition:
|
|
33
|
+
Enabled: false
|
|
34
|
+
Style/BlockDelimiters:
|
|
35
|
+
Enabled: false
|
|
36
|
+
Style/AndOr:
|
|
37
|
+
Enabled: false
|
|
38
|
+
Layout/AlignParameters:
|
|
39
|
+
EnforcedStyle: with_fixed_indentation
|
|
40
|
+
Rails/ActionFilter:
|
|
41
|
+
Enabled: false
|
|
42
|
+
Layout/MultilineMethodCallIndentation:
|
|
43
|
+
EnforcedStyle: indented
|
|
44
|
+
Style/FrozenStringLiteralComment:
|
|
45
|
+
Enabled: false
|
|
46
|
+
# class Admin::PageController
|
|
47
|
+
Style/ClassAndModuleChildren:
|
|
48
|
+
Enabled: false
|
|
49
|
+
|
|
50
|
+
# asddsa == 0 -> asddsa.zero?
|
|
51
|
+
Style/NumericPredicate:
|
|
52
|
+
Enabled: false
|
|
53
|
+
Performance/StringReplacement:
|
|
54
|
+
Enabled: false
|
|
55
|
+
# ->() {} -- lambda {|a| }
|
|
56
|
+
Style/Lambda:
|
|
57
|
+
EnforcedStyle: 'literal'
|
|
58
|
+
# if bla.nil? -- if bla == nil
|
|
59
|
+
Style/NilComparison:
|
|
60
|
+
Enabled: false
|
|
61
|
+
# Ruby 3
|
|
62
|
+
Style/FrozenStringLiteralComment:
|
|
63
|
+
Enabled: false
|
|
64
|
+
# Rails 5 -> im Controller/Request Test get :foo, params: {}
|
|
65
|
+
Rails/HttpPositionalArguments:
|
|
66
|
+
Enabled: false
|
|
67
|
+
# def bla; end
|
|
68
|
+
Style/EmptyMethod:
|
|
69
|
+
Enabled: false
|
|
70
|
+
# [ "700", "200" ] -> %w[w w]
|
|
71
|
+
Style/WordArray:
|
|
72
|
+
Enabled: false
|
|
73
|
+
# RSpec nervt
|
|
74
|
+
Metrics/BlockLength:
|
|
75
|
+
ExcludedMethods: ['task', 'namespace', 'get', 'post', 'describe', 'context', 'specify', 'it', 'route_param', 'draw', 'register', 'register_page', 'controller', 'included', 'params', 'resource', 'with_options', 'use_cassette', 'configure']
|
|
76
|
+
|
|
77
|
+
Bundler/OrderedGems:
|
|
78
|
+
Enabled: false
|
|
79
|
+
# update_all, update_column
|
|
80
|
+
# set_ und get_ verbote
|
|
81
|
+
Naming/AccessorMethodName:
|
|
82
|
+
Enabled: false
|
|
83
|
+
Style/TrailingCommaInArrayLiteral:
|
|
84
|
+
Enabled: false
|
|
85
|
+
Style/TrailingCommaInHashLiteral:
|
|
86
|
+
Enabled: false
|
|
87
|
+
|
|
88
|
+
Style/SymbolArray:
|
|
89
|
+
Enabled: false
|
|
90
|
+
|
|
91
|
+
Style/AsciiComments:
|
|
92
|
+
Enabled: false
|
|
93
|
+
Style/FormatString:
|
|
94
|
+
Enabled: false
|
|
95
|
+
Style/FormatStringToken:
|
|
96
|
+
Enabled: false
|
|
97
|
+
Metrics/PerceivedComplexity:
|
|
98
|
+
Enabled: false
|
|
99
|
+
Style/DoubleNegation:
|
|
100
|
+
Enabled: false
|
|
101
|
+
Style/ZeroLengthPredicate:
|
|
102
|
+
Enabled: false
|
|
103
|
+
Style/SafeNavigation:
|
|
104
|
+
Enabled: false
|
|
105
|
+
Lint/MissingCopEnableDirective:
|
|
106
|
+
Enabled: false
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
pltt (0.1.0.beta)
|
|
5
|
+
gitlab (~> 4.4.0)
|
|
6
|
+
hashids
|
|
7
|
+
oj
|
|
8
|
+
terminal-table (>= 1.8.0)
|
|
9
|
+
thor
|
|
10
|
+
tty-prompt
|
|
11
|
+
|
|
12
|
+
GEM
|
|
13
|
+
remote: https://rubygems.org/
|
|
14
|
+
specs:
|
|
15
|
+
coderay (1.1.2)
|
|
16
|
+
equatable (0.5.0)
|
|
17
|
+
gitlab (4.4.0)
|
|
18
|
+
httparty (>= 0.14.0)
|
|
19
|
+
terminal-table (>= 1.5.1)
|
|
20
|
+
hashids (1.0.4)
|
|
21
|
+
hitimes (1.2.6)
|
|
22
|
+
httparty (0.16.2)
|
|
23
|
+
multi_xml (>= 0.5.2)
|
|
24
|
+
method_source (0.9.0)
|
|
25
|
+
multi_xml (0.6.0)
|
|
26
|
+
necromancer (0.4.0)
|
|
27
|
+
oj (3.6.2)
|
|
28
|
+
pastel (0.7.2)
|
|
29
|
+
equatable (~> 0.5.0)
|
|
30
|
+
tty-color (~> 0.4.0)
|
|
31
|
+
pry (0.11.3)
|
|
32
|
+
coderay (~> 1.1.0)
|
|
33
|
+
method_source (~> 0.9.0)
|
|
34
|
+
rake (10.5.0)
|
|
35
|
+
terminal-table (1.8.0)
|
|
36
|
+
unicode-display_width (~> 1.1, >= 1.1.1)
|
|
37
|
+
thor (0.20.0)
|
|
38
|
+
timers (4.1.2)
|
|
39
|
+
hitimes
|
|
40
|
+
tty-color (0.4.2)
|
|
41
|
+
tty-cursor (0.5.0)
|
|
42
|
+
tty-prompt (0.16.1)
|
|
43
|
+
necromancer (~> 0.4.0)
|
|
44
|
+
pastel (~> 0.7.0)
|
|
45
|
+
timers (~> 4.0)
|
|
46
|
+
tty-cursor (~> 0.5.0)
|
|
47
|
+
tty-reader (~> 0.3.0)
|
|
48
|
+
tty-reader (0.3.0)
|
|
49
|
+
tty-cursor (~> 0.5.0)
|
|
50
|
+
tty-screen (~> 0.6.4)
|
|
51
|
+
wisper (~> 2.0.0)
|
|
52
|
+
tty-screen (0.6.4)
|
|
53
|
+
unicode-display_width (1.4.0)
|
|
54
|
+
wisper (2.0.0)
|
|
55
|
+
|
|
56
|
+
PLATFORMS
|
|
57
|
+
ruby
|
|
58
|
+
|
|
59
|
+
DEPENDENCIES
|
|
60
|
+
bundler (~> 1.16)
|
|
61
|
+
pltt!
|
|
62
|
+
pry
|
|
63
|
+
rake (~> 10.0)
|
|
64
|
+
|
|
65
|
+
BUNDLED WITH
|
|
66
|
+
1.16.2
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Stefan Wienert
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Pltt
|
|
2
|
+
|
|
3
|
+
Pltt is a Gitlab Time Tracker for the command line. It mimicks the interface of [kriskbx/gitlab-time-tracker]( https://github.com/kriskbx/gitlab-time-tracker ) and is compatible to the config and frame database. Thus, it works as a drop-in-replacement.
|
|
4
|
+
|
|
5
|
+
Goals/Pros:
|
|
6
|
+
|
|
7
|
+
* Fast interface, even though it's ruby, the boot time is faster right now
|
|
8
|
+
* More friendly interface, error persistent, e.g. forgotten stoppings, issue creation with question-response cycles
|
|
9
|
+
* More robust interface with Gitlab:
|
|
10
|
+
* Not possible to book on non-existend or closed issues
|
|
11
|
+
* Time Entries are booked on stop by default, so no time shifting
|
|
12
|
+
* pltt status shows issue body, milestone etc. too
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Install it yourself as:
|
|
17
|
+
|
|
18
|
+
$ gem install pltt
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Starting Time Tracking
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# start without issue id -> shows a selection menu of 30 most recent issues in project
|
|
26
|
+
pltt start
|
|
27
|
+
|
|
28
|
+
# start with issue id -> validates issue exists and is not closed
|
|
29
|
+
pltt start 123
|
|
30
|
+
|
|
31
|
+
# create new issue with interactive question for issue creation
|
|
32
|
+
# issue will be created instantly, not on sync
|
|
33
|
+
# You can enter issue title, select labels, and description
|
|
34
|
+
pltt create
|
|
35
|
+
|
|
36
|
+
# Starts time tracking with
|
|
37
|
+
pltt resume
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Stopping, Synching and Maintenance
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# stops time tracking & syncs to gitlab
|
|
44
|
+
# 2 interactive questions can easly fix missing started entries
|
|
45
|
+
# can adjust start time and duration (minutes)
|
|
46
|
+
pltt stop
|
|
47
|
+
|
|
48
|
+
# Edit current entry in EDITOR
|
|
49
|
+
pltt edit
|
|
50
|
+
pltt edit 19ad20
|
|
51
|
+
|
|
52
|
+
# Cancel = delete current running entry
|
|
53
|
+
pltt cancel
|
|
54
|
+
|
|
55
|
+
# normally not needed, as sync is made after stop, only in case of error
|
|
56
|
+
pltt sync
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Reporting / General
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# show all issues in project as table
|
|
63
|
+
pltt list
|
|
64
|
+
pltt list --my
|
|
65
|
+
pltt list --label Bug
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Development
|
|
69
|
+
|
|
70
|
+
Missing before release:
|
|
71
|
+
|
|
72
|
+
* [x] gtt start with no arguments shows the list of open issues to select one from
|
|
73
|
+
* [x] gtt create can optionally create a MR + branch
|
|
74
|
+
* [x] gtt stop / sync note creation
|
|
75
|
+
* [ ] First-Start Guide, Generator which creates .gtt.yml in a project, gets the project url from .git/config
|
|
76
|
+
* [ ] Timezone
|
|
77
|
+
* [ ] Frame Cleanup, everything older than X month can delete
|
|
78
|
+
|
|
79
|
+
Missing, but not planned soon, as not needed by us:
|
|
80
|
+
|
|
81
|
+
* [ ] Logging/reporting of all bookings
|
|
82
|
+
* [ ] No Booking on Merge requests implemented
|
|
83
|
+
* [ ] No delete implemented, as cancel is enough. deleting frames is also not very useful, when they are already synced to Gitlab
|
|
84
|
+
|
|
85
|
+
## Contributing
|
|
86
|
+
|
|
87
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pludoni/pltt.
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "bundler/setup"
|
|
4
|
+
require "pltt"
|
|
5
|
+
|
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
8
|
+
|
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
10
|
+
# require "pry"
|
|
11
|
+
# Pry.start
|
|
12
|
+
|
|
13
|
+
require "irb"
|
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/pltt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
dir = File.join(File.dirname(File.realdirpath(__FILE__)), '..')
|
|
3
|
+
|
|
4
|
+
if RUBY_VERSION < '1.9.2'
|
|
5
|
+
$stderr.puts 'your ruby is too old!'
|
|
6
|
+
exit 1
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
$LOAD_PATH.unshift File.join(dir, 'lib')
|
|
10
|
+
|
|
11
|
+
ENV['BUNDLE_GEMFILE'] ||= File.join(dir, 'Gemfile')
|
|
12
|
+
|
|
13
|
+
require 'pltt'
|
|
14
|
+
require 'bundler/setup'
|
|
15
|
+
require 'pltt/runner'
|
data/lib/pltt.rb
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
require 'oj'
|
|
3
|
+
require_relative '../entry'
|
|
4
|
+
require_relative '../colorize'
|
|
5
|
+
|
|
6
|
+
class Pltt::Actions::Base
|
|
7
|
+
def self.run(*args)
|
|
8
|
+
new.run(*args)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def config
|
|
12
|
+
self.class.config
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.config
|
|
16
|
+
return @config if @config
|
|
17
|
+
master = File.expand_path('~/.gtt/config.yml')
|
|
18
|
+
unless File.exist?(master)
|
|
19
|
+
raise ".gtt/config.yml existiert nicht!"
|
|
20
|
+
end
|
|
21
|
+
config = YAML.load_file(master)
|
|
22
|
+
locale = File.join(Dir.pwd, '.gtt.yml')
|
|
23
|
+
if File.exist?(locale)
|
|
24
|
+
config = config.merge(YAML.load_file(locale))
|
|
25
|
+
end
|
|
26
|
+
config['frame_dir'] ||= '~/.gtt/frames/'
|
|
27
|
+
config['gitlab_url'] ||= config['url'].sub(%r{/api/v4/?}, '')
|
|
28
|
+
@config = config
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def current_entry
|
|
32
|
+
max = Time.now - 3600 * 24 * 7
|
|
33
|
+
recent_entries = all_frames.select { |i| File.mtime(i) > max }
|
|
34
|
+
recent_entries.each do |entry|
|
|
35
|
+
e = load_entry(entry)
|
|
36
|
+
return e if e.current?
|
|
37
|
+
end
|
|
38
|
+
nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def load_entry(path_to_frame)
|
|
42
|
+
File.read(path_to_frame).yield_self { |i| Oj.load(i) }.yield_self(&Pltt::Entry.method(:new))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def all_frames
|
|
46
|
+
Dir[File.join(File.expand_path(config['frame_dir']), '*.json')]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def exit_if_running!
|
|
50
|
+
if current_entry
|
|
51
|
+
puts "Already started!".red
|
|
52
|
+
puts current_entry.status
|
|
53
|
+
exit 1
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def exit_if_not_running!
|
|
58
|
+
unless current_entry
|
|
59
|
+
puts "Not started!".red
|
|
60
|
+
exit 1
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def gitlab_api
|
|
65
|
+
@gitlab_api ||=
|
|
66
|
+
begin
|
|
67
|
+
require_relative '../gitlab_wrapper'
|
|
68
|
+
Pltt::GitlabWrapper.new(config['url'], config['token'], config['project'])
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def sync_all_unsaved_entries
|
|
73
|
+
gitlab_api
|
|
74
|
+
max = Time.now - 3600 * 24 * 7
|
|
75
|
+
recent_entries = all_frames.select { |i| File.mtime(i) > max }
|
|
76
|
+
recent_entries.each do |e|
|
|
77
|
+
entry = load_entry(e)
|
|
78
|
+
next if entry.synced? || entry.stop.nil?
|
|
79
|
+
sync!(entry)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def sync!(entry)
|
|
84
|
+
c = entry
|
|
85
|
+
minutes = c.duration_seconds.round / 60
|
|
86
|
+
require 'pry'
|
|
87
|
+
|
|
88
|
+
min_part = minutes % 60
|
|
89
|
+
hour_part = minutes / 60
|
|
90
|
+
|
|
91
|
+
gitlab_time_format =
|
|
92
|
+
case [hour_part > 0, min_part > 0]
|
|
93
|
+
when [true, true] then "#{hour_part}h#{min_part}m"
|
|
94
|
+
when [false, true] then "#{min_part}m"
|
|
95
|
+
when [true, false] then "#{hour_part}m"
|
|
96
|
+
else return
|
|
97
|
+
end
|
|
98
|
+
puts "Synching: #{gitlab_time_format.inspect} on #{c.project}##{c.iid}"
|
|
99
|
+
gitlab_api.add_time_spent_on_issue(c.project, c.iid, gitlab_time_format)
|
|
100
|
+
|
|
101
|
+
note_id = Gitlab.issue_notes(entry.project, entry.iid).auto_paginate.max_by { |i| i.created_at }.id
|
|
102
|
+
c.add_note(note_id, c.duration_seconds.round)
|
|
103
|
+
c.persist!
|
|
104
|
+
end
|
|
105
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
require 'tty-prompt'
|
|
3
|
+
class Pltt::Actions::Create < Pltt::Actions::Base
|
|
4
|
+
def run
|
|
5
|
+
puts "New issue in project #{config['project'].green}:"
|
|
6
|
+
prompt = TTY::Prompt.new
|
|
7
|
+
title = prompt.ask('Enter issue title:') do |q|
|
|
8
|
+
q.required true
|
|
9
|
+
end
|
|
10
|
+
description = prompt.multiline("Description").join("\n")
|
|
11
|
+
labels = gitlab_api.labels.map(&:name)
|
|
12
|
+
selected_labels = if labels.length > 0
|
|
13
|
+
prompt.multi_select("Select labels", labels, per_page: 20)
|
|
14
|
+
else
|
|
15
|
+
[]
|
|
16
|
+
end
|
|
17
|
+
issue = gitlab_api.create_issue(title, description, selected_labels)
|
|
18
|
+
_entry = Pltt::Entry.create_new_for_gitlab_issue(config['project'], issue)
|
|
19
|
+
|
|
20
|
+
branch_name = "#{issue.iid}-#{issue.title.downcase.gsub(/[\W]+/, '-')}"
|
|
21
|
+
if prompt.yes?("Automatically create a branch #{branch_name} and check out locally?")
|
|
22
|
+
gitlab_api.create_branch_and_merge_request(branch_name, issue)
|
|
23
|
+
system 'git fetch'
|
|
24
|
+
system "git checkout #{branch_name}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
class Pltt::Actions::Edit < Pltt::Actions::Base
|
|
3
|
+
def run(id)
|
|
4
|
+
if id
|
|
5
|
+
raise NotImplementedError
|
|
6
|
+
else
|
|
7
|
+
exit_if_not_running!
|
|
8
|
+
c = current_entry
|
|
9
|
+
c.frame_path
|
|
10
|
+
|
|
11
|
+
exec ENV['EDITOR'] || 'vim', c.frame_path
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
# rubocop:disable Naming/UncommunicativeMethodParamName
|
|
3
|
+
class Pltt::Actions::List < Pltt::Actions::Base
|
|
4
|
+
def run(my: false, label: nil)
|
|
5
|
+
require 'terminal-table'
|
|
6
|
+
require 'pry'
|
|
7
|
+
|
|
8
|
+
table = Terminal::Table.new
|
|
9
|
+
gitlab_api.issues(scope: my ? 'assigned-to-me' : 'all', label: label).each do |issue|
|
|
10
|
+
table.add_row [
|
|
11
|
+
issue.iid.to_s.magenta,
|
|
12
|
+
issue.title.green + "\n#{issue.web_url.dark_gray}",
|
|
13
|
+
issue.state.gray,
|
|
14
|
+
issue.milestone&.title,
|
|
15
|
+
issue.labels.map { |i| "[~#{i}]" }.join
|
|
16
|
+
]
|
|
17
|
+
end
|
|
18
|
+
puts table
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
class Pltt::Actions::Resume < Pltt::Actions::Base
|
|
3
|
+
def run
|
|
4
|
+
require 'pry'
|
|
5
|
+
exit_if_running!
|
|
6
|
+
|
|
7
|
+
last_one = all_frames.sort_by { |i| File.mtime(i) }.reverse.lazy.
|
|
8
|
+
map { |i| load_entry(i) }.
|
|
9
|
+
select { |i| i.project == config['project'] }.
|
|
10
|
+
take(5).max_by { |i| i.stop }
|
|
11
|
+
|
|
12
|
+
unless last_one
|
|
13
|
+
puts "No previous entry found for #{config['project']}!".red
|
|
14
|
+
exit 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
new_entry = Pltt::Entry.from_resume(last_one)
|
|
18
|
+
new_entry.persist!
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
class Pltt::Actions::Start < Pltt::Actions::Base
|
|
3
|
+
def run(iid)
|
|
4
|
+
exit_if_running!
|
|
5
|
+
|
|
6
|
+
issue = nil
|
|
7
|
+
if iid
|
|
8
|
+
issue = gitlab_api.issue(iid.to_i)
|
|
9
|
+
puts "Issue: #{issue.title.green}"
|
|
10
|
+
else
|
|
11
|
+
require 'tty-prompt'
|
|
12
|
+
prompt = TTY::Prompt.new
|
|
13
|
+
recent = gitlab_api.issues.take(30)
|
|
14
|
+
issue = prompt.select("Select issue to start on", per_page: 20) do |menu|
|
|
15
|
+
recent.each do |this_issue|
|
|
16
|
+
menu.choice "#{this_issue.iid.to_s.magenta} #{this_issue.title}", this_issue
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
start_by_issue(issue)
|
|
21
|
+
rescue StandardError => e
|
|
22
|
+
puts "Issue #{issue.iid} not found in project #{config['project']}".red
|
|
23
|
+
puts e.inspect
|
|
24
|
+
exit 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def start_by_issue(issue)
|
|
28
|
+
if issue.closed?
|
|
29
|
+
puts "This issue is closed"
|
|
30
|
+
exit 1
|
|
31
|
+
end
|
|
32
|
+
Pltt::Entry.create_new_for_gitlab_issue(config['project'], issue)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
class Pltt::Actions::Status < Pltt::Actions::Base
|
|
3
|
+
def run
|
|
4
|
+
exit_if_not_running!
|
|
5
|
+
puts current_entry.status
|
|
6
|
+
|
|
7
|
+
if (iid = current_entry.resource['id'])
|
|
8
|
+
issue = gitlab_api.issue(iid)
|
|
9
|
+
puts "-------------------------------------------".black
|
|
10
|
+
puts <<~DOC
|
|
11
|
+
#{issue.title.green} (##{iid})
|
|
12
|
+
#{issue.time_stats.human_total_time_spent&.dark_gray} #{issue.assignees.map { |i| "@#{i['username']}".blue }.join(' ')}
|
|
13
|
+
#{issue.labels.map { |i| "[~#{i}]".red }.join(' ')} #{issue.milestone&.title&.magenta}
|
|
14
|
+
|
|
15
|
+
#{issue.description}
|
|
16
|
+
DOC
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require_relative './base'
|
|
2
|
+
require 'tty-prompt'
|
|
3
|
+
# rubocop:disable Style/NegatedIf
|
|
4
|
+
class Pltt::Actions::Stop < Pltt::Actions::Base
|
|
5
|
+
def run
|
|
6
|
+
exit_if_not_running!
|
|
7
|
+
c = current_entry
|
|
8
|
+
|
|
9
|
+
minutes = (c.duration_seconds / 60).round
|
|
10
|
+
puts "Currently running for #{minutes} min"
|
|
11
|
+
prompt = TTY::Prompt.new
|
|
12
|
+
too_large = minutes > 480
|
|
13
|
+
if !prompt.no?("Was started on #{c.start.localtime.to_s.green}, fix beginning?")
|
|
14
|
+
time = prompt.ask("Enter beginning *time* only (HH:MM)") do |q|
|
|
15
|
+
q.required true
|
|
16
|
+
q.validate(/\A\d+:\d+\Z/)
|
|
17
|
+
q.convert :string
|
|
18
|
+
end
|
|
19
|
+
h, m = time.split(':').map(&:to_i)
|
|
20
|
+
c.start = Time.new(c.start.year, c.start.month, c.start.day, h, m)
|
|
21
|
+
end
|
|
22
|
+
minutes = (c.duration_seconds / 60).round
|
|
23
|
+
puts "Currently running for #{minutes} min"
|
|
24
|
+
if too_large || !prompt.no?("Fix duration before saving? (#{minutes}min)")
|
|
25
|
+
puts "Error: To many minutes, must be not greater than 8h (480min)" if too_large
|
|
26
|
+
new_minutes = prompt.ask("New Minutes, beginning from #{c.start.localtime}") do |q|
|
|
27
|
+
q.required true
|
|
28
|
+
q.convert :int
|
|
29
|
+
end
|
|
30
|
+
stop = (c.start + new_minutes * 60).utc
|
|
31
|
+
else
|
|
32
|
+
stop = Time.now.utc
|
|
33
|
+
end
|
|
34
|
+
c.stop = stop
|
|
35
|
+
|
|
36
|
+
c.persist!
|
|
37
|
+
|
|
38
|
+
sync_all_unsaved_entries
|
|
39
|
+
rescue StandardError => e
|
|
40
|
+
puts "Issue #{c.id} not found in project #{config['project']}".red
|
|
41
|
+
puts e.inspect
|
|
42
|
+
exit 1
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def dark_gray
|
|
3
|
+
"\e[90m#{self}\e[0m"
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def black
|
|
7
|
+
"\e[30m#{self}\e[0m"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def red
|
|
11
|
+
"\e[31m#{self}\e[0m"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def green
|
|
15
|
+
"\e[32m#{self}\e[0m"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def brown
|
|
19
|
+
"\e[33m#{self}\e[0m"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def blue
|
|
23
|
+
"\e[34m#{self}\e[0m"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def magenta
|
|
27
|
+
"\e[35m#{self}\e[0m"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def cyan
|
|
31
|
+
"\e[36m#{self}\e[0m"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def gray
|
|
35
|
+
"\e[37m#{self}\e[0m"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def gray39
|
|
39
|
+
"\e[39m#{self}\e[0m"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def bg_black
|
|
43
|
+
"\e[40m#{self}\e[0m"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def bg_red
|
|
47
|
+
"\e[41m#{self}\e[0m"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def bg_green
|
|
51
|
+
"\e[42m#{self}\e[0m"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def bg_brown
|
|
55
|
+
"\e[43m#{self}\e[0m"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def bg_blue
|
|
59
|
+
"\e[44m#{self}\e[0m"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def bg_magenta
|
|
63
|
+
"\e[45m#{self}\e[0m"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def bg_cyan
|
|
67
|
+
"\e[46m#{self}\e[0m"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def bg_gray
|
|
71
|
+
"\e[47m#{self}\e[0m"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def bold
|
|
75
|
+
"\e[1m#{self}\e[22m"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def italic
|
|
79
|
+
"\e[3m#{self}\e[23m"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def underline
|
|
83
|
+
"\e[4m#{self}\e[24m"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def blink
|
|
87
|
+
"\e[5m#{self}\e[25m"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def reverse_color
|
|
91
|
+
"\e[7m#{self}\e[27m"
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/pltt/entry.rb
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
class Pltt::Entry
|
|
2
|
+
attr_reader :id, :project, :start, :stop, :resource
|
|
3
|
+
attr_writer :start, :stop
|
|
4
|
+
|
|
5
|
+
def self.from_resume(other_entry)
|
|
6
|
+
new('project' => other_entry.project, 'resource' => other_entry.resource, 'start' => Time.now.utc.iso8601)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.create_new_for_gitlab_issue(project, issue)
|
|
10
|
+
entry = Pltt::Entry.new('project' => project, 'resource' => { 'id' => issue.iid, 'type' => 'issue' }, 'start' => Time.now.utc.iso8601)
|
|
11
|
+
entry.persist!
|
|
12
|
+
entry
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(json)
|
|
16
|
+
@id = json['id']
|
|
17
|
+
@project = json['project']
|
|
18
|
+
@resource = json['resource']
|
|
19
|
+
@notes = json['notes'] || []
|
|
20
|
+
@start = Time.iso8601(json['start']) if json['start']
|
|
21
|
+
@stop = if json['stop']
|
|
22
|
+
Time.iso8601(json['stop'])
|
|
23
|
+
else
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
@_json = json
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def current?
|
|
30
|
+
!@stop
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def status
|
|
34
|
+
duration = duration_time.strftime("%H:%M:%S")
|
|
35
|
+
<<~DOC
|
|
36
|
+
#{@project}##{iid}, #{duration.green} (id: #{@id})
|
|
37
|
+
#{url.gray}
|
|
38
|
+
DOC
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def duration_time
|
|
42
|
+
Time.at(duration_seconds).utc
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def duration_seconds
|
|
46
|
+
(@stop || Time.now.utc) - @start.utc
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def url
|
|
50
|
+
"#{Pltt::Actions::Base.config['gitlab_url']}/#{@project}/issues/#{iid}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def frame_path
|
|
54
|
+
@frame_path ||= File.join(File.expand_path(Pltt::Actions::Base.config['frame_dir']), @id + ".json")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def cancel!
|
|
58
|
+
if File.exist?(frame_path)
|
|
59
|
+
puts "Entry deleted"
|
|
60
|
+
File.unlink(frame_path)
|
|
61
|
+
else
|
|
62
|
+
puts "Entry already deleted!"
|
|
63
|
+
exit 1
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def persist!
|
|
68
|
+
require 'oj'
|
|
69
|
+
Oj.mimic_JSON
|
|
70
|
+
unless @id
|
|
71
|
+
require 'hashids'
|
|
72
|
+
@id = Hashids.new('', 9).encode(@start.to_i)
|
|
73
|
+
end
|
|
74
|
+
output = JSON.pretty_generate(id: @id,
|
|
75
|
+
project: @project,
|
|
76
|
+
resource: @resource,
|
|
77
|
+
notes: @notes,
|
|
78
|
+
start: @start && @start.iso8601,
|
|
79
|
+
stop: @stop && @stop.iso8601)
|
|
80
|
+
File.write(frame_path, output)
|
|
81
|
+
unless @stop
|
|
82
|
+
puts "Started:"
|
|
83
|
+
end
|
|
84
|
+
puts status
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def add_note(id, time)
|
|
88
|
+
@notes ||= []
|
|
89
|
+
@notes << { id: id, time: time }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def iid
|
|
93
|
+
@resource['id']
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def synced?
|
|
97
|
+
@notes && @notes.length > 0
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class Pltt::GitlabWrapper
|
|
2
|
+
def initialize(url, token, project)
|
|
3
|
+
require 'gitlab'
|
|
4
|
+
@project = project
|
|
5
|
+
|
|
6
|
+
Gitlab.endpoint = url
|
|
7
|
+
Gitlab.private_token = token
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def issues(scope: 'assigned-to-me', order_by: 'updated_at', state: 'opened', label: nil)
|
|
11
|
+
Gitlab.issues(@project, state: state, order_by: order_by, scope: scope, labels: label ? label : nil).auto_paginate
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def issue(id)
|
|
15
|
+
Gitlab.issue(@project, id)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_issue(title, description, labels)
|
|
19
|
+
user_id = Gitlab.user.id
|
|
20
|
+
Gitlab.create_issue(@project, title, description: description, labels: labels.join(','), assignee_ids: [user_id])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def labels
|
|
24
|
+
Gitlab.labels(@project)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def create_branch_and_merge_request(branch_name, issue)
|
|
28
|
+
Gitlab.create_branch(@project, branch_name, 'master')
|
|
29
|
+
Gitlab.create_merge_request(@project, "Resolve #{issue.title}",
|
|
30
|
+
source_branch: branch_name,
|
|
31
|
+
target_branch: 'master',
|
|
32
|
+
description: "Closes ##{issue.iid}",
|
|
33
|
+
remove_source_branch: true)
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def add_time_spent_on_issue(project, issue_id, duration)
|
|
38
|
+
Gitlab.add_time_spent_on_issue(project, issue_id, duration)
|
|
39
|
+
end
|
|
40
|
+
end
|
data/lib/pltt/runner.rb
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
|
|
3
|
+
class Pltt::Runner < Thor
|
|
4
|
+
desc "resume", "resume last issue in current project"
|
|
5
|
+
def resume
|
|
6
|
+
require_relative './actions/resume'
|
|
7
|
+
Pltt::Actions::Resume.run
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
desc "create", "create new issue in current project"
|
|
11
|
+
def create
|
|
12
|
+
require_relative './actions/create'
|
|
13
|
+
Pltt::Actions::Create.run
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "start [ID]", "start tracking for issue #ID"
|
|
17
|
+
def start(id = nil)
|
|
18
|
+
require_relative './actions/start'
|
|
19
|
+
Pltt::Actions::Start.run(id)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc "stop", "Stop"
|
|
23
|
+
def stop
|
|
24
|
+
require_relative './actions/stop'
|
|
25
|
+
Pltt::Actions::Stop.run
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
desc "list", "List all project issues"
|
|
29
|
+
option :my, type: :boolean
|
|
30
|
+
option :label, type: :string
|
|
31
|
+
def list
|
|
32
|
+
require_relative './actions/list'
|
|
33
|
+
Pltt::Actions::List.run(my: options[:my], label: options[:label])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
desc "status", "Status"
|
|
37
|
+
def status
|
|
38
|
+
require_relative './actions/status'
|
|
39
|
+
Pltt::Actions::Status.run
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
desc "edit [ID = CURRENT]", "start tracking for issue #ID"
|
|
43
|
+
def edit(id = nil)
|
|
44
|
+
require_relative './actions/edit'
|
|
45
|
+
Pltt::Actions::Edit.run(id)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
desc "cancel", "cancel current entry"
|
|
49
|
+
def cancel
|
|
50
|
+
require_relative './actions/base'
|
|
51
|
+
if (c = Pltt::Actions::Base.new.current_entry)
|
|
52
|
+
c.cancel!
|
|
53
|
+
else
|
|
54
|
+
puts "No running entry to cancel"
|
|
55
|
+
exit 1
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
desc 'sync', 'sync all unsaved entries'
|
|
60
|
+
def sync
|
|
61
|
+
require_relative './actions/base'
|
|
62
|
+
Pltt::Actions::Base.new.sync_all_unsaved_entries
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
Pltt::Runner.start(ARGV)
|
data/lib/pltt/version.rb
ADDED
data/pltt.gemspec
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require "pltt/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "pltt"
|
|
7
|
+
spec.version = Pltt::VERSION
|
|
8
|
+
spec.authors = ["Stefan Wienert"]
|
|
9
|
+
spec.email = ["info@stefanwienert.de"]
|
|
10
|
+
|
|
11
|
+
spec.summary = %{}
|
|
12
|
+
spec.description = %{}
|
|
13
|
+
spec.homepage = ""
|
|
14
|
+
spec.license = "MIT"
|
|
15
|
+
|
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
|
18
|
+
end
|
|
19
|
+
spec.bindir = "exe"
|
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
21
|
+
spec.require_paths = ["lib"]
|
|
22
|
+
|
|
23
|
+
spec.add_dependency 'gitlab', '~> 4.4.0'
|
|
24
|
+
spec.add_dependency 'hashids'
|
|
25
|
+
spec.add_dependency 'oj'
|
|
26
|
+
spec.add_dependency 'terminal-table', '>= 1.8.0'
|
|
27
|
+
spec.add_dependency 'thor'
|
|
28
|
+
spec.add_dependency 'tty-prompt'
|
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
|
30
|
+
spec.add_development_dependency "pry"
|
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
|
32
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: pltt
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0.beta
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Stefan Wienert
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-06-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: gitlab
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 4.4.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 4.4.0
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: hashids
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: oj
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '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'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: terminal-table
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 1.8.0
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: 1.8.0
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: thor
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: tty-prompt
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: bundler
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '1.16'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '1.16'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: pry
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: rake
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - "~>"
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '10.0'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - "~>"
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '10.0'
|
|
139
|
+
description: ''
|
|
140
|
+
email:
|
|
141
|
+
- info@stefanwienert.de
|
|
142
|
+
executables:
|
|
143
|
+
- pltt
|
|
144
|
+
extensions: []
|
|
145
|
+
extra_rdoc_files: []
|
|
146
|
+
files:
|
|
147
|
+
- ".agignore"
|
|
148
|
+
- ".gitignore"
|
|
149
|
+
- ".rubocop.yml"
|
|
150
|
+
- Gemfile
|
|
151
|
+
- Gemfile.lock
|
|
152
|
+
- LICENSE.txt
|
|
153
|
+
- README.md
|
|
154
|
+
- Rakefile
|
|
155
|
+
- bin/console
|
|
156
|
+
- bin/setup
|
|
157
|
+
- exe/pltt
|
|
158
|
+
- lib/pltt.rb
|
|
159
|
+
- lib/pltt/actions/base.rb
|
|
160
|
+
- lib/pltt/actions/create.rb
|
|
161
|
+
- lib/pltt/actions/edit.rb
|
|
162
|
+
- lib/pltt/actions/list.rb
|
|
163
|
+
- lib/pltt/actions/resume.rb
|
|
164
|
+
- lib/pltt/actions/start.rb
|
|
165
|
+
- lib/pltt/actions/status.rb
|
|
166
|
+
- lib/pltt/actions/stop.rb
|
|
167
|
+
- lib/pltt/colorize.rb
|
|
168
|
+
- lib/pltt/entry.rb
|
|
169
|
+
- lib/pltt/gitlab_wrapper.rb
|
|
170
|
+
- lib/pltt/runner.rb
|
|
171
|
+
- lib/pltt/version.rb
|
|
172
|
+
- pltt.gemspec
|
|
173
|
+
homepage: ''
|
|
174
|
+
licenses:
|
|
175
|
+
- MIT
|
|
176
|
+
metadata: {}
|
|
177
|
+
post_install_message:
|
|
178
|
+
rdoc_options: []
|
|
179
|
+
require_paths:
|
|
180
|
+
- lib
|
|
181
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
182
|
+
requirements:
|
|
183
|
+
- - ">="
|
|
184
|
+
- !ruby/object:Gem::Version
|
|
185
|
+
version: '0'
|
|
186
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
|
+
requirements:
|
|
188
|
+
- - ">"
|
|
189
|
+
- !ruby/object:Gem::Version
|
|
190
|
+
version: 1.3.1
|
|
191
|
+
requirements: []
|
|
192
|
+
rubyforge_project:
|
|
193
|
+
rubygems_version: 2.7.7
|
|
194
|
+
signing_key:
|
|
195
|
+
specification_version: 4
|
|
196
|
+
summary: ''
|
|
197
|
+
test_files: []
|