kitkat 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fbdbb6ec1c0293541eed2e6d3227dd23157f6de455499df55d5bc32f6044c025
4
+ data.tar.gz: 2c02ad2202530ef1d4d2201711bc4dcf18ef1cfeb3543d3b54756b5238cc3be3
5
+ SHA512:
6
+ metadata.gz: bc533656a79f62e7f1ab832166035c24ad2d614e090b4fec5a08a5b5c4218c987aab94437141870fb02931330785819b467034aa437b5be55fedae37c2c90c54
7
+ data.tar.gz: af88084f7c99abcd4c141d419b11628b74178615acf959b667f7d66b1c5881d32e3f64946fb2765c2045094226b28cc8ac0ebb463d2e06744703c05dd3a2429f
data/.editorconfig ADDED
@@ -0,0 +1,8 @@
1
+ # See http://editorconfig.org/
2
+
3
+ [*]
4
+ trim_trailing_whitespace = true
5
+ indent_style = space
6
+ indent_size = 2
7
+ insert_final_newline = true
8
+ end_of_line = lf
@@ -0,0 +1,31 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ verify:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ['2.6', '2.7', '3.0']
15
+
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+ - name: Set up Ruby
19
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
20
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
21
+ # uses: ruby/setup-ruby@v1
22
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
23
+ with:
24
+ ruby-version: ${{ matrix.ruby-version }}
25
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
26
+ - name: Lint
27
+ run: bin/rubocop
28
+ - name: Test
29
+ run: bin/rspec spec --format documentation
30
+ - name: Dependency Audit
31
+ run: bin/bundler-audit check --update
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ *.gem
3
+ /tmp
4
+ /coverage
5
+ Gemfile.lock
6
+ /pkg
7
+ kitkat.db
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.6
4
+ Exclude:
5
+ - bin/*
6
+ - vendor/bundle/**/*
7
+
8
+ Metrics/MethodLength:
9
+ Max: 20
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.6.6
@@ -0,0 +1,73 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported. All complaints will be reviewed and investigated and will result in a response that
59
+ is deemed necessary and appropriate to the circumstances. The project team is
60
+ obligated to maintain confidentiality with regard to the reporter of an incident.
61
+ Further details of specific enforcement policies may be posted separately.
62
+
63
+ Project maintainers who do not follow or enforce the Code of Conduct in good
64
+ faith may face temporary or permanent repercussions as determined by other
65
+ members of the project's leadership.
66
+
67
+ ## Attribution
68
+
69
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
70
+ available at [http://contributor-covenant.org/version/1/4][version]
71
+
72
+ [homepage]: http://contributor-covenant.org
73
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ guard :rspec, cmd: 'DISABLE_SIMPLECOV=true bin/rspec --format=documentation' do
4
+ require 'guard/rspec/dsl'
5
+ dsl = Guard::RSpec::Dsl.new(self)
6
+
7
+ # RSpec files
8
+ rspec = dsl.rspec
9
+ watch(rspec.spec_helper) { rspec.spec_dir }
10
+ watch(rspec.spec_support) { rspec.spec_dir }
11
+ watch(rspec.spec_files)
12
+
13
+ # Ruby files
14
+ ruby = dsl.ruby
15
+ dsl.watch_spec_files_for(ruby.lib_files)
16
+ end
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Kitkat
2
+
3
+ #### File/Metadata Database Populator
4
+
5
+ [![Gem Version](https://badge.fury.io/rb/kitkat.svg)](https://badge.fury.io/rb/kitkat) [![Ruby Gem CI](https://github.com/mattruggio/kitkat/actions/workflows/rubygem.yml/badge.svg)](https://github.com/mattruggio/kitkat/actions/workflows/rubygem.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ I had a need to recursively enumerate a directory and load the paths, and some metadata about the files, into a SQLite file.
8
+
9
+ ## Installation
10
+
11
+ To install through Rubygems:
12
+
13
+ ````
14
+ gem install kitkat
15
+ ````
16
+
17
+ You can also add this to your Gemfile using:
18
+
19
+ ````
20
+ bundle add kitkat
21
+ ````
22
+
23
+ ## Usage
24
+
25
+ ### Executable
26
+
27
+ This library ships with an executable: `exe/kitkat`. Simply run this from your shell:
28
+
29
+ ````zsh
30
+ exe/kitkat <path> <database>
31
+ ````
32
+
33
+ For Example: `bin/kitkat some_directory some_directory_contents.db`. This will recursively scan the relative path at: `some_directory` and list all its contents in a SQLite database file relatively located at: `some_directory_contents.db`.
34
+
35
+ Note: database positional argument is optional. If it is not supplied then it will default to: `kitkat.db`
36
+
37
+ ### Ruby API
38
+
39
+ You can also include this gem and use directly through code:
40
+
41
+ ```ruby
42
+ Kitkat.crawl(db: 'some_directory_contents.db', path: 'some_directory')
43
+ ```
44
+
45
+ The Ruby code above is functionally equivalent to running the executable script above.
46
+
47
+ ## Contributing
48
+
49
+ ### Development Environment Configuration
50
+
51
+ Basic steps to take to get this repository compiling:
52
+
53
+ 1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/) (check kitkat.gemspec for versions supported)
54
+ 2. Install bundler (gem install bundler)
55
+ 3. Clone the repository (git clone git@github.com:mattruggio/kitkat.git)
56
+ 4. Navigate to the root folder (cd kitkat)
57
+ 5. Install dependencies (bundle)
58
+
59
+ ### Running Tests
60
+
61
+ To execute the test suite run:
62
+
63
+ ````zsh
64
+ bin/rspec spec --format documentation
65
+ ````
66
+
67
+ Alternatively, you can have Guard watch for changes:
68
+
69
+ ````zsh
70
+ bin/guard
71
+ ````
72
+
73
+ Also, do not forget to run Rubocop:
74
+
75
+ ````zsh
76
+ bin/rubocop
77
+ ````
78
+
79
+ And auditing the dependencies:
80
+
81
+ ````zsh
82
+ bin/bundler-audit check --update
83
+ ````
84
+
85
+ ### Publishing
86
+
87
+ Note: ensure you have proper authorization before trying to publish new versions.
88
+
89
+ After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
90
+
91
+ 1. Merge Pull Request into main
92
+ 2. Update `version.rb` using [semantic versioning](https://semver.org/)
93
+ 3. Install dependencies: `bundle`
94
+ 4. Update `CHANGELOG.md` with release notes
95
+ 5. Commit & push main to remote and ensure CI builds main successfully
96
+ 6. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
97
+
98
+ ## Code of Conduct
99
+
100
+ Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mattruggio/kitkat/blob/main/CODE_OF_CONDUCT.md).
101
+
102
+ ## License
103
+
104
+ This project is MIT Licensed.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
9
+
10
+ task default: %i[rubocop spec]
data/bin/_guard-core ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application '_guard-core' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("guard", "_guard-core")
data/bin/bundle-audit ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle-audit' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("bundler-audit", "bundle-audit")
data/bin/bundler-audit ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundler-audit' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("bundler-audit", "bundler-audit")
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'kitkat'
6
+ require 'pry'
7
+
8
+ Pry.start
data/bin/guard ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'guard' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("guard", "guard")
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
data/bin/rspec ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rspec' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/rubocop ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
data/exe/kitkat ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'kitkat'
6
+
7
+ path = ARGV[0].to_s
8
+ db = ARGV[1].to_s.empty? ? 'kitkat.db' : ARGV[1].to_s
9
+
10
+ Kitkat.crawl(db: db, path: path)
data/kitkat.gemspec ADDED
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/kitkat/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'kitkat'
7
+ s.version = Kitkat::VERSION
8
+ s.summary = 'File/Metadata Database Populator'
9
+
10
+ s.description = <<-DESCRIPTION
11
+ Small library that can populate a SQLite database with the recursive list of all files and their respective metadata.
12
+ DESCRIPTION
13
+
14
+ s.authors = ['Matthew Ruggio']
15
+ s.email = ['mattruggio@icloud.com']
16
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ s.bindir = 'exe'
18
+ s.executables = %w[kitkat]
19
+ s.license = 'MIT'
20
+ s.homepage = 'https://github.com/mattruggio/kitkat'
21
+ s.metadata = {
22
+ 'bug_tracker_uri' => 'https://github.com/mattruggio/kitkat/issues',
23
+ 'changelog_uri' => 'https://github.com/mattruggio/kitkat/blob/main/CHANGELOG.md',
24
+ 'documentation_uri' => 'https://www.rubydoc.info/gems/kitkat',
25
+ 'homepage_uri' => s.homepage,
26
+ 'source_code_uri' => s.homepage,
27
+ 'rubygems_mfa_required' => 'true'
28
+ }
29
+
30
+ s.required_ruby_version = '>= 2.6'
31
+
32
+ s.add_dependency('sqlite3')
33
+
34
+ s.add_development_dependency('bundler-audit')
35
+ s.add_development_dependency('guard-rspec')
36
+ s.add_development_dependency('pry')
37
+ s.add_development_dependency('rake')
38
+ s.add_development_dependency('rspec')
39
+ s.add_development_dependency('rubocop')
40
+ s.add_development_dependency('rubocop-rake')
41
+ s.add_development_dependency('rubocop-rspec')
42
+ s.add_development_dependency('simplecov')
43
+ s.add_development_dependency('simplecov-console')
44
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitkat
4
+ # Database-level operations.
5
+ class Database
6
+ def initialize(path)
7
+ @connection = SQLite3::Database.new(path)
8
+
9
+ load_schema
10
+
11
+ freeze
12
+ end
13
+
14
+ def insert(file_info)
15
+ connection.execute(
16
+ sql_statement,
17
+ file_info.relative_path,
18
+ file_info.mime_type,
19
+ file_info.mime_subtype,
20
+ file_info.bytesize,
21
+ file_info.last_modified_at.to_s,
22
+ file_info.digest,
23
+ Time.now.utc.to_s
24
+ )
25
+
26
+ self
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :connection
32
+
33
+ def sql_statement
34
+ 'INSERT OR IGNORE INTO files VALUES (?, ?, ?, ?, ?, ?, ?)'
35
+ end
36
+
37
+ def load_schema
38
+ connection.execute <<-SQL
39
+ CREATE TABLE IF NOT EXISTS files (
40
+ path varchar NOT NULL,
41
+ mime_type varchar NOT NULL,
42
+ mime_subtype varchar NOT NULL,
43
+ bytesize integer NOT NULL,
44
+ last_modified_at datetime,
45
+ digest varchar NOT NULL,
46
+ created_at datetime NOT NULL
47
+ );
48
+ SQL
49
+
50
+ connection.execute <<-SQL
51
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_files_path ON files (path);
52
+ SQL
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitkat
4
+ # File-level operations.
5
+ class FileInfo
6
+ BLANK = ''
7
+ MIME_TYPE_SEPARATOR = '/'
8
+
9
+ attr_reader :path, :root
10
+
11
+ def initialize(path, root: BLANK)
12
+ @path = path
13
+ @root = root
14
+ end
15
+
16
+ def relative_path
17
+ path.delete_prefix(root).delete_prefix(File::SEPARATOR)
18
+ end
19
+
20
+ def full_mime_type
21
+ @full_mime_type ||= IO.popen(
22
+ ['file', '--brief', '--mime-type', path],
23
+ in: :close, err: :close
24
+ ) { |io| io.read.chomp }.to_s
25
+ end
26
+
27
+ def mime_type
28
+ full_mime_type.split(MIME_TYPE_SEPARATOR).first
29
+ end
30
+
31
+ def mime_subtype
32
+ full_mime_type.split(MIME_TYPE_SEPARATOR).last
33
+ end
34
+
35
+ def digest
36
+ File.directory?(path) ? BLANK : Digest::SHA256.file(path).hexdigest
37
+ end
38
+
39
+ def last_modified_at
40
+ File.mtime(path).utc
41
+ end
42
+
43
+ def bytesize
44
+ File.size(path)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'file_info'
4
+
5
+ module Kitkat
6
+ # Directory operations.
7
+ class Reader
8
+ attr_reader :root
9
+
10
+ def initialize(root)
11
+ @root = File.expand_path(root)
12
+
13
+ freeze
14
+ end
15
+
16
+ def each(&block)
17
+ return enum_for(:each) unless block_given?
18
+
19
+ traverse(root, &block)
20
+
21
+ self
22
+ end
23
+
24
+ private
25
+
26
+ def traverse(dir, &block)
27
+ Dir[File.join(dir, '*')].each do |path|
28
+ yield FileInfo.new(path, root: root)
29
+
30
+ traverse(path, &block) if File.directory?(path)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitkat
4
+ VERSION = '0.0.1'
5
+ end
data/lib/kitkat.rb ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+ require 'sqlite3'
5
+
6
+ require_relative 'kitkat/database'
7
+ require_relative 'kitkat/reader'
8
+
9
+ # Main example/easiest entry-point for this application.
10
+ module Kitkat
11
+ class << self
12
+ def crawl(path:, db:, io: $stdout)
13
+ reader = Reader.new(path)
14
+ db = Database.new(db)
15
+
16
+ reader.each.with_index(1) do |file_info, index|
17
+ io.puts("[#{index}] #{file_info.relative_path}")
18
+
19
+ db.insert(file_info)
20
+ end
21
+
22
+ io.puts('Complete')
23
+ end
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,230 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitkat
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matthew Ruggio
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2022-06-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sqlite3
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler-audit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: guard-rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: simplecov-console
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: " Small library that can populate a SQLite database with the recursive
168
+ list of all files and their respective metadata.\n"
169
+ email:
170
+ - mattruggio@icloud.com
171
+ executables:
172
+ - kitkat
173
+ extensions: []
174
+ extra_rdoc_files: []
175
+ files:
176
+ - ".editorconfig"
177
+ - ".github/workflows/rubygem.yml"
178
+ - ".gitignore"
179
+ - ".rubocop.yml"
180
+ - ".tool-versions"
181
+ - CODE_OF_CONDUCT.md
182
+ - Gemfile
183
+ - Guardfile
184
+ - README.md
185
+ - Rakefile
186
+ - bin/_guard-core
187
+ - bin/bundle-audit
188
+ - bin/bundler-audit
189
+ - bin/console
190
+ - bin/guard
191
+ - bin/rake
192
+ - bin/rspec
193
+ - bin/rubocop
194
+ - exe/kitkat
195
+ - kitkat.gemspec
196
+ - lib/kitkat.rb
197
+ - lib/kitkat/database.rb
198
+ - lib/kitkat/file_info.rb
199
+ - lib/kitkat/reader.rb
200
+ - lib/kitkat/version.rb
201
+ homepage: https://github.com/mattruggio/kitkat
202
+ licenses:
203
+ - MIT
204
+ metadata:
205
+ bug_tracker_uri: https://github.com/mattruggio/kitkat/issues
206
+ changelog_uri: https://github.com/mattruggio/kitkat/blob/main/CHANGELOG.md
207
+ documentation_uri: https://www.rubydoc.info/gems/kitkat
208
+ homepage_uri: https://github.com/mattruggio/kitkat
209
+ source_code_uri: https://github.com/mattruggio/kitkat
210
+ rubygems_mfa_required: 'true'
211
+ post_install_message:
212
+ rdoc_options: []
213
+ require_paths:
214
+ - lib
215
+ required_ruby_version: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - ">="
218
+ - !ruby/object:Gem::Version
219
+ version: '2.6'
220
+ required_rubygems_version: !ruby/object:Gem::Requirement
221
+ requirements:
222
+ - - ">="
223
+ - !ruby/object:Gem::Version
224
+ version: '0'
225
+ requirements: []
226
+ rubygems_version: 3.0.3
227
+ signing_key:
228
+ specification_version: 4
229
+ summary: File/Metadata Database Populator
230
+ test_files: []