git_snip 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -1
- data/README.md +17 -4
- data/Rakefile +2 -1
- data/bin/git-snip +1 -0
- data/lib/git_snip/branch.rb +28 -22
- data/lib/git_snip/cleaner.rb +2 -0
- data/lib/git_snip/cli.rb +21 -36
- data/lib/git_snip/config.rb +2 -0
- data/lib/git_snip/options.rb +24 -0
- data/lib/git_snip/printer.rb +41 -0
- data/lib/git_snip/version.rb +3 -1
- data/lib/git_snip.rb +2 -0
- data/spec/lib/git_snip/branch_spec.rb +2 -1
- data/spec/lib/git_snip/cleaner_spec.rb +2 -0
- data/spec/lib/git_snip/cli_help_spec.rb +2 -0
- data/spec/lib/git_snip/cli_spec.rb +2 -0
- data/spec/lib/git_snip/config_spec.rb +2 -0
- data/spec/lib/git_snip/options_spec.rb +32 -0
- data/spec/lib/git_snip/printer_spec.rb +55 -0
- data/spec/spec_helper.rb +4 -2
- data/spec/support/cli_helper.rb +2 -0
- data/spec/support/cli_runner.rb +3 -1
- data/spec/support/config_shared_context.rb +2 -0
- data/spec/support/repo.rb +2 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1821b121c5779025b31a185db88508692503638a
|
4
|
+
data.tar.gz: 325f84bb5bcf7124fc9ce9b3836885813f5b2f22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85454425cbcfe23ed00f5c40a07e8157be5ec24181b45fe491deb53c6d8a567dbebf1872a4287fc56d2d572759e564dd57de23b5c4171cccf38084553f9339bb
|
7
|
+
data.tar.gz: d337e1dd14cbc59f54e7191f1c3972744bb325d8697d8e1a354e909f3473b226adae03bf6830d80d4e6e849715950cd02140b17a71bd9943abc668c3bd74f031
|
data/.travis.yml
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
+
before_install:
|
2
|
+
- gem update bundler
|
3
|
+
|
1
4
|
before_script:
|
2
5
|
- git config --global user.email "you@example.com"
|
3
6
|
- git config --global user.name "Your Name"
|
4
7
|
|
5
|
-
script: CODECLIMATE_REPO_TOKEN=ea0ada8842b47f59715526e88df53a81afff061152ce67bb73a8baa75443ea43 bundle exec rspec
|
8
|
+
script: CODECLIMATE_REPO_TOKEN=ea0ada8842b47f59715526e88df53a81afff061152ce67bb73a8baa75443ea43 bundle exec rspec && bundle exec codeclimate-test-reporter
|
6
9
|
|
7
10
|
rvm:
|
8
|
-
- 2.0.0
|
9
11
|
- 2.1.0
|
10
12
|
- 2.2.0
|
11
|
-
-
|
13
|
+
- 2.3.0
|
14
|
+
- 2.4.0
|
12
15
|
- ruby-head
|
13
16
|
|
14
17
|
cache: bundler
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -12,6 +12,8 @@ deleted and will build up, making it harder to find your relevant branches.
|
|
12
12
|
This gem aims to fix that by doing using [`git cherry`][git-cherry] to find
|
13
13
|
local branches which have been merged and delete them.
|
14
14
|
|
15
|
+
[![asciicast](https://asciinema.org/a/32614.png)](https://asciinema.org/a/32614)
|
16
|
+
|
15
17
|
## Installation
|
16
18
|
|
17
19
|
Install using RubyGems:
|
@@ -30,6 +32,21 @@ And then execute:
|
|
30
32
|
|
31
33
|
## Usage
|
32
34
|
|
35
|
+
You can list the available options from command line:
|
36
|
+
|
37
|
+
$ git snip help
|
38
|
+
Usage:
|
39
|
+
git-snip
|
40
|
+
Options:
|
41
|
+
-f, [--force] # Will refuse to run unless given -f or -n.
|
42
|
+
-n, [--dry-run], [--no-dry-run] # Show branches which would be deleted.
|
43
|
+
[--repo=<path>] # Path to git repository.
|
44
|
+
# Default: .
|
45
|
+
[--target=<branch>] # Branch to compare equivalence against.
|
46
|
+
# Default: master
|
47
|
+
[--ignore=one two three] # List of branches to ignore.
|
48
|
+
[--full], [--no-full] # Show most branch information without cropping.
|
49
|
+
|
33
50
|
Show branches which would be deleted (accepts the same arguments as `-f`):
|
34
51
|
|
35
52
|
$ git snip -n
|
@@ -55,10 +72,6 @@ Delete branches already merged to `branch_a`:
|
|
55
72
|
|
56
73
|
$ git snip -f --target=branch_a
|
57
74
|
|
58
|
-
You can also list the available options from command line:
|
59
|
-
|
60
|
-
$ git snip help
|
61
|
-
|
62
75
|
## Config file
|
63
76
|
|
64
77
|
If you want some arguments to always be set, add a file to the root of the
|
data/Rakefile
CHANGED
data/bin/git-snip
CHANGED
data/lib/git_snip/branch.rb
CHANGED
@@ -1,35 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
|
1
5
|
module GitSnip
|
2
6
|
module Branch
|
3
7
|
Row = Struct.new(:sha, :name, :date, :author, :message)
|
4
8
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
class << self
|
10
|
+
def row(branch)
|
11
|
+
Row.new.tap do |row|
|
12
|
+
row.sha = column(branch.gcommit.sha, 7)
|
13
|
+
row.name = column(branch.name, 12)
|
14
|
+
row.date = column(branch.gcommit.date.strftime('%F'), 10)
|
15
|
+
row.author = column(branch.gcommit.author.email.sub(/@.*/, ''), 8)
|
16
|
+
row.message = column(first_line(branch.gcommit.message), 39)
|
17
|
+
end
|
12
18
|
end
|
13
|
-
end
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def full_row(branch)
|
21
|
+
Row.new.tap do |row|
|
22
|
+
row.sha = branch.gcommit.sha
|
23
|
+
row.name = branch.name
|
24
|
+
row.date = branch.gcommit.date.iso8601
|
25
|
+
row.author = branch.gcommit.author.email
|
26
|
+
row.message = first_line(branch.gcommit.message)
|
27
|
+
end
|
22
28
|
end
|
23
|
-
end
|
24
29
|
|
25
|
-
|
30
|
+
private
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
def column(string, width)
|
33
|
+
string[0, width].ljust(width)
|
34
|
+
end
|
30
35
|
|
31
|
-
|
32
|
-
|
36
|
+
def first_line(string)
|
37
|
+
string.gsub(/[\r\n].*/, '')
|
38
|
+
end
|
33
39
|
end
|
34
40
|
end
|
35
41
|
end
|
data/lib/git_snip/cleaner.rb
CHANGED
data/lib/git_snip/cli.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thor'
|
2
4
|
require 'git_snip/cleaner'
|
3
5
|
require 'git_snip/branch'
|
4
6
|
require 'git_snip/config'
|
7
|
+
require 'git_snip/printer'
|
8
|
+
require 'git_snip/options'
|
5
9
|
|
6
10
|
module GitSnip
|
7
11
|
class CLI < Thor
|
@@ -17,7 +21,7 @@ module GitSnip
|
|
17
21
|
desc: 'Will refuse to run unless given -f or -n.'
|
18
22
|
|
19
23
|
option :dry_run, type: :boolean, aliases: '-n',
|
20
|
-
desc:
|
24
|
+
desc: 'Show branches which would be deleted.'
|
21
25
|
|
22
26
|
option :repo, default: '.', banner: '<path>',
|
23
27
|
desc: 'Path to git repository.'
|
@@ -38,23 +42,23 @@ module GitSnip
|
|
38
42
|
end
|
39
43
|
|
40
44
|
if !opts[:force]
|
41
|
-
|
45
|
+
printer.force_option_needed
|
42
46
|
exit 64
|
43
47
|
end
|
44
48
|
|
45
49
|
cleaner = GitSnip::Cleaner.new(*cleaner_args)
|
46
50
|
|
47
|
-
|
51
|
+
printer.deleting_branches
|
48
52
|
|
49
53
|
deleted_branches = cleaner.delete_merged_branches do |branch|
|
50
|
-
|
54
|
+
printer.branch_info(branch_row(branch))
|
51
55
|
true
|
52
56
|
end
|
53
57
|
|
54
58
|
if deleted_branches.empty?
|
55
|
-
|
59
|
+
printer.no_branches_deleted
|
56
60
|
else
|
57
|
-
|
61
|
+
printer.done
|
58
62
|
end
|
59
63
|
end
|
60
64
|
default_task :snip
|
@@ -64,54 +68,35 @@ module GitSnip
|
|
64
68
|
def dry_run
|
65
69
|
cleaner = GitSnip::Cleaner.new(*cleaner_args)
|
66
70
|
|
67
|
-
|
71
|
+
printer.will_delete_branches
|
68
72
|
|
69
73
|
merged_branches = cleaner.merged_branches
|
70
74
|
|
71
75
|
merged_branches.each do |branch|
|
72
|
-
|
76
|
+
printer.branch_info(branch_row(branch))
|
73
77
|
end
|
74
78
|
|
75
79
|
if merged_branches.any?
|
76
|
-
|
80
|
+
printer.done
|
77
81
|
else
|
78
|
-
|
82
|
+
printer.no_branches_to_delete
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
def say_branch_info(branch, full = false)
|
83
|
-
row = opts[:full] ? Branch.full_row(branch) : Branch.row(branch)
|
84
|
-
|
85
|
-
say row.sha + ' ', :yellow
|
86
|
-
say row.name + ' ', :magenta
|
87
|
-
say row.date + ' ', :green
|
88
|
-
say row.author + ' ', [:blue, :bold]
|
89
|
-
say row.message.strip + "\n"
|
90
|
-
end
|
91
|
-
|
92
86
|
def cleaner_args
|
93
87
|
opts.values_at(:repo, :target, :ignore)
|
94
88
|
end
|
95
89
|
|
96
90
|
def opts
|
97
|
-
@opts ||=
|
98
|
-
|
99
|
-
|
100
|
-
options_dup = options.dup
|
101
|
-
|
102
|
-
options_dup.each_pair do |k, v|
|
103
|
-
if v.is_a?(Array) && v.empty?
|
104
|
-
config_value = config.options[k]
|
91
|
+
@opts ||= Options.merge(options, Config.new(options[:repo]).options)
|
92
|
+
end
|
105
93
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
end
|
94
|
+
def printer
|
95
|
+
@printer ||= Printer.new(self)
|
96
|
+
end
|
111
97
|
|
112
|
-
|
113
|
-
|
114
|
-
end
|
98
|
+
def branch_row(branch)
|
99
|
+
opts[:full] ? Branch.full_row(branch) : Branch.row(branch)
|
115
100
|
end
|
116
101
|
end
|
117
102
|
end
|
data/lib/git_snip/config.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module GitSnip
|
6
|
+
module Options
|
7
|
+
def self.merge(primary = {}, secondary = {})
|
8
|
+
primary = primary.dup
|
9
|
+
|
10
|
+
primary.each_pair do |k, v|
|
11
|
+
if v.is_a?(Array) && v.empty?
|
12
|
+
secondary_value = secondary[k]
|
13
|
+
|
14
|
+
if secondary_value.is_a?(Array) && secondary_value.any?
|
15
|
+
primary[k] = secondary_value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Thor::CoreExt::HashWithIndifferentAccess.new(
|
21
|
+
secondary.merge(primary)).freeze
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GitSnip
|
4
|
+
class Printer
|
5
|
+
def initialize(cli)
|
6
|
+
@cli = cli
|
7
|
+
end
|
8
|
+
|
9
|
+
def force_option_needed
|
10
|
+
@cli.say '-f option is needed to delete branches.', :red
|
11
|
+
end
|
12
|
+
|
13
|
+
def deleting_branches
|
14
|
+
@cli.say "Deleting the following branches...\n\n", :green
|
15
|
+
end
|
16
|
+
|
17
|
+
def no_branches_deleted
|
18
|
+
@cli.say 'No branches were deleted.', :green
|
19
|
+
end
|
20
|
+
|
21
|
+
def will_delete_branches
|
22
|
+
@cli.say "Would delete the following branches...\n\n", :green
|
23
|
+
end
|
24
|
+
|
25
|
+
def no_branches_to_delete
|
26
|
+
@cli.say 'No branches would be deleted.', :green
|
27
|
+
end
|
28
|
+
|
29
|
+
def done
|
30
|
+
@cli.say "\nDone.", :green
|
31
|
+
end
|
32
|
+
|
33
|
+
def branch_info(row)
|
34
|
+
@cli.say row.sha + ' ', :yellow
|
35
|
+
@cli.say row.name + ' ', :magenta
|
36
|
+
@cli.say row.date + ' ', :green
|
37
|
+
@cli.say row.author + ' ', [:blue, :bold]
|
38
|
+
@cli.say row.message.strip + "\n"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/git_snip/version.rb
CHANGED
data/lib/git_snip.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'git_snip/options'
|
4
|
+
|
5
|
+
RSpec.describe GitSnip::Options do
|
6
|
+
describe '#merge' do
|
7
|
+
it 'should return HashWithIndifferentAccess' do
|
8
|
+
expect(described_class.merge)
|
9
|
+
.to be_a(Thor::CoreExt::HashWithIndifferentAccess)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should return a frozen object' do
|
13
|
+
expect(described_class.merge).to be_frozen
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should prioritize primary' do
|
17
|
+
expect(described_class.merge({ a: 1 }, { a: 2 })).to eq('a' => 1)
|
18
|
+
end
|
19
|
+
|
20
|
+
specify 'false on primary should override true on secondary' do
|
21
|
+
expect(described_class.merge({ a: false }, { a: true })).to eq('a' => false)
|
22
|
+
end
|
23
|
+
|
24
|
+
specify 'empty array on secondary should not override' do
|
25
|
+
expect(described_class.merge({ a: [1] }, { a: [] })).to eq('a' => [1])
|
26
|
+
end
|
27
|
+
|
28
|
+
specify 'empty array on primary should be overridden' do
|
29
|
+
expect(described_class.merge({ a: [] }, { a: [2] })).to eq('a' => [2])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'git_snip/printer'
|
4
|
+
|
5
|
+
RSpec.describe GitSnip::Printer do
|
6
|
+
[
|
7
|
+
[:force_option_needed, '-f option is needed to delete branches.', :red],
|
8
|
+
[:deleting_branches, "Deleting the following branches...\n\n", :green],
|
9
|
+
[:no_branches_deleted, 'No branches were deleted.', :green],
|
10
|
+
[:will_delete_branches, "Would delete the following branches...\n\n", :green],
|
11
|
+
[:no_branches_to_delete, 'No branches would be deleted.', :green],
|
12
|
+
[:done, "\nDone.", :green]
|
13
|
+
].each do |method, text, color|
|
14
|
+
describe "##{method}" do
|
15
|
+
let(:sayer) { spy('sayer') }
|
16
|
+
let(:printer) { described_class.new(sayer) }
|
17
|
+
|
18
|
+
it "should print #{text.inspect} in #{color}" do
|
19
|
+
printer.send(method)
|
20
|
+
expect(sayer).to have_received(:say).with(text, color)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#branch_info' do
|
26
|
+
let(:sayer) { spy('sayer') }
|
27
|
+
let(:printer) { described_class.new(sayer) }
|
28
|
+
|
29
|
+
it 'should print a row of branch info' do
|
30
|
+
printer.branch_info(row_double)
|
31
|
+
|
32
|
+
expect(sayer).to have_received(:say).with('sha ', :yellow).ordered
|
33
|
+
expect(sayer).to have_received(:say).with('name ', :magenta).ordered
|
34
|
+
expect(sayer).to have_received(:say).with('date ', :green).ordered
|
35
|
+
expect(sayer).to have_received(:say).with('author ', [:blue, :bold]).ordered
|
36
|
+
expect(sayer).to have_received(:say).with("hello world\n").ordered
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should strip the last row and append new line' do
|
40
|
+
printer.branch_info(row_double(message: " hello world \n\n\n"))
|
41
|
+
|
42
|
+
expect(sayer).to have_received(:say).with("hello world\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
def row_double(attrs = {})
|
46
|
+
instance_double('GitSnip::Branch::Row', {
|
47
|
+
sha: 'sha',
|
48
|
+
name: 'name',
|
49
|
+
date: 'date',
|
50
|
+
author: 'author',
|
51
|
+
message: 'hello world'
|
52
|
+
}.merge(attrs))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/cli_helper.rb
CHANGED
data/spec/support/cli_runner.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'git_snip/cli'
|
2
4
|
|
3
5
|
# https://github.com/erikhuda/thor/wiki/Integrating-with-Aruba-In-Process-Runs
|
@@ -28,7 +30,7 @@ module GitSnip
|
|
28
30
|
# of an unhandled exception.
|
29
31
|
b = e.backtrace
|
30
32
|
@stderr.puts("#{b.shift}: #{e.message} (#{e.class})")
|
31
|
-
@stderr.puts(b.map{|s| "\tfrom #{s}"}.join("\n"))
|
33
|
+
@stderr.puts(b.map { |s| "\tfrom #{s}" }.join("\n"))
|
32
34
|
1
|
33
35
|
rescue SystemExit => e
|
34
36
|
e.status
|
data/spec/support/repo.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git_snip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hendy Tanata
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git
|
@@ -103,12 +103,16 @@ files:
|
|
103
103
|
- lib/git_snip/cleaner.rb
|
104
104
|
- lib/git_snip/cli.rb
|
105
105
|
- lib/git_snip/config.rb
|
106
|
+
- lib/git_snip/options.rb
|
107
|
+
- lib/git_snip/printer.rb
|
106
108
|
- lib/git_snip/version.rb
|
107
109
|
- spec/lib/git_snip/branch_spec.rb
|
108
110
|
- spec/lib/git_snip/cleaner_spec.rb
|
109
111
|
- spec/lib/git_snip/cli_help_spec.rb
|
110
112
|
- spec/lib/git_snip/cli_spec.rb
|
111
113
|
- spec/lib/git_snip/config_spec.rb
|
114
|
+
- spec/lib/git_snip/options_spec.rb
|
115
|
+
- spec/lib/git_snip/printer_spec.rb
|
112
116
|
- spec/spec_helper.rb
|
113
117
|
- spec/support/cli_helper.rb
|
114
118
|
- spec/support/cli_runner.rb
|
@@ -134,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
138
|
version: '0'
|
135
139
|
requirements: []
|
136
140
|
rubyforge_project:
|
137
|
-
rubygems_version: 2.
|
141
|
+
rubygems_version: 2.6.13
|
138
142
|
signing_key:
|
139
143
|
specification_version: 4
|
140
144
|
summary: Clean obsolete branches on your local git repository safely
|
@@ -144,6 +148,8 @@ test_files:
|
|
144
148
|
- spec/lib/git_snip/cli_help_spec.rb
|
145
149
|
- spec/lib/git_snip/cli_spec.rb
|
146
150
|
- spec/lib/git_snip/config_spec.rb
|
151
|
+
- spec/lib/git_snip/options_spec.rb
|
152
|
+
- spec/lib/git_snip/printer_spec.rb
|
147
153
|
- spec/spec_helper.rb
|
148
154
|
- spec/support/cli_helper.rb
|
149
155
|
- spec/support/cli_runner.rb
|