k_fileset 0.0.3
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 +7 -0
- data/.github/workflows/main.yml +31 -0
- data/.gitignore +50 -0
- data/.rspec +3 -0
- data/.rubocop.yml +93 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +25 -0
- data/Guardfile +30 -0
- data/LICENSE.txt +21 -0
- data/README.md +89 -0
- data/Rakefile +33 -0
- data/STORIES.md +52 -0
- data/USAGE.md +19 -0
- data/bin/console +16 -0
- data/bin/k +36 -0
- data/bin/kgitsync +76 -0
- data/bin/khotfix +244 -0
- data/bin/setup +11 -0
- data/hooks/pre-commit +87 -0
- data/hooks/update-version +33 -0
- data/k_fileset.gemspec +44 -0
- data/lib/k_fileset/file_set.rb +195 -0
- data/lib/k_fileset/file_set_examples.rb +64 -0
- data/lib/k_fileset/glob_entry.rb +57 -0
- data/lib/k_fileset/glob_info.rb +55 -0
- data/lib/k_fileset/glob_props.rb +10 -0
- data/lib/k_fileset/path_entry.rb +141 -0
- data/lib/k_fileset/version.rb +5 -0
- data/lib/k_fileset/whitelist.rb +62 -0
- data/lib/k_fileset.rb +24 -0
- metadata +90 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KFileset
|
4
|
+
# Glob entry can be used to find <PathEntries> that match a Glob
|
5
|
+
# with optional exclusion patterns and flags
|
6
|
+
class GlobEntry
|
7
|
+
include GlobProps
|
8
|
+
|
9
|
+
def initialize(working_directory, glob, flags, exclusions)
|
10
|
+
@working_directory = working_directory
|
11
|
+
@glob = glob
|
12
|
+
@flags = flags
|
13
|
+
@exclusions = exclusions
|
14
|
+
end
|
15
|
+
|
16
|
+
# Dealing with edge cases:
|
17
|
+
# https://bugs.ruby-lang.org/issues/17280
|
18
|
+
|
19
|
+
def path_entries
|
20
|
+
Dir.chdir(working_directory) do
|
21
|
+
Dir.glob(glob, flags)
|
22
|
+
.reject { |file| exclusions.any? { |pattern| pattern_match?(pattern, file) } }
|
23
|
+
.map do |file|
|
24
|
+
# pathname = Pathname.new(file)
|
25
|
+
# key = pathname.realpath.to_s
|
26
|
+
# key = File.join(key, '.') if file.ends_with?('.')
|
27
|
+
# PathEntry.new(key, pathname, Dir.pwd, file)
|
28
|
+
PathEntry.new(file)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def match?(absolute_file)
|
34
|
+
# match the inclusion Glob first
|
35
|
+
|
36
|
+
# Using absolute files because two sibling Globs may have different exclusion rules
|
37
|
+
# and the incoming file needs to be tested against the correct Glob and it's exclusions
|
38
|
+
absolute_glob = File.expand_path(glob, path)
|
39
|
+
|
40
|
+
return false unless File.fnmatch?(absolute_glob, absolute_file)
|
41
|
+
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def pattern_match?(pattern, file)
|
48
|
+
return pattern.match?(file) if pattern.is_a?(Regexp)
|
49
|
+
return pattern.call(file) if pattern.respond_to?(:call)
|
50
|
+
|
51
|
+
File.fnmatch?(pattern, file) # As String
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
# File.fnmatch('?', '/', File::FNM_PATHNAME) #=> false : wildcard doesn't match '/' on FNM_PATHNAME
|
56
|
+
# File.fnmatch('*', '/', File::FNM_PATHNAME) #=> false : ditto
|
57
|
+
# File.fnmatch('[/]', '/', File::FNM_PATHNAME) #=> false : ditto
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KFileset
|
4
|
+
# GlobConfig, GlobBuilder
|
5
|
+
class GlobInfo
|
6
|
+
include GlobProps
|
7
|
+
|
8
|
+
def initialize(glob, exclude = nil, flags = File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
9
|
+
@working_directory = Dir.pwd
|
10
|
+
@glob = Pathname.new(glob).cleanpath.to_s
|
11
|
+
@glob += File::SEPARATOR if glob.end_with?(File::SEPARATOR)
|
12
|
+
@flags = flags
|
13
|
+
|
14
|
+
# absolute_path_glob
|
15
|
+
@exclusions = build_exclusions(exclude)
|
16
|
+
end
|
17
|
+
|
18
|
+
def entry
|
19
|
+
GlobEntry.new(working_directory, glob, flags, exclusions)
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
# rubocop:disable Metrics/AbcSize:
|
24
|
+
def build_glob_entries(glob_infos)
|
25
|
+
glob_entries = []
|
26
|
+
|
27
|
+
glob_infos.each do |glob_info|
|
28
|
+
found = glob_entries.find_index { |entry| entry.working_directory == glob_info.working_directory && entry.glob == glob_info.glob }
|
29
|
+
|
30
|
+
if found
|
31
|
+
glob_entries[found].exclusions = (glob_entries[found].exclusions + glob_info.exclusions).uniq
|
32
|
+
else
|
33
|
+
glob_entries << GlobEntry.new(glob_info.working_directory, glob_info.glob, glob_info.flags, glob_info.exclusions)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
glob_entries
|
37
|
+
end
|
38
|
+
# rubocop:enable Metrics/AbcSize:
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Handles String based Glob, Regexp pattern or lambda expression
|
44
|
+
def build_exclusions(exclude)
|
45
|
+
return [] if exclude.nil?
|
46
|
+
return [exclude] if valid_exclusion?(exclude)
|
47
|
+
|
48
|
+
exclude.select { |ex| valid_exclusion?(ex) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def valid_exclusion?(exclusion)
|
52
|
+
exclusion.is_a?(String) || exclusion.is_a?(Regexp) || exclusion.respond_to?(:call)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KFileset
|
4
|
+
# PathEntry is a (RUBY) Pathname object with some extra properties
|
5
|
+
class PathEntry < Pathname
|
6
|
+
include KLog::Logging
|
7
|
+
# unique absolute path name e.g.(/abc, /abc/.)
|
8
|
+
# attr_reader :key
|
9
|
+
# attr_reader :path_name # Pathname
|
10
|
+
attr_reader :working_directory
|
11
|
+
|
12
|
+
# attr_reader :relative_path
|
13
|
+
|
14
|
+
# _path_name,
|
15
|
+
def initialize(path)
|
16
|
+
super(path)
|
17
|
+
# @key = realpath.to_s
|
18
|
+
# @key = File.join(@key, '.') if pathname.ends_with?('.')
|
19
|
+
# puts @key
|
20
|
+
# @path_name = path_name
|
21
|
+
@working_directory = Dir.getwd
|
22
|
+
# @pathname = pathname
|
23
|
+
# debug
|
24
|
+
end
|
25
|
+
|
26
|
+
def key
|
27
|
+
return @key if defined? @key
|
28
|
+
|
29
|
+
@key = begin
|
30
|
+
key = realpath.to_s
|
31
|
+
key = File.join(key, '.') if basename.to_s == '.' # if pathname.ends_with?('.')
|
32
|
+
key
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Realpath (is the absolute path of the entry)
|
37
|
+
#
|
38
|
+
# The Realpath is based on the current directory at the time this entry was created
|
39
|
+
# def realpath
|
40
|
+
# path_name.realpath(working_directory).to_s
|
41
|
+
# end
|
42
|
+
|
43
|
+
def path
|
44
|
+
realpath.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
def debug
|
48
|
+
# puts "expand_path : #{self.expand_path.to_s}"
|
49
|
+
# puts "realdirpath : #{self.realdirpath.to_s}"
|
50
|
+
# puts "realpath : #{self.realpath.to_s}"
|
51
|
+
# puts "extname : #{self.extname.to_s}"
|
52
|
+
# puts "basename : #{self.basename.to_s}"
|
53
|
+
# puts "dirname : #{self.dirname.to_s}"
|
54
|
+
# puts "to_path : #{self.to_path.to_s}"
|
55
|
+
# puts "parent : #{self.parent.to_s}"
|
56
|
+
# log.line
|
57
|
+
log.kv 'key', key
|
58
|
+
log.kv 'working_directory', working_directory
|
59
|
+
log.kv 'pathname', path
|
60
|
+
|
61
|
+
log.kv 'to_path', to_path
|
62
|
+
log.kv 'cleanpath', cleanpath
|
63
|
+
|
64
|
+
# log.kv 'directory?', directory?
|
65
|
+
# log.kv 'root?', root?
|
66
|
+
# log.kv 'absolute?', absolute?
|
67
|
+
# log.kv 'relative?', relative?
|
68
|
+
# log.kv 'exist?', exist?
|
69
|
+
# log.kv 'file?', file?
|
70
|
+
# log.kv 'size?', size?
|
71
|
+
# log.kv 'ftype', ftype
|
72
|
+
# log.kv 'empty?', empty?
|
73
|
+
# log.kv 'readable?', readable?
|
74
|
+
# log.kv 'birthtime', birthtime
|
75
|
+
# log.kv 'expand_path', expand_path
|
76
|
+
# log.kv 'realdirpath', realdirpath
|
77
|
+
# log.kv 'realpath', realpath
|
78
|
+
# log.kv 'extname', extname
|
79
|
+
# log.kv 'basename', basename
|
80
|
+
# log.kv 'dirname', dirname
|
81
|
+
# log.kv 'to_path', to_path
|
82
|
+
# log.kv 'size', size
|
83
|
+
|
84
|
+
log.line
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# relative_path() if its in two places
|
90
|
+
|
91
|
+
# Useful Pathname methods
|
92
|
+
#
|
93
|
+
# p.directory?
|
94
|
+
# p.root?
|
95
|
+
# p.absolute?
|
96
|
+
# p.relative?
|
97
|
+
# p.exist?
|
98
|
+
# p.file?
|
99
|
+
# p.size?
|
100
|
+
# p.zero?
|
101
|
+
# p.ftype
|
102
|
+
# p.empty?
|
103
|
+
# p.each_line
|
104
|
+
# p.read
|
105
|
+
# p.readlines
|
106
|
+
|
107
|
+
# p.readable?
|
108
|
+
# p.birthtime
|
109
|
+
|
110
|
+
# p.join
|
111
|
+
# p.mkpath
|
112
|
+
# p.find
|
113
|
+
# p.entries
|
114
|
+
# p.stat
|
115
|
+
# p.each_entry
|
116
|
+
# p.relative_path_from
|
117
|
+
|
118
|
+
# p.expand_path
|
119
|
+
# p.realdirpath
|
120
|
+
# p.realpath
|
121
|
+
# p.extname
|
122
|
+
# p.basename
|
123
|
+
# p.dirname
|
124
|
+
# p.relative_path_from
|
125
|
+
# p.to_path
|
126
|
+
# p.parent
|
127
|
+
# p.split
|
128
|
+
# p.size
|
129
|
+
# p.cleanpath
|
130
|
+
# p.children
|
131
|
+
# p.mkdir
|
132
|
+
# p.rmdir
|
133
|
+
# p.glob
|
134
|
+
# p.fnmatch
|
135
|
+
# p.fnmatch?
|
136
|
+
# p.delete
|
137
|
+
# p.each_filename
|
138
|
+
# p.each_line
|
139
|
+
|
140
|
+
# p.read
|
141
|
+
# p.readlines
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KFileset
|
4
|
+
# Whitelist rules around including of files with optional exclusion rules
|
5
|
+
class Whitelist
|
6
|
+
def initialize
|
7
|
+
@glob_entries = nil # glob_entries
|
8
|
+
@globs = [] # glob_infos /
|
9
|
+
end
|
10
|
+
|
11
|
+
def path_entries
|
12
|
+
glob_entries.flat_map(&:path_entries)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(glob, exclude = nil, flags = nil)
|
16
|
+
flags ||= FileSet::DEF_FLAGS
|
17
|
+
@glob_entries = nil
|
18
|
+
@globs << KFileset::GlobInfo.new(glob, exclude, flags)
|
19
|
+
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def clear
|
24
|
+
@glob_entries = nil
|
25
|
+
@globs = []
|
26
|
+
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return true if file is matched against an entry in the whitelist
|
31
|
+
def match?(file)
|
32
|
+
glob_entries.any? { |entry| entry.match?(file) }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Return GlobInfo entries with the directory, glob and exclusions
|
36
|
+
#
|
37
|
+
# Will denormalize the entries where matching (path and glob), whilst expanding with any new exclusions.
|
38
|
+
def glob_entries
|
39
|
+
@glob_entries ||= KFileset::GlobInfo.build_glob_entries(@globs)
|
40
|
+
end
|
41
|
+
|
42
|
+
# def glob_entries
|
43
|
+
# @glob_entries ||= begin
|
44
|
+
# glob_entries = []
|
45
|
+
|
46
|
+
# @globs.each do |glob|
|
47
|
+
# # found = glob_entries.find_index { |entry| entry.path == glob.absolute_path && entry.glob == glob.absolute_glob }
|
48
|
+
# found = glob_entries.find_index { |entry| entry.path == glob.path && entry.glob == glob.glob }
|
49
|
+
|
50
|
+
# if found
|
51
|
+
# glob_entries[found].exclusions = (glob_entries[found].exclusions + glob.exclusions).uniq
|
52
|
+
# else
|
53
|
+
# glob_entries << glob.entry
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# glob_entries
|
57
|
+
# end
|
58
|
+
|
59
|
+
# @glob_entries
|
60
|
+
# end
|
61
|
+
end
|
62
|
+
end
|
data/lib/k_fileset.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'k_log'
|
4
|
+
require 'k_fileset/version'
|
5
|
+
require 'k_fileset/whitelist'
|
6
|
+
require 'k_fileset/path_entry'
|
7
|
+
require 'k_fileset/glob_props'
|
8
|
+
require 'k_fileset/glob_entry'
|
9
|
+
require 'k_fileset/glob_info'
|
10
|
+
require 'k_fileset/file_set'
|
11
|
+
|
12
|
+
module KFileset
|
13
|
+
# raise KFileset::Error, 'Sample message'
|
14
|
+
class Error < StandardError; end
|
15
|
+
|
16
|
+
# Your code goes here...
|
17
|
+
end
|
18
|
+
|
19
|
+
if ENV['KLUE_DEBUG']&.to_s&.downcase == 'true'
|
20
|
+
namespace = 'KFileset::Version'
|
21
|
+
file_path = $LOADED_FEATURES.find { |f| f.include?('k_fileset/version') }
|
22
|
+
version = KFileset::VERSION.ljust(9)
|
23
|
+
puts "#{namespace.ljust(35)} : #{version.ljust(9)} : #{file_path}"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: k_fileset
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Cruwys
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-11-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: k_log
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.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.0.0
|
27
|
+
description: " K-Fileset provides file system snapshot using GLOB inclusions and
|
28
|
+
exclusions\n"
|
29
|
+
email:
|
30
|
+
- david@ideasmen.com.au
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".github/workflows/main.yml"
|
36
|
+
- ".gitignore"
|
37
|
+
- ".rspec"
|
38
|
+
- ".rubocop.yml"
|
39
|
+
- CODE_OF_CONDUCT.md
|
40
|
+
- Gemfile
|
41
|
+
- Guardfile
|
42
|
+
- LICENSE.txt
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- STORIES.md
|
46
|
+
- USAGE.md
|
47
|
+
- bin/console
|
48
|
+
- bin/k
|
49
|
+
- bin/kgitsync
|
50
|
+
- bin/khotfix
|
51
|
+
- bin/setup
|
52
|
+
- hooks/pre-commit
|
53
|
+
- hooks/update-version
|
54
|
+
- k_fileset.gemspec
|
55
|
+
- lib/k_fileset.rb
|
56
|
+
- lib/k_fileset/file_set.rb
|
57
|
+
- lib/k_fileset/file_set_examples.rb
|
58
|
+
- lib/k_fileset/glob_entry.rb
|
59
|
+
- lib/k_fileset/glob_info.rb
|
60
|
+
- lib/k_fileset/glob_props.rb
|
61
|
+
- lib/k_fileset/path_entry.rb
|
62
|
+
- lib/k_fileset/version.rb
|
63
|
+
- lib/k_fileset/whitelist.rb
|
64
|
+
homepage: http://appydave.com/gems/k-fileset
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata:
|
68
|
+
homepage_uri: http://appydave.com/gems/k-fileset
|
69
|
+
source_code_uri: https://github.com/klueless-io/k_fileset
|
70
|
+
changelog_uri: https://github.com/klueless-io/k_fileset/commits/master
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '2.5'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubygems_version: 3.2.7
|
87
|
+
signing_key:
|
88
|
+
specification_version: 4
|
89
|
+
summary: K-Fileset provides file system snapshot using GLOB inclusions and exclusions
|
90
|
+
test_files: []
|