git-status-tree 3.0.0 → 3.1.0
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 +4 -4
- data/ext/git_tree/extconf.rb +1 -1
- data/lib/node.rb +63 -22
- data/lib/nodes_collection.rb +4 -15
- data/lib/version.rb +0 -1
- data/src/git_status_tree.rb +3 -4
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2eaa4e24f5f6fed7c2340c5a4ae93e1cf51247be86881d043688755dc4796e76
|
4
|
+
data.tar.gz: 6b7916c3a0d9ca337884e336c3eb47a021bde591fc2287bf08048bd3e61855a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3bac80ae5b85406a6ba49dd584af3c7afa92ccbfa3c29b38206f00d7852aa3df60efe2e3ff8291d73af62a64bf8eaa0692f2a5cc8c91eb96317cd4902cd0e02
|
7
|
+
data.tar.gz: ebf4bfae6b713928c5fb6ef8b3d61459ee27398701346a13546dad8f62222c42b791c3ff22ae187a6b7865fba734ac7e3e0437ead298e43c96bc3fed531e4ad5
|
data/ext/git_tree/extconf.rb
CHANGED
@@ -8,7 +8,7 @@ find_executable('make')
|
|
8
8
|
|
9
9
|
# Trick Rubygems into thinking the generated Makefile was executed
|
10
10
|
compile = File.join(Dir.pwd, "git_tree.#{RbConfig::CONFIG['DLEXT']}")
|
11
|
-
File.
|
11
|
+
File.write(compile, '')
|
12
12
|
|
13
13
|
# Install "git tree"
|
14
14
|
puts `../../bin/git_add_alias_tree`
|
data/lib/node.rb
CHANGED
@@ -5,7 +5,7 @@ class NodeChildrenError < StandardError; end
|
|
5
5
|
class NodeTypeError < StandardError; end
|
6
6
|
|
7
7
|
# A Node represents a file or directory in the git-status-tree
|
8
|
-
class Node
|
8
|
+
class Node
|
9
9
|
class << self
|
10
10
|
attr_accessor :indent
|
11
11
|
end
|
@@ -39,6 +39,62 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
39
39
|
|
40
40
|
def self.node_from_gs(gs_porcelain)
|
41
41
|
status = status(gs_porcelain)
|
42
|
+
|
43
|
+
# Handle renamed files specially
|
44
|
+
if status.include?('R')
|
45
|
+
node_from_renamed_file(gs_porcelain, status)
|
46
|
+
else
|
47
|
+
# Original logic for non-renamed files
|
48
|
+
node_from_regular_file(gs_porcelain, status)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.node_from_renamed_file(gs_porcelain, status)
|
53
|
+
paths_part = gs_porcelain[3..]
|
54
|
+
return node_from_regular_file(gs_porcelain, status) unless paths_part.include?(' -> ')
|
55
|
+
|
56
|
+
old_path, new_path = paths_part.split(' -> ')
|
57
|
+
old_dir = File.dirname(old_path)
|
58
|
+
|
59
|
+
rename_display = build_rename_display(old_path, new_path)
|
60
|
+
|
61
|
+
build_node_structure(old_dir, rename_display, status)
|
62
|
+
end
|
63
|
+
|
64
|
+
private_class_method :node_from_renamed_file
|
65
|
+
|
66
|
+
def self.build_rename_display(old_path, new_path)
|
67
|
+
old_dir = File.dirname(old_path)
|
68
|
+
new_dir = File.dirname(new_path)
|
69
|
+
old_filename = File.basename(old_path)
|
70
|
+
new_filename = File.basename(new_path)
|
71
|
+
|
72
|
+
if old_dir == new_dir
|
73
|
+
"#{old_filename} -> #{new_filename}"
|
74
|
+
else
|
75
|
+
"#{old_filename} -> #{new_path}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
private_class_method :build_rename_display
|
79
|
+
|
80
|
+
def self.build_node_structure(dir_path, leaf_name, status)
|
81
|
+
if dir_path == '.'
|
82
|
+
# File is in root directory
|
83
|
+
new(leaf_name, nil, status)
|
84
|
+
else
|
85
|
+
# File is in subdirectory
|
86
|
+
ary_nodes = "./#{dir_path}".split(%r{/})
|
87
|
+
|
88
|
+
name = ary_nodes.shift
|
89
|
+
# Add the leaf_name as the last element
|
90
|
+
ary_nodes << leaf_name
|
91
|
+
children = NodesCollection.create_from_array(ary_nodes, status)
|
92
|
+
new(name, children)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
private_class_method :build_node_structure
|
96
|
+
|
97
|
+
def self.node_from_regular_file(gs_porcelain, status)
|
42
98
|
ary_nodes = "./#{gs_porcelain[3..]}".split(%r{/})
|
43
99
|
|
44
100
|
name = ary_nodes.shift
|
@@ -49,6 +105,7 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
49
105
|
new(name, nil, status)
|
50
106
|
end
|
51
107
|
end
|
108
|
+
private_class_method :node_from_regular_file
|
52
109
|
|
53
110
|
private_class_method :node_from_gs
|
54
111
|
|
@@ -76,13 +133,9 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
76
133
|
end
|
77
134
|
|
78
135
|
def valid?
|
79
|
-
|
80
|
-
return valid_file? if file?
|
81
|
-
|
82
|
-
false
|
136
|
+
file? ? valid_file? : valid_dir?
|
83
137
|
end
|
84
138
|
|
85
|
-
# @return [NodesCollection]
|
86
139
|
def +(other)
|
87
140
|
raise 'not valid' unless valid? && other.valid?
|
88
141
|
raise "not a #{self.class}" unless other.is_a?(self.class)
|
@@ -94,10 +147,8 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
94
147
|
|
95
148
|
def <=>(other)
|
96
149
|
return (name <=> other.name) if file? == other.file?
|
97
|
-
return -1 if dir? && other.file?
|
98
|
-
return 1 if file? && other.dir?
|
99
150
|
|
100
|
-
|
151
|
+
dir? && other.file? ? -1 : 1
|
101
152
|
end
|
102
153
|
|
103
154
|
def to_tree_s(depth = 0, open_parents = [0], last: true)
|
@@ -111,42 +162,34 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
111
162
|
str_tree
|
112
163
|
end
|
113
164
|
|
114
|
-
# 'M' modified
|
115
165
|
def modified?
|
116
166
|
status.include?('M')
|
117
167
|
end
|
118
168
|
|
119
|
-
# 'A' added
|
120
169
|
def added?
|
121
170
|
status.include?('A')
|
122
171
|
end
|
123
172
|
|
124
|
-
# 'D' deleted
|
125
173
|
def deleted?
|
126
174
|
status.include?('D')
|
127
175
|
end
|
128
176
|
|
129
|
-
# 'R' renamed
|
130
177
|
def renamed?
|
131
178
|
status.include?('R')
|
132
179
|
end
|
133
180
|
|
134
|
-
# 'C' copied
|
135
181
|
def copied?
|
136
182
|
status.include?('C')
|
137
183
|
end
|
138
184
|
|
139
|
-
# 'U' updated but unmerged
|
140
185
|
def unmerged?
|
141
186
|
status.include?('U')
|
142
187
|
end
|
143
188
|
|
144
|
-
# '?' new
|
145
189
|
def new?
|
146
190
|
status.include?('?')
|
147
191
|
end
|
148
192
|
|
149
|
-
# '+' staged
|
150
193
|
def staged?
|
151
194
|
status.include?('+')
|
152
195
|
end
|
@@ -161,7 +204,8 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
161
204
|
raise NodeNameError, msg if name.empty?
|
162
205
|
|
163
206
|
msg = '"name" must not contain "/", use create_from_string.'
|
164
|
-
|
207
|
+
# Allow forward slashes in rename displays (containing " -> ")
|
208
|
+
raise NodeNameError, msg if name =~ %r{/} && !name.include?(' -> ')
|
165
209
|
end
|
166
210
|
|
167
211
|
def color_name
|
@@ -176,21 +220,18 @@ class Node # rubocop:disable Metrics/ClassLength
|
|
176
220
|
color_name + BashColor::NONE
|
177
221
|
end
|
178
222
|
|
179
|
-
# Has a valid name?
|
180
223
|
def name_valid?
|
181
224
|
name.is_a?(String) &&
|
182
225
|
name.length.positive? &&
|
183
|
-
name.match(%r{/}).nil?
|
226
|
+
(name.match(%r{/}).nil? || name.include?(' -> '))
|
184
227
|
end
|
185
228
|
|
186
|
-
# Is a valid dir?
|
187
229
|
def valid_dir?
|
188
230
|
name_valid? &&
|
189
231
|
children.is_a?(NodesCollection) &&
|
190
232
|
children.valid?
|
191
233
|
end
|
192
234
|
|
193
|
-
# Is a valid file?
|
194
235
|
def valid_file?
|
195
236
|
name_valid? &&
|
196
237
|
children.nil?
|
data/lib/nodes_collection.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# error class for invalid NodeCollection types
|
4
3
|
class NodesCollectionTypeError < StandardError
|
5
4
|
end
|
6
5
|
|
7
|
-
# collection of
|
8
|
-
class NodesCollection
|
6
|
+
# A collection of Node objects representing a git status tree structure
|
7
|
+
class NodesCollection
|
9
8
|
attr_accessor :nodes
|
10
9
|
|
11
10
|
def self.create_from_string(str_nodes, status = ' ')
|
@@ -73,7 +72,6 @@ class NodesCollection # rubocop:disable Metrics/ClassLength
|
|
73
72
|
@nodes = nodes
|
74
73
|
end
|
75
74
|
|
76
|
-
# @return [NodesCollection]
|
77
75
|
def +(other)
|
78
76
|
raise 'not a Node or NodesCollection' unless other.is_a?(Node) || other.is_a?(self.class)
|
79
77
|
|
@@ -85,12 +83,10 @@ class NodesCollection # rubocop:disable Metrics/ClassLength
|
|
85
83
|
self.class.new(dir_nodes + file_nodes)
|
86
84
|
end
|
87
85
|
|
88
|
-
# @return [Integer]
|
89
86
|
def <=>(other)
|
90
87
|
to_primitive <=> other.to_primitive
|
91
88
|
end
|
92
89
|
|
93
|
-
# @return [Array<Node>]
|
94
90
|
def nodes_not_in(other)
|
95
91
|
self_names = nodes.map(&:name)
|
96
92
|
other_names = other.nodes.map(&:name)
|
@@ -100,7 +96,6 @@ class NodesCollection # rubocop:disable Metrics/ClassLength
|
|
100
96
|
nodes.select { |node| self_only_names.include?(node.name) }
|
101
97
|
end
|
102
98
|
|
103
|
-
# @return [Array<Node>]
|
104
99
|
def merge_common_nodes_with(other)
|
105
100
|
self_names = nodes.map(&:name)
|
106
101
|
other_names = other.nodes.map(&:name)
|
@@ -113,16 +108,10 @@ class NodesCollection # rubocop:disable Metrics/ClassLength
|
|
113
108
|
end
|
114
109
|
end
|
115
110
|
|
116
|
-
# @return [Array<Node>]
|
117
111
|
def merge_nodes_with(other)
|
118
|
-
|
119
|
-
when Node
|
120
|
-
nodes_merged = merge_nodes_with_node(other)
|
121
|
-
when NodesCollection
|
122
|
-
nodes_merged = merge_nodes_with_collection(other)
|
123
|
-
end
|
112
|
+
return merge_nodes_with_node(other) if other.is_a?(Node)
|
124
113
|
|
125
|
-
|
114
|
+
merge_nodes_with_collection(other)
|
126
115
|
end
|
127
116
|
|
128
117
|
def files
|
data/lib/version.rb
CHANGED
data/src/git_status_tree.rb
CHANGED
@@ -3,16 +3,15 @@
|
|
3
3
|
require File.join File.dirname(__FILE__), '../lib/node'
|
4
4
|
require File.join File.dirname(__FILE__), '../lib/nodes_collection'
|
5
5
|
require File.join File.dirname(__FILE__), '../lib/bash_color'
|
6
|
-
require File.join File.dirname(__FILE__), '../
|
6
|
+
require File.join File.dirname(__FILE__), '../lib/version'
|
7
7
|
|
8
|
-
#
|
9
|
-
# use GitStatusTree.new.to_s to print the current git-status-tree
|
8
|
+
# Main class for generating and displaying git status as a tree structure
|
10
9
|
class GitStatusTree
|
11
10
|
attr_reader :files, :nodes, :tree
|
12
11
|
|
13
12
|
def initialize(options = {})
|
14
13
|
Node.indent = indent(options)
|
15
|
-
@files = `git status --porcelain`.split(
|
14
|
+
@files = `git status --porcelain`.split("\n")
|
16
15
|
@nodes = files.map { |file| Node.create_from_string file }
|
17
16
|
@tree = nodes.reduce { |a, i| (a + i).nodes[0] }
|
18
17
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-status-tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wolfgang Teuber
|
@@ -29,12 +29,13 @@ files:
|
|
29
29
|
- lib/rubygems_plugin.rb
|
30
30
|
- lib/version.rb
|
31
31
|
- src/git_status_tree.rb
|
32
|
-
homepage: https://github.com/
|
32
|
+
homepage: https://github.com/wteuber/git-status-tree
|
33
33
|
licenses:
|
34
34
|
- MIT
|
35
35
|
- GPL-2.0
|
36
36
|
metadata:
|
37
|
-
source_code_uri: https://github.com/
|
37
|
+
source_code_uri: https://github.com/wteuber/git-status-tree
|
38
|
+
rubygems_mfa_required: 'true'
|
38
39
|
rdoc_options: []
|
39
40
|
require_paths:
|
40
41
|
- lib
|