git-status-tree 3.0.0 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 261d0c82a5a74d301f58b8524456d4c2fbe29feac0f120e459f2ebd154a0ca57
4
- data.tar.gz: dbe0de28748947459d8a6d1be0a535f69c7c72abb445565a4d05d667d99925dd
3
+ metadata.gz: d8090f4d4d90afb6b0fedbb5ca793aac7badc80bac59f30c580cc89804822124
4
+ data.tar.gz: 505b37d46f5ad80c3cad0deb34c67bc8deaf70e188ab90b8023c74f92fee9636
5
5
  SHA512:
6
- metadata.gz: f0283802e22db622c566a797487849add4b5d08d607e8bed7bdc406be7da782f353a464894e0b45f62434c78d314785e98e674cb0bbc56b3dba3087250ce200e
7
- data.tar.gz: 1282ceceb1e13cfacec5292c9c705b4c2ad2981559bf705b6dc3d1513987b2d54c8a4c3d85142df870c245ebedd290f69c2ca7a1f9dfe07a63754cbe1eaf05af
6
+ metadata.gz: 909be6e6800f62f52803e865426b276511f9e17b252dcae4c0d2326e9ecc752e5f05f9c53a3e7b4bf61debc0dd3eaa06e59def4014ac55e6f5edca498839b8fb
7
+ data.tar.gz: ecf289d4983dd92adac996462ed60cd8e31053c53475690df3908633fd5a430ce6baf1e636362807e36711c86aef0795c04bf7793d69b91a0bfcd1f7c39b8a0d
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 3.2.0
data/bin/git-status-tree CHANGED
@@ -5,9 +5,15 @@ require 'optparse'
5
5
  require File.join File.dirname(__FILE__), '../src/git_status_tree'
6
6
  require File.join File.dirname(__FILE__), '../lib/version'
7
7
 
8
+ options = {}
9
+
8
10
  parser = OptionParser.new do |opts|
9
11
  opts.banner = 'Usage: git-status-tree [options]'
10
12
 
13
+ opts.on('-i', '--indent INDENT', Integer, 'Set indentation (2-10 spaces)') do |indent|
14
+ options[:indent] = indent
15
+ end
16
+
11
17
  opts.on('-v', '--version', 'Show version') do
12
18
  puts "git-status-tree #{GitStatusTree::VERSION}"
13
19
  exit 0
@@ -27,4 +33,4 @@ rescue OptionParser::InvalidOption => e
27
33
  exit 1
28
34
  end
29
35
 
30
- puts GitStatusTree.new
36
+ puts GitStatusTree.new(options)
@@ -5,7 +5,7 @@ BIN_DIR=`pwd`
5
5
  popd > /dev/null
6
6
 
7
7
  git config --global status-tree.indent 4
8
- git config --global alias.tree "!sh -c \"$BIN_DIR/git-status-tree\""
8
+ git config --global alias.tree "!sh -c \"$BIN_DIR/git-status-tree \\\"\\\$@\\\"\" --"
9
9
  echo '#############################'
10
10
  echo '# "git tree" has been added #'
11
11
  echo '# Run: git tree #'
@@ -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.open(compile, 'w') {}
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 # rubocop:disable Metrics/ClassLength
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
- return valid_dir? if dir?
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
- 0
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
- raise NodeNameError, msg if name =~ %r{/}
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?
@@ -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 nodes
8
- class NodesCollection # rubocop:disable Metrics/ClassLength
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
- case other
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
- nodes_merged
114
+ merge_nodes_with_collection(other)
126
115
  end
127
116
 
128
117
  def files
data/lib/version.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Version information for git-status-tree
4
3
  class GitStatusTree
5
4
  VERSION_FILE = File.expand_path('../VERSION', __dir__)
6
5
  VERSION = File.exist?(VERSION_FILE) ? File.read(VERSION_FILE).strip : 'unknown'
@@ -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__), '../src/git_status_tree'
6
+ require File.join File.dirname(__FILE__), '../lib/version'
7
7
 
8
- # GitStatusTree
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(/\n/)
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.0.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wolfgang Teuber
@@ -18,6 +18,7 @@ extensions:
18
18
  - ext/git_tree/extconf.rb
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - VERSION
21
22
  - bin/git-status-tree
22
23
  - bin/git_add_alias_tree
23
24
  - bin/git_remove_alias_tree
@@ -29,12 +30,13 @@ files:
29
30
  - lib/rubygems_plugin.rb
30
31
  - lib/version.rb
31
32
  - src/git_status_tree.rb
32
- homepage: https://github.com/knugie/git-status-tree
33
+ homepage: https://github.com/wteuber/git-status-tree
33
34
  licenses:
34
35
  - MIT
35
36
  - GPL-2.0
36
37
  metadata:
37
- source_code_uri: https://github.com/knugie/git-status-tree
38
+ source_code_uri: https://github.com/wteuber/git-status-tree
39
+ rubygems_mfa_required: 'true'
38
40
  rdoc_options: []
39
41
  require_paths:
40
42
  - lib