list_enabled_extensions 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8a06e95534c9bd4d57500dbbff08e25d59f2837737cb0e2c11eb99bb72ff4ee4
4
+ data.tar.gz: 8ebde44c421028931f828ea2490cfd68a3840b3b7b0df54de6a12f5b8278c15b
5
+ SHA512:
6
+ metadata.gz: 5cbb649c340505d1722d7b689b9714df83c9d54e59f7515c7ba2d6f7d11876c40d4a326eaebcaa5bff2c72076aab2726a7fb4eb26185141025c205e3c5a302b5
7
+ data.tar.gz: 794b9b169e86cbc06b1bd0d73354a3fce04828d348d1b7c4693cf1d7b8e9bea815b6a73e30c3132db53ba1eafa2c11f1235b20120be943e8fd070a6c8ce81309
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ build/
2
+ *gem
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ load Pathname.new(__dir__).join('list_enabled_extensions').to_s
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'pathname'
5
+ require_relative '../lib/database_reader'
6
+ require_relative '../lib/workspace_storage_finder'
7
+
8
+ class CommandLineInterface
9
+ def initialize
10
+ @options = {}
11
+ parse_options
12
+ end
13
+
14
+ def run
15
+ if db_path
16
+ read_specific_db
17
+ else
18
+ search_for_db
19
+ end
20
+ rescue WorkspaceStorageFinder::Error, DatabaseReader::Error => e
21
+ $stderr.puts e.message
22
+ exit 1
23
+ end
24
+
25
+ private
26
+
27
+ def parse_options
28
+ OptionParser.new do |opts|
29
+ opts.banner = 'Usage: find_workspace_hash [options] [workspace_path (default: current directory)]'
30
+
31
+ opts.on('--storage-path PATH', 'Path to the VSCode workspace storage (If not picked automatically or you changed it)') do |path|
32
+ @options[:workspaces_storage_path] = Pathname.new(path).expand_path
33
+ end
34
+
35
+ opts.on('--db-path PATH', 'Direct path of the state.vscdb file') do |path|
36
+ @options[:db_path] = Pathname.new(path).expand_path
37
+ end
38
+
39
+ opts.on('--sql-query SQL QUERY', "default: #{DatabaseReader.default_query}") do |path|
40
+ @options[:sql_query] = nil
41
+ end
42
+
43
+ opts.on_tail('-h', '--help', 'Show this message') do
44
+ puts opts
45
+ exit
46
+ end
47
+ end.parse!
48
+ end
49
+
50
+ def read_specific_db
51
+ print_extensions_maybe(db_reader: db_reader(path: db_path))
52
+ end
53
+
54
+ def search_for_db
55
+ storage_finder = WorkspaceStorageFinder.new(path: workspaces_storage_path)
56
+ print_extensions_maybe(db_reader: db_reader(path: storage_finder.find_path(needle: current_workspace_path).join('state.vscdb')))
57
+ end
58
+
59
+ def print_extensions_maybe(db_reader:)
60
+ extensions = db_reader.extensions
61
+ if extensions.any?
62
+ puts "\e[38;5;10mFOUND EXTENSIONS:\e[0m"
63
+ extensions.each do |extension|
64
+ puts "#{extension}"
65
+ end
66
+ else
67
+ $stderr.puts "No extensions found in the database file '#{db_reader.path}' ❌"
68
+ exit 1
69
+ end
70
+ end
71
+
72
+ def db_reader(path: db_path)
73
+ DatabaseReader.new(path:)
74
+ end
75
+
76
+ def db_path
77
+ @options[:db_path]
78
+ end
79
+
80
+ def current_workspace_path
81
+ @current_workspace_path ||= Pathname.new(ARGV[0] || Dir.pwd).expand_path
82
+ end
83
+
84
+ def workspaces_storage_path
85
+ @workspaces_storage_path ||= self.class.possible_workspaces_storage_path
86
+ end
87
+
88
+ class << self
89
+ def possible_workspaces_storage_path
90
+ case RbConfig::CONFIG['host_os']
91
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
92
+ Pathname.new(ENV.fetch('APPDATA') { raise 'APPDATA environment variable not set.' })
93
+ when /darwin|mac os/
94
+ Pathname.new(Dir.home) + 'Library/Application Support'
95
+ when /linux|solaris|bsd/
96
+ Pathname.new(Dir.home) + '.config'
97
+ else
98
+ raise 'Unsupported OS'
99
+ end.join('Code/User/workspaceStorage')
100
+ end
101
+ end
102
+ end
103
+
104
+ # Run the script
105
+ CommandLineInterface.new.run
@@ -0,0 +1,53 @@
1
+ require 'json'
2
+ require 'sqlite3'
3
+ require 'pathname'
4
+ require 'forwardable'
5
+
6
+ class DatabaseReader
7
+ extend Forwardable
8
+ class Error < StandardError; end
9
+ class NotFoundError < Error; end
10
+
11
+ def initialize(path:, query: nil)
12
+ @path = Pathname.new(path)
13
+ @query = query || default_query
14
+ end
15
+
16
+ delegate default_query: :'self.class'
17
+
18
+ def extensions
19
+ @extensions ||=
20
+ JSON.parse(query_extensions.dig(0, 1) || raise(NotFoundError, "Unexpected query result #{query_extensions}"))
21
+ .map { |ext| ext['id'] }
22
+ end
23
+
24
+ private
25
+
26
+ def query_extensions
27
+ connection.execute(query)
28
+ rescue SQLite3::Exception => e
29
+ raise Error, "Error querying database: #{e}"
30
+ ensure
31
+ connection.close if connection
32
+ end
33
+
34
+ def connection
35
+ return @connection if @connection && !@connection.closed?
36
+
37
+ @connection = SQLite3::Database.new(path.to_s)
38
+ rescue SQLite3::Exception => e
39
+ raise Error, "Error opening database: #{e} (path: #{path})"
40
+ end
41
+
42
+ public
43
+
44
+ attr_reader :path, :query
45
+
46
+ class << self
47
+ def default_query
48
+ <<~SQL
49
+ SELECT * FROM ItemTable WHERE key LIKE 'extensionsIdentifiers/enabled'
50
+ SQL
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,34 @@
1
+ require 'json'
2
+ require 'pathname'
3
+
4
+ class WorkspaceStorageFinder
5
+ class Error < StandardError; end
6
+ class NotFoundError < Error; end
7
+
8
+ def initialize(path:)
9
+ @root = Pathname.new(path)
10
+ end
11
+
12
+ def find_path(needle:)
13
+ needle = Pathname.new(needle).realpath.to_s
14
+ worspace_storage_paths.each do |path|
15
+ next unless path.exist?
16
+
17
+ workspace_json_path = path.join('workspace.json')
18
+ next unless workspace_json_path.exist?
19
+
20
+ workspace_data = JSON.parse(workspace_json_path.read)
21
+ folder_value = workspace_data['folder']
22
+ return path if folder_value && folder_value == "file://#{needle}"
23
+ end
24
+
25
+ raise(NotFoundError, "Workspace storage not found for #{needle}. Searched in #{worspace_storage_paths.count} " \
26
+ "folders within \"#{root}\".")
27
+ end
28
+
29
+ def worspace_storage_paths
30
+ @worspace_storage_paths ||= root.children.select(&:directory?)
31
+ end
32
+
33
+ attr_reader :root
34
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: list_enabled_extensions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - GPT-4
8
+ - Anton Topchii
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2024-05-30 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 2.5.11
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 2.5.11
28
+ - !ruby/object:Gem::Dependency
29
+ name: standardrb
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: 1.0.1
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: 1.0.1
42
+ - !ruby/object:Gem::Dependency
43
+ name: minitest
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 5.23.1
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 5.23.1
56
+ - !ruby/object:Gem::Dependency
57
+ name: sqlite3
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.4'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.4'
70
+ description: This gem provides a command-line tool to list enabled VSCode extensions
71
+ for a given workspace.
72
+ email:
73
+ - player1@infinitevoid.net
74
+ executables:
75
+ - list-enabled-extensions
76
+ - list_enabled_extensions
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - ".gitignore"
81
+ - exe/list-enabled-extensions
82
+ - exe/list_enabled_extensions
83
+ - lib/database_reader.rb
84
+ - lib/workspace_storage_finder.rb
85
+ homepage: http://github.com/crawler/list_enabled_extensions
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 3.1.0
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.3.27
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: A tool to list enabled VSCode extensions for a workspace
108
+ test_files: []