code_manifest 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +42 -0
- data/lib/code_manifest/manifest.rb +46 -0
- data/lib/code_manifest/rule.rb +46 -0
- data/lib/code_manifest/version.rb +5 -0
- data/lib/code_manifest.rb +47 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: be523e36c254ee8749c037a2e1c9fa57dd10d2e86d83b49aed3349f56da72bdb
|
4
|
+
data.tar.gz: 6741764dfc73fc92fa87f9c5acfbba1fae8650c617a5aa15efabafec25bb8dd0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fc9bd31b43bdc5637de024cb0063f88519c09a3120025f452a5733fff4dfca6d1f4f9c5067866fea82395c846e3a2027388cfe7a74d77f50c13665fde43d6303
|
7
|
+
data.tar.gz: e802a2695b4409eb40fac80e9a79a0f88b1fcac45a4549c4be1a496540b4769d99ebbed2389ccb7deeca4bc5a002b1a8515eedd82930c2881ab6e391dc638bbf
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# CodeManifest
|
2
|
+
|
3
|
+
Simple manifest to fetch file by globs and generate digest.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
8
|
+
|
9
|
+
$ bundle add code_manifest
|
10
|
+
|
11
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
12
|
+
|
13
|
+
$ gem install code_manifest
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Put a `.code_manifest.yml` config file under your project root, for example:
|
18
|
+
|
19
|
+
```yml
|
20
|
+
ruby:
|
21
|
+
- app/**/*.rb
|
22
|
+
js:
|
23
|
+
- frontend/**/*.js
|
24
|
+
```
|
25
|
+
|
26
|
+
Then use it with:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require 'code_manifest'
|
30
|
+
|
31
|
+
# Returns a `Set` with filepaths
|
32
|
+
CodeManifest['ruby'].files
|
33
|
+
CodeManifest['js'].files
|
34
|
+
|
35
|
+
# Returns a digest based on all files specified under same namespace
|
36
|
+
CodeManifest['ruby'].digest
|
37
|
+
CodeManifest['js'].digest
|
38
|
+
```
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/code_manifest.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require 'digest/md5'
|
5
|
+
require_relative 'rule'
|
6
|
+
|
7
|
+
module CodeManifest
|
8
|
+
class Manifest
|
9
|
+
attr_reader :root
|
10
|
+
|
11
|
+
def initialize(root, patterns)
|
12
|
+
@root = root
|
13
|
+
@patterns = patterns.map(&:to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def files
|
17
|
+
@files ||= (inclusion_rules.map(&:files).reduce(Set.new, :merge) - exclusion_rules.map(&:files).reduce(Set.new, :merge)).sort.to_set
|
18
|
+
end
|
19
|
+
|
20
|
+
def digest
|
21
|
+
@digest ||= begin
|
22
|
+
digests = files.map { |file| Digest::MD5.file(root.join(file)).hexdigest }
|
23
|
+
Digest::MD5.hexdigest(digests.join)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def rules
|
30
|
+
@rules ||= @patterns.each_with_object([]) do |pattern, rules|
|
31
|
+
pattern = pattern.strip
|
32
|
+
unless pattern.match?(/\A(#|\z)/)
|
33
|
+
rules << Rule.new(root, pattern)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def inclusion_rules
|
39
|
+
@inclusion_rules ||= rules.reject(&:exclude)
|
40
|
+
end
|
41
|
+
|
42
|
+
def exclusion_rules
|
43
|
+
@exclusion_rules ||= rules.select(&:exclude)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CodeManifest
|
4
|
+
class Rule
|
5
|
+
GLOB_OPTIONS = File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB
|
6
|
+
|
7
|
+
attr_reader :exclude
|
8
|
+
attr_reader :glob
|
9
|
+
|
10
|
+
def initialize(root, pattern)
|
11
|
+
@root = root
|
12
|
+
@exclude = false
|
13
|
+
@glob = @root
|
14
|
+
|
15
|
+
if pattern[0] == '!'
|
16
|
+
@exclude = true
|
17
|
+
pattern = pattern[1..-1]
|
18
|
+
end
|
19
|
+
|
20
|
+
if pattern.start_with?('/')
|
21
|
+
pattern = pattern[1..-1]
|
22
|
+
else
|
23
|
+
@glob = @glob.join('**')
|
24
|
+
end
|
25
|
+
|
26
|
+
@glob = @glob.join(pattern).to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def files
|
30
|
+
@files ||= begin
|
31
|
+
matched = Dir.glob(glob, GLOB_OPTIONS)
|
32
|
+
matched.map! { |file| Pathname.new(file) }
|
33
|
+
matched.reject!(&:directory?)
|
34
|
+
matched.map! { |file| file.relative_path_from(@root.expand_path).to_s }
|
35
|
+
Set.new(matched.sort!)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def match?(file)
|
40
|
+
file = Pathname.new(file)
|
41
|
+
file = @root.join(file) unless file.absolute?
|
42
|
+
|
43
|
+
File.fnmatch?(glob, file.to_s, GLOB_OPTIONS)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require_relative "code_manifest/version"
|
5
|
+
require_relative "code_manifest/manifest"
|
6
|
+
|
7
|
+
module CodeManifest
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
DOTFILE = '.code_manifest.yml'.freeze
|
11
|
+
KEY_PATTERN = /[a-z_0-9]+/.freeze
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def [](name)
|
15
|
+
manifests[name.to_s]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def manifests
|
21
|
+
@manifests ||= begin
|
22
|
+
config_file = traverse_files(DOTFILE, Dir.pwd)
|
23
|
+
|
24
|
+
raise "#{DOTFILE} was not found in your project directory, please check README for instructions." unless config_file
|
25
|
+
|
26
|
+
root = Pathname.new(config_file).dirname
|
27
|
+
|
28
|
+
YAML.load_file(config_file).each_with_object({}) do |(name, patterns), collection|
|
29
|
+
next unless name.match?(KEY_PATTERN)
|
30
|
+
|
31
|
+
if collection.key?(name)
|
32
|
+
raise ArgumentError, "#{name} defined multiple times in #{DOTFILE}"
|
33
|
+
end
|
34
|
+
|
35
|
+
collection[name] = Manifest.new(root, patterns)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def traverse_files(filename, start_dir)
|
41
|
+
Pathname.new(start_dir).expand_path.ascend do |dir|
|
42
|
+
file = dir.join(filename)
|
43
|
+
return file.to_s if file.exist?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: code_manifest
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gusto Engineers
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
description: A code manifest
|
28
|
+
email:
|
29
|
+
- dev@gusto.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- README.md
|
35
|
+
- lib/code_manifest.rb
|
36
|
+
- lib/code_manifest/manifest.rb
|
37
|
+
- lib/code_manifest/rule.rb
|
38
|
+
- lib/code_manifest/version.rb
|
39
|
+
homepage: https://github.com/rubyatscale/code_manifest
|
40
|
+
licenses: []
|
41
|
+
metadata:
|
42
|
+
homepage_uri: https://github.com/rubyatscale/code_manifest
|
43
|
+
source_code_uri: https://github.com/rubyatscale/code_manifest
|
44
|
+
changelog_uri: https://github.com/rubyatscale/code_manifest/blob/main/releases
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.7'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubygems_version: 3.3.7
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: A code manifest
|
64
|
+
test_files: []
|