From: Igor Vlasenko <vlasenko@imath.kiev.ua> To: devel@lists.altlinux.org Subject: [devel] I: embedded language for src.rpm/spec file editing (part II). Date: Sat, 5 Nov 2011 21:18:43 +0200 Message-ID: <20111105191843.GA15650@dad.imath.kiev.ua> (raw) Уважаемые коллеги, продолжение вводной документации. == программирование на языке манипуляций spec-файлом == === Загрузка полезного кода опциями --hook === начнем знакомство с файла template.pl, содержащего шаблон для наиболее частых правок, которые приходится вносить в спек-файлы при импорте из Fedora. На основе такого шаблона при необходимости удобно создавать личный hook пакета с именем %{name}.pl, который в дальнейшем будет автоматически использоваться при импорте следующих версий этого пакета в системе fedoraimport. #!/usr/bin/perl -w Итак, файл: push @SPECHOOKS, sub { my ($spec, $parent) = @_; $spec->add_patch('',STRIP=>1); $spec->get_section('package','')->subst_body(qr'',''); $spec->get_section('package','')->subst_body_if(qr'','',qr'Requires:'); $spec->get_section('prep')->push_body(q!!."\n"); $spec->get_section('package','')->unshift_body('BuildRequires: '."\n"); }; Собственно, минимально необходимая обвязка - это push @SPECHOOKS, sub { my ($spec, $parent) = @_; }; Мы видим, что в наш код утилита передает 2 объекта perl: $spec, который соответствует текущему редактируемому spec-файлу или src.rpm пакету, и $parent, который соответствует предку редактируемого пакета - например, предыдущей версии этого пакета в Сизифе при импорте или старой версии пакета при обновлении. $spec определен всегда, $parent может и не быть определен. В наших простых примерах $parent не понадобится. Методы объекта $spec делятся на методы, применяемые ко всему spec-файлу, и методы, применяемые к отдельным секциям spec-файла. Примером методов на уровне spec-файла является метод add_patch. push @SPECHOOKS, sub { my ($spec, $parent) = @_; $spec->add_patch('foo-1.2-alt-fix-something.patch',STRIP=>3); }; Этот код скопирует файл foo-1.2-alt-fix-something.patch из ./patches в %_sourcedir данного пакета (возможно, временный каталог, созданный утилитой srpmnmu или ей родственной); Добавит в спек тег PatchXX: foo-1.2-alt-fix-something.patch, где XX -- некоторый незанятый номер, и добавит в секцию %prep строку %patchXX -p3 где 3 указано через параметр STRIP=>3. Другой пример -- метод add_source. Допустим, мы хотим провести NMU -- добавить в пакеты файлы .service для systemd. Насобираем коллекцию .service файлов, названных по имени пакета (вида %name.service), в папке ./patches. Создадим файл add_systemd_service.pl push @SPECHOOKS, sub { my ($spec, $parent) = @_; my $sourcenum=$spec->add_source('%name.service'); $spec->get_section('install')->push_body( 'install -Dm644 %{SOURCE'.$sourcenum.'} %buildroot%_systemd/%name.service'."n"); $spec->get_section('files')->push_body('%_systemd/%name.service'."n"); }; Передадим этот файл в утилиту girar-nmu-prepare --hook add_systemd_service.pl ... Метод add_source разворачивает '%name.service' в момент выполнения, поэтому наш код будет работать для каждого пакета, обрабатываемого с помощью girar-nmu utils, для которого найдется ./patches/%name.service. Метод add_source скопирует файл, добавит в спек тег SourceXX: %name.service Метод add_source возвращает число XX, которое позднее использовано в коде для добавления в секцию %install строки install -Dm644 %{SOURCEXX} %buildroot%_systemd/%name.service === Методы редактирования на уровне секции. === В предыдущем примере использовался метод редактирования на уровне секции push_body. В действительности, использовалась связка $spec->get_section('...'[,'...'])->push_body('some text'."\n"); Этот код можно еще переписать my $section = $spec->get_section('install'); $section->push_body('some text'."\n"); Т.е. сначала получаем объект секции %install, затем добавляем в конец секции строку 'some text'."\n" . Это отражает дизайн: сначала находим в spec-файлe нужную секцию, затем редактируем ее. === Получаем секции === Как получить секцию? примеры с get_section: # одна и та же главная секция (секция, # с которой начинается любой spec-файл) $spec->get_section('package',''); $spec->get_section('package'); # выделенный метод специально для главной секции $spec->get_main_section; # разные извращения, которые тоже работают # и возвращают главную секцию (Name: foo) $spec->get_section('package','-n foo'); $spec->get_section('package','-n %name'); # секция package для подпакета doc $spec->get_section('package','doc'); $spec->get_section('package','-n foo-doc'); $spec->get_section('package','-n %name-doc'); # секция files для подпакета doc $spec->get_section('files','doc'); Секции можно найти и по-другому. Переберем всевозможные У объекта $section есть методы get_type, get_canonical_package. Для секции files подпакета doc get_type равно 'files', get_canonical_package равно 'doc'. Пример: сосчитаем число секций %changelog. Наш rpm не допускает больше одной секции %changelog, но в сети можно найти всякое. push @SPECHOOKS, sub { my ($spec, $parent) = @_; my $count_changelog=0; foreach my $section ($spec->get_sections()) { $count_changelog++ if $section->get_type() eq 'changelog'; } print "What a horrible spec! $count_changelog changelogs." if $count_changelog>1; }; Заметим, что метод get_sections создает временный массив. и не годится для некоторых специальных случаев, когда мы в цикле удаляем секции, которых еще не посетили. Для таких особых случаев лучше использовать итератор: my $section = $spec->get_main_section; do { ... } while ($section=$section->next); Продолжение в части III: ==== Работа с телом секции ==== -- Dr. Igor Vlasenko -------------------- Topology Department Institute of Math Kiev, Ukraine -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
reply other threads:[~2011-11-05 19:18 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20111105191843.GA15650@dad.imath.kiev.ua \ --to=vlasenko@imath.kiev.ua \ --cc=devel@lists.altlinux.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
ALT Linux Team development discussions This inbox may be cloned and mirrored by anyone: git clone --mirror http://lore.altlinux.org/devel/0 devel/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 devel devel/ http://lore.altlinux.org/devel \ devel@altlinux.org devel@altlinux.ru devel@lists.altlinux.org devel@lists.altlinux.ru devel@linux.iplabs.ru mandrake-russian@linuxteam.iplabs.ru sisyphus@linuxteam.iplabs.ru public-inbox-index devel Example config snippet for mirrors. Newsgroup available over NNTP: nntp://lore.altlinux.org/org.altlinux.lists.devel AGPL code for this site: git clone https://public-inbox.org/public-inbox.git