gitXplorer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,219 @@
1
+ require "hilighter"
2
+ require "scoobydoo"
3
+
4
+ class GitXplorer
5
+ def absolute_path(path = nil)
6
+ path ||= ""
7
+ return "#{@cwd.join("/")}#{"/" if (!@cwd.empty?)}#{path}"
8
+ end
9
+ private :absolute_path
10
+
11
+ def cd(path = nil)
12
+ path ||= ""
13
+
14
+ # No path means go to top-level
15
+ @cwd.clear if (path.empty?)
16
+
17
+ target = @tree.get(absolute_path(path))
18
+ if (target.nil?)
19
+ raise GitXplorer::Error::NoFileOrDirectory.new(path)
20
+ elsif (!target.is_a?(GitXplorer::GitObject::Directory))
21
+ raise GitXplorer::Error::NotDirectory.new(path)
22
+ end
23
+
24
+ path.split("/"). each do |dir|
25
+ case dir
26
+ when "."
27
+ # Do nothing
28
+ when ".."
29
+ @cwd.delete_at(-1)
30
+ else
31
+ @cwd.push(dir)
32
+ end
33
+ end
34
+
35
+ # Return the target
36
+ return target
37
+ end
38
+
39
+ def exist?(path)
40
+ return @tree.exist?(absolute_path(path))
41
+ end
42
+
43
+ def get_completions(input)
44
+ return @tree.get_completions(absolute_path(input))
45
+ end
46
+
47
+ def get_filenames(dir = "", pattern = ".")
48
+ dir ||= ""
49
+ pattern ||= "."
50
+
51
+ found = %x(
52
+ git log --diff-filter=ACR --name-only --pretty=tformat: \
53
+ -- #{dir}
54
+ ).split("\n").map do |file|
55
+ file.gsub(/^#{dir}/, "")
56
+ end.select do |file|
57
+ file.match(/#{pattern}/)
58
+ end
59
+
60
+ return found
61
+ end
62
+
63
+ def git(args, refresh = true)
64
+ if (args.match(/.*;.*/))
65
+ raise GitXplorer::Error::NoSemicolonsAllowed.new
66
+ end
67
+
68
+ if (args.match(/(\$|<)\(.+\)/))
69
+ raise GitXplorer::Error::NoSubshellsAllowed.new
70
+ end
71
+
72
+ if (args.match(/\&\&|\|\|/))
73
+ raise GitXplorer::Error::NoChainingAllowed.new
74
+ end
75
+
76
+ out = %x(git #{args})
77
+ refresh = true if (refresh.nil?)
78
+ @tree = refresh_tree if (refresh)
79
+ return out
80
+ end
81
+
82
+ def initialize
83
+ @cwd = Array.new
84
+ @repo = %x(git rev-parse --show-toplevel).split("/")[-1].strip
85
+ @tree = refresh_tree
86
+ end
87
+
88
+ def ls(path = nil)
89
+ path = absolute_path(path)
90
+
91
+ # Get target directory if it exists
92
+ target = @tree.get(path)
93
+ if (target.nil?)
94
+ raise GitXplorer::Error::NoFileOrDirectory.new(path)
95
+ end
96
+
97
+ return target.children
98
+ end
99
+
100
+ def pwd
101
+ # Return repo name if at top-level
102
+ return @repo if (@cwd.empty?)
103
+
104
+ # Return repo name followed by CWD
105
+ return "#{@repo}/#{@cwd.join("/")}#{"/" if (!@cwd.empty?)}"
106
+ end
107
+
108
+ def pwd_short
109
+ # Return repo name if at top-level
110
+ return @repo if (@cwd.empty?)
111
+
112
+ # Return only the last 3 directories if more than 3 deep
113
+ return @cwd[-3..-1].join("/") if (@cwd.length >= 3)
114
+
115
+ # Return repo name followed by CWD
116
+ return "#{@repo}/#{@cwd.join("/")}#{"/" if (!@cwd.empty?)}"
117
+ end
118
+
119
+ def refresh_tree
120
+ # Create tree root
121
+ tree = GitXplorer::GitObject::Directory.new("/", nil)
122
+
123
+ # Add files to tree
124
+ get_filenames.sort do |a, b|
125
+ a.downcase <=> b.downcase
126
+ end.each do |path|
127
+ tree.add(path)
128
+ end
129
+
130
+ # Return the tree
131
+ return tree
132
+ end
133
+ private :refresh_tree
134
+
135
+ def search(dir = "", pattern = ".")
136
+ dir ||= ""
137
+ pattern ||= "."
138
+
139
+ found = %x(
140
+ git grep -HIinP "#{pattern}" $(git rev-list --all) -- \
141
+ #{dir}
142
+ ).split("\n").map do |line|
143
+ line.gsub(
144
+ /^([^:]+):([^:]+):(\d+):(.*)$/,
145
+ "\\2:\\1:\\3:\\4"
146
+ )
147
+ end
148
+
149
+ return found
150
+ end
151
+
152
+ def show(file)
153
+ # Check if file exists
154
+ if (!exist?(file))
155
+ raise GitXplorer::Error::NoFileOrDirectory.new(file)
156
+ end
157
+
158
+ file, _, rev = absolute_path(file).partition(":")
159
+
160
+ # Get target and ensure it's a file
161
+ target = @tree.get(file)
162
+ if (!target.is_a?(GitXplorer::GitObject::File))
163
+ raise GitXplorer::Error::NotFile.new(file)
164
+ end
165
+
166
+ # If revision was specified, ensure it exists
167
+ if (!rev.empty? && !target.has_child?(rev))
168
+ raise GitXplorer::Error::InvalidRevision.new(rev)
169
+ end
170
+
171
+ # Default to newest revision
172
+ rev = target.newest.name if (rev.empty?)
173
+
174
+ system("git --no-pager show #{rev}:#{file}")
175
+ end
176
+
177
+ def vim(file, readonly = false)
178
+ # Check if file exists
179
+ if (!exist?(file))
180
+ raise GitXplorer::Error::NoFileOrDirectory.new(file)
181
+ end
182
+
183
+ file, _, rev = absolute_path(file).partition(":")
184
+
185
+ # Get target and ensure it's a file
186
+ target = @tree.get(file)
187
+ if (!target.is_a?(GitXplorer::GitObject::File))
188
+ raise GitXplorer::Error::NotFile.new(file)
189
+ end
190
+
191
+ # If revision was specified, ensure it exists
192
+ if (!rev.empty? && !target.has_child?(rev))
193
+ raise GitXplorer::Error::InvalidRevision.new(rev)
194
+ end
195
+
196
+ # Default to newest revision
197
+ rev = target.newest.name if (rev.empty?)
198
+
199
+ op = nil
200
+ op = "vi" if (ScoobyDoo.where_are_you("vi"))
201
+ op = "vim" if (ScoobyDoo.where_are_you("vim"))
202
+
203
+ readonly ||= false
204
+ if (readonly && op.nil?)
205
+ system("git show #{rev}:#{file}")
206
+ else
207
+ name = "/tmp/gitXplorer_"
208
+ name += File.read("/dev/urandom", 4).unpack("H*").join
209
+ File.open(name, "w") do |f|
210
+ f.write(%x(git show #{rev}:#{file}))
211
+ end
212
+ system("#{op}#{" -R" if (readonly)} #{name}")
213
+ FileUtils.rm_f(name)
214
+ end
215
+ end
216
+ end
217
+
218
+ require "git_xplorer/error"
219
+ require "git_xplorer/git_object"
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitXplorer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Miles Whittaker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.3'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 12.3.2
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '12.3'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 12.3.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: djinni
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.2.4
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.2.4
53
+ - !ruby/object:Gem::Dependency
54
+ name: hilighter
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.2'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.2.3
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.2'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.2.3
73
+ - !ruby/object:Gem::Dependency
74
+ name: scoobydoo
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '0.1'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 0.1.6
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.1'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.1.6
93
+ description: GitXplorer will start a shell-like session that simulates a filesystem.
94
+ Easily navigate through directories and browse all files across all revisions.
95
+ email: mjwhitta@gmail.com
96
+ executables:
97
+ - gitX
98
+ - gitx
99
+ - gitXplorer
100
+ - gitxplorer
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - bin/gitX
105
+ - bin/gitXplorer
106
+ - bin/gitx
107
+ - bin/gitxplorer
108
+ - lib/git_xplorer.rb
109
+ - lib/git_xplorer/error.rb
110
+ - lib/git_xplorer/error/invalid_revision.rb
111
+ - lib/git_xplorer/error/no_chaining_allowed.rb
112
+ - lib/git_xplorer/error/no_file_or_directory.rb
113
+ - lib/git_xplorer/error/no_semicolons_allowed.rb
114
+ - lib/git_xplorer/error/no_subshells_allowed.rb
115
+ - lib/git_xplorer/error/not_directory.rb
116
+ - lib/git_xplorer/error/not_file.rb
117
+ - lib/git_xplorer/git_object.rb
118
+ - lib/git_xplorer/git_object/directory.rb
119
+ - lib/git_xplorer/git_object/file.rb
120
+ - lib/git_xplorer/git_object/revision.rb
121
+ - lib/git_xplorer/wish/cat_wish.rb
122
+ - lib/git_xplorer/wish/change_directory_wish.rb
123
+ - lib/git_xplorer/wish/find_wish.rb
124
+ - lib/git_xplorer/wish/git_wish.rb
125
+ - lib/git_xplorer/wish/grep_wish.rb
126
+ - lib/git_xplorer/wish/list_directory_wish.rb
127
+ - lib/git_xplorer/wish/pwd_wish.rb
128
+ - lib/git_xplorer/wish/vi_wish.rb
129
+ homepage: https://gitlab.com/mjwhitta/gitXplorer
130
+ licenses:
131
+ - GPL-3.0
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubygems_version: 3.0.2
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: Simulate a Linux shell to browse a git tree.
152
+ test_files: []