firespring_dev_commands 1.3.0

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.
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