Фон
У меня есть каталог файлов. Большинство из них .patch
файлы, хотя некоторые из них нет. Для каждого файла патча мне нужно отсканировать первую строку, которая всегда является строкой, и извлечь часть этой строки. С комбинацией имени каждого файла, этой части каждой первой строки и уникального идентификатора для каждого файла мне нужно создать ха sh, который я затем преобразую в json и запишу в файл.
Вот примеры:
Каталог файлов (пример)
|__ .gitkeep
|__ pmet-add-install-module-timings.patch
|__ pmet-change-sample-data-load-order.patch
|__ pmet-stop-catching-sample-data-errrors-during-install.patch
|__ pmet-fix-admin-label-word-breaking.patch
|__ pmet-declare-shipping-factory-for-compilation.patch.disabled
...
Примеры первой строки
Имя файла: pmet-add-install-module-timings.patch
Первая строка: diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php
Имя файла: pmet-change-sample-data-load-order.patch
Первая строка: diff --git a/vendor/magento/module-sample-data/etc/module.xml b/vendor/magento/module-sample-data/etc/module.xml
Имя файла: pmet-stop-catching-sample-data-errrors-during-install.patch
Первая строка: diff --git a/vendor/magento/framework/Setup/SampleData/Executor.php b/vendor/magento/framework/Setup/SampleData/Executor.php
Имя файла: pmet-fix-admin-label-word-breaking.patch
Первая строка: diff --git a/vendor/magento/theme-adminhtml-backend/web/css/styles-old.less b/vendor/magento/theme-adminhtml-backend/web/css/styles-old.less
JSON Пример файла
{
"patches": {
"magento/magento2-base": {
"Patch 1": "m2-hotfixes/pmet-add-install-module-timings.patch"
},
"magento/module-sample-data": {
"Patch 2": "m2-hotfixes/pmet-change-sample-data-load-order.patch"
},
"magento/theme-adminhtml-backend": {
"Patch 3": "m2-hotfixes/pmet-fix-admin-label-word-breaking.patch"
},
"magento/framework": {
"Patch 4": "m2-hotfixes/pmet-stop-catching-sample-data-errrors-during-install.patch"
}
}
}
Решение Пока что scrape.rb
Вот код целиком. Ниже я разберу его ниже:
files_hash = Hash.new
modules = Array.new
data_hash = {
patches: {}
}
files = Dir["*.patch"]
files.each do |file|
files_hash.store(files.index(file), file)
end
files_hash.each do |key, file|
value = File.open(file, &:readline).split('/')[3]
if value.match(/module-/) || value.match(/theme-/)
result = "magento/#{value}"
else
result = "magento2-base"
end
modules << result
modules.each do |val|
data_hash[:patches][val][key] = "m2-hotfixes/#{file}"
end
end
print data_hash
Прежде чем высветить проблему, мне нужно сначала подробно рассказать, что я сделал для достижения желаемого конечного результата:
Сначала я установил пустые файлы ha sh, массив модулей и данные ha sh:
files_hash = Hash.new
modules = Array.new
data_hash = {
patches: {}
}
Затем я сканирую каталог файлов исправлений на наличие .patch
файлов и сохраняю их в файлах ha sh со своими ключами. (Я полагаю, что я могу использовать ключи в качестве меток патчей в файле JSON):
files = Dir["*.patch"]
files.each do |file|
files_hash.store(files.index(file), file)
end
Далее я использую файл ha sh для чтения первой строки каждого файла патчей. Я заметил в файлах патчей паттерн, который, по моему мнению, будет надежным: каждый файл имеет magento/module-name
, magento/theme-name
или что-то еще. В случаях module-name
и theme-name
будет использоваться синтаксис magento/#{value}
. В случае "что-то еще" будет использоваться magento/magento2-base
:
files_hash.each do |key, file|
value = File.open(file, &:readline).split('/')[3]
if value.match(/module-/) || value.match(/theme-/)
result = "magento/#{value}"
else
result = "magento2-base"
end
modules << result
...
Это не самое лучшее решение (что, если структура diff изменится?), Но пока оно работает, и я не мог понять, какое регулярное выражение использовать для поиска строк и возврата того же результата. Приведенный выше код дает мне то, что я хочу, это следующий массив:
#=>["magento2-base", "magento/module-sample-data", "magento/theme-adminhtml-backend", "magento2-base"]
Далее, хотя я все еще могу получить доступ к именам файлов и ключам из файла ha sh, мне нужно l oop через этот массив и создавать хэши, которые имеют значения массива в качестве ключа и имена файлов в качестве значений (добавляются к пути к файлу). Вот так (или я так думал):
modules.each do |val|
data_hash[:patches][val][key] = "m2-hotfixes/#{file}"
end
end
Это та часть кода, с которой у меня возникают проблемы. Запуск этого дает мне следующую ошибку:
Traceback (most recent call last):
4: from scrape.rb:10:in `<main>'
3: from scrape.rb:10:in `each'
2: from scrape.rb:18:in `block in <main>'
1: from scrape.rb:18:in `each'
scrape.rb:19:in `block (2 levels) in <main>': undefined method `[]=' for nil:NilClass (NoMethodError)
Я заметил, что если я опущу key
, например, так: data_hash
до data_hash[:patches][val]
, я получу ха sh значений.
Итак, мой очевидный вопрос:
Почему мой подход к вложению хешей на один уровень дальше с использованием ключей не работает выше?