firespring_dev_commands 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +83 -0
  4. data/lib/firespring_dev_commands/audit/report/item.rb +33 -0
  5. data/lib/firespring_dev_commands/audit/report/levels.rb +36 -0
  6. data/lib/firespring_dev_commands/audit/report.rb +49 -0
  7. data/lib/firespring_dev_commands/aws/account/info.rb +15 -0
  8. data/lib/firespring_dev_commands/aws/account.rb +164 -0
  9. data/lib/firespring_dev_commands/aws/cloudformation/parameters.rb +26 -0
  10. data/lib/firespring_dev_commands/aws/cloudformation.rb +188 -0
  11. data/lib/firespring_dev_commands/aws/codepipeline.rb +96 -0
  12. data/lib/firespring_dev_commands/aws/credentials.rb +136 -0
  13. data/lib/firespring_dev_commands/aws/login.rb +131 -0
  14. data/lib/firespring_dev_commands/aws/parameter.rb +32 -0
  15. data/lib/firespring_dev_commands/aws/profile.rb +55 -0
  16. data/lib/firespring_dev_commands/aws/s3.rb +42 -0
  17. data/lib/firespring_dev_commands/aws.rb +10 -0
  18. data/lib/firespring_dev_commands/boolean.rb +7 -0
  19. data/lib/firespring_dev_commands/common.rb +112 -0
  20. data/lib/firespring_dev_commands/daterange.rb +171 -0
  21. data/lib/firespring_dev_commands/docker/compose.rb +271 -0
  22. data/lib/firespring_dev_commands/docker/status.rb +38 -0
  23. data/lib/firespring_dev_commands/docker.rb +276 -0
  24. data/lib/firespring_dev_commands/dotenv.rb +6 -0
  25. data/lib/firespring_dev_commands/env.rb +38 -0
  26. data/lib/firespring_dev_commands/eol/product_version.rb +86 -0
  27. data/lib/firespring_dev_commands/eol.rb +58 -0
  28. data/lib/firespring_dev_commands/git/info.rb +13 -0
  29. data/lib/firespring_dev_commands/git.rb +420 -0
  30. data/lib/firespring_dev_commands/jira/issue.rb +33 -0
  31. data/lib/firespring_dev_commands/jira/project.rb +13 -0
  32. data/lib/firespring_dev_commands/jira/user/type.rb +20 -0
  33. data/lib/firespring_dev_commands/jira/user.rb +31 -0
  34. data/lib/firespring_dev_commands/jira.rb +78 -0
  35. data/lib/firespring_dev_commands/logger.rb +8 -0
  36. data/lib/firespring_dev_commands/node/audit.rb +39 -0
  37. data/lib/firespring_dev_commands/node.rb +107 -0
  38. data/lib/firespring_dev_commands/php/audit.rb +71 -0
  39. data/lib/firespring_dev_commands/php.rb +109 -0
  40. data/lib/firespring_dev_commands/rake.rb +24 -0
  41. data/lib/firespring_dev_commands/ruby/audit.rb +30 -0
  42. data/lib/firespring_dev_commands/ruby.rb +113 -0
  43. data/lib/firespring_dev_commands/second.rb +22 -0
  44. data/lib/firespring_dev_commands/tar/pax_header.rb +49 -0
  45. data/lib/firespring_dev_commands/tar/type_flag.rb +49 -0
  46. data/lib/firespring_dev_commands/tar.rb +149 -0
  47. data/lib/firespring_dev_commands/templates/aws.rb +84 -0
  48. data/lib/firespring_dev_commands/templates/base_interface.rb +54 -0
  49. data/lib/firespring_dev_commands/templates/ci.rb +138 -0
  50. data/lib/firespring_dev_commands/templates/docker/application.rb +177 -0
  51. data/lib/firespring_dev_commands/templates/docker/default.rb +200 -0
  52. data/lib/firespring_dev_commands/templates/docker/node/application.rb +145 -0
  53. data/lib/firespring_dev_commands/templates/docker/php/application.rb +190 -0
  54. data/lib/firespring_dev_commands/templates/docker/ruby/application.rb +146 -0
  55. data/lib/firespring_dev_commands/templates/eol.rb +23 -0
  56. data/lib/firespring_dev_commands/templates/git.rb +147 -0
  57. data/lib/firespring_dev_commands/version.rb +11 -0
  58. data/lib/firespring_dev_commands.rb +21 -0
  59. metadata +436 -0
