k_fileset 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|