Skip to content

Commit

Permalink
add tests for memory consumption
Browse files Browse the repository at this point in the history
  • Loading branch information
ezekg committed Nov 1, 2024
1 parent 3090c00 commit b63678f
Show file tree
Hide file tree
Showing 18 changed files with 144 additions and 457 deletions.
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/VERSION ident
spec/fixtures/files/* filter=lfs diff=lfs merge=lfs -text
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,5 @@ group :test do
gem 'database_cleaner', '~> 2.0'
gem 'webmock', '~> 3.14.0'
gem 'elif', '~> 0.1.0'
gem 'memory_profiler'
end
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ GEM
net-smtp
marcel (1.0.4)
matrix (0.4.2)
memory_profiler (1.1.0)
mime-types (3.4.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2022.0105)
Expand Down Expand Up @@ -552,6 +553,7 @@ DEPENDENCIES
kaminari (~> 1.2.0)
listen (>= 3.8.0)
lograge
memory_profiler
minitar
msgpack (~> 1.7)
nokogiri (~> 1.16.5)
Expand Down
9 changes: 6 additions & 3 deletions app/workers/process_docker_image_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ def perform(artifact_id)
.body

# unpack the package tarball
tar = gunzip(tgz)
io = gunzip(tgz)

unpack tar do |archive|
archive.each do |entry|
unpack io do |tar|
tar.each do |entry|
case entry.name
in 'manifest.json'
raise ImageNotAcceptableError, 'manifest must be a manifest.json file' unless
Expand Down Expand Up @@ -66,6 +66,9 @@ def perform(artifact_id)
end
end

# not sure why GzipReader#open doesn't take an io?
io.close

artifact.update!(status: 'UPLOADED')

BroadcastEventService.call(
Expand Down
56 changes: 26 additions & 30 deletions app/workers/process_npm_package_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,35 @@ def perform(artifact_id)
.body

# unpack the package tarball
tar = gunzip(tgz)

unpack tar do |archive|
archive.each do |entry|
# NOTE(ezekg) npm prefixes everything in the archive with package/
case entry.name
in 'package/package.json'
raise PackageNotAcceptableError, 'manifest must be a package.json file' unless
entry.file?

raise PackageNotAcceptableError, 'manifest is too big' if
entry.size > MAX_MANIFEST_SIZE

# the manifest is already in json format
json = entry.read

ReleaseManifest.create!(
account_id: artifact.account_id,
environment_id: artifact.environment_id,
release_id: artifact.release_id,
release_artifact_id: artifact.id,
content: json,
)

# all we need
break
else
end
end
io = gunzip(tgz)

unpack io do |tar|
# NOTE(ezekg) npm prefixes everything in the archive with package/
entry = tar.find { _1.name in 'package/package.json' }

raise PackageNotAcceptableError, 'manifest at package/package.json must exist' if
entry.nil?

raise PackageNotAcceptableError, 'manifest must be a package.json file' unless
entry.file?

raise PackageNotAcceptableError, 'manifest is too big' if
entry.size > MAX_MANIFEST_SIZE

# the manifest is already in json format
json = entry.read

ReleaseManifest.create!(
account_id: artifact.account_id,
environment_id: artifact.environment_id,
release_id: artifact.release_id,
release_artifact_id: artifact.id,
content: json,
)
end

# not sure why GzipReader#open doesn't take an io?
tar.close
io.close

artifact.update!(status: 'UPLOADED')

Expand Down
73 changes: 3 additions & 70 deletions spec/fixtures/files/expired.lic
Original file line number Diff line number Diff line change
@@ -1,70 +1,3 @@
-----BEGIN LICENSE FILE-----
eyJlbmMiOiJMbU01YWNYUWNHY2tZYnB1WUJmMDVTMHJFd1B3bklhdGt2N1Fy
MGxDWnovcEFwbGh1OHpJOGxrZlpNY3hRZWFydWtOUXdLOFpCYXJzVDUxbkh0
Z0VGTVN6TGxUc2hCRWZURDRKd01XNUlubUE3MHdNbWR3UkpVQU9TT2xZTE1v
Z2NpaTl0Q2VPczQrY2Nha0RsU2hzMitmQzJBSFAwRUVCYjQvRjQ5ZUh0Qk5C
VXJ5cHJUQXNOb2RqNG1ic1ZTQXowVUZiZXk5c2Q3OTFGdnlyaVF0MU8rYmVo
cjl4WGp0RmV3bThYcUFtR0tqcnU4RXVEQzdRWHduK1Fzb0ljRmI2OThkNnh2
aE9SL3ErbE1velV5b09CSktPM0NiRG40QjdwVFc2YlRHeFpCdUxna1V3QW5w
ZnBJem9sbDR5RmNQK0hHWVo0T05VdG52TnZ1eVlFUHp6VTRuOXpJQmMyckk1
Ym5mSkZSMFhBQ2ttTjNwczJzQVZGZ3E1UzNXQis3c0g3aHNyQ2ExNUNQYzcz
eXVWVVljUG9GV3R2UUczR3p0aDhLT1JIdHdqNWlKSlF6dFdBR3JYTjhvVU1Q
OWlPMkdRNGlEU1J0MGdlUFZhOVk4RUNOaWF2V1Vkbjd4dUNJTklRcUw5NUQv
QkEraGh0RkplSEhjYmV3V3lYNHNsSGZldlVjSVdmak0vWXkvRk1BWWM1TDIx
YjBmRnlxaHRTdVFXZG5HbmZ3cUlqSmI4bzRDaVdOd2ZIajJQc1FKTjR2Mm1Y
RGRCb0NSOWVCSG42MnAxUStoY2laUEZ6STlxOGoyd3huYkRGQjVDR1VBQUJC
b2c5SHJtaUxCUHBHNG1WY2FaQlNhWTdsNmlpanNGY3lxdVEwVnpLd2NoM1Nu
TUF5dE9jbTBmcmozZzd3bml4dWRIaVFhMCtxSDBHbzlFbHRHaE9FbEZjUlkw
b0xyUmZTUzZPM05jc2NBT3A0RFdFdGdnZlJFWkxaVmtxN0w5dW1qNThuLzJU
RFZaMllYNDAwbUZFNmxSNUJ0S0ZyMjd0Mmx6QXB1UFNWRGc1SFhRSzdjY3hO
TlhQSDdhbUptdzdmWWV4NnZYM0ZmWTZBNktwMXFYTk9keGVyWTduMmNUT1hK
Y3JxZXp1b1A2ck9WbUI4aTFuTVRrUzYvRFJSaGRJQy9SWWZHRWdONVlTdjNX
UkNsVDBLbjNrM1BOdzhvc2c0Yy96RnQwMHRmcFNNSTlodm1HUjhmTHdReVJ4
QUZrNDhaRE9TeGVMOVMwT0N0MHZxUTg3TUxoUGUxV1NneFI1VkthWjlTWE55
REMzeGo1eXlGM0lCOXgxRHBSWFRBaytETkQ3KzBjOUJKd0RBeFJjK3E3czVv
VGJnVGdUdTJyM24vUmpIaXZBcHJERlpPOVRSdmZOTTl3ZlpvM3VIZlM3MWo0
b3Y2ZkRvbkJybzdRZEdmd1FaTTUydWRja0hnZTlVTU5jNFVYbXZhcVkzUlVZ
Yzk5NnpnMWNFQ09DMVBleUZVRVA4RFFRdDRMaThlb1FUTkNFUEhIZitya3Bh
T0l5QlRyblBmdnRSMFFJai8wZzd5Sy9PME9abWNJZTlTQ3c1c0ttUitNckhp
RjY3VDQ4b29TNldybHhlc3E2ejFnRTlwME0rZXRnYnU1UnJtKzAramdmV2Ir
ZE4wNVdmUCtxQ3BZdGRwL0o4YmJSWWxWUlExWHFKWG1RRzJ0MW84eFk0YU9m
TG9JTG4yMTQ3TGZSY3oxRUhoSzBOazdrSXcvZVFsL0pwMDhIYWZMekhvSzVl
NmxYUGNTWnhjM05IbnZxZG1haVVXRVgzRGNNejl6UGtXRmFpSjlkZDA1cG80
aVBGemJQd2RQYXpSYWJjcy8zT1lUT3RhcGVTTTJyOXlLeU00SGZyS2NxcTEv
aW9WMlVGNEYrTTloenNBRVRvcEp4ZjI1N2dLSmRJUGUrYlZWNTM4RUVReS9M
SXVxTlhnUW9NRjVBVTU5eFdyRnliMkRUN3BrSkxlUDJudVA1T0FJM3BCRURs
WkNUM0xiUTg5WVZBOXk1WTBTK1ZKNVpvbUVZdThzYXAvMXJqWXZERCsxMTZ4
eUhCS1RiT0dUeWI2RmdxQkR1elhXZ3Blblo5VWRtSzk4OWlwT2prLzFsaWpF
WjNHSmFFd051U0FMeE5zMzZoaDl0bGxwVkM2Ny84RjI4RGhpZFFjOUJKUDJn
NFpYd25jcTRhL3BySWxRN3hVbjhSLzNydDlqSXhHSE1qWE8ra3Z3NFBidDA4
ZW1sZXNEcklMbjBrVDRreVJKSEMwazMvY1FES253bXhDdldVQld2cUtEa0pq
UXRHK1YzK1pvVm5IK2lQRGZSM0d4YnJSRENxNnM4UVRKQm5tbElnVHNobUZN
S0FiQWoyUHRpNWVjNHQ0azZ0Z2FMeDZaTExpRUd6MnVoWFpDUzJ4RVFGbHhU
ckVEbURqQkkrSmVoVUJXV2N4bUJNc2FsdWxLTCtvdWJyQWxNOVkrNThNM3lR
SmhEZWNvL0pyZU1RVEpEYmNqS0Y1L3ZQSFpDanlSc1dhdURacE1pcVlCNzVG
UTlRdkxHNVo4MWpLVVZJZlk0NTRGL1FCRW9ESDBqOXREV1FSQWJRZCtaTWQy
K3VyTnhMVnY1eHQyZ3BNeExBOWZuOUU3aHpXOHhuZEExdmszZHE3MkROeXhy
aGtMU2xlSFRiYmNBb0p1b1FDRFdoVWFmQ0pvdE5COHQwQ3c2ZEpGdTBKajdV
Si9kWCtPN1g5WDROWm1DUzM4K3hXZmpEWk01OWcvcG05VXF6YnpSc2x2WHRV
Z3VKNXlQRTVsMG92cDlPbTQ1OWcxZlpiV0xhNjlpUVRaQm5nNmVnOS9nVHY4
MjczK1RlTklFUlJZVmx5NERUWmwvOVQ5bkNUQ3JSUmUyaW50L2NRVDRIeUcx
ZnQ2dGZkcHV2d0VSQTI3SXNxOXhUdTd4UFFhNWdRR0NlbjdJSG5WZlVmbnhv
R2RsNnBpWUhGRVNITk5lV2RrY2hqQkR2MkxyMEovUU50WENLRGxpdHF2L1BL
UUVkelBKZnliLzlTRHI0RnJadGQ4QXkzSS9RcFJ4Mmc5VDR5R0pSUTFCV1Rj
RDIyaXpQckx1aFJXdjQ4TVk2c2lNaVVnbCtNWmlCZ2QzbUtia2VUdC9rNlBC
UndSYWd2YjIrbGRjdXZuT1Q4bjVmUUV1MXptYUcvZHovV3hhcVJrdFNxVFJl
VG04Nk5SbHBwVHd1S1Z5RlZtbFhCdEZXSEwrZ01jQ0ZqSytvNVM5YTFaN3N5
Q21Nei9ZQ1RBOW5NSlN2MlFKSVdBMWIzUzludTRyb3pWNjZjTnJzSnZ3ZWRa
bXhDMnk5aUhFWGY1SUhaNmFIWXVDWWZBWTFObE8zWDlKN2REU0UrNGFuQU12
ZFowRXVBV2tOaXFqYnhPbTA3T1VWWXRMYnd2WXBubjNIRHA0YllPZmtwb0U5
UW1FQm5KZjd4V0M0Sk00ZmhhREtCNDVERzJacHFqOE82NXQyTkk2NVBlRS9l
Ukd1Zkh3a1AvNitDNzFHWHY1czhZdUFJZUs3SHNHblZzSU53VFpRRmRCVE1C
a1hPZUozV3Q1Q1FyWGtQdTNrRU5ZQnQzRFNwM0FoT0UyQWdJd0U3S29sOC9H
U1JpVit3UEhqak5oU0svNFZtcHhIOTUwSlB1ZmZxcXIvTFhOSXAvWWtsaWZT
WVVMSkU2QThqVytrWXdjNUdtZXVsdTFpOXptYWxmQnVRTHp4d1kvekJkcVdv
YnhiNlFUcGhFeGlTZ2dBPT0uTExhTTVxQkVpSTYwaHRIMy5NY2Iybklxczd0
UnA4SDRKNkM0TDF3PT0iLCJzaWciOiJ5V0gycWRkWW9haFArcjVQN01ELzJP
REpxTWYvNy9udlE4U1pkaTkzbnUyWFBPaGU0K2ZucXdyVzJYbWg2Z0FRT1Ir
OXp6QjRKdnpXdEtxMG5TV21Ddz09IiwiYWxnIjoiYWVzLTI1Ni1nY20rZWQy
NTUxOSJ9
-----END LICENSE FILE-----
version https://git-lfs.github.com/spec/v1
oid sha256:2084119fe3a1137a01ff2f93fe0a94264dbc2bb7f4627e8676ff77f1354ed664
size 4152
Binary file modified spec/fixtures/files/hello-2.0.0.tgz
Binary file not shown.
Binary file modified spec/fixtures/files/invalid-1.0.0.gem
Binary file not shown.
Binary file modified spec/fixtures/files/invalid-2.0.0.tgz
Binary file not shown.
3 changes: 3 additions & 0 deletions spec/fixtures/files/large.tar.gz
Git LFS file not shown
Binary file modified spec/fixtures/files/ping-1.0.0-java.gem
Binary file not shown.
Binary file modified spec/fixtures/files/ping-1.0.0.gem
Binary file not shown.
126 changes: 3 additions & 123 deletions spec/fixtures/files/tampered.lic
Original file line number Diff line number Diff line change
@@ -1,123 +1,3 @@
-----BEGIN LICENSE FILE-----
eyJlbmMiOiJJd0RxQmc3N2xvUWtHQ0lrSTAvYlZNMFFMNm0yYmUwdCszMSs3
bEhkQjhxcFB4L0RldW9HZm1qcndpc0hCeUNnejBHTGhLMTBYRlQwTTIvdktG
TjdHNFV2UXpiMEZ5S3A4eGpBWWpuVkQzbGlxTmdFUVlHMTROZUpqc1BJczlu
V0xMSkVQSFcrL1R6Z0ZEblFKSmxycUlRbmlIaGpzWmVRQmIzeVJiREZzTTBh
VDFQYWRKVVVmOE51aTcvUnlBMHR2Z1U4QVFLMUJVdlFBM2tlbmNoempkRDJG
a2tIZjVMckNVTFMyQlFhWExsUTJJWnZVdktZM0liM3Jmb29RdHdLYmIzRmlC
UW5DaUh1ZEJjU0ljT1BkRGdRcmZCYkhsYlpPcTJXazlSNklRQ2VCeDB3M25F
MHFnaVRjZ056dHIvaDl6OUNZTXY3SEJCMXVPSFRYQmdXQmVMV3c3SDRSd3JJ
a1pIUnMycGNsRDBGS215UTlyamR1VHJETjV5ZzJydm1KRGpSSm9nSkxaQ1Vr
YzJHU3BzMGtHdDRuVEhjUDJsV3NhYXJnRDZhRU1sdm1qMGwrSUpHejF1bFNn
VUxyelFTU0tyM2dGZ3JPbVdRNk9QZDlXNXdPbndFdDZwdkc2SFpKM042akQ5
MVBJTUJ3emE4OHJwOG43aU0vWG9aeFVxOXpFQzdXd2dyUXFiZUJ0NUhidTVD
eHRHZ1g3VjUxRHVuQ21EYVpzek5LNXJ0K094ZzUrcWczTXNiSmdaeWk3dzY4
aFB6SHdadzhhTHVOYzFpVUE1L3ptVHhwelpJaHdkZWZJeUVWc3RYSEIvWWZL
a2s0Y3NDWWpUOUZGYURpMHdqdFJCZUdQYzRGTGFsZjNXSTMzRjRYNlErRi85
SFNLa2xLZTBacC8rZXpzR25tTlpNajN2TDVqT2t5MU41MllDZDdaZXZHLzRJ
Q3VQU0YrRy9naHp6VEdSRVRybGw0eU5WQ0FwWlh4VUFXcTZ4emFQa21ENERJ
L2YwVXRRL0MyN2RjSUlERkhoeExxUWYvdy9jSjRFQmpvajhGcWZUcVZxeG5j
K0NCNTBWRy80ZHNzUmNWUk9FZ1ZWbERPalI0czJuN1B1cmRWdlRLMHl0SG5q
WFc0ZkgvMkN3elBWSVY0Q2RyNFZiNHR6ZzA0Y2NlT2o2L1pxdXBEQWhLaksx
Y0UwZTZ0ZnF4VVNQTitDOHl4bjg1V1JKamFUUVFGTXJsOU43dmlJZFNxNWx6
aER5d1MwclN1L3dGUndKd3pwTFdpelJ0dkpPbW9BSk9TdHAzemdkdVNoK0pl
eDZBamFHN2s1eFdieEo2UDZtVWM5bWVpSU1kUmdxOUlYUXFtNUtrT0tDdUF0
b2IzTFlhYkljSFpaR0VRTFlvTFFaU1dKQUZndWd5TVk5a3F3c0c3aHJaTTRq
VjB4OUM2TFZHMEtQU1FzaGFka25Ec1l2SDZ1UGVTbHpONGdGUkZHSFVmWjNO
c1RQTWwzUXFNb2hrdUlyT05TcmY4NGl5UEdVRFhtUXhCMDJmTnhiQmxBOUov
Q0RwbkRnWG1BU2xwNloxam9qRUcxQTNUaUM4c2xENTdON0ppV3ZleWZQaWdV
YWdYd0M0eEVIRGg4TkRMcWpzYWVxanVWNVNkSXQ4ZU13RGdCbDNINjJvWW1i
bStLR25vZXhweDRCaWl0MGtlbHpJT0t6ZFVtS0lBR1BQZDJrdmVaOGJiQVRE
M3FJUXVocmd2eGszajVaRER0MGhQaGFsaytUZjFQN0g2TUx4M2h3WFNJdlBG
NFVIazFBK1hJdU5BZHdnWHZvVkxEYXNwZnBjZ3JCeXVBWDVRS0NTb1NiMG9G
Y2NDUUpNdGFNclFKeHRGeDNDc21EdE9aU2ZyQ3lzMFg3S2dYVGZ3UmZoRmVR
eHB4VlcvTm9Hc2FBOGdsbURyR0JrVm85eFFJdDNNOXNqbkRKQlN3S2xoVDNh
K1BFSU1ZeWRUSFUwaVlhVW5kN1U3VFBoV1JVK1pFM1REL25CdENFVjczbU1M
cUFqdTQrY2plOHFkSHRwcUozdVdKS0VjeXhvdk9RZnpnRHQvU2F5aDdaN1Jq
OEM1RGN4cGZnS1FPM05CaEYwbytNR29ld3RxNjlkblE2bmZBY2pxcDRvZ0Zr
WWltVm1DSVUyN2ZKV3IwWEZTbFZYdmpGM0dFN05ZV1I5ZkJUNWt0clIvekJY
RHdUSXcrcjRKUURkVGdXOXVTQVNhSHhCQzB3cG82engxd2JtWUVvSDRHeGt4
VTNDWTlMaXNTV2t3VXc2L0s0Vk1seGJ6Tm4wc08yU200OXdOeU5KL1IvcGlT
UFVIZjUvWnIvL2hWNzY4Q083Nk1maEZCNnloVFY5eWNtK2Q4ZkhwaitQV2dG
UnpGYk4yRkI4VEs5ZXRCeTVlNE11eHZldnR5N0JQY2xJVE1FZXZsNEYzRWZx
S1BDa0dNNnZiUktvNkMxUjBSMkN5S1prZ1ZkWmh2TkJhUDhwZTRHbnVxclBk
RGY2dFNyZFkzd0N2azg4aTRKV2Y0V2tic2Y5WUcwMEp6TGtTUy83UlZ6UG9Q
cFV3U1A3UDFYVjlvdkJCUENZVHpkVkZvTFY5V1dSa1lHMUFvQ2I1U1JaQy91
WEs0eHNOM1V6NlF6M0VSbzZ0MzMya2w4ak9HSU1jTkViSVN0aGc4UXg2UHdS
bXllNTBkVmJVM0o3Mmd4UEdCMWQ4aU94Y016Q3RVWGhuMklvYnZDSVN3cGlL
QmlSTU5ZNnlBWHhzZFBDRmhiVU1nMVlBOUp4Z043YW1LMy9XRFMrYzIycHgy
LzVYb292RHVoZFVuRThMYWlGQ01HZGgyWlo1MXpFNnkrYkpsZ05XV04zWXJ3
Zmg5VFZ6eUJKS2c1TVVEeHVtSmJ2SkJ4aXhWcExTa0NnTm1sSzJldUZnU1J2
dFpkcksyTjVLNXJMdk5oaHNiYTdpNUJQN0ZWNmtydEcrL21uZDhsd2ZEelI0
ZlJaalM3blhENmRTNWUxVVZ5eW0xcGZmUTlSZFFTeDNaSm5yQ0FGdHloUHIx
Q3pxRUY5citKb0lWdk94NU04dVZIcmdkM3RqVTZJSy92em9uNFRRSmY3T016
K1ZNYkNZcDV1ZTdVdkhsbFFWQ1NKL1g2RHJpcWp6Ty81bFllTzhTUStJdU9y
eXo1MXFMRFFPZk5vd1pWdVlESU1jQmlBNGxVakJJbUc5N2x0a1lPNFVjU2N4
VFdTandoUTVqNU1pWE9ZTkRGSE4yZlJvS2FtRDNVMExFcnRkVzdlMjVlREhB
M3VTSGM2U0Y1NTB0azhyOXZVQTRDODg5dlJwQ3RqTzk5RlFkVnBRRlR6Nmla
c1FTejRSbFA4WXVJelVmTHQ2R3R0dGJJamVlWnBLU285M1I5YkExQTZ5RFdw
ZThwcDN1Y2hxYVFHeU9iV1E3V2tib0lxU0NnVXVjRUdkbXhXY0pXYnZ3OGk4
eENRaklvYXFNZStQNDNiNkVmUDNxYlhZZFFDV0JzdzJTTmV0bU02c1UrZnNX
VnAvbVYzd2hkSzM2Y0Q1VjVmeFVjSmtqQ3RpbllEbjBDdzdJTVVNQUhleDlZ
YjJUZzVLOHV3V3k1dWhIaTRYMFNFYnphOS8wV0ZONnJFd1NoeDJzQjdqK0V3
QWZIZkxNb0ovc2FwZmhhT2dRemlPTkNoWTY0ZnFaa1Q1UWpSNCtyZlk4VjY1
RE1VZVZJMEc2Rm1kVXFRUEk1bVQyaDBlaklaYU9GMS9Yb3lEUHpBdW5XRk83
bTZ2TUQzKzdtTGNXbGoyVXBYRzNlMFJXTEN1UU9oMmEwVTVxbjlvdytFS3J6
YTdLYWFnSlA1Z0h5NDNPelU2c3RpdWhWVjUwQ3dwdVZpczVrSmFHcWQzbk1q
V2tVUFVmeW9YT2FOL3dXbkFaRDhVb0VQV2xKUlZyUmNZMVZlYTRubHJiSWNx
Snd1WWJoQWprU3UrdjJCOFJOek83TjhvNzNWeFMwb0JPMzlmUTZMUVgvQzd5
c0JvNzNPRjh4SklidDlQclJHeENFMWRLNG12UDlpbFFDNmVHQmI2aFA5S3Ja
Wk8rSmZTeXA1OTNsdlhjOHZGUmx6TUFCWE9KRzdkdzB3LzNsL3lVVnZ0b01C
Q3kwVnllTnY4VVBWU2lHbnpja3Y5c0U2U2p0VVhOLzBWdG1Ccy9GK3g2MC9y
ZStVYlNqMUdLaEZRRzA5U2FJQmZGbDNMRXZnczM1ZHBuV1dnWlE5TkFSN2hu
anEybTczVGhkMVk4L3ZVeGxQTFc4ZUpnYnBPeDFRSjNmTUJzbEFNVEFXdGcw
MHhmWHRKbWwvMGZ0dUI5ejFzaXVSaHplZURkc0FHRE5WZHR0RGcvU3VEc0pr
S1FsUnFWN1ZnSXRPdzdwMzY4WUdMSnJFRWQyc3N4WE96dXF3NmUxc1dtVC9q
YVgzSzBjZEgrWGxiRTVuemRUYjdvTWxVOEk0RHp1SlYxM2E2YVlRWmhUSFNU
a0NIY0Z6YzVVT1h1YkpldWI0TUNkdVhhRDRNVFMxMXhVM3NRTGNzTWtLdjJM
L29meUN1Y3BnRnNFWmQ3OFU2a0Y2WUhvRTlyTWg1MXJiaE1SdjJ2bFcvZ1Nr
d241Z0NkU2NMUEVEL1JmalFBb1VZRlY5V252RTBKQmw1N3lCWUhHaHIwUXlI
M0p1VWtaSFhqR0RVWlRYOEltOHd6eUNzUmFFTzA4M1JrMitYNU5TbEhQUmt1
ZDBETC9hSVFBS2NjcWRNUml0R3hSRFNwZ3B5RWI4d0tMZmFnZk11NGpaWUtG
OGJlV3loM0xkVnNWTEFRdjd6SFl4Q09VdmZUZ1BCQVdZUjY1eTZmaUErMFlS
SnZlTUZHNDdtbkRJVFNwdE9MN3o3WG1mTFVGdXU1ZVk2VFpnMzhkdkpSSkFy
RzlFTVdWSE9wTXRlZk1uL3JpY25SK1hUODh4akNmZG5UTU5abnRrTXkyejhO
SzRkemVaWEhSdzM3TVhxWEM3eTIrOU1hSkxod3VVNGt1dkRiNWVkZUpwdkhm
bUlwaXNRNWd3NkQzcGdCSG9kL2Q2cEt5THJyWnZCSFMvMzJZODNnSDgzR2Qx
NDhqRE9tdTNCd0pMeFdpQ2g5T3MveHd3aVYybDRVSG9hdFpITDZvaUJOUE1R
RjJGbFVLNXpOOXJ0WkwwaTRGOXMzckN3aUd4TExZL3VObmRkTm5DaHVFcVo3
YmRWZjFkNTdNa2pHZ2NnNWErOTB5WXBta2R3NW5vRkRjeGZUSU5iK2tMQnc4
ZWxoVFE5K1ZsWVJOUGVSbHZrNHYzbHp1aHV0Q0p6TVd2QnhieTdVQzRKOTUv
cm9JNlEzNnBLTzBaNVdWbDNXaTBjRnM2Y2ZBbFA5c0hYWkdSWG9URzVQSU0w
Y1BjNXBqRmIwUkVic0w4WUpGaVBqZk83d2t2VlJBYXVvK1dDb2piR2xlTUhI
QjBKWFV6WS9xZis0bEZUVjJjeHJaZjFadGp4MElleFR3ekVRUkltV2hidVhm
RnNXNE0zZTdSREFNUmNuR1hzZUtiMHRqT2cyVDI5R21oaUJYUTQzcGlob2Iz
V1VyM0dZZ2JmS1I3bnlDYVJMSktQZkpIdWhoN3ZmWE5RV1pGZGVZbURoYWwy
MUIxVkQ4azhub3JaN1Qwd21zeFJ0d3I4VW9LT1Qya3NzUU4rdkpxUis1NmtH
QlVIZkNjeGpvaVB6SXoyd0J4YytEcXFZSFhQUGxLVkoxeFhYUjBNN3ZTNllr
V2VwNGhCRG1rN3M3MURxQW1Rb2FaN0NjNVQzMGZlWW5UZ3VSMlFTSmR0MUh2
VVhPT0ZpVE5PTE5ZK3Y1OEJyemdOWmFZSU40OTRPeUs4ckViNWN5VWVkQkw5
SDM0VTJQcEpiOFhzaTZ1SmdPcCtkZEJNaEREWGg3QjkwSVRyOXoraE5YQ2hZ
OE4xZHBxakhhRVV0cmVHQmF6R2VTSG5FTGdSL2xNQnV2eWNkOGUyR1pNWCs2
ZjJ3MXl2R21iWElvNFdCMzdLSEU4Vjd1ZVF2d0Qvcm9tTDZzMXR1Mk1PcUFV
NTh5cllSQUFjUENvUzM3elNBcFhFTU5KcThIMldjb0JMcXE2US9Rclhzdk5t
aXNFeDdGZW1JbW8yZmFlT3cwZG5uSlEzUjRUZXY4d01Td24veWVWdytONzRJ
aTE0WU9rZG4xanBXVmorVkNVaC9ObW1sVGVOakRyaERVbVQvOGE5QTFNTGhn
Z3FxbVFVVHovdmpHb3lvdHYrdXlPVWJPZ0t2M0NLSDZ2aVVQajgyRlpJZWpo
cXZ6YTVxMFJEam1HdUw4TXQ4TW5sOW5mM2g0Q1pkV25ZdzUzY3dqR3MrQUEx
TmJLZFR0UUVaYmNraDJWb2hjeVRwZG1BbXlST3Z3TjlEdzYzRWtnVlM0N3Fs
ZVJocGVKMTRJSVcvYjlsYWNEa050Q2pPYk42cUhZZXpUVGJvb2pmeEdBTk1R
Sk9WTnVqcitTSHZuNEFUViswRjc3OFRZR0laczlISjJqYjA5dXlFTW9nYmN4
QjVnODdFZFJSQUs2cjE5YWhGeHptRHZZNTcyYlBmWDRWR21hSzgwOXNGZkRp
cFpWZmtQV2xrREtKYm1GeDlUZlNROEMrT3kwQjVEQXJvUFhRd3E1NG0wbllE
ZHA2Vm5mcC9qZzgzV293eFgzRkxyU2pleFFNMFJTQkl3WDdMbUJvNXlzU0Ri
Tnh2bzdTL3pyQVg2aGltbExPVDRDQU5NYnhqdVEwOTh6UUl3UGUvckdsaUVD
bFRoczJjSlFLQXUwWVlNa3o0NHRBcENJdUNsTnlGWlVkY08xNUhPbGMyNEhl
OWQrSTEzOE1OcGtRYXhjM0Q4RFJBdjZpMnlZdFl0eVIzNEJjT1BSa2NNY3I1
ejlMd0phQUpVdmZuZkgvek9EQ2dJWGkvZ1RXL09hOW4rZGFVTTJjZm0xdERw
L2pnWW5zRytKdUU9LlhmamFwVnFuQkNCZ2l1d2QuUmhCK1pWYTFMRzZtRnkz
d3Z5UFVjdz09Iiwic2lnIjoiblViRDFVU095bDNvQllJNnFqMElIeGN1YWlw
cEI3ZjlaQW1PT0VEMHMvMytzV3Bxa1hhUlA3YU1kNWtEbVRoQkdRTFVETzNl
ZS9KWUQvdGF3YUE4Q1E9PSIsImFsZyI6ImFlcy0yNTYtZ2NtK2VkMjU1MTki
fQ==
-----END LICENSE FILE-----
version https://git-lfs.github.com/spec/v1
oid sha256:bdf591aae6bbf27f34dfe25da87325d93abe61429f5c96ab598bf2f7ba912940
size 7381
Loading

0 comments on commit b63678f

Please sign in to comment.