@@ -0,0 +1,107 @@
1
+ module Dev
2
+ # Class containing methods related to node application
3
+ class Node
4
+ # The default path of the application inside the container
5
+ DEFAULT_PATH = '/usr/src/app'.freeze
6
+
7
+ # The default name of the node package file
8
+ DEFAULT_PACKAGE_FILE = 'package.json'.freeze
9
+
10
+ # Config object for setting top level git config options
11
+ Config = Struct.new(:container_path, :local_path, :package_file) do
12
+ def initialize
13
+ self.container_path = DEFAULT_PATH
14
+ self.local_path = DEV_COMMANDS_ROOT_DIR
15
+ self.package_file = DEFAULT_PACKAGE_FILE
16
+ end
17
+ end
18
+
19
+ class << self
20
+ # Instantiates a new top level config object if one hasn't already been created
21
+ # Yields that config object to any given block
22
+ # Returns the resulting config object
23
+ def config
24
+ @config ||= Config.new
25
+ yield(@config) if block_given?
26
+ @config
27
+ end
28
+
29
+ # Alias the config method to configure for a slightly clearer access syntax
30
+ alias_method :configure, :config
31
+ end
32
+
33
+ attr_accessor :container_path, :local_path, :package_file
34
+
35
+ def initialize(container_path: nil, local_path: nil, package_file: nil)
36
+ @container_path = container_path || self.class.config.container_path
37
+ @local_path = local_path || self.class.config.local_path
38
+ @package_file = package_file || self.class.config.package_file
39
+ end
40
+
41
+ # The base npm command that is the starting point for all subsequent commands
42
+ def base_command
43
+ ['npm', '--prefix', container_path]
44
+ end
45
+
46
+ # Build the command which can be use to perform a security audit report
47
+ def audit_command
48
+ audit = base_command
49
+ audit << 'audit'
50
+ audit << '--audit-level=none'
51
+ audit << '--json'
52
+ audit.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
53
+ audit << '2>&1' << '||' << 'true'
54
+
55
+ # Run the command as part of a shell script
56
+ ['sh', '-c', audit.join(' ')]
57
+ end
58
+
59
+ # Build the command to fix any security vulnerabilities that were found
60
+ def audit_fix_command
61
+ audit_fix = base_command
62
+ audit_fix << 'audit' << 'fix'
63
+ audit_fix.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
64
+ audit_fix
65
+ end
66
+
67
+ # Build the npm install command
68
+ def install_command
69
+ install = base_command
70
+ install << 'install'
71
+ install.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
72
+ install
73
+ end
74
+
75
+ # Build the node lint command
76
+ def lint_command
77
+ lint = base_command
78
+ lint << 'run' << 'lint'
79
+ lint.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
80
+ lint
81
+ end
82
+
83
+ # Build the node lint fix command
84
+ def lint_fix_command
85
+ lint_fix = base_command
86
+ lint_fix << 'run' << 'lint-fix'
87
+ lint_fix.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
88
+ lint_fix
89
+ end
90
+
91
+ # Build the node test command
92
+ def test_command
93
+ test = base_command
94
+ test << 'run' << 'test'
95
+ test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
96
+ test
97
+ end
98
+
99
+ # Build the node test command
100
+ def test_coverage_command
101
+ test = base_command
102
+ test << 'run' << 'test:coverage'
103
+ test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
104
+ test
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,71 @@
1
+ require 'json'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ module Dev
6
+ class Php
7
+ # Class which contains commands and customizations for security audit reports
8
+ class Audit
9
+ attr_accessor :data
10
+
11
+ def initialize(data)
12
+ @data = JSON.parse(Dev::Common.new.strip_non_json(data))
13
+ end
14
+
15
+ # Convert the php audit data to the standardized audit report object
16
+ def to_report
17
+ Dev::Audit::Report.new(
18
+ data['advisories'].map do |_, v|
19
+ v.map do |it|
20
+ Dev::Audit::Report::Item.new(
21
+ id: it['advisoryId'],
22
+ name: it['packageName'],
23
+ severity: severity(it['cve']),
24
+ title: it['title'],
25
+ url: it['link'],
26
+ version: it['affectedVersions']
27
+ )
28
+ end
29
+ end.flatten
30
+ )
31
+ end
32
+
33
+ # Takes the give CVE number and looks it up on the NIST api
34
+ # Returns the highest severity reported (worst case scneario)
35
+ def severity(cve)
36
+ # Sleep to make sure we don't get rate limited
37
+ sleep(6)
38
+ url = "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=#{cve}"
39
+ response = Net::HTTP.get_response(URI.parse(url))
40
+
41
+ # If we can't talk to NIST, just assume the worst at 'unknown'
42
+ raise "#{response.code} #{response.message}" unless response.is_a?(Net::HTTPSuccess)
43
+
44
+ # Get the cve data out of the json body
45
+ cve_data = JSON.parse(response.body)['vulnerabilities'].first['cve']
46
+
47
+ # Sanity check to make sure it gave us the correct information
48
+ raise 'returned cve did not matche expected' unless cve == cve_data['id']
49
+
50
+ # Find the max cvss reported for this vulnerability
51
+ max_cvss = cve_data['metrics']['cvssMetricV31']&.map { |it| it['cvssData']['baseScore'] }&.max.to_f
52
+
53
+ # Map that severity to the correct level
54
+ cvss_to_severity(max_cvss)
55
+ rescue => e
56
+ LOG.error("Error looking up severity for #{cve}: #{e.message}")
57
+ LOG.error('WARNING: Unable to determine severity - ignoring with UNKNOWN')
58
+ Dev::Audit::Report::Level::UNKNOWN
59
+ end
60
+
61
+ # Take a given cvss scrore and map it to a severity string
62
+ def cvss_to_severity(score)
63
+ return Dev::Audit::Report::Level::LOW if score <= 3.9
64
+ return Dev::Audit::Report::Level::MODERATE if score <= 6.9
65
+ return Dev::Audit::Report::Level::HIGH if score <= 8.9
66
+
67
+ Dev::Audit::Report::Level::CRITICAL
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,109 @@
1
+ module Dev
2
+ # Class containing methods related to php applicatio
3
+ class Php
4
+ # The default path of the application inside the container
5
+ DEFAULT_PATH = '/usr/src/app'.freeze
6
+
7
+ # The default name of the php package file
8
+ DEFAULT_PACKAGE_FILE = 'composer.json'.freeze
9
+
10
+ # Config object for setting top level git config options
11
+ Config = Struct.new(:container_path, :local_path, :package_file) do
12
+ def initialize
13
+ self.container_path = DEFAULT_PATH
14
+ self.local_path = DEV_COMMANDS_ROOT_DIR
15
+ self.package_file = DEFAULT_PACKAGE_FILE
16
+ end
17
+ end
18
+
19
+ class << self
20
+ # Instantiates a new top level config object if one hasn't already been created
21
+ # Yields that config object to any given block
22
+ # Returns the resulting config object
23
+ def config
24
+ @config ||= Config.new
25
+ yield(@config) if block_given?
26
+ @config
27
+ end
28
+
29
+ # Alias the config method to configure for a slightly clearer access syntax
30
+ alias_method :configure, :config
31
+ end
32
+
33
+ attr_accessor :container_path, :local_path, :package_file
34
+
35
+ def initialize(container_path: nil, local_path: nil, package_file: nil)
36
+ @container_path = container_path || self.class.config.container_path
37
+ @local_path = local_path || self.class.config.local_path
38
+ @package_file = package_file || self.class.config.package_file
39
+ end
40
+
41
+ # The base npm command that is the starting point for all subsequent commands
42
+ def base_command
43
+ ['composer', '--working-dir', container_path]
44
+ end
45
+
46
+ # Build the command which can be use to perform a security audit report
47
+ def audit_command
48
+ audit = base_command
49
+ audit << 'audit'
50
+ audit << '--no-interaction'
51
+ audit << '--no-cache'
52
+ audit << '--format' << 'json'
53
+ audit.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
54
+ audit << '2>&1' << '||' << 'true'
55
+
56
+ # Run the command as part of a shell script
57
+ ['sh', '-c', audit.join(' ')]
58
+ end
59
+
60
+ # Build the command to fix any security vulnerabilities that were found
61
+ # def audit_fix_command
62
+ # audit_fix = base_command
63
+ # audit_fix << 'audit' << 'fix'
64
+ # audit_fix.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
65
+ # audit_fix
66
+ # end
67
+
68
+ # Build the php install command
69
+ def install_command
70
+ install = base_command
71
+ install << 'install'
72
+ install.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
73
+ install
74
+ end
75
+
76
+ # Build the php lint command
77
+ def lint_command
78
+ lint = base_command
79
+ lint << 'lint'
80
+ lint.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
81
+ lint
82
+ end
83
+
84
+ # Build the php lint fix command
85
+ def lint_fix_command
86
+ lint_fix = base_command
87
+ lint_fix << 'lint-fix'
88
+ lint_fix.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
89
+ lint_fix
90
+ end
91
+
92
+ # Build the php test command
93
+ def test_command
94
+ test = []
95
+ test << './vendor/bin/phpunit'
96
+ test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
97
+ test
98
+ end
99
+
100
+ # Build the php fast test command
101
+ def test_fast_command(processes = 4)
102
+ test = []
103
+ test << './vendor/bin/paratest'
104
+ test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
105
+ test << "-p#{processes}" << '--runner=WrapperRunner'
106
+ test
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,24 @@
1
+ require 'colorize'
2
+ require 'rake'
3
+
4
+ # Base rake module
5
+ module ::Rake
6
+ # Class override for the execute method
7
+ # This has been added to allow the user to configure whether they want to see a stacktrace
8
+ # when an error has been raised to the top level by rake
9
+ class Task
10
+ # Create an alias method called orig_execute which is a copy of the original execute method
11
+ alias_method :orig_execute, :execute
12
+
13
+ # Create a new execute method which runs the original execute and catches any errors it raises
14
+ # Specify STACKTRACE=true or TRACE=true to print the full stack trace of the error
15
+ def execute(args = nil)
16
+ orig_execute(args)
17
+ rescue => e
18
+ # Exception notification stuff
19
+ puts "\n #{e}\n".light_red
20
+ puts "\n#{e.backtrace.join("\n")}\n" if ENV['STACKTRACE'].to_s.strip == 'true' || ENV['TRACE'].to_s.strip == 'true'
21
+ exit 1
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ require 'json'
2
+
3
+ module Dev
4
+ class Ruby
5
+ # Class which contains commands and customizations for security audit reports
6
+ class Audit
7
+ attr_accessor :data
8
+
9
+ def initialize(data)
10
+ @data = JSON.parse(Dev::Common.new.strip_non_json(data))
11
+ end
12
+
13
+ # Convert the php audit data to the standardized audit report object
14
+ def to_report
15
+ Dev::Audit::Report.new(
16
+ data['results'].map do |it|
17
+ Dev::Audit::Report::Item.new(
18
+ id: it['advisory']['id'],
19
+ name: it['gem']['name'],
20
+ severity: it['advisory']['criticality'] || Dev::Audit::Report::Level::UNKNOWN,
21
+ title: it['advisory']['title'],
22
+ url: it['advisory']['url'],
23
+ version: it['gem']['version']
24
+ )
25
+ end
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,113 @@
1
+ module Dev
2
+ # Class containing methods related to ruby application
3
+ class Ruby
4
+ # The default path of the application inside the container
5
+ DEFAULT_PATH = '/usr/src/app'.freeze
6
+
7
+ # The default name of the ruby package file
8
+ DEFAULT_PACKAGE_FILE = 'Gemfile'.freeze
9
+
10
+ # Config object for setting top level git config options
11
+ Config = Struct.new(:container_path, :local_path, :package_file, :min_version, :max_version) do
12
+ def initialize
13
+ self.container_path = DEFAULT_PATH
14
+ self.local_path = DEV_COMMANDS_ROOT_DIR
15
+ self.package_file = DEFAULT_PACKAGE_FILE
16
+ self.min_version = nil
17
+ self.max_version = nil
18
+ end
19
+ end
20
+
21
+ class << self
22
+ # Instantiates a new top level config object if one hasn't already been created
23
+ # Yields that config object to any given block
24
+ # Returns the resulting config object
25
+ def config
26
+ @config ||= Config.new
27
+ yield(@config) if block_given?
28
+ @config
29
+ end
30
+
31
+ # Alias the config method to configure for a slightly clearer access syntax
32
+ alias_method :configure, :config
33
+
34
+ # Returns the version of the ruby executable running on the system
35
+ def version
36
+ @version ||= RUBY_VERSION
37
+ end
38
+ end
39
+
40
+ attr_accessor :container_path, :local_path, :package_file
41
+
42
+ def initialize(container_path: nil, local_path: nil, package_file: nil)
43
+ @container_path = container_path || self.class.config.container_path
44
+ @local_path = local_path || self.class.config.local_path
45
+ @package_file = package_file || self.class.config.package_file
46
+ check_version
47
+ end
48
+
49
+ # Checks the min and max version against the current ruby version if they have been configured
50
+ def check_version
51
+ min_version = self.class.config.min_version
52
+ raise "requires ruby version >= #{min_version} (found #{self.class.version})" if min_version && !Dev::Common.new.version_greater_than(min_version, self.class.version)
53
+
54
+ max_version = self.class.config.max_version
55
+ raise "requires ruby version < #{max_version} (found #{self.class.version})" if max_version && Dev::Common.new.version_greater_than(max_version, self.class.version)
56
+ end
57
+
58
+ # The base npm command that is the starting point for all subsequent commands
59
+ def base_command
60
+ ['bundle']
61
+ end
62
+
63
+ # Build the command which can be use to perform a security audit report
64
+ def audit_command
65
+ audit = base_command
66
+ audit << 'audit' << 'check'
67
+ audit << '--format' << 'json'
68
+ audit.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
69
+ audit << '2>&1' << '||' << 'true'
70
+
71
+ # Run the command as part of a shell script
72
+ ['sh', '-c', audit.join(' ')]
73
+ end
74
+
75
+ # Build the command to fix any security vulnerabilities that were found
76
+ # def audit_fix_command
77
+ # audit_fix = base_command
78
+ # audit_fix << 'audit' << 'fix'
79
+ # audit_fix.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
80
+ # audit_fix
81
+ # end
82
+
83
+ # Build the bundle install command
84
+ def install_command
85
+ install = base_command
86
+ install << 'install'
87
+ install.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
88
+ install
89
+ end
90
+
91
+ # Build the bundle lint command
92
+ def lint_command
93
+ lint = ['rubocop']
94
+ lint.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
95
+ lint
96
+ end
97
+
98
+ # Build the bundle lint fix command
99
+ def lint_fix_command
100
+ lint_fix = ['rubocop']
101
+ lint_fix << '-A'
102
+ lint_fix.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
103
+ lint_fix
104
+ end
105
+
106
+ # Build the bundle test command
107
+ def test_command
108
+ test = ['rspec']
109
+ test.concat(Dev::Common.new.tokenize(ENV['OPTS'].to_s))
110
+ test
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,22 @@
1
+ module Dev
2
+ # Class containing constants defining the number of seconds in other frames of time
3
+ class Second
4
+ # Number of seconds in a minute
5
+ PER_MINUTE = 60
6
+
7
+ # Number of seconds in an hour
8
+ PER_HOUR = PER_MINUTE * 60
9
+
10
+ # Number of seconds in a day
11
+ PER_DAY = PER_HOUR * 24
12
+
13
+ # Number of seconds in a week
14
+ PER_WEEK = PER_DAY * 7
15
+
16
+ # Number of seconds in a month
17
+ PER_MONTH = PER_DAY * 30
18
+
19
+ # Number of seconds in a year
20
+ PER_YEAR = PER_DAY * 365
21
+ end
22
+ end
@@ -0,0 +1,49 @@
1
+ module Dev
2
+ class Tar
3
+ # Contains different available pax headers
4
+ # From https://golang.org/src/archive/tar/common.go?s=5701:5766
5
+ module PaxHeader
6
+ # pax atime
7
+ PAX_ATIME = 'atime'.freeze
8
+
9
+ # pax charset
10
+ PAX_CHARSET = 'charset'.freeze
11
+
12
+ # pax comment
13
+ PAX_COMMENT = 'comment'.freeze
14
+
15
+ # pax ctime
16
+ PAX_CTIME = 'ctime'.freeze # please note that ctime is not a valid pax header.
17
+
18
+ # pax gid
19
+ PAX_GID = 'gid'.freeze
20
+
21
+ # pax gname
22
+ PAX_GNAME = 'gname'.freeze
23
+
24
+ # pax linkpath
25
+ PAX_LINKPATH = 'linkpath'.freeze
26
+
27
+ # pax mtime
28
+ PAX_MTIME = 'mtime'.freeze
29
+
30
+ # pax path
31
+ PAX_PATH = 'path'.freeze
32
+
33
+ # pax size
34
+ PAX_SIZE = 'size'.freeze
35
+
36
+ # pax uid
37
+ PAX_UID = 'uid'.freeze
38
+
39
+ # pax uname
40
+ PAX_UNAME = 'uname'.freeze
41
+
42
+ # pax xattr
43
+ PAX_XATTR = 'SCHILY.xattr.'.freeze
44
+
45
+ # pax none
46
+ PAX_NONE = ''.freeze
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ module Dev
2
+ class Tar
3
+ # Contains different available file types
4
+ # From https://golang.org/src/archive/tar/common.go?s=5701:5766
5
+ module TypeFlag
6
+ # regular file
7
+ TYPE_REG = '0'.freeze
8
+
9
+ # regular file
10
+ TYPE_REG_A = '\x00'.freeze
11
+
12
+ # hard link
13
+ TYPE_LINK = '1'.freeze
14
+
15
+ # symbolic link
16
+ TYPE_SYMLINK = '2'.freeze
17
+
18
+ # character device node
19
+ TYPE_CHAR = '3'.freeze
20
+
21
+ # block device node
22
+ TYPE_BLOCK = '4'.freeze
23
+
24
+ # directory
25
+ TYPE_DIR = '5'.freeze
26
+
27
+ # fifo node
28
+ TYPE_FIFO = '6'.freeze
29
+
30
+ # reserved
31
+ TYPE_CONT = '7'.freeze
32
+
33
+ # extended header
34
+ TYPE_X_HEADER = 'x'.freeze
35
+
36
+ # global extended header
37
+ TYPE_X_GLOBAL_HEADER = 'g'.freeze
38
+
39
+ # Next file has a long name
40
+ TYPE_GNU_LONG_NAME = 'L'.freeze
41
+
42
+ # Next file symlinks to a file w/ a long name
43
+ TYPE_GNU_LONG_LINK = 'K'.freeze
44
+
45
+ # sparse file
46
+ TYPE_GNU_SPARSE = 'S'.freeze
47
+ end
48
+ end
49
+ end