123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008 |
- #! /usr/bin/perl -w
- # ex:ts=4
- #
- # portlint - lint for port directory
- # implemented by:
- # Jun-ichiro itojun Hagino <itojun@itojun.org>
- # Yoshishige Arai <ryo2@on.rim.or.jp>
- #
- # Copyright(c) 1997 by Jun-ichiro Hagino <itojun@itojun.org>.
- # All rights reserved.
- # Freely redistributable. Absolutely no warranty.
- #
- # Please note that this perl code used to be able to handle (Open|Net|Free)BSD
- # bsd.port.mk. There are significant differences in those so non-FreeBSD code
- # was removed.
- #
- # $MCom$
- #
- use strict;
- use warnings;
- use Getopt::Std;
- use File::Find;
- use IPC::Open2;
- use File::Basename;
- use POSIX qw(strftime);
- sub perror($$$$);
- our ($opt_a, $opt_A, $opt_b, $opt_C, $opt_c, $opt_g, $opt_h, $opt_m, $opt_t, $opt_v, $opt_M, $opt_N, $opt_B, $opt_V, @ALLOWED_FULL_PATHS);
- my ($err, $warn);
- my ($extrafile, $parenwarn, $committer, $verbose, $usetabs, $newport,
- $grouperrs, $checkmfiles);
- my $contblank;
- my $portdir;
- my $makeenv = "";
- my @errlst = ();
- my %errcache = ();
- $err = $warn = 0;
- $extrafile = $parenwarn = $committer = $verbose = $usetabs = $newport = 0;
- $checkmfiles = 0;
- $contblank = 1;
- $portdir = '.';
- @ALLOWED_FULL_PATHS = qw(/boot/loader.conf /compat/ /dev/null /etc/fstab /etc/inetd.conf /proc);
- # version variables
- my $major = 2;
- my $minor = 19;
- my $micro = 14;
- # default setting - for FreeBSD
- my $portsdir = '/usr/ports';
- my $rcsidstr = 'FreeBSD';
- my $localbase = '/usr/local';
- my $numpitems = 6;
- my %lang_pref = qw(
- arabic ar
- chinese zh
- french fr
- german de
- hebrew iw
- hungarian hu
- japanese ja
- korean ko
- polish pl
- portuguese pt
- russian ru
- ukrainian uk
- vietnamese vi
- );
- my @lang_cat = keys %lang_pref;
- my @lang_short = values %lang_pref;
- my $re_lang_short = '(' . join('|', @lang_short) . ')-';
- my ($prog) = ($0 =~ /([^\/]+)$/);
- sub usage {
- print STDERR <<EOF;
- usage: $prog [-AabCcghmvtN] [-M ENV] [-B#] [port_directory]
- -a additional check for scripts/* and pkg-*
- -A turn on all additional checks (equivalent to -abcmNt)
- -b warn \$(VARIABLE)
- -c committer mode (implies -m)
- -C pedantic committer mode (equivalent to -abcmt)
- -g group errors together to avoid duplication (disabled if -v is specified)
- -h show summary of command line options
- -v verbose mode
- -t nit pick about use of spaces
- -m check \${PORTSDIR}/MOVED, UIDs, and GIDs files
- -N writing a new port
- -V print the version and exit
- -M ENV set make variables to ENV (ex. PORTSDIR=/usr/ports.work)
- -B# allow # contiguous blank lines (default: $contblank line)
- EOF
- exit 0;
- }
- sub version {
- print "$prog version $major.$minor.$micro\n";
- exit $major;
- }
- getopts('AabCcghmtvB:M:NV');
- &usage if $opt_h;
- &version if $opt_V;
- $extrafile = 1 if $opt_a || $opt_A || $opt_C;
- $parenwarn = 1 if $opt_b || $opt_A || $opt_C;
- $committer = 1 if $opt_c || $opt_A || $opt_C;
- $verbose = 1 if $opt_v;
- $grouperrs = 1 if $opt_g && !$opt_v;
- $checkmfiles = 1 if $opt_m || $opt_c || $opt_A || $opt_C;
- $newport = 1 if $opt_N || $opt_A;
- $usetabs = 1 if $opt_t || $opt_A || $opt_C;
- $contblank = $opt_B if $opt_B;
- $makeenv = $opt_M if $opt_M;
- $portdir = $ARGV[0] ? $ARGV[0] : '.';
- # The PORTSDIR environment variable overrides our defaults.
- # And if PORTSDIR is defined in /etc/make.conf, that will
- # be checked next.
- if (defined $ENV{'PORTSDIR'}) {
- $portsdir = $ENV{PORTSDIR};
- } else {
- my $mconf_portsdir = &get_makeconf_var('PORTSDIR');
- if ($mconf_portsdir ne '') {
- $portsdir = $mconf_portsdir;
- }
- }
- $ENV{'PL_GIT_IGNORE'} //= '';
- my $mfile_moved = "${portsdir}/MOVED";
- my $mfile_uids = "${portsdir}/UIDs";
- my $mfile_gids = "${portsdir}/GIDs";
- if ($verbose) {
- print "OK: config: portsdir: \"$portsdir\" ".
- "localbase: $localbase ".
- "\n";
- }
- #
- # just for safety.
- #
- if (! -d $portdir) {
- print STDERR "FATAL: invalid directory $portdir specified.\n";
- exit 1;
- }
- chdir "$portdir" || die "$portdir: $!";
- # get make vars
- my @varlist = qw(
- PORTNAME PORTVERSION PORTREVISION PORTEPOCH PKGNAME PKGBASE
- PKGNAMEPREFIX PKGNAMESUFFIX DISTVERSIONPREFIX DISTVERSION
- DISTVERSIONSUFFIX DISTNAME DISTFILES CATEGORIES MASTERDIR MAINTAINER
- MASTER_SITES WRKDIR WRKSRC NO_WRKSUBDIR SCRIPTDIR FILESDIR
- PKGDIR COMMENT WWW DESCR PLIST PKGCATEGORY PKGINSTALL PKGDEINSTALL
- PKGREQ PKGMESSAGE DISTINFO_FILE .CURDIR USE_LDCONFIG USE_AUTOTOOLS
- USE_GNOME USE_PERL5 USE_QT USE_QT5 INDEXFILE PKGORIGIN
- CONFLICTS CONFLICTS_BUILD CONFLICTS_INSTALL PKG_VERSION
- PLIST_FILES PLIST_DIRS PORTDOCS PORTEXAMPLES
- OPTIONS_DEFINE OPTIONS_RADIO OPTIONS_SINGLE OPTIONS_MULTI
- OPTIONS_GROUP OPTIONS_SUB INSTALLS_OMF USE_RC_SUBR USES DIST_SUBDIR
- ALLFILES CHECKSUM_ALGORITHMS INSTALLS_ICONS GNU_CONFIGURE
- CONFIGURE_ARGS MASTER_SITE_SUBDIR LICENSE LICENSE_COMB NO_STAGE
- DEVELOPER SUB_FILES SHEBANG_LANG MASTER_SITES_SUBDIRS FLAVORS
- USE_PYTHON LICENSE_PERMS USE_PYQT USE_GITHUB USE_GITLAB
- );
- my %makevar;
- my $i = 0;
- for (split(/\n/, get_makevar(@varlist))) {
- $_ =~ s/\0//;
- print "OK: makevar: $varlist[$i] = $_\n" if ($verbose);
- $makevar{$varlist[$i]} = $_;
- $i++;
- }
- #
- # variables for global checks.
- #
- my $sharedocused = 0;
- my %predefined = ();
- my @popt = ();
- # historical, no longer in FreeBSD's bsd.sites.mk
- foreach my $i (split(/\n/, <<EOF)) {
- GNU ftp://prep.ai.mit.edu/pub/gnu/%SUBDIR%/
- SUNSITE ftp://sunsite.unc.edu/pub/Linux/%SUBDIR%/
- EOF
- my ($j, $k) = split(/\t+/, $i);
- $predefined{$k} = $j;
- }
- # Read bsd.sites.mk
- my $sites_mk = "$portsdir/Mk/bsd.sites.mk";
- open(MK, $sites_mk) || die "$sites_mk: $!";
- my @site_groups = grep($_ = /^MASTER_SITE_(\w+)/ && $1, <MK>);
- close(MK);
- my $cmd = join(' -V MASTER_SITE_', "make $makeenv ", @site_groups);
- $i = 0;
- open2(\*IN, \*OUT, $cmd);
- close(OUT);
- while (<IN>) {
- my $g = $site_groups[$i];
- for my $s (split()) {
- $predefined{$s} = $g;
- }
- $i++;
- }
- close(IN);
- open(MK, 'Makefile') || die "Makefile: $!";
- my $ulineno = -1;
- my $uulineno = -1;
- my @muses = ();
- my @omuses = ();
- while (my $mline = <MK>) {
- if ($uulineno == -1 && $mline =~ /^USE_/) {
- $uulineno = $.;
- }
- if ($mline =~ /^USES[?+]?=\s*(.*)/) {
- if ($ulineno == -1) {
- $ulineno = $.;
- }
- if ($1) {
- push @muses, split(/\s+/, $1);
- }
- }
- if ($mline =~ /^[\w\d]+_USES[?+]?=\s*(.*)/) {
- if ($1) {
- push @omuses, split(/\s+/, $1);
- }
- }
- }
- if ($uulineno > -1 && $ulineno > -1 && $uulineno < $ulineno) {
- &perror("WARN", 'Makefile', $uulineno, "USE_* seen before USES. ".
- "According to the porters-handbook, USES must appear first.");
- }
- my %hmuses = map { $_ => 1 } @muses;
- foreach my $omuse (@omuses) {
- if ($hmuses{$omuse}) {
- &perror("WARN", 'Makefile', -1, "$omuse is specified in both USES ".
- "and a optional *_USES. It only needs to be specified in one.");
- }
- }
- foreach my $muse (@muses) {
- $makevar{USES} .= " " . $muse;
- }
- #
- # check for files.
- #
- my @checker = ($makevar{DESCR}, 'Makefile', $makevar{DISTINFO_FILE});
- my %checker = (
- $makevar{DESCR} => \&checkdescr,
- 'Makefile' => \&checkmakefile,
- $makevar{DISTINFO_FILE} => \&checkdistinfo
- );
- if ($extrafile) {
- my @files = (
- <$makevar{SCRIPTDIR}/*>,
- @makevar{qw(DESCR PLIST PKGINSTALL PKGDEINSTALL PKGREQ PKGMESSAGE)}
- );
- foreach my $i (@files) {
- next if (! -T $i);
- next if (defined $checker{$i});
- if ($i =~ /\bpkg-plist/) {
- unshift(@checker, $i);
- $checker{$i} = \&checkplist;
- } else {
- push(@checker, $i);
- $checker{$i} = \&checkpathname;
- }
- }
- }
- if ($checkmfiles) {
- foreach my $i ($mfile_moved, $mfile_uids, $mfile_gids) {
- next if (! -T $i);
- next if (defined $checker{$i});
- push(@checker, $i);
- $checker{$i} = \&checkmfile;
- }
- }
- foreach my $i (<$makevar{FILESDIR}/patch-*>) {
- next if (! -T $i);
- next if (defined $checker{$i});
- push(@checker, $i);
- $checker{$i} = \&checkpatch;
- }
- foreach my $i (@checker) {
- print "OK: checking $i.\n" if ($verbose);
- if (! -f "$i") {
- &perror("FATAL", "", -1, "no $i in \"$portdir\".") unless $i eq $makevar{DISTINFO_FILE} && $makevar{DISTFILES} eq "";
- } else {
- my $proc = $checker{$i};
- &$proc($i) || &perror("", "", -1, "Cannot open the file $i\n");
- if ($proc ne \&checkpatch) {
- &checklastline($i)
- || &perror("", "", -1, "Cannot open the file $i\n");
- }
- }
- }
- checkpatches(<$makevar{FILESDIR}/patch-*>);
- if ($committer) {
- sub find_proc {
- return if /^\.\.?$/;
- (my $fullname = $File::Find::name) =~ s#^\./##;
- print "OK: checking the file name of $fullname.\n" if ($verbose);
- if ($fullname eq 'work') {
- &perror("FATAL", $fullname, -1, "be sure to cleanup the working directory ".
- "before committing the port.");
- $File::Find::prune = 1;
- } elsif (-l) {
- &perror("WARN", $fullname, -1, "this is a symlink. ".
- "Please remove it.");
- } elsif (-z) {
- &perror("FATAL", $fullname, -1, "empty file and should be removed. ".
- "If it still needs to be there, put a dummy comment ".
- "to state that the file is intentionally left empty.");
- } elsif (-d && scalar(my @x = <$_/{*,.?*}>) <= 1) {
- &perror("FATAL", $fullname, -1, "empty directory should be removed.") unless ($fullname =~ /^\.git/);
- } elsif (/^\./) {
- &perror("WARN", $fullname, -1, "dotfiles are not preferred. ".
- "If this file is a dotfile to be installed as an example, ".
- "consider importing it as \"dot$_\".") unless
- (-d && $_ eq '.git');
- } elsif (/[^-.a-zA-Z0-9_\+]/) {
- &perror("WARN", $fullname, -1, "only use characters ".
- "[-_.a-zA-Z0-9+] for patch or script names.");
- } elsif (/\.(orig|rej|bak)$/ || /~$/ || /^\#/) {
- &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
- "backup files before committing the port.");
- } elsif (/(^|\.)core$/) {
- &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
- "core files before committing the port.");
- } elsif (/README.html/) {
- &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
- "README.html files before committing the port.");
- } elsif ($_ eq '.git' && -d) {
- &perror("FATAL", $fullname, -1, "for safety, be sure to cleanup ".
- "git files before committing the port.");
- $File::Find::prune = 1;
- } elsif (-f) {
- my $fullpath = $makevar{'.CURDIR'}.'/'.$fullname;
- my $result = `type git >/dev/null 2>&1 && git status --porcelain $fullpath`;
- chomp $result;
- if (substr($result, 0, 1) eq '?') {
- &perror("FATAL", "", -1, "$fullname not under git.")
- unless (eval { /$ENV{'PL_GIT_IGNORE'}/, 1 } &&
- /$ENV{'PL_GIT_IGNORE'}/);
- }
- }
- }
- find(\&find_proc, '.');
- # Check for ports that may break INDEX
- my $indexerr = `env LOCALBASE=/nonexistentlocal make $makeenv describe 2>&1 >/dev/null`;
- chomp $indexerr;
- $indexerr =~ tr/\n/ /s;
- &perror("FATAL", "", -1, "breaks INDEX ($indexerr).")
- if ($indexerr);
- # Suggest to set DEVELOPER knob in /etc/make.conf
- if (!$makevar{DEVELOPER}) {
- &perror("WARN", "", -1, "Consider to set DEVELOPER=yes in /etc/make.conf");
- }
- }
- if ($err || $warn) {
- my($errtext, $warntext) = ("error", "warning");
- $errtext .= "s" unless ($err == 1);
- $warntext .= "s" unless ($warn == 1);
- if ($grouperrs) {
- foreach my $msg (@errlst) {
- my $lines;
- if ($errcache{$msg} && scalar(@{$errcache{$msg}})) {
- $lines = "[" . (join(",", @{$errcache{$msg}})) . "]: ";
- } else {
- $lines = "";
- }
- $msg =~ s/%%LINES%%/$lines/;
- print $msg, "\n";
- }
- }
- printf("%d fatal %s and %d %s found.\n", $err, $errtext, $warn, $warntext);
- } else {
- print "looks fine.\n";
- }
- exit $err;
- #
- # distinfo
- #
- sub checkdistinfo {
- my($file) = @_;
- my($dist_subdir) = $makevar{DIST_SUBDIR};
- my(@allfiles) = split (/\s+/, $makevar{ALLFILES});
- my %algorithms = ();
- my %records = ();
- foreach my $i (split (/\s+/, uc ($makevar{CHECKSUM_ALGORITHMS}))) {
- $algorithms{$i} = 1;
- }
- open(IN, "< $file") || return 0;
- while (<IN>) {
- if (/^\s*$/) {
- &perror("FATAL", $file, $., "found blank line.");
- next;
- }
- if (/^TIMESTAMP\s+=\s+(\d+)$/) {
- my $now = time;
- if ($1 > $now) {
- &perror("FATAL", $file, $., "TIMESTAMP is in the future");
- }
- next;
- }
- if (/(\S+)\s+\((\S+)\)\s+=\s+(\S+)/) {
- my ($tag, $path, $value) = ($1, $2, $3);
- if ($records{$path}{$tag}) {
- &perror("FATAL", $file, $., "duplicate file listed.");
- }
- $records{$path}{$tag} = $value;
- if (!$algorithms{$tag} && $tag ne "SIZE") {
- &perror("FATAL", $file, $., "unsupported checksum algorithm ".
- "found: $tag.");
- }
- } else {
- &perror("FATAL", $file, $., "line format error.");
- }
- }
- close(IN);
- # For all files check SIZE and checksums
- foreach my $f (@allfiles) {
- # Remove hindering chars from DISTNAME
- $f =~ s/['\\]//g;
- my $path = $f;
- $path = "$dist_subdir/$f" if $dist_subdir;
- if (!defined($records{$path}{SIZE})) {
- &perror("FATAL", $file, -1, "has no SIZE record for $path.");
- }
- my $n = 0;
- foreach my $alg (keys %algorithms) {
- $n++ if exists($records{$path}{$alg});
- }
- if ($n == 0) {
- &perror("FATAL", $file, -1, "no checksum record for $path.");
- }
- if ($n < scalar(keys %algorithms)) {
- &perror("WARN", $file, -1, "no checksum records for all ".
- "supported algorithms (".join(" ",keys %algorithms).") for ".
- "$path.");
- }
- }
- return 1;
- }
- #
- # pkg-descr
- #
- sub checkdescr {
- my($file) = @_;
- my(%maxchars) = ($makevar{DESCR}, 80);
- my(%maxlines) = ($makevar{DESCR}, 24);
- my(%minlines) = ($makevar{DESCR}, 2);
- my(%toolongerrmsg) = ($makevar{DESCR},
- "exceeds $maxlines{$makevar{DESCR}} ".
- "lines, make it shorter if possible.");
- my(%tooshorterrmsg) = ($makevar{DESCR},
- "contains less than $minlines{$makevar{DESCR}} ".
- "lines, make it longer if possible.");
- my($longlines, $linecnt, $tmp) = (0, 0, "");
- open(IN, "< $file") || return 0;
- while (<IN>) {
- if ($_ =~ /[ \t]+\n?$/) {
- &perror("WARN", $file, $., "whitespace before end ".
- "of line.");
- }
- $tmp .= $_;
- chomp || &perror("WARN", $file, -1, "lines should terminate with a ".
- "newline (i.e. '\\n').");
- if (/
$/) {
- &perror("WARN", $file, -1, "lines should not contain carriage ".
- "returns. Strip all carriage returns (e.g. run dos2unix) ".
- "in $file.");
- }
- if (/^WWW:(\s+)(\S*)/) {
- my $wwwurl = $2;
- &perror("WARN", $file, -1, "the URL of the project website has been ".
- "moved into the Makefile. ".
- "Remove the WWW: line from this file and add \"WWW=$wwwurl\"".
- "to the Makefile immediately below the COMMENT line.");
- }
- $linecnt++;
- $longlines++ if ($maxchars{$file} < length);
- }
- if ($linecnt > $maxlines{$file}) {
- &perror("WARN", $file, -1, "$toolongerrmsg{$file}".
- "(currently $linecnt lines)");
- } elsif ($linecnt < $minlines{$file}) {
- &perror("WARN", $file, -1, "$tooshorterrmsg{$file}".
- "(currently $linecnt ".($linecnt > 1 ? "lines" : "line").")");
- } else {
- print "OK: $file: has $linecnt lines.\n" if ($verbose);
- }
- if ($longlines > 0) {
- &perror("WARN", $file, -1, "includes lines that exceed $maxchars{$file} ".
- "characters.");
- }
- if ($tmp =~ /[\033\200-\377]/) {
- &perror("WARN", $file, -1, "includes iso-8859-1, or ".
- "other local characters. files should be in ".
- "plain 7-bit ASCII");
- }
- if ($file =~ /\bpkg-descr/ && $tmp =~ m,https?://,) {
- my $has_url = 0;
- my $has_www = 0;
- my $cpan_url = 0;
- my $has_endslash = 0;
- foreach my $line (grep($_ =~ "https?://", split(/\n+/, $tmp))) {
- $has_url = 1;
- if ($line =~ m,WWW:[ \t]+https?://,) {
- $has_www = 1;
- if ($line =~ m,search.cpan.org,) {
- $cpan_url = 1;
- if ($line =~ m,/$,) {
- $has_endslash = 1;
- }
- }
- }
- }
- if (!$has_url) {
- &perror("WARN", $file, -1, "add \"WWW: URL:\" for this port if possible");
- }
- if ($cpan_url && !$has_endslash) {
- &perror("WARN", $file, -1, "end WWW CPAN URL with a \"/\"");
- }
- if ($has_url && ! $has_www) {
- &perror("FATAL", $file, -1, "contains a URL but no \"WWW:\"");
- }
- }
- close(IN);
- }
- #
- # pkg-plist
- #
- sub checkplist {
- my($file) = @_;
- my($curdir) = ($localbase);
- my $seen_special = 0;
- my $item_count = 0;
- my $owner_seen = 0;
- my $group_seen = 0;
- my $found_so = 0;
- # Variables that are allowed to be out-of-sync in the XXXDIR check.
- # E.g., %%PORTDOCS%%%%RUBY_MODDOCDIR%% will be OK because there is
- # no %%PORTRUBY_MODDOC%% substitution.
- my %check_xxxdir_ok = (
- "DOCS" => "DOCS",
- "EXAMPLES" => "EXAMPLES",
- "DATA" => "DATA",
- "RUBY_DOC" => "DOCS",
- "RUBY_EXAMPLES" => "EXAMPLES",
- "RUBY_MODDOC" => "DOCS",
- "RUBY_MODEXAMPLES" => "EXAMPLES",
- );
- open(IN, "< $file") || return 0;
- while (<IN>) {
- $item_count++;
- if ($_ =~ /[ \t]+\n?$/) {
- &perror("WARN", $file, $., "whitespace before end ".
- "of line.");
- }
- # make it easier to handle.
- $_ =~ s/\s+$//;
- $_ =~ s/\n$//;
- if ($_ eq "") {
- &perror("WARN", $file, $., "empty line found in plist.");
- }
- # store possible OPTIONS knobs for OPTIONS_SUB
- if ($makevar{OPTIONS_SUB}) {
- while (/\%\%([^%]+)\%\%/g) {
- if ($1 =~ /PORTDOCS/) {
- push @popt, "DOCS";
- } elsif ($1 =~ /PORTEXAMPLES/) {
- push @popt, "EXAMPLES";
- } else {
- push @popt, $1;
- }
- }
- }
- if ($_ =~ /\.DS_Store/) {
- &perror("WARN", $file, $., ".DS_Store meta data files must not ".
- "be installed.");
- }
- if (m'lib/perl5/site_perl/mach/%%PERL_VER%%') {
- &perror("WARN", $file, $., "use \%\%SITE_ARCH\%\% ".
- "instead of lib/perl5/site_perl/mach/\%\%PERL_VER\%\%");
- } elsif (m'lib/perl5/site_perl') {
- &perror("WARN", $file, $., "use \%\%SITE_PERL\%\% ".
- "instead of lib/perl5/site_perl.");
- }
- if (m'([\w\d]+-portbld-freebsd\d+\.\d+)') {
- &perror("WARN", $file, $., "possible direct use of the ".
- "CONFIGURE_TARGET value ($1). Consider using the plist ".
- "substitution %%CONFIGURE_TARGET%% instead.");
- }
- if (m'\@dirrm(try)?\s+libdata/pkgconfig') {
- &perror("FATAL", $file, $., "libdata/pkgconfig should not be ".
- "removed. It is listed in BSD.local.dist.");
- }
- if (m'\@dirrm(try)?\s') {
- &perror("WARN", $file, $., "\@dirrm[try] is deprecated. If you ".
- "require special directory handling, use \@dir instead and ".
- "consult the porter's handbook.");
- }
- if (m'\@cwd') {
- &perror("WARN", $file, $., "\@cwd is deprecated. Please use ".
- "absolute pathnames instead.");
- }
- if (m'\@stopdaemon\s') {
- &perror("WARN", $file, $., "\@stopdaemon is deprecated. The ".
- "pkg(8) has a generic mechanism to provide the same function, ".
- "see HANDLE_RC_SCRIPTS in pkg.conf(5).");
- }
- if (m'^\@(un)?exec') {
- &perror("WARN", $file, $., "@[un]exec is deprecated in ".
- "favor of \@<pre|post>[un]exec as the latter specifies ".
- "the exact part of the pkg lifecycle the commands need ".
- "to run");
- }
- $seen_special++ if /[\%\@]/;
- if ($_ =~ /^\@/) {
- if ($_ =~ /^\@(cwd|cd)[ \t]+(\S+)/) {
- $curdir = $2;
- } elsif ($_ =~ /^\@unexec[ \t]+rm[ \t]/) {
- if ($_ !~ /%[DB]/) {
- &perror("WARN", $file, $., "use \"%D\" or \"%B\" to ".
- "specify prefix.");
- }
- if ($_ !~ /true$/ && $_ !~ /rm -f/) {
- &perror("WARN", $file, $., "add \"2>&1 ".
- ">/dev/null || true\" ".
- "to \"\@unexec rm\".");
- }
- } elsif ($_ =~ /^\@unexec[ \t]+rmdir/) {
- if ($_ !~ /%[DB]/) {
- &perror("WARN", $file, $., "use \"%D\" or \"%B\" to ".
- "specify prefix.");
- }
- &perror("WARN", $file, $., "use \"\@dirrmtry\" ".
- "instead of \"\@unexec rmdir\".");
- } elsif ($_ =~ /^\@unexec[ \t]+install-info[ \t]+--delete\s+(.+)\s+(.+)$/) {
- &perror("WARN", $file, $., "\@unexec install-info is deprecated in favor of adding info files into the Makefile using the INFO macro.");
- } elsif ($_ =~ /^\@(pre|post)?(exec|unexec|)/) {
- if (/ldconfig/) {
- &perror("WARN", $file, $., "possible ".
- "direct use of ldconfig ".
- "in PLIST found. use ".
- "USE_LDCONFIG instead.");
- }
- if (/scrollkeeper/) {
- &perror("WARN", $file, $., "possible ".
- "direct use of scrollkeeper commands ".
- "in PLIST found. Use ".
- "INSTALLS_OMF instead ".
- "(see http://www.FreeBSD.org/gnome/docs/porting.html ".
- "for more details).");
- }
- } elsif ($_ =~ /^\@(comment)/) {
- &perror("FATAL", $file, $., "\$$rcsidstr\$ is deprecated in Git.") if (/\$$rcsidstr[:\$]/);
- } elsif ($_ =~ m!^\@(dirrm|dirrmtry)\s+/!) {
- &perror("WARN", $file, $., "Using \@$1 with absolute path ".
- "will not work as you expected in most cases. Use ".
- "\@dir... if you want to remove a directory such as ".
- "/var/\${PORTNAME}");
- } elsif ($_ eq "\@cwd") {
- ; # @cwd by itself means change directory back to the original
- # PREFIX.
- } elsif ($_ =~ /^\@\(/) {
- if ($_ !~ /^\@\([^,]*,[^,]*,[^\),]*(,[^\)]*)?\)/) {
- &perror("WARN", $file, $., "Invalid use of \@(...). ".
- "Arguments should be owner,group,perms[,fflags]");
- }
- } elsif ($_ =~ /^\@sample\s+(.+)/) {
- my $sl = $.;
- my @sampleparts = split(/\s+/, $1);
- if (scalar @sampleparts == 1 && $sampleparts[0] !~ /\.sample$/) {
- &perror("WARN", $file, $sl, "\@sample directive references".
- " file that does not end in ``.sample''. Sample".
- " files must end in ``.sample''.");
- }
- } elsif ($_ =~ /^\@owner/) {
- if ($_ =~ /^\@owner\s+.+/) {
- if ($owner_seen > 0) {
- &perror("WARN", $file, $., "Nested setting of \@owner ".
- "found. Reset \@owner before setting it again.");
- }
- $owner_seen++;
- } else {
- if ($owner_seen == 0) {
- &perror("WARN", $file, $., "\@owner reset seen before ".
- "a new owner section was started.");
- }
- $owner_seen--;
- }
- } elsif ($_ =~ /^\@group/) {
- if ($_ =~ /^\@group\s+.+/) {
- if ($group_seen > 0) {
- &perror("WARN", $file, $., "Nested setting of \@group ".
- "found. Reset \@group before setting it again.");
- }
- $group_seen++;
- } else {
- if ($group_seen == 0) {
- &perror("WARN", $file, $., "\@group reset seen before ".
- "a new group section was started.");
- }
- $group_seen--;
- }
- } elsif ($_ =~ /^\@(dir|dirrm|dirrmtry|rmtry|option|stopdaemon|owner|group|mode|fc|fcfontsdir|fontsdir|info|shell)\b/) {
- ; # no check made
- } else {
- &perror("WARN", $file, $.,
- "unknown pkg-plist directive \"$_\"");
- }
- next;
- }
- if ($_ =~ /charset\.alias$/ || $_ =~ /locale\.alias$/) {
- &perror("WARN", $file, $., "installing charset.alias or locale.alias, ".
- "please add USES[+]=gettext and use libintl from devel/gettext ".
- "instead of from outdated bundled one if possible. ".
- "See http://www.freebsd.org/cgi/query-pr.cgi?pr=ports/71531 ".
- "for more details.");
- }
- if ($_ =~ /\%gconf.*\.xml/ || $_ =~ /gconf.*\.schemas?/) {
- &perror("FATAL", $file, $., "explicitly listing \%gconf key files ".
- "or GConf schema files in the plist is not supported. ".
- "Use GCONF_SCHEMAS in the Makefile instead. ".
- "See http://www.FreeBSD.org/gnome/docs/porting.html ".
- "for more details.");
- }
- if ($_ =~ m|lib/pkgconfig/[^\/]+.pc$|) {
- &perror("FATAL", $file, $., "installing pkg-config files into ".
- "lib/pkgconfig. All pkg-config files must be installed ".
- "into libdata/pkgconfig for them to be found by pkg-config.");
- }
- if ($_ =~ m|lib[^\/]+\.so\.\d+$| &&
- $makevar{USE_LDCONFIG} eq '') {
- &perror("WARN", $file, $., "installing shared libraries, ".
- "please define USE_LDCONFIG as appropriate");
- } elsif ($_ =~ m|lib[^\/]+\.so[.\d]*$|) {
- $found_so++;
- }
- if ($_ =~ m|\.omf$| && $makevar{INSTALLS_OMF} eq '') {
- &perror("WARN", $file, $., "installing OMF files, ".
- "please define INSTALLS_OMF (see the FreeBSD GNOME ".
- "porting guide at ".
- "http://www.FreeBSD.org/gnome/docs/porting.html ".
- "for more details)");
- }
- if ($_ =~ m|\.desktop$| && $makevar{USES} !~ /\bdesktop-file-utils\b/) {
- &perror("FATAL", $file, $., "this port installs .desktop files. ".
- "Please add `desktop-file-utils` to USES.");
- }
- if ($_ =~ m|^(%%([^%]+)%%)?.*\.mo$| && $makevar{USES} !~ /\bgettext\b/) {
- my $show_nls_warn = 1;
- if ($2) {
- my $mv = get_makevar($2."_USES");
- if ($mv =~ /\bgettext\b/) {
- $show_nls_warn = 0;
- }
- }
- if ($show_nls_warn) {
- &perror("WARN", $file, $., "installing gettext translation files, ".
- "please define USES[+]=gettext as appropriate");
- }
- }
- if ($_ =~ m|\.core$| && $_ !~ /^\@/) {
- &perror("WARN", $file, $., "this port installs a file which ends ".
- "in \".core\". This file may be deleted if ".
- "daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ".
- "If possible, install this file with a different name.");
- }
- if ($_ =~ m|/a\.out$| && $_ !~ /^\@/) {
- &perror("WARN", $file, $., "this port installs a file named ".
- "\"a.out\". This file may be deleted if ".
- "daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ".
- "If possible, install this file with a different name.");
- }
- if ($_ =~ /\.info$/) {
- &perror("WARN", $file, $., "enumerating info files in the plist is deprecated in favor of adding info files into the Makefile using the INFO macro.");
- }
- if ($_ =~ /\.info-\d+$/) {
- &perror("FATAL", $file, $., "numbered info files are obsolete and not portable; add info files using the INFO macro in the Makefile.");
- }
- if ($_ =~ /^(\%\%PORTDOCS\%\%)?share\/doc\//) {
- &perror("WARN", $file, $., "If and only if your port is ".
- "DOCSDIR-safe (that is, a user can override DOCSDIR ".
- "when building this port and the port will still work ".
- "correctly) consider using DOCSDIR macro; if you are ".
- "unsure if this port is DOCSDIR-safe, then ignore ".
- "this warning");
- $sharedocused++;
- } elsif ($_ =~ /^(\%\%PORTDOCS\%\%)?\%\%DOCSDIR\%\%/) {
- $sharedocused++;
- }
- if ($_ =~ /^share\/examples\//) {
- &perror("WARN", $file, $., "If and only if your port is ".
- "EXAMPLESDIR-safe (that is, a user can override EXAMPLESDIR ".
- "when building this port and the port will still work ".
- "correctly) consider using EXAMPLESDIR macro; if you are ".
- "unsure if this port is EXAMPLESDIR-safe, then ignore this ".
- "warning");
- }
- {
- my $tmpportname = quotemeta($makevar{PORTNAME});
- if ($_ =~ /^share\/$tmpportname\//) {
- &perror("WARN", $file, $., "If and only if your port is ".
- "DATADIR-safe (that is, a user can override DATADIR when ".
- "building this port and the port will still work ".
- "correctly) consider using DATADIR macro; if you are ".
- "unsure if this port is DATADIR-safe, then ignore this ".
- "warning");
- }
- }
- if ($_ =~ m{^%%PORT(\w+)%%(.*?)%%(\w+)DIR%%(.*)$} and $1 ne $3 and
- defined($check_xxxdir_ok{$3})) {
- &perror("WARN", $file, $., "Do not mix %%PORT$1%% with %%$3DIR%%. ".
- "Use '%%PORT$check_xxxdir_ok{$3}%%$2%%$3DIR%%$4' instead and update Makefile ".
- "accordingly.") unless ($check_xxxdir_ok{$3} eq $1);
- }
- # It is now recommended for manpages to be installed under share/man.
- #if ($_ =~ m#share/man/#) {
- # &perror("FATAL", $file, $., "Man pages must be installed into ".
- # "``man'' not ``share/man''.");
- #}
- if ($_ =~ m#man/([^/]+/)?man[1-9ln]/([^\.]+\.[1-9ln])(\.gz)?$#) {
- if (!$3) {
- &perror("FATAL", $file, $., "Unpacked man file $2 listed. ".
- "Must be gzipped.");
- }
- }
- if ($curdir !~ m#^$localbase#) {
- &perror("WARN", $file, $., "installing to ".
- "directory $curdir discouraged. ".
- "could you please avoid it?");
- }
- if ("$curdir/$_" =~ m#^$localbase/share/doc/#) {
- print "OK: $file [$.]: seen installation to share/doc. ".
- "($curdir/$_)\n" if ($verbose);
- $sharedocused++;
- }
- }
- if ($owner_seen > 0) {
- &perror("WARN", $file, -1, "A \@owner section was started but never ".
- "reset. USe \@owner without any arguments to reset the owner");
- }
- if ($group_seen > 0) {
- &perror("WARN", $file, -1, "A \@group section was started but never ".
- "reset. Use \@group without any arguments to reset the group");
- }
- if (!$seen_special && $item_count < $numpitems) {
- &perror("WARN", $file, -1, "There are only $item_count items in the plist. Consider using PLIST_FILES instead of pkg-plist when installing less than $numpitems items.");
- }
- if ($makevar{USE_LDCONFIG} ne '' && !$found_so) {
- &perror("WARN", $file, -1, "You have defined USE_LDCONFIG, but this ".
- "port does not install any shared objects.");
- }
- close(IN);
- 1;
- }
- #
- # ${PORTSDIR}/MOVED, UIDs, GIDs files
- #
- sub checkmfile {
- my ($file) = @_;
- my $line = 0;
- my $format;
- my @entries;
- my @sorted;
- my $dosort;
- if ($file =~ m/MOVED$/) {
- $format = '^[^|]*\|[^|]*\|[^|]*\|[^|]*$';
- $dosort = 0;
- } elsif ($file =~ m/UIDs$/) {
- $format = '^[^:]+:\*:[0-9]+:[0-9]+:[^:]*:0:0:[^:]+:[^:]+:[^:]+$';
- $dosort = 1;
- } elsif ($file =~ m/GIDs$/) {
- $format = '^[^:]+:\*:[0-9]+:[^:]*$';
- $dosort = 1;
- } else {
- &perror("FATAL", $file, -1, "Internal error. ".
- "Invalid name for mfiles.");
- }
- open(IN, "<$file") || return 0;
- while (<IN>) {
- chomp;
- $line++;
- next if (m,^\s*#,);
- if (!m,${format},) {
- &perror("FATAL", $file, -1,
- "malformed line at ".
- "${line}.\n => $_");
- } else {
- push @entries, "$line:$_";
- next;
- }
- }
- if ($dosort) {
- my $errline;
- @sorted = sort {(split /:/, $a)[3] <=> (split /:/, $b)[3] } @entries;
- for (my $n = 0; $n < @entries; $n++) {
- if (!defined($sorted[$n]) or
- $entries[$n] ne $sorted[$n]) {
- ($line, $errline) = ($entries[$n] =~ m/([0-9]+):(.*)/);
- &perror("WARN", $file, -1,
- "malformed sorting order at " .
- "${line}.\n => $errline");
- }
- }
- }
- close(IN);
- }
- #
- # misc files
- #
- sub checkpathname {
- my($file) = @_;
- my($whole);
- open(IN, "< $file") || return 0;
- $whole = '';
- while (<IN>) {
- $whole .= $_;
- }
- &abspathname($whole, $file);
- close(IN);
- }
- sub checklastline {
- my($file) = @_;
- my($whole);
- open(IN, "< $file") || return 0;
- $whole = '';
- while (<IN>) {
- $whole .= $_;
- }
- if ($whole !~ /\n$/) {
- &perror("FATAL", $file, -1, "the last line has to be ".
- "terminated by \\n.");
- }
- if ($whole =~ /\n([ \t]*\n)+$/) {
- &perror("WARN", $file, -1, "seems to have unnecessary blank lines ".
- "at the last part.");
- }
- close(IN);
- }
- sub checkpatches {
- my (@patchfiles) = @_;
- my @patched_files;
- foreach my $file (@patchfiles) {
- open(IN, "< $file") || return 0;
- while (<IN>) {
- if ($_ =~ /^\+\+\+\s(.*?)\s.*/) {
- #if($1 ~~ @patched_files) {
- if (grep {$_ eq $1} @patched_files) {
- &perror("WARN", $file, -1, "$1 patched multiple times");
- }
- else {
- push(@patched_files, $1);
- }
- }
- }
- }
- }
- sub checkpatch {
- my($file) = @_;
- my($whole);
- if (-z "$file") {
- &perror("FATAL", $file, -1, "has no content. should be removed ".
- "from repository.");
- return;
- }
- my $bfile = basename($file);
- if (length $bfile > 100) {
- &perror("FATAL", $file, -1, "make sure patch file names contain no ".
- "more than 100 characters.");
- }
- open(IN, "< $file") || return 0;
- $whole = '';
- my $checked_header = 0;
- while (<IN>) {
- $whole .= $_;
- if (/^--- / && !$checked_header) {
- $checked_header = 1;
- if ($_ !~ /UTC\s*$/) {
- &perror("WARN", $file, -1, "patch was not generated using ".
- "``make makepatch''. It is recommended to use ".
- "``make makepatch'' when you need to [re-]generate a ".
- "patch to ensure proper patch format.");
- }
- }
- }
- if ($committer && $whole =~ /\wjavavm\w/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "since javavmwrapper 2.0, the ".
- "``javavm'' command to invoke a JVM is deprecated. Use ".
- "``java'' instead");
- }
- if ($whole =~ /
/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "patch contains ^M characters. ".
- "Consider defining USES=dos2unix to remove DOS line endings ".
- "from source files.");
- }
- if ($whole !~ /\n$/s) {
- &perror("FATAL", $file, -1, "patch does not end with a newline, and the commit check ".
- "hook will fail.");
- }
- close(IN);
- }
- sub check_depends_syntax {
- my $tmp = shift;
- my $file = shift;
- my (%seen_depends, $j);
- $ENV{'PORTSDIR'} //= $portsdir;
- foreach my $i (grep(/^(PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS[?+]?=/, split(/\n/, $tmp))) {
- $i =~ s/^((PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS)[?+]?=[ \t]*//;
- $j = $1;
- $seen_depends{$j}++;
- if ($j ne 'DEPENDS' &&
- $i =~ /^\$\{([A-Z_]+DEPENDS)}\s*$/ &&
- $seen_depends{$1} &&
- $j ne $1)
- {
- print "OK: $j refers to $1, skipping checks.\n"
- if ($verbose);
- next;
- } elsif ($j ne 'DEPENDS' && $i =~ /^\$\{([A-Z_]+DEPENDS)}\s*$/ && !$seen_depends{$1}) {
- # make(1) does lazy variable evaluation, so we can use a variable before it is
- # declared. However, portlint scans line by line. Allow this behavior.
- print "OK: $j refers to $1 (which hasn't been declared yet, but it will work), skipping checks.\n"
- if ($verbose);
- next;
- }
- print "OK: checking ports listed in $j.\n" if ($verbose);
- my @ks = split(/\s+/, $i);
- while (@ks) {
- my $k = shift @ks;
- if ($k =~ /^#/) {
- last;
- }
- my $ok = $k;
- if ($k =~ /^\$\{([^\}]+)\}$/) {
- $k = get_makevar_shallow($1);
- push @ks, split(/\s+/, $k);
- next;
- }
- if ($k eq '') {
- next;
- }
- my ($tmp_depends, $fl) = split(/\@/, $k);
- $tmp_depends =~ s/\$\{[^}]+}//g;
- my @l = split(':', $tmp_depends);
- print "OK: checking dependency value for $j.\n"
- if ($verbose);
- if ($ok =~ /\$\{((PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)*DEPENDS)}/) {
- &perror("WARN", $file, -1, "do not set $j to $ok. ".
- "Instead, explicity list out required $j dependencies.");
- }
- if (($j ne 'DEPENDS'
- && scalar(@l) != 2 && scalar(@l) != 3)) {
- &perror("WARN", $file, -1, "wrong dependency value ".
- "for $j. $j requires ".
- "2 or 3 ".
- "colon-separated tuples.");
- next;
- }
- my %m = ();
- $m{'dep'} = $l[0];
- $m{'dir'} = $l[1];
- $m{'fla'} = $fl // '';
- $m{'tgt'} = $l[2] // '';
- my %depmvars = ();
- foreach my $dv ($m{'dep'}, $m{'dir'}, $m{'tgt'}) {
- foreach my $mv ($dv =~ /\$\{([^}]+)\}/g) {
- if (defined($depmvars{$mv})) {
- next;
- }
- if (defined($makevar{$mv})) {
- $depmvars{$mv} = $makevar{$mv};
- } else {
- $depmvars{$mv} = &get_makevar($mv);
- }
- }
- }
- # check Python flavor
- my $bdir = basename($m{'dir'});
- if ($bdir =~ /^py-/) {
- if ($m{'fla'} ne '${PY_FLAVOR}') {
- &perror("WARN", $file, -1, "you may want directory for ".
- "dependency $m{'dep'} to be $m{'dir'}\@\${PY_FLAVOR}");
- }
- }
- # check JAVALIBDIR
- if ($m{'dep'} =~ m|share/java/classes|) {
- &perror("FATAL", $file, -1, "you should use \${JAVALIBDIR} ".
- "in BUILD_DEPENDS/RUN_DEPENDS to define ".
- "dependencies on JAR files installed in ".
- "\${JAVAJARDIR}");
- }
- foreach my $dv ($m{'dep'}, $m{'dir'}, $m{'tgt'}) {
- foreach my $dmv (keys %depmvars) {
- $dv =~ s/\$\{$dmv\}/$depmvars{$dmv}/g;
- }
- }
- print "OK: dep=\"$m{'dep'}\", ".
- "dir=\"$m{'dir'}\", tgt=\"$m{'tgt'}\"\n"
- if ($verbose);
- # check USES=perl5
- if ($m{'dep'} =~ /^perl5(\.\d+)?$/) {
- &perror("WARN", $file, -1, "dependency to perl5 ".
- "listed in $j. consider using ".
- "USES[+]=perl5.");
- }
- # Check for ${SITE_PERL} in depends
- if ($m{'dep'} =~ m|^(\$\{SITE_PERL}/.*)$|) {
- &perror("WARN", $file, -1, "dependency to $1 ".
- "listed in $j. consider using p5-Example-Package-Name>=0. See ".
- "http://www.freebsd.org/doc/en/books/porters-handbook/using-perl.html".
- " for more details.");
- }
- # check USES=iconv
- if ($m{'dep'} =~ /^(iconv\.\d+)$/) {
- &perror("WARN", $file, -1, "dependency to $1 ".
- "listed in $j. consider using ".
- "USES[+]=iconv.");
- }
- # check USES=gettext
- if ($m{'dep'} =~ /^(intl\.\d+)$/) {
- &perror("WARN", $file, -1, "dependency to $1 ".
- "listed in $j. consider using ".
- "USES[+]=gettext.");
- }
- # check USES=gmake
- if ($m{'dep'} =~ /^(gmake|\$\{GMAKE})$/) {
- &perror("WARN", $file, -1, "dependency to $1 ".
- "listed in $j. consider using ".
- "USES[+]=gmake.");
- }
- my %udeps = (
- 'bison' => 'bison',
- 'fmake' => 'fmake',
- );
- foreach my $udep (keys %udeps) {
- if ($m{'dep'} =~ /^$udep/) {
- &perror("WARN", $file, -1, "dependency to $udep ".
- "listed in $j. consider using ".
- "USES[+]=$udeps{$udep}.");
- }
- }
- # check USE_QT
- if ($m{'dep'} =~ /^(qt\d)+$/) {
- &perror("WARN", $file, -1, "dependency to $1 ".
- "listed in $j. consider using ".
- "USE_QT.");
- }
- # check LIBLTDL
- if ($m{'dep'} =~ /^(ltdl\.\d)+$/) {
- &perror("WARN", $file, -1, "dependency to $1 ".
- "listed in $j. consider using ".
- "USE_LIBLTDL.");
- }
- # check GHOSTSCRIPT
- if ($m{'dep'} eq "gs") {
- &perror("WARN", $file, -1, "dependency to gs ".
- "listed in $j. consider using ".
- "USE_GHOSTSCRIPT(_BUILD|_RUN).");
- }
- # check for PREFIX
- if ($m{'dep'} =~ /\$\{PREFIX}/) {
- &perror("FATAL", $file, -1, "\${PREFIX} must not be ".
- "contained in *_DEPENDS. ".
- "use \${LOCALBASE} instead.");
- }
- # Check for direct dependency on apache.
- if ($m{'dep'} =~ /\/www\/apache\d*\//) {
- &perror("FATAL", $file, -1, "do not depend on any apache ".
- "port in *_DEPENDS directly. ".
- "Instead use USE_APACHE=VERSION, where VERSION can be ".
- "found in \${PORTSDIR}/Mk/Uses/apache.mk.");
- }
- # Check for over-specific shared library dependencies
- if ($j eq 'LIB_DEPENDS' && $m{'dep'} =~ m/(\.\d+$)/) {
- &perror("WARN", $file, -1, "$j don't specify the " .
- "ABI version number $1 in $m{'dep'} unless it is " .
- "really necessary.");
- }
- # Check for old-style LIB_DEPENDS
- if ($j eq 'LIB_DEPENDS' && $m{'dep'} !~ m/^lib.*\.so$/) {
- &perror("WARN", $file, -1, "$j the new format is ".
- "libFOO.so (e.g., lib$m{'dep'}.so).");
- }
- # Check port dir existence
- $k = $ENV{'PORTSDIR'}.'/'.$m{'dir'};
- if (! -d $k) {
- &perror("WARN", $file, -1, "no port directory $k ".
- "found, even though it is ".
- "listed in $j.");
- } else {
- print "OK: port directory $k found.\n"
- if ($verbose);
- }
- # Check for relative path
- if ($k =~ /\/\.\.\//) {
- &perror("FATAL", $file, -1, "use absolute path".
- "instead of $k in *_DEPENDS.");
- } else {
- print "OK: path for port directory $k is absolute.\n"
- if ($verbose);
- }
- }
- }
- }
- #
- # Makefile
- #
- sub checkmakefile {
- my($file) = @_;
- my($rawwhole, $whole, $idx, @sections);
- my($i, $j, $k, $l);
- my @cat = ();
- my $has_lang_cat = 0;
- my $port_lang = '';
- my $tmp;
- my $bogusdistfiles = 0;
- my @varnames = ();
- my($portname, $portversion, $distfiles, $distversionprefix, $distversion, $distversionsuffix, $distname, $extractsufx) = ('') x 8;
- my $masterport = 0;
- my $slaveport = 0;
- my $use_gnome_hack = 0;
- my $use_java = 0;
- my $use_ant = 0;
- my($realwrksrc, $wrksrc, $nowrksubdir) = ('', '', '');
- my(@mman, @pman);
- my(@aopt, @mopt, @opt);
- my($pkg_version, $versiondir, $versionfile) = ('', '', '');
- my $indexfile = '';
- my $useindex = 0;
- my %deprecated = ();
- my @deplist = ();
- my %autocmdnames = ();
- my $pre_mk_line = 0;
- my $options_mk_line = 0;
- my $docsused = 0;
- my $optused = 0;
- my $desktop_entries = '';
- my $conflicts = "";
- my $masterdir = $makevar{MASTERDIR};
- if ($masterdir ne '' && $masterdir ne $makevar{'.CURDIR'}) {
- $slaveport = 1;
- }
- open(IN, "< $file") || return 0;
- $rawwhole = '';
- $tmp = 0;
- while (<IN>) {
- if ($_ =~ /[ \t]+\n?$/) {
- &perror("WARN", $file, $., "whitespace before ".
- "end of line.");
- }
- if ($_ =~ /^ /) { # 8 spaces here!
- &perror("WARN", $file, $., "use tab (not space) to make ".
- "indentation");
- }
- if ($usetabs) {
- if (m/^[A-Za-z0-9_-]+.?=\t*? \t*?/) {
- if (m/[?+]=/) {
- &perror("WARN", $file, $., "use a tab (not space) after a ".
- "variable name");
- } else {
- &perror("FATAL", $file, $., "use a tab (not space) after a ".
- "variable name");
- }
- }
- }
- $rawwhole .= $_;
- }
- close(IN);
- #
- # whole file: blank lines.
- #
- $whole = "\n" . $rawwhole;
- study $whole;
- print "OK: checking contiguous blank lines in $file.\n"
- if ($verbose);
- $i = "\n" x ($contblank + 2);
- if ($whole =~ /$i/) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "contiguous blank lines ".
- "(> $contblank lines) found.");
- }
- #
- # whole file: header
- #
- my @lines = split("\n", $whole);
- print "OK: checking header in $file.\n" if ($verbose);
- if ($lines[1] =~ /^# (?:New )?[Pp]orts collection [mM]akefile/) {
- &perror("FATAL", $file, 1, "old style headers found.");
- } elsif ($lines[1] =~ /^# \$$rcsidstr[:\$]/) {
- &perror("FATAL", $file, 1, "\$$rcsidstr\$ is deprecated in Git.");
- } elsif ($lines[1] =~ /^# Created by: \S/) {
- if ($lines[2] =~ /^# \$$rcsidstr[:\$]/) {
- &perror("FATAL", $file, 2, "\$$rcsidstr\$ is deprecated in Git.");
- }
- if ($lines[2] !~ /^$/) {
- #&perror("FATAL", $file, 2, "do not add extra ".
- # "empty comments after header.");
- }
- # special case for $rcsidsrt\nMCom:
- } elsif ($lines[1] =~ /^#\s+\$MCom[:\$]/ and $lines[2] =~ /^$/) {
- # DO NOTHING
- }
- #
- # whole file: $(VARIABLE)
- #
- if ($parenwarn) {
- print "OK: checking for \$(VARIABLE).\n" if ($verbose);
- if ($whole =~ /[^\$]\$\([\w\d]+\)/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "use \${VARIABLE}, instead of ".
- "\$(VARIABLE).");
- }
- }
- #
- # whole file: empty(${VARIABLE})
- #
- if ($parenwarn) {
- print "OK: checking for empty(\${VARIABLE}).\n" if ($verbose);
- if ($whole =~ /empty\(\$\{[\w\d]+/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "use empty(VARIABLE), instead of ".
- "empty(\${VARIABLE}).");
- }
- }
- #
- # whole file: use of !=
- #
- print "OK: checking for use of !=.\n" if ($verbose);
- if ($whole =~ /^[\w\d_]+\!=/m) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "use of != in assignments is almost ".
- "never a good thing to do. Try to avoid using them. See ".
- "http://lists.freebsd.org/pipermail/freebsd-ports/2008-July/049777.html ".
- "for some helpful hints on what to do instead.");
- }
- #
- # whole file: use of .elseif
- #
- print "OK: checking for use of .elseif.\n" if ($verbose);
- if ($whole =~ /^\.\s*else\s*if/m) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "use of .elseif (or .else if) is not ".
- "supported in all versions of FreeBSD. Use .elif instead.");
- }
- #
- # whole file: use of @${INSTALL_foo}
- #
- print "OK: checking for use of muted INSTALL_ commands.\n" if ($verbose);
- if ($whole =~ /^\s+\@\$\{INSTALL_/m) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "do not use muted INSTALL_foo ".
- "commands (i.e., those that start with '\@'). These should be ".
- "printed.");
- }
- #
- # checking for use of ${ENV}
- #
- print "OK: checking for use of \${ENV} instead of \${SETENV}.\n" if ($verbose);
- if ($whole =~ /\$\{ENV}/m) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "most uses of \${ENV} should really ".
- "be \${SETENV} to avoid strange behaviors in sh(1).");
- }
- #
- # whole file: use of IGNOREFILES
- #
- print "OK: checking for use of IGNOREFILES.\n" if ($verbose);
- if ($whole =~ /\nIGNOREFILES.?=/m) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "IGNOREFILES considered unsafe and ".
- "not supported anymore.");
- }
- #
- # whole file: use of PLIST_DIRSTRY
- #
- print "OK: checking for use of PLIST_DIRSTRY.\n" if ($verbose);
- if ($whole =~ /\nPLIST_DIRSTRY.?=/m) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "PLIST_DIRSTRY is deprecated. Please ".
- "use PLIST_DIRS instead.");
- }
- #
- # whole file: PLIST_FILES and PLIST_DIRS
- #
- print "OK: checking PLIST_FILES and PLIST_DIRS.\n" if ($verbose);
- my $python_plist = 0;
- if ($makevar{USE_PYTHON} && $makevar{USE_PYTHON} =~ /\bautoplist\b/) {
- $python_plist = 1;
- }
- if ($whole =~ /\nPLIST_FILES.?=/ || $whole =~ /\nPLIST_DIRS.?=/) {
- if (-f 'pkg-plist') {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "You may remove pkg-plist ".
- "if you use PLIST_FILES and/or PLIST_DIRS.");
- }
- my @plist_files = split(/\s+/, $makevar{PLIST_FILES});
- foreach my $plist_file (@plist_files) {
- if ($plist_file =~ m|lib[^\/]+\.so(\.\d+)?$| &&
- $makevar{USE_LDCONFIG} eq '') {
- &perror("WARN", "", -1, "PLIST_FILES: installing shared libraries, ".
- "please define USE_LDCONFIG as appropriate");
- }
- if ($plist_file =~ m|\.omf$| && $makevar{INSTALLS_OMF} eq '') {
- &perror("WARN", "", -1, "PLIST_FILES: installing OMF files, ".
- "please define INSTALLS_OMF (see the FreeBSD GNOME ".
- "porting guide at ".
- "http://www.FreeBSD.org/gnome/docs/porting.html ".
- "for more details)");
- }
- if ($plist_file =~ m|\.core$| && $plist_file !~ /^\@/) {
- &perror("WARN", "", -1, "PLIST_FILES: this port installs a file which ".
- "ends in \".core\". This file may be deleted if ".
- "daily_clean_disks_enable=\"YES\" in /etc/periodic.conf. ".
- "If possible, install this file with a different name.");
- }
- if ($plist_file =~ /%%[\w_\d]+%%/) {
- &perror("FATAL", "", -1, "PLIST_FILES: files cannot contain ".
- "%%FOO%% variables. Use make variables and logic instead");
- }
- if ($plist_file =~ m|\.desktop$| && $makevar{USES} !~ /\bdesktop-file-utils\b/) {
- &perror("FATAL", "", -1, "PLIST_FILES: this port installs .desktop files. ".
- "please add `desktop-file-utils` to USES.");
- }
- }
- }
- #
- # whole file: USE_* and others variables used too late
- #
- my @options_early = qw(
- OPTIONS_DEFAULT
- OPTIONS_DEFINE
- OPTIONS_EXCLUDE
- OPTIONS_GROUP.*?
- OPTIONS_MULTI.*?
- OPTIONS_RADIO.*?
- OPTIONS_SINGLE.*?
- );
- pos($whole) = 0;
- if ($whole =~ /^\.include\s+<bsd\.port\.pre\.mk>$/gm) {
- # Remember position
- $pre_mk_line = &linenumber($`) + 1;
- print "OK: checking for USE_* used too late.\n" if ($verbose);
- my @use_early = qw(
- BZIP2
- GNUSTEP
- IMAKE
- KDE(?:BASE|LIBS)_VER
- (?:LIB)?RUBY
- LINUX_PREFIX
- OPENSSL
- PYTHON
- QT2?
- QT_VER
- X_PREFIX
- ZIP
- );
- my @other_early = qw(
- EMACS_PORT_NAME
- );
- my $earlypattern = join('|', 'USE_(?:'.join('|', @use_early).')',
- @other_early, @options_early);
- while ($whole =~ /^($earlypattern)[+?:!]?=/gmo) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "$1 is set after ".
- "including bsd.port.pre.mk.");
- }
- }
- #
- # whole file: check OPTIONS
- #
- print "OK: checking OPTIONS.\n" if ($verbose);
- pos($whole) = 0;
- if ($whole =~ /^\.include\s+<bsd\.port\.options\.mk>$/gm) {
- # Remember position
- $options_mk_line = &linenumber($`) + 1;
- }
- pos($whole) = 0;
- if ($whole =~ /^\.include\s+<bsd\.port\.options\.mk>$/gm) {
- my $earlypattern = join('|', @options_early);
- while ($whole =~ /^($earlypattern)[+?]?=/gmo) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "$1 is set after ".
- "including bsd.port.options.mk.");
- }
- }
- pos($whole) = 0;
- foreach my $i ("OPTIONS_RADIO","OPTIONS_SINGLE",
- "OPTIONS_MULTI","OPTIONS_GROUP") {
- foreach my $j (split(/\s+/, $makevar{$i})) {
- if ($j) {
- my @ocount = split(/\s+/, get_makevar("${i}_${j}"));
- if (!scalar(@ocount)) {
- &perror("FATAL", $file, -1,
- "Description for ${i}_${j} does not exist");
- } else {
- push @aopt, @ocount;
- }
- }
- }
- }
- my @aropt = ();
- while ($whole =~ /^OPTIONS_DEFINE_[\d\w]+(.)=\s*(.+)$/mg) {
- push @aropt, split(/\s+/, $2);
- }
- @opt = split(/\s+/, $makevar{OPTIONS_DEFINE});
- pos($whole) = 0;
- while ($whole =~ /PORT_OPTIONS:M(\w+)/mg) {
- push @mopt, $1;
- my $lineno = &linenumber($`) + 1;
- &perror("FATAL", $file, $lineno, "PORT_OPTIONS:M$1 is used before ".
- "including bsd.port.pre.mk or bsd.port.options.mk.")
- if ($optused && $lineno < $pre_mk_line &&
- $lineno < $options_mk_line);
- }
- my @options_helpers = qw(
- __DUMMY__
- ALL_TARGET
- BUILD_DEPENDS
- EXTRACT_DEPENDS
- FETCH_DEPENDS
- LIB_DEPENDS
- PKG_DEPENDS
- RUN_DEPENDS
- CATEGORIES
- CFLAGS
- CMAKE_OFF
- CMAKE_ON
- CMAKE_BOOL_OFF
- CMAKE_BOOL
- CONFIGURE_ENABLE
- CONFIGURE_ENV
- CONFIGURE_OFF
- CONFIGURE_ON
- CONFIGURE_WITH
- CPPFLAGS
- CXXFLAGS
- DISTFILES
- INSTALL_TARGET
- LDFLAGS
- MAKE_ARGS
- MAKE_ENV
- EXTRA_PATCHES
- PATCHFILES
- PATCH_DEPENDS
- PATCH_SITES
- PLIST_DIRS
- PLIST_DIRSTRY
- PLIST_FILES
- QMAKE_OFF
- QMAKE_ON
- USE
- USES
- VARS
- VARS_OFF
- );
- my $m = join("|", @options_helpers);
- if ($makevar{OPTIONS_SUB}) {
- if ($makevar{PLIST_FILES}) {
- foreach my $i (split(/\s+/, $makevar{PLIST_FILES})) {
- while ($i =~ /\%\%([^%]+)\%\%/g) {
- push @popt, $1;
- }
- }
- }
- if ($makevar{PLIST_DIRS}) {
- foreach my $i (split(/\s+/, $makevar{PLIST_DIRS})) {
- while ($i =~ /\%\%([^%]+)\%\%/g) {
- push @popt, $1;
- }
- }
- }
- if (-f 'pkg-plist') {
- open(PL, 'pkg-plist');
- my @pcontents = <PL>;
- close(PL);
- foreach my $i (@pcontents) {
- while ($i =~ /\%\%([^%]+)\%\%/g) {
- push @popt, $1;
- }
- }
- }
- # special cases for PORTDOCS/PORTEXAMPLES
- push @popt, "DOCS" if $makevar{PORTDOCS};
- push @popt, "EXAMPLES" if $makevar{PORTEXAMPLES};
- # uniq(@popt)
- my %seen = ();
- @popt = grep { !$seen{$_}++ } @popt;
- }
- foreach my $i (@popt) {
- if ($i eq 'PORTDOCS') {
- if (!grep(/^DOCS$/, @opt)) {
- &perror("FATAL", $file, -1, "PORTDOCS appears in plist ".
- "but DOCS is not listed in OPTIONS_DEFINE.");
- }
- } elsif ($i eq 'PORTEXAMPLES') {
- if (!grep(/^EXAMPLES$/, @opt)) {
- &perror("FATAL", $file, -1, "PORTEXAMPLES appears in plist ".
- "but EXAMPLES is not listed in OPTIONS_DEFINE.");
- }
- }
- }
- my %seen_opts = ();
- foreach my $i ((@opt, @aopt, @aropt)) {
- # skip global options
- next if ($i eq 'DOCS' or $i eq 'NLS' or $i eq 'EXAMPLES' or $i eq 'IPV6' or $i eq 'X11' or $i eq 'DEBUG');
- if (!$seen_opts{$i}) {
- $seen_opts{$i}++;
- my $odescr = &get_makevar("${i}_DESC");
- if ($odescr eq "" && $whole !~ /^${i}_DESC.?=/m) {
- &perror("FATAL", $file, -1, "OPTION $i does not have a description (${i}_DESC).");
- }
- }
- if (!grep(/^$i$/, (@mopt, @popt))) {
- if ($whole !~ /\n${i}_($m)(_\w+)?(.)?=[^\n]+/ and $whole !~ /\n[-\w]+-${i}-(on|off):\n/) {
- my $found_opt_use = 0;
- foreach my $oarg ('BUILD_DEPENDS', 'RUN_DEPENDS', 'LIB_DEPENDS') {
- my $oarg_var = &get_makevar("${i}_${oarg}");
- if ($oarg_var ne "") {
- $found_opt_use = 1;
- last;
- }
- }
- if (!$found_opt_use) {
- if (!$slaveport) {
- &perror("WARN", $file, -1, "$i is listed in ".
- "OPTIONS_DEFINE, but no PORT_OPTIONS:M$i appears.");
- } else {
- &perror("WARN", $file, -1, "$i is listed in ".
- "OPTIONS_DEFINE, but no PORT_OPTIONS:M$i appears ".
- "in this slave Makefile. Make sure it appears in ".
- "the master's Makefile.");
- }
- }
- }
- }
- }
- foreach my $i (@mopt) {
- if (!grep(/^$i$/, @opt, @aopt, @aropt)) {
- # skip global options
- next if ($i eq 'DOCS' or $i eq 'NLS' or $i eq 'EXAMPLES' or $i eq 'IPV6' or $i eq 'X11');
- &perror("WARN", $file, -1, "$i appears in PORT_OPTIONS:M, ".
- "but is not listed in OPTIONS_DEFINE.");
- }
- }
- #
- # whole file: check DESKTOP_ENTRIES for ${TRUE}/${FALSE}
- #
- print "OK: checking DESKTOP_ENTRIES for \${TRUE}/\${FALSE}.\n" if ($verbose);
- $desktop_entries = &get_makevar_raw('DESKTOP_ENTRIES');
- if ($desktop_entries =~ /\$\{TRUE}/ or $desktop_entries =~ /\$\{FALSE}/ or
- $desktop_entries =~ /\"true\"/ or $desktop_entries =~ /\"false\"/) {
- &perror("FATAL", $file, -1, "Use true/false (without quotes) instead of \${TRUE}/\${FALSE} in DESKTOP_ENTRIES.");
- }
- #
- # whole file: USE_* as a user-settable option
- #
- print "OK: checking for USE_* as a user-settable option.\n" if ($verbose);
- while ($whole =~ /\n\s*\.\s*(?:el)?if[^\n]*?\b(\w*USE_)(\w+)(?![^\n]*\n#?\.error)/g) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "is $1$2 a user-settable option? ".
- "Consider using WITH_$2 instead.")
- if ($1.$2 ne 'USE_GCC' && $1.$2 ne 'USE_LDCONFIG32');
- }
- #
- # whole file: check for use of *_CMAKE_ARGS
- #
- print "OK: checking for use of *_CMAKE_ARGS instead of *_CMAKE_ON|OFF.\n" if ($verbose);
- if ($whole =~ /\n([\w\d]+)_CMAKE_ARGS/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "Use $1_CMAKE_ON or $1_CMAKE_OFF instead ".
- "of $1_CMAKE_ARGS. The former macros will automatically update ".
- "CMAKE_ARGS.");
- }
- #
- # whole file: check that CMAKE_BOOL just has words
- #
- print "OK: checking that *_CMAKE_BOOL only contains words.\n" if ($verbose);
- if ($whole =~ /\n([\w\d]+)_CMAKE_BOOL[?+:]?=([^\n]+)\n/) {
- my $lineno = &linenumber($`);
- my $o = $1;
- if ($2 =~ /-D/) {
- &perror("FATAL", $file, $lineno, "Only bare words can be used for ".
- "${o}_CMAKE_BOOL. The -D flag will be added automatically.");
- }
- }
- print "OK: checking that *CMAKE* co-occurs with *USES+=cmake.\n" if ($verbose);
- while ($whole =~ /\n([\w\d]+_)?CMAKE_(ARGS|BOOL|BOOL_ON|BOOL_OFF|OFF|ON)\b/g) {
- my $lineno = &linenumber($`);
- my $o = $1;
- my $found_cmake = 0;
- unless ($makevar{USES} =~ /\b(cmake\b|cmake:)/) {
- $o = "" unless ($o);
- &perror("FATAL", $file, $lineno, "${o}CMAKE_$2 is set without USES+=cmake");
- }
- }
- #
- # whole file: NO_CHECKSUM
- #
- # XXX Don't compress newlines since it messes up line number calculation.
- #$whole =~ s/\n#[^\n]*/\n/g;
- #$whole =~ s/\n\n+/\n/g;
- print "OK: checking NO_CHECKSUM.\n" if ($verbose);
- if ($whole =~ /\nNO_CHECKSUM/) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "NO_CHECKSUM is a user ".
- "variable and is not to be set in a port's Makefile.");
- }
- #
- # whole file: MACHINE_ARCH
- #
- print "OK: checking MACHINE_ARCH.\n" if ($verbose);
- if ($whole =~ /\nMACHINE_ARCH/) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "MACHINE_ARCH should never be ".
- "overridden.");
- }
- #
- # whole file: DEPRECATED
- #
- print "OK: checking DEPRECATED.\n" if ($verbose);
- if ($whole =~ /\nDEPRECATED[+?]?=[ \t]*"/ &&
- $whole !~ /\nDEPRECATED[+?]?=[ \t]*"\$\{BROKEN\}"/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "DEPRECATED messages should not ".
- "be quoted unless they are exactly \"\${BROKEN}\".");
- }
- if ($whole =~ /\nDEPRECATED[+?]?=[^"]*\$\{BROKEN\}/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "\"\${BROKEN}\" must be quoted ".
- "when it is the source of DEPRECATED.");
- }
- #
- # whole file: BROKEN et al.
- #
- my ($var);
- foreach $var (qw(IGNORE BROKEN(_[\w\d]+)? COMMENT FORBIDDEN MANUAL_PACKAGE_BUILD NO_CDROM NO_PACKAGE RESTRICTED)) {
- print "OK: checking ${var}.\n" if ($verbose);
- if ($whole =~ /\n${var}[+?]?=[ \t]+"/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "${var} messages should not ".
- "be quoted.");
- }
- }
- if ($makevar{COMMENT} =~ /^An? / || $makevar{COMMENT} =~ /^The /) {
- &perror("WARN", $file, -1, "COMMENT is not supposed to begin with ".
- "'A ', 'An ', or 'The '.");
- }
- if ($whole =~ /\nIGNORE[+?]?=[ \t]+[^a-z \t]/ ||
- $whole =~ /^IGNORE[+?]?=[ \t]+.*\.$/m) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "IGNORE messages should begin ".
- "with a lowercase letter and end without a period.");
- }
- if ($whole =~ /\nBROKEN(_[\w\d]+)?[+?]?=[ \t]+[^a-z \t]/ ||
- $whole =~ /^BROKEN(_[\w\d]+)?[+?]?=[ \t]+.*\.$/m) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "BROKEN messages should begin ".
- "with a lowercase letter and end without a period.");
- }
- #
- # whole file: PKGNAME
- #
- print "OK: checking PKGNAME.\n" if ($verbose);
- if ($whole =~ /\nPKGNAME.?=/) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "PKGNAME is obsoleted by PORTNAME, ".
- "PORTVERSION, PKGNAMEPREFIX and PKGNAMESUFFIX.");
- }
- #
- # whole file: MAKE_JOBS_UNSAFE
- #
- print "OK: checking for MAKE_JOBS_UNSAFE in combination with NO_BUILD.\n" if ($verbose);
- if ($whole =~ /\nMAKE_JOBS_UNSAFE.?=/) {
- my $matched = $1;
- if ($whole =~ /\nNO_BUILD.?=/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "MAKE_JOBS_UNSAFE should not ".
- "be used in combination with NO_BUILD. You ".
- "should remove MAKE_JOBS_UNSAFE from your Makefile.");
- }
- }
- #
- # whole file: Check if some macros are sorted
- #
- my @macros_to_sort = qw(
- ONLY_FOR_ARCHS
- NOT_FOR_ARCHS
- );
- print "OK: checking to see if certain macros are sorted.\n" if ($verbose);
- foreach my $sorted_macro (@macros_to_sort) {
- while ($whole =~ /\n$sorted_macro.?=\s*([^#\n]+)(#.*)?\n/g) {
- my $lineno = &linenumber($`);
- my $srex = $1;
- $srex =~ s/\s+$//;
- my @smacros = sort(split / /, $srex);
- if (join(" ", @smacros) ne $srex) {
- &perror("WARN", $file, $lineno, "the arguments to $sorted_macro ".
- "are not sorted. Please consider sorting them.");
- }
- }
- }
- #
- # whole file: USE_GNOME=pkgconfig
- #
- print "OK: checking for USE_GNOME=pkgconfig.\n" if ($verbose);
- if ($makevar{USE_GNOME} =~ /pkgconfig/) {
- &perror("WARN", $file, -1, "USE_GNOME=pkgconfig is now obsolete. ".
- "Use USES[+]=pkgconfig instead.");
- }
- #
- # whole file: using INSTALLS_ICONS when it is not wanted
- #
- if (!($makevar{INSTALLS_ICONS} eq '')) {
- &perror("WARN", $file, -1, "INSTALLS_ICONS is now deprecated. It should be removed.");
- }
- #
- # whole file: EXPIRATION_DATE
- #
- print "OK: checking for valid EXPIRATION_DATE.\n" if ($verbose);
- my $edate;
- if (($edate) = ($whole =~ m/\nEXPIRATION_DATE\??=[ \t]*([^\n]*)\n/)) {
- my $lineno = &linenumber($`);
- my $ndate = $edate;
- if ($ndate eq '' || length $ndate < 10) {
- $ndate = '0000-00-00';
- }
- if ($ndate ne strftime("%Y-%m-%d", 0, 0, 0,
- substr($ndate, 8, 2),
- substr($ndate, 5, 2) - 1,
- substr($ndate, 0, 4) - 1900)) {
- &perror("FATAL", $file, $lineno, "EXPIRATION_DATE ($edate) is ".
- "either not in YYYY-MM-DD format or it is not a valid ".
- "date.");
- }
- }
- #
- # whole file: IS_INTERACTIVE/NOPORTDOCS|PORT_OPTIONS:MDOCS
- #
- print "OK: checking IS_INTERACTIVE.\n" if ($verbose);
- if ($whole =~ /\nIS_INTERACTIVE/) {
- if ($whole !~ /defined\((BATCH|FOR_CDROM)\)/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "use of IS_INTERACTIVE ".
- "discouraged. provide batch mode by using BATCH and/or ".
- "FOR_CDROM.");
- }
- }
- print "OK: checking for use of PORT_OPTIONS:MDOCS.\n" if ($verbose);
- if ($sharedocused && $whole =~ /PORT_OPTIONS:MDOCS/) {
- $docsused++;
- }
- print "OK: checking for use of NOPORTDOCS.\n" if ($verbose);
- if ($whole =~ /defined\s*\(?NOPORTDOCS\)?/ ||
- $whole =~ /def\s*\(?NOPORTDOCS\)?/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "NOPORTDOCS is deprecated. Please ".
- "use PORT_OPTIONS:MDOCS instead.");
- }
- print "OK: checking for use of NOPORTEXAMPLES.\n" if ($verbose);
- if ($whole =~ /defined\s*\(?NOPORTEXAMPLES\)?/ ||
- $whole =~ /def\s*\(?NOPORTEXAMPLES\)?/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "NOPORTEXAMPLES is deprecated. Please ".
- "use PORT_OPTIONS:MEXAMPLES instead.");
- }
- if ($sharedocused && $whole !~ /defined\s*\(?NOPORTDOCS\)?/
- && $whole !~ /def\s*\(?NOPORTDOCS\)?/) {
- if ($docsused == 1
- && $whole !~ m#(\$[\{\(]PREFIX[\}\)]|$localbase)/share/doc/#) {
- &perror("WARN", $file, -1, "you should only use \".if \${PORT_OPTIONS:MDOCS}\" to wrap ".
- "installation of files into $localbase/share/doc if the".
- " collection of files is large and it takes considerable time".
- " to copy.");
- }
- } else {
- $docsused++;
- }
- if ($docsused > 1) {
- &perror("FATAL", $file, -1, "Both NOPORTDOCS and PORT_OPTIONS:MDOCS are found. ".
- "Remove one or another.");
- }
- print "OK: checking for use of NOPORTDOCS.\n" if ($verbose);
- if ($whole =~ /NOPORTDOCS/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "NOPORTDOCS found. Consider ".
- "using PORT_OPTIONS:MDOCS.");
- }
- #
- # whole file: check for USES[+]=gettext
- #
- print "OK: checking for USES=gettext without PORT_OPTIONS:MNLS.\n" if ($verbose);
- if ($makevar{USES} =~ /\bgettext\b/ && $whole !~ /PORT_OPTIONS:MNLS/
- && $whole !~ /NLS_USES=.*\bgettext\b/) {
- &perror("WARN", $file, -1, "Consider adding support for a NLS ".
- "knob to conditionally disable gettext support.");
- }
- #
- # whole file: check for deprecated commands
- #
- print "OK: checking for deprecated macros.\n" if $verbose;
- %deprecated = (
- USE_RCORDER => 'USE_RC_SUBR',
- );
- @deplist = (\%deprecated);
- for my $dlst (@deplist) {
- my $hurl = $dlst->{'__HELP__'};
- foreach my $depmacro (keys %{$dlst}) {
- if ($whole =~ /\n($depmacro)[+?:!]?=/) {
- my $derror = "$depmacro is ".
- "deprecated, use $dlst->{$1} instead";
- if (defined($hurl)) {
- $derror .= " (see $hurl for more details)";
- }
- &perror("FATAL", $file, -1, $derror);
- }
- }
- }
- #
- # whole file: DOS line endings
- #
- print "OK: checking for DOS line ending removal.\n" if ($verbose);
- if ($whole =~ /
/ || $whole =~ /:cntrl:/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "Possible manual removal of DOS ".
- "line endings found. Consider defining USES=dos2unix instead.");
- }
- #
- # whole file: direct use of command names
- #
- my %cmdnames = ();
- print "OK: checking direct use of command names.\n" if ($verbose);
- foreach my $i (qw(
- awk basename brandelf cat chmod chown cp cpio dialog dirname egrep expr
- false file find gmake grep gzcat ldconfig ln md5 mkdir mv objcopy paste patch
- pax perl printf rm rmdir ruby sed sdl-config sh sort sysctl touch tr which
- xargs xmkmf
- )) {
- $cmdnames{$i} = "\$\{\U$i\E\}";
- }
- $cmdnames{'echo'} = '${ECHO_CMD} or ${ECHO_MSG}';
- $cmdnames{'env'} = '${SETENV}';
- $cmdnames{'gunzip'} = '${GUNZIP_CMD}';
- $cmdnames{'gzip'} = '${GZIP_CMD}';
- $cmdnames{'install'} = '${INSTALL_foobar}';
- $cmdnames{'python'} = '${PYTHON_CMD}';
- $cmdnames{'sdl-config'} = '${SDL_CONFIG}';
- $cmdnames{'strip'} = '${STRIP_CMD}';
- $cmdnames{'unzip'} = '${UNZIP_CMD}';
- $cmdnames{'pkg_create'} = '${PKG_CMD}';
- foreach my $i (qw(aclocal autoconf autoheader automake autoreconf autoupdate autoscan ifnames libtoolize)) {
- $autocmdnames{$i} = "\$\{" . ( ( $i !~ /auto|aclocal/ ) ? "AUTO" : "" ) . "\U$i\E\}";
- }
- #
- # ignore parameter string to echo command.
- # note that we leave the command as is, since we need to check the
- # use of echo itself.
- $j = $whole;
- $j =~ s/([ \t][\@\-]{0,2})(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+(?:"(?:\\'|\\"|[^"])*"|'(?:\\'|\\"|[^'])*')[ \t]*;?(\n?)/$1$2;$3/g; #"
- # ignore variables names in .for loops, but not what's at the end
- # of the for loop
- $j =~ s/(\.for +)([^ ]*)( .*)/$1$3/;
- foreach my $i (keys %cmdnames) {
- # XXX This is a hack. Really, we should break $j up into individual
- # lines, and go through each one.
- while ($j =~ /^(.*\b$i\b.*)$/gm) {
- my $lineno = &linenumber($`);
- my $curline = $1;
- my $dte_test = $curline;
- $dte_test =~ s/^\s+//g;
- if ($desktop_entries =~ /\Q$dte_test\E$/) {
- next;
- }
- if ($curline =~ /(?:^|\s)[\@\-]{0,2}$i(?:$|\s)/
- && $curline !~ /^PORTNAME=[^\n]+$i/m
- && $curline !~ /^[A-Z]+_TARGET[?+]?=[^\n]+$i/m
- && $curline !~ /^[A-Z]+_INSTALL_TARGET[?+]?=[^\n]+$i/m
- && $curline !~ /^IGNORE(_[\w\d]+)?(.)?=[^\n]+$i/m
- && $curline !~ /^BROKEN(_[\w\d]+)?(.)?=[^\n]+$i/m
- && $curline !~ /^RESTRICTED(.)?=[^\n]+$i/m
- && $curline !~ /^NO_PACKAGE(.)?=[^\n]+$i/m
- && $curline !~ /^NO_CDROM(.)?=[^\n]+$i/m
- && $curline !~ /^MAINTAINER(.)?=[^\n]+$i/m
- && $curline !~ /^WWW(.)?=[^\n]+$i/m
- && $curline !~ /^CATEGORIES(.)?=[^\n]+$i/m
- && $curline !~ /^(\w+)?USES(.)?=[^\n]+$i/m
- && $curline !~ /^WX_COMPS(.)?=[^\n]+$i/m
- && $curline !~ /^ONLY_FOR_ARCHS_REASON(_[\w\d]+)?(.)?=[^\n]+$i/m
- && $curline !~ /^NOT_FOR_ARCHS_REASON(_[\w\d]+)?(.)?=[^\n]+$i/m
- && $curline !~ /^SHEBANG_FILES(.)?=[^\n]+$i/m
- && $curline !~ /^[\w\d]+_OLD_CMD(.)?=[^\n]+$i/m
- && $curline !~ /^[A-Z0-9_]+_DESC=[^\n]+$i/m
- && $curline !~ /#.*?$i/m
- && $curline !~ /^\s*#.+$/m
- && $curline !~ /\$\{MAKE_CMD\}.*\binstall\b/m
- && $curline !~ /\-\-$i/m
- && $curline !~ /^COMMENT(.)?=[^\n]+$i/m) {
- &perror("WARN", $file, $lineno, "possible direct use of ".
- "command \"$i\" found. use ".
- "$cmdnames{$i} instead.");
- }
- }
- }
- foreach my $i (keys %autocmdnames) {
- # XXX Same hack as above.
- while ($j =~ /^(.*(\b$i\d*).*)$/gm) {
- my $lm = $1;
- my $sm = $2;
- my $lineno = &linenumber($`);
- if ($lm =~ /(^|\s+)[\@\-]{0,2}($i\d*)\b/
- && $lm !~ /^[A-Z]+_TARGET[?+]?=[^\n]+($i\d*)/m
- && $lm !~ /^IGNORE(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^BROKEN(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^RESTRICTED(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^NO_PACKAGE(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^NO_CDROM(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^MAINTAINER(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^WWW(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^CATEGORIES(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^USES(.)?=[^\n]+$i/m
- && $lm !~ /^[A-Z0-9_]+_DESC=[^\n]+($i\d*)/m
- && $lm !~ /^SHEBANG_FILES(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^USE_AUTOTOOLS(.)?=[^\n]+($i\d*)/m
- && $lm !~ /^\s*#.+$/m
- && $lm !~ /^COMMENT(.)?=[^\n]+($i\d*)/m) {
- &perror("WARN", $file, $lineno, "possible direct use of ".
- "command \"$sm\" found. Use $autocmdnames{$i} ".
- "instead and set USES=autoreconf and GNU_CONFIGURE=yes");
- }
- }
- }
- if ($makevar{'USE_AUTOTOOLS'} =~ /\blibtool\b/) {
- &perror("WARN", $file, -1, "USE_AUTOTOOLS=libtool is deprecated. ".
- "Use USES=libtool instead.");
- }
- if ($makevar{'USE_AUTOTOOLS'} =~ /\blibtoolize\b/) {
- &perror("WARN", $file, -1, "USE_AUTOTOOLS=libtoolize is deprecated. ".
- "Use \"USES=autoreconf libtool\" instead.");
- } elsif ($makevar{'USE_AUTOCONF'}) {
- &perror("WARN", $file, -1, "USE_AUTOTOOLS is deprecated. ".
- "Use USES=autoreconf and set GNU_CONFIGURE=yes instead.");
- }
- #
- # whole file: check for use of paths that have macro replacements
- #
- my %pathnames = ();
- print "OK: checking for paths that have macro replacements.\n"
- if ($verbose);
- $pathnames{'$\{PREFIX\}/share/java/classes'} = 'JAVADIR';
- $pathnames{'$\{PREFIX\}/share/java'} = 'JAVASHAREDIR';
- foreach my $i (keys %pathnames) {
- my $lineno = &linenumber($`);
- if ($j =~ m|$i|gm) {
- &perror("FATAL", $file, $lineno, "you should use ".
- "$pathnames{$i} rather than $i");
- }
- }
- #
- # whole file: ${GZIP_CMD} -9 (or any other number)
- #
- print "OK: checking for compression arguments passed to \${GZIP_CMD}.\n"
- if ($verbose);
- if ($j =~ /\$\{GZIP_CMD}\s+-(\w+(\s+-)?)*(\d)/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "possible use of \"\${GZIP_CMD} -$3\" ".
- "found. \${GZIP_CMD} includes \"-\${GZIP}\" which ".
- "sets the compression level.");
- }
- #
- # whole file: ${CHMOD} used
- #
- print "OK: checking for \${CHMOD}.\n" if ($verbose);
- if ($j =~ /\n\s*\$\{CHMOD}/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "possible use of \"\${CHMOD}\" ".
- "found. Use @(owner,group,mode) syntax or \@owner/\@group ".
- "operators in pkg-plist instead.");
- }
- #
- # whole file: ${INSTALL} -o | -g used
- #
- print "OK: checking for \${INSTALL} -o | -g.\n" if ($verbose);
- if ($j =~ /\n\s*\$\{INSTALL}(.*-\b(o|g)\b.*)/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "possible use of \"\${INSTALL} -o | -g\" ".
- "found. Use @(owner,group,mode) syntax or \@owner/\@group ".
- "operators in pkg-plist instead.");
- }
- #
- # whole file: ${MKDIR} -p
- #
- print "OK: checking for \${MKDIR} -p.\n"
- if ($verbose);
- if ($j =~ /\$\{MKDIR}\s+-p/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "possible use of \"\${MKDIR} -p\" ".
- "found. \${MKDIR} includes ".
- "\"-p\" by default.");
- }
- #
- # check for use of ${FIND} ... ${XARGS} ${RM}
- #
- print "OK: checking for instances of \${FIND} ... \${XARGS} \${RM}.\n"
- if ($verbose);
- if ($j =~ /\$\{FIND\}.*\|.*\$\{XARGS\}.*\$\{RM\}/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "possible use of ".
- "\"\${FIND} ... \${XARGS} \${RM}\" when ".
- "\"\${FIND} ... -delete\" will work.");
- }
- #
- # whole file: ${MACHINE_ARCH}
- #
- print "OK: checking for instances of \${MACHINE_ARCH} being test.\n"
- if ($verbose);
- if ($j =~ /\$\{MACHINE_ARCH}\s*[!=]=/) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "MACHINE_ARCH should never be tested ".
- "directly; use ARCH instead.");
- }
- #
- # whole file: full path name
- #
- &abspathname($whole, $file);
- #
- # whole file: SITE_PERL
- #
- print "OK: checking SITE_PERL.\n" if ($verbose);
- if ($whole =~ /\nSITE_PERL[?:]?=/) {
- my $lineno = &linenumber($`);
- &perror("FATAL", $file, $lineno, "use of SITE_PERL discouraged. ".
- "it is set in bsd.port.mk.");
- }
- #
- # whole file: ${LOCALBASE}/lib/perl5/site_perl
- #
- if ($j =~ m'\$\{(?:LOCALBASE|PREFIX)}/lib/perl5/site_perl') {
- my $lineno = &linenumber($`);
- if ($1 !~ /PREFIX/) {
- &perror("WARN", $file, $lineno, "possible use of \"\${LOCALBASE}/lib/perl5/site_perl\" ".
- "found. use \"\${SITE_PERL}\" instead.");
- } else {
- &perror("WARN", $file, $lineno, "possible use of \"\${PREFIX}/lib/perl5/site_perl\" ".
- "found. use \"\${PREFIX}/\${SITE_PERL_REL}\" instead.");
- }
- }
- #
- # whole file: check for misuse of STAGE with SITE_PERL and SITE_ARCH
- #
- if ($j =~ m'\$\{STAGEDIR}\$\{SITE_PERL}') {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "\${STAGEDIR}\${SITE_PERL} should be ".
- "replaced by \${STAGEDIR}\${PREFIX}/\${SITE_PERL_REL}.");
- }
- if ($j =~ m'\$\{STAGEDIR}\$\{SITE_ARCH}') {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "\${STAGEDIR}\${SITE_ARCH} should be ".
- "replaced by \${STAGEDIR}\${PREFIX}/\${SITE_ARCH_REL}.");
- }
- #
- # whole file: USE_GNOME check
- #
- if ($whole =~ /^USE_GNOME[?:]?=\s*(.*)$/m) {
- if ($1 =~ /gnomehack/) {
- $use_gnome_hack = 1;
- }
- }
- #
- # whole file: USE_KDE check
- #
- if ($whole =~ /^USE_KDE[?:]?=\s*(.*)$/m) {
- if ($makevar{USES} !~ /\bkde:[45]/) {
- my $lineno = &linenumber($`);
- &perror("WARN", $file, $lineno, "USE_KDE is defined without ".
- "defining USES=kde:[45]");
- }
- }
- #
- # whole file: USES=pyqt:5
- #
- if ($makevar{USES} =~ /\bpyqt:5/ && $whole !~ /^USE_PYQT[?:]?=\s(.*)$/m && $makevar{USE_PYQT} eq '') {
- &perror("WARN", $file, -1, "When USES=pyqt:5 is defined, you must also define ".
- "USE_PYQT=xxxx");
- }
- #
- # whole file: USE_GCC checks
- #
- if ($whole =~ /^USE_GCC[?:]?=\s*([^\s#]*).*$/m) {
- my $lineno = &linenumber($`);
- my $gcc_val = $1;
- if ($gcc_val eq 'any' || $gcc_val eq 'yes') {
- # Just accept these two.
- } elsif ($gcc_val !~ /\+/) {
- &perror("WARN", $file, $lineno, "Setting a specific version for ".
- "USE_GCC should only be done as a last resort. Unless you ".
- "have confirmed this port does not build with later ".
- "versions of GCC, please use USE_GCC=$gcc_val+.");
- }
- }
- #
- # whole file: USE_JAVA check
- #
- if ($whole =~ /^USE_JAVA[?:]?=\s*(.*)$/m) {
- $use_java = 1;
- }
- #
- # whole file: USE_ANT check
- #
- if ($whole =~ /^USE_ANT[?:]?=\s*(.*)$/m) {
- $use_ant = 1;
- }
- #
- # whole file: USE_JAVA not defined, but other Java components are requested
- #
- if (!$use_java && ($use_ant || $whole =~ /^JAVA_VERSION[?:]?=\s*(.*)$/m ||
- $whole =~ /^JAVA_OS[?:]?=\s*(.*)$/m ||
- $whole =~ /^JAVA_VENDOR[?:]?=\s*(.*)$/m ||
- $whole =~ /^JAVA_RUN[?:]?=\s*(.*)$/m ||
- $whole =~ /^JAVA_BUILD[?:]?=\s*(.*)$/m)) {
- &perror("FATAL", $file, -1, "the port uses Java features, but USE_JAVA ".
- "is not defined");
- }
- #
- # whole file: check for USE_ANT and USES=gmake both defined
- #
- if ($use_ant && $makevar{USES} =~ /\bgmake\b/) {
- &perror("WARN", $file, -1, "a port shall not define both USE_ANT ".
- "and USES[+]=gmake");
- }
- #
- # whole file: check for USE_APACHE=yes
- #
- if ($whole =~ /^USE_APACHE[?:]?=\s*(yes)$/m) {
- &perror("FATAL", $file, -1, "Use USE_APACHE=VERSION ".
- "(where version can be found in \${PORTSDIR}/Mk/bsd.apache.mk) ".
- "instead of yes");
- }
- #
- # whole file: check for WITH_APACHE\d+
- #
- if ($whole =~ /WITH_APACHE\d+/) {
- &perror("FATAL", $file, -1, "Use WITH_APACHE=yes and .if ".
- "\${APACHE_VERSION} [==|<|>] 13|20|22|24");
- }
- #
- # whole file: check for JAVA_BUILD and NO_BUILD
- #
- if ($whole =~ /^NO_BUILD[?:]?=\s*(.*)$/m &&
- $whole =~ /^JAVA_BUILD[?:]?=\s*(.*)$/m) {
- &perror("FATAL", $file, -1, "JAVA_BUILD and NO_BUILD cannot be set ".
- "at the same time");
- }
- #
- # whole file: check for reassignment of ECHO_MSG
- #
- if ($whole =~ /^ECHO_MSG[?:]?=\s*(.*)$/m) {
- &perror("FATAL", $file, -1, "Re-assigning ECHO_MSG can break ".
- "``make readme''. Consider using \${PRINTF} directly instead ".
- "for custom message output.");
- }
- #
- # whole file: check for --build, --mandir, and --infodir
- # when GNU_CONFIGURE
- #
- if ($makevar{GNU_CONFIGURE} ne '' &&
- $makevar{CONFIGURE_ARGS} =~ /--(build|(man|info)dir)/) {
- &perror("WARN", $file, -1, "--build, --mandir, and --infodir ".
- "are not needed in CONFIGURE_ARGS as they are already set in ".
- "bsd.port.mk.");
- }
- #
- # whole file: check for redundant SHEBANG_LANGs
- #
- if ($whole =~ /^SHEBANG_LANG[?+]?=\s*(.*)$/m) {
- my $sh_lang = $1;
- my @shebang_langs = split(/\s+/, $makevar{SHEBANG_LANG} // '');
- my %sh_seen = ();
- foreach my $shebang_lang (@shebang_langs) {
- if ($sh_seen{$shebang_lang}) {
- $sh_seen{$shebang_lang}++;
- } else {
- $sh_seen{$shebang_lang} = 1;
- }
- if ($sh_seen{$shebang_lang} > 1 && $sh_lang =~ /\b$shebang_lang\b/) {
- &perror("WARN", $file, -1, "$shebang_lang is already included in ".
- "SHEBANG_LANG. You should remove this from $file.");
- }
- }
- }
- #
- # whole file: CONFIGURE_ENV
- #
- if ($whole =~ /\nCONFIGURE_ENV[?:+]?=\s*([^\\\n]+(\\\n[^\\\n]+)*)/) {
- my $configure_env = $1;
- my $cflags = undef;
- my $cxxflags = undef;
- if ($configure_env =~ /\bCFLAGS="([^"]+)"/ ||
- $configure_env =~ /\bCFLAGS='([^']+)'/ ||
- $configure_env =~ /\bCFLAGS=(\S+)/) {
- $cflags = $1;
- }
- if ($configure_env =~ /\bCXXFLAGS="([^"]+)"/ ||
- $configure_env =~ /\bCXXFLAGS='([^']+)'/ ||
- $configure_env =~ /\bCXXFLAGS=(\S+)/) {
- $cxxflags = $1;
- }
- if (defined($cflags) || defined($cxxflags)) {
- &perror("WARN", $file, -1, "CFLAGS/CXXFLAGS are not needed in ".
- "CONFIGURE_ENV as they are already added there in bsd.port.mk.");
- }
- if ($makevar{GNU_CONFIGURE} ne '') {
- if ((defined($cflags) && $cflags =~ /-I/) ||
- (defined($cxxflags) && $cxxflags =~ /-I/)) {
- &perror("WARN", $file, -1, "Consider passing include paths ".
- "to configure via the CPPFLAGS macro ".
- "(i.e. CPPFLAGS+=-I...)");
- }
- }
- if (defined($cflags) && $cflags !~ /\$\{CFLAGS/) {
- &perror("FATAL", $file, -1, "CFLAGS are clobbered in ".
- "CONFIGURE_ENV. Alter CFLAGS in the Makefile with ".
- "CFLAGS+=... instead");
- }
- if (defined($cxxflags) && $cxxflags !~ /\$\{CXXFLAGS/) {
- &perror("FATAL", $file, -1, "CXXFLAGS are clobbered in ".
- "CONFIGURE_ENV. Alter CXXFLAGS in the Makefile with ".
- "CXXFLAGS+=... instead");
- }
- if ($configure_env =~ /(FC)=/ ||
- $configure_env =~ /(F77)=/ ||
- $configure_env =~ /(FFLAGS)=/) {
- &perror("FATAL", $file, -1, "$1 is already ".
- "passed in CONFIGURE_ENV via bsd.gcc.mk. If you need to ".
- "override the default value, alter $1 in the Makefile ".
- "instead with $1=...");
- }
- if ($configure_env =~ /(\bCPPFLAGS)=/) {
- &perror("FATAL", $file, -1, "$1 is already ".
- "passed in CONFIGURE_ENV via bsd.port.mk. If you need to ".
- "override the default value, alter $1 in the Makefile ".
- "instead with $1+=...");
- }
- if ($configure_env =~ /(\bLDFLAGS)=/) {
- &perror("FATAL", $file, -1, "$1 is already passed in ".
- "CONFIGURE_ENV via bsd.port.mk. If you need to ".
- "override the default value, alter $1 in the Makefile ".
- "instead with $1+=...");
- }
- }
- #
- # whole file: *FLAGS
- #
- foreach my $f (qw(CFLAGS CXXFLAGS CPPFLAGS LDFLAGS)) {
- if ($whole =~ /^$f=/m) {
- &perror("WARN", $file, -1, "$f is overridden in the Makefile ".
- "clobbering a value possibly set by a user. Consider ".
- "using $f+=... if you want to add or $f:=\${$f:C/...//} ".
- "if you want to remove specific flags");
- }
- }
- #
- # whole file: MAKE_ENV
- #
- if ($whole =~ /\nMAKE_ENV[?:+]?=\s*([^\\\n]+(\\\n[^\\\n]+)*)/) {
- my $make_env = $1;
- if ($make_env =~ /(CPPFLAGS)=/) {
- &perror("FATAL", $file, -1, "$1 is already ".
- "passed in MAKE_ENV via bsd.port.mk. If you need to ".
- "override the default value, alter $1 in the Makefile ".
- "instead with $1=...");
- }
- }
- #
- # slave port check
- #
- if ($slaveport) {
- print "OK: slave port detected, checking for inclusion of $masterdir/Makefile.\n"
- if ($verbose);
- if ($whole =~ /^\.\s*include\s*[<"]bsd\.port(?:\.post)?\.mk[">]/m) {
- &perror("FATAL", $file, -1, "supposedly non-slave port with".
- " .CURDIR != MASTERDIR");
- } elsif ($whole =~ /^\.\s*include\s*[<"]bsd\.port\.pre\.mk[">]/m) {
- &perror("FATAL", $file, -1, "slave ports may not include".
- " bsd.port.pre.mk");
- }
- if ($whole !~ /\n\.include\s+"\$\{MASTERDIR\}\/Makefile"\s*$/s) {
- &perror("FATAL", $file, -1, "the last line of a slave port's Makefile has to be".
- ' .include "${MASTERDIR}/Makefile"');
- }
- print "OK: checking master port in $masterdir.\n" if ($verbose);
- if (! -e "$masterdir/Makefile") {
- &perror("WARN", "", -1, "unable to locate master port in $masterdir");
- }
- if ($whole !~ /^MASTERDIR=\s*\$\{\.CURDIR\}(?:\/\.\.){1,2}(?:\/[\w\@.+-]+){1,2}\s*$/m) {
- &perror("WARN", $file, -1, "slave ports must define MASTERDIR=".
- '${.CURDIR}/..(/../<category>)/<port>');
- }
- } else {
- #$slaveport = 0;
- print "OK: non-slave port detected, checking for anything after bsd.port(.post).mk.\n"
- if ($verbose);
- if ($whole !~ /\n\.include\s+<bsd\.port(?:\.post)?\.mk>\s*$/s &&
- $whole !~ /\n\.endif\s*$/s) {
- &perror("FATAL", $file, -1, "the last line of Makefile has to be".
- ' .include <bsd.port(.post).mk> (or .endif in the case of a conditional)');
- }
- if ($whole =~ /^MASTERDIR\s*[+?:!]?\s*=/m) {
- &perror("WARN", $file, -1, "non-slave ports may not define MASTERDIR");
- }
- }
- #
- # break the makefile into sections.
- #
- $tmp = $rawwhole;
- $tmp =~ s/\\\n/ /g;
- # keep comment, blank line, comment in the same section
- # XXX: Take this out since it breaks some commenting; see PR240359.
- #$tmp =~ s/(#.*\n)\n+(#.*)/$1$2/g;
- @sections = split(/\n\n+/, $tmp);
- for ($i = 0; $i <= $#sections; $i++) {
- if ($sections[$i] !~ /\n$/) {
- $sections[$i] .= "\n";
- }
- }
- $idx = 0;
- my @linestocheck = ();
- # check if all lines in the first section are comments
- if (grep(/^#/, split(/\n/, $sections[$idx])) == split(/\n/, $sections[$idx])) {
- #
- # section 1: comment lines.
- #
- print "OK: checking comment section of $file.\n" if ($verbose);
- @linestocheck = split("\n", <<EOF);
- Whom
- Date [cC]reated
- EOF
- $tmp = $sections[$idx++];
- $tmp = "\n" . $tmp; # to make the begin-of-line check easier
- if ($tmp =~ /\n[^#]/) {
- &perror("FATAL", $file, -1, "non-comment line in comment section.");
- }
- if ($tmp =~ m/Version [rR]equired/) {
- &perror("WARN", $file, -1, "Version required is no longer needed in the comment section.");
- }
- }
- #
- # for the rest of the checks, comment lines are not important.
- #
- for ($i = 0; $i < scalar(@sections); $i++) {
- $sections[$i] = "\n" . $sections[$i];
- $sections[$i] =~ s/\n#[^\n]*//g;
- $sections[$i] =~ s/\n\n+/\n/g;
- $sections[$i] =~ s/^\n//;
- }
- #
- # section 2: PORTNAME/PORTVERSION/...
- #
- print "OK: checking first section of $file (PORTNAME/...).\n"
- if ($verbose);
- $tmp = $sections[$idx++];
- # check the order of items.
- &checkorder('PORTNAME', $tmp, $file, qw(
- PORTNAME PORTVERSION DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX
- PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES MASTER_SITE_SUBDIR
- PROJECTHOST PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX DISTFILES(_\w+)?
- DIST_SUBDIR EXTRACT_ONLY
- ));
- # check the items that has to be there.
- $tmp = "\n" . $tmp;
- print "OK: checking PORTNAME/PORTVERSION/DISTVERSION.\n" if ($verbose);
- if ($tmp !~ /\nPORTNAME(.)?=/) {
- &perror("FATAL", $file, -1, "PORTNAME has to be there.") unless ($slaveport && $makevar{PORTNAME} ne '');
- } elsif (defined $1 && $1 ne '') {
- &perror("WARN", $file, -1, "unless this is a master port, PORTNAME has to be set by \"=\", ".
- "not by \"$1=\".") unless ($masterport);
- }
- if ($tmp !~ /\n(PORTVERSION|DISTVERSION)(.)?=/) {
- &perror("FATAL", $file, -1, "PORTVERSION or DISTVERSION has to be there.") unless (($makevar{PORTVERSION} ne '' || $makevar{DISTVERSION} ne ''));
- if (!$slaveport && ($makevar{PORTVERSION} ne '' || $makevar{DISTVERSION} ne '')) {
- &perror("WARN", $file, -1, "PORTVERSION/DISTVERSION is set externally to this port's Makefile, but this port is not configured as a slave port.");
- }
- } elsif (defined $2 && $2 ne '') {
- &perror("WARN", $file, -1, "unless this is a master port, PORTVERSION has to be set by \"=\", ".
- "not by \"$2=\".") unless ($masterport);
- }
- if ($tmp =~ /\nPORTVERSION.?=/ && $tmp =~ /\nDISTVERSION.?=/) {
- &perror("FATAL", $file, -1, "either PORTVERSION or DISTVERSION must be ".
- "specified, not both.");
- }
- if ($newport) {
- print "OK: checking for existence of PORTREVISION in new port.\n"
- if ($verbose);
- if ($tmp =~ /^PORTREVISION(.)?=/m) {
- &perror("WARN", $file, -1, "new ports should not set PORTREVISION.");
- }
- } elsif (!$slaveport) {
- print "OK: checking for PORTREVISION=0.\n" if ($verbose);
- if ($tmp =~ /^PORTREVISION=\s*0/m) {
- &perror("WARN", $file, -1, "Setting PORTREVISION to 0 is not ".
- "necessary.");
- }
- }
- if ($newport) {
- print "OK: checking for existence of PORTEPOCH in new port.\n"
- if ($verbose);
- if ($tmp =~ /^PORTEPOCH(.)?=/m) {
- &perror("WARN", $file, -1, "new ports should not set PORTEPOCH.");
- }
- }
- print "OK: checking CATEGORIES.\n" if ($verbose);
- if ($tmp !~ /\nCATEGORIES(.)?=/) {
- &perror("FATAL", $file, -1, "CATEGORIES has to be there.") unless ($makevar{CATEGORIES} ne '');
- if (!$slaveport && $makevar{CATEGORIES} ne '') {
- &perror("WARN", $file, -1, "CATEGORIES is set externally to this port's Makefile, but this port is not configured as a slave port.");
- }
- } elsif (defined $1 && ($i = $1) ne '' && $i =~ /[^?+]/) {
- &perror("WARN", $file, -1, "unless this is a master port, CATEGORIES should be set by \"=\", \"?=\", or \"+=\", ".
- "not by \"$i=\".") unless ($masterport);
- }
- @cat = split(/\s+/, $makevar{CATEGORIES});
- if (@cat == 0) {
- &perror("FATAL", $file, -1, "CATEGORIES left blank. set it to \"misc\"".
- " if nothing seems apropriate.");
- } else {
- my %seencat = ();
- foreach my $cat (@cat) {
- if ($seencat{$cat}) {
- &perror("WARN", $file, -1, "Duplicate category, $cat specified".
- " in CATEGORIES.");
- } else {
- $seencat{$cat} = 1;
- }
- }
- }
- if ($use_java && !grep /^java$/, @cat) {
- &perror("WARN", $file, -1, "the port uses Java but is not part of the ".
- "``java'' category");
- }
- if (scalar(@cat) == 1 && $cat[0] eq "java") {
- &perror("FATAL", $file, -1, "the ``java'' category shall not be the only ".
- "one for a port");
- }
- if ($newport && scalar(@cat) > 0 && $cat[0] eq "java") {
- &perror("WARN", $file, -1, "save for ports directly related to the Java ".
- "language, porters are encouraged not to use ``java'' as ".
- "the main category for a port");
- }
- if ($committer && $makevar{'.CURDIR'} =~ m/\Q${portsdir}\E\/([^\/]+)\/[^\/]+\/?$/) {
- if ($cat[0] ne $1 && $makevar{PKGCATEGORY} ne $1 ) {
- &perror("FATAL", $file, -1, "category \"$1\" must be listed first");
- }
- }
- #MICHAEL: can these three lang cat checks be combined?
- # skip the first category specification if it's a language specific one.
- if (grep($_ eq $cat[0], @lang_cat)) {
- $has_lang_cat = 1;
- $port_lang = $lang_pref{$cat[0]};
- shift @cat;
- }
- # skip further if more language specific ones follow.
- if (@cat && grep($_ eq $cat[0], @lang_cat)) {
- &perror("WARN", $file, -1, "multiple language specific categories detected. ".
- "are you sure?");
- do {
- shift @cat;
- } while (@cat && grep($_ eq $cat[0], @lang_cat));
- }
- # check x11 in CATEGORIES
- #MICHAEL: I don't understand this line
- if (2 <= @cat && $cat[1] eq "x11") {
- &perror("WARN", $file, -1, "only specific kind of apps should ".
- "specify \"x11\" in CATEGORIES. ".
- "Do you mean just USE_XORG? ".
- "Then remove \"x11\" from CATEGORIES.");
- }
- if (2 <= @cat) {
- # skip the first one that we know is _not_ language specific.
- shift @cat;
- # any language specific one after non language specific ones?
- foreach my $cat (@cat) {
- if (grep($_ eq $cat, @lang_cat)) {
- $has_lang_cat = 1;
- $port_lang = $lang_pref{$cat};
- &perror("WARN", $file, -1, "when you specify multiple categories, ".
- "language specific category should come first.");
- }
- }
- }
- # check the URL
- if (($tmp =~ /\nMASTER_SITES[+?]?=[ \t]*([^\n]*)\n/
- && $1 !~ /^[ \t]*$/) || ($makevar{MASTER_SITES} ne '')) {
- print "OK: seen MASTER_SITES, sanity checking URLs.\n"
- if ($verbose);
- my $urlseen = 0;
- my @sites = split(/\s+/, $1 // '');
- my $ftphttp = 0;
- foreach my $i (@sites) {
- last if ($i =~ /^#/);
- if ($i =~ m#^\w+://#) {
- $urlseen = 1;
- $ftphttp = 1 if ($i =~ /^(ftp|http):/);
- &urlcheck($i, $file);
- unless (&is_predefined($i, $file)) {
- print "OK: URL \"$i\" ok.\n"
- if ($verbose);
- }
- } else {
- my $good_ms = 1;
- foreach my $mss (split(/\s+/, $makevar{MASTER_SITES_SUBDIRS})) {
- my ($ms, $sd) = split(/:/, $mss);
- if ($i =~ /^$ms/ && $i ne $ms) {
- my $ip = $i;
- $ip =~ s/^$ms\///;
- my (@ip_parts) = split(/:/, $ip);
- my $check_var = $ip_parts[0];
- shift(@ip_parts);
- foreach my $check_part (@ip_parts) {
- if ($check_part =~ /^[A-Z]}/) {
- $check_var .= ":$check_part";
- }
- }
- my $exp_sd = get_makevar($check_var);
- if ($exp_sd eq $sd) {
- &perror("WARN", $file, -1, "typically when you specify magic site $ms ".
- "you do not need anything else as $sd is assumed");
- $good_ms = 0;
- }
- }
- }
- if ($good_ms) {
- print "OK: non-URL \"$i\" ok.\n"
- if ($verbose);
- }
- # Assume variables contain an ftp/http site.
- $ftphttp = 1;
- }
- }
- } else {
- &perror("WARN", $file, -1, "no MASTER_SITES found. is it ok?");
- }
- # check DISTFILES and related items.
- $distfiles = $1 if ($tmp =~ /\nDISTFILES[+?]?=[ \t]*([^\n]+)\n/);
- $portname = $makevar{PORTNAME};
- $portversion = $makevar{PORTVERSION};
- $distversionprefix = $makevar{DISTVERSIONPREFIX};
- $distversion = $makevar{DISTVERSION};
- $distversionsuffix = $makevar{DISTVERSIONSUFFIX};
- $distname = $1 if ($tmp =~ /\nDISTNAME[+?]?=[ \t]*([^\n]+)\n/);
- $extractsufx = $1 if ($tmp =~ /\nEXTRACT_SUFX[+?]?=[ \t]*([^\n]+)\n/);
- # check bogus EXTRACT_SUFX.
- if ($extractsufx ne '') {
- print "OK: seen EXTRACT_SUFX, checking value.\n" if ($verbose);
- if ($distfiles ne '') {
- &perror("WARN", $file, -1, "no need to define EXTRACT_SUFX if ".
- "DISTFILES is defined.");
- }
- if ($extractsufx eq '.tar.gz') {
- &perror("WARN", $file, -1, "EXTRACT_SUFX is \".tar.gz.\" ".
- "by default. you don't need to specify it.");
- }
- if ($extractsufx =~ /^\.tar\.(bz2|lzma|xz|Z)$/) {
- my $ext = $1;
- $ext = 'bzip2' if ($ext eq 'bz2');
- &perror("WARN", $file, -1, "EXTRACT_SUFX is \".tar.$ext\". ".
- "Please use USES=tar:$ext instead.");
- }
- if ($extractsufx =~ /^\.(tgz|tbz|txz)$/) {
- &perror("WARN", $file, -1, "EXTRACT_SUFX is \".$1\". ".
- "Please use USES=tar:$1 instead.");
- }
- if ($extractsufx eq '.zip') {
- &perror("WARN", $file, -1, "EXTRACT_SUFX is \".zip\" ".
- "You should use USES[+]=zip instead.");
- }
- } else {
- print "OK: no EXTRACT_SUFX seen, using default value.\n"
- if ($verbose);
- $extractsufx = '.tar.gz';
- }
- print "OK: sanity checking PORTNAME/PORTVERSION/DISTVERSIONPREFIX/DISTVERSION/DISTVERSIONSUFFIX.\n" if ($verbose);
- if ($distname ne '') {
- my $exp_distname = $makevar{DISTNAME};
- if ($exp_distname eq "$portname-$portversion") {
- &perror("WARN", $file, -1, "DISTNAME is \${PORTNAME}-\${PORTVERSION} by ".
- "default, you don't need to define DISTNAME.");
- } else {
- if ($exp_distname eq "$portname-$distversionprefix$distversion$distversionsuffix") {
- &perror("WARN", $file, -1, "DISTNAME is \${PORTNAME}-\${DISTVERSIONPREFIX}\${DISTVERSION}\${DISTVERSIONSUFFIX} by ".
- "default, you don't need to define DISTNAME.");
- }
- }
- if ($distname =~ /PORTREVISION/) {
- &perror("FATAL", $file, -1, "DISTNAME contains a reference to ".
- "PORTREVISION. You should only be using PORTVERSION");
- }
- if ($distname =~ /PORTEPOCH/) {
- &perror("FATAL", $file, -1, "DISTNAME contains a reference to ".
- "PORTEPOCH. You should only be using PORTVERSION");
- }
- }
- if ($portname =~ /^$re_lang_short/) {
- &perror("FATAL", $file, -1, "language prefix is automatically".
- " set by PKGNAMEPREFIX.".
- " you must remove it from PORTNAME.");
- }
- if ($portname =~ /([|<>=! ])/) {
- &perror("FATAL", $file, -1, "PORTNAME contains the illegal character \"$1\".".
- " You should modify \"$portname\".");
- } elsif ($portname =~ /\$[\{\(].+[\}\)]/) {
- &perror("WARN", $file, -1, "using variable in PORTNAME.".
- " consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX.");
- } elsif ($portname =~ /([^\w._@+-])/) {
- &perror("WARN", $file, -1, "using \"$1\" in PORTNAME.".
- " You should modify \"$portname\".");
- } elsif ($portname =~ /-/ && $distname ne '') {
- &perror("WARN", $file, -1, "using hyphen in PORTNAME.".
- " consider using PKGNAMEPREFIX and/or PKGNAMESUFFIX.");
- }
- if ($portversion eq '' && $distversion eq '') {
- &perror("FATAL", $file, -1, "either PORTVERSION or DISTVERSION must be specified");
- }
- if ($portversion =~ /^pl[0-9]*$/
- || $portversion =~ /^[0-9]*[A-Za-z]?[0-9]*([.+][0-9]*[A-Za-z]?[0-9+]*)*$/) {
- print "OK: PORTVERSION \"$portversion\" looks fine.\n" if ($verbose);
- } elsif ($portversion =~ /^[^\-]*\$[{\(].+[\)}][^\-]*$/) {
- &perror("WARN", $file, -1, "using variable, \"$portversion\", as version ".
- "number");
- } elsif ($portversion =~ /([-,_<>=! #*])/) {
- &perror("FATAL", $file, -1, "PORTVERSION must not contain \"$1\". ".
- "You should modify \"$portversion\".");
- } else {
- &perror("FATAL", $file, -1, "PORTVERSION looks illegal. ".
- "You should modify \"$portversion\".");
- }
- $pkg_version = $makevar{PKG_VERSION};
- $conflicts = $makevar{CONFLICTS};
- if ($makevar{CONFLICTS_BUILD}) {
- $conflicts .= " " if $conflicts;
- $conflicts .= $makevar{CONFLICTS_BUILD};
- }
- if ($makevar{CONFLICTS_INSTALL}) {
- $conflicts .= " " if $conflicts;
- $conflicts .= $makevar{CONFLICTS_INSTALL};
- }
- if ($conflicts) {
- print "OK: checking CONFLICTS.\n" if ($verbose);
- my %seen;
- foreach my $conflict (split ' ', $conflicts) {
- if (not $seen{$conflict}) {
- if ($conflict =~ m/-\[0-9\]\*$/) {
- &perror("WARN", $file, -1, "CONFLICTS definition \"$conflict\" ".
- "ends in redundant version pattern. ".
- "You should remove \"-[0-9]*\" from that pattern.");
- }
- $seen{$conflict} = 1;
- }
- }
- }
- $versiondir = $ENV{VERSIONDIR} // '/var/db/chkversion';
- $indexfile = "$portsdir/$makevar{INDEXFILE}";
- $versionfile = "$versiondir/VERSIONS";
- $useindex = !-r "$versionfile";
- $versionfile = $indexfile
- if $useindex;
- if (-r "$versionfile") {
- print "OK: checking if PORTVERSION is going backwards.\n" if ($verbose);
- open VERSIONS, "<$versionfile";
- while (<VERSIONS>) {
- my($origin, $version) = ('', '');
- chomp;
- next if /^(#|$)/;
- if ($useindex) {
- ($version, $origin) = split /\|/;
- $origin =~ s,^.*/([^/]+/[^/]+)/?$,$1,;
- } else {
- ($origin, $version) = split;
- }
- if ($origin eq $makevar{PKGORIGIN}) {
- my $newversion = $makevar{PKGNAME};
- my $oldversion = $version;
- my $result = '';
- $newversion =~ s/^.*-//;
- $oldversion =~ s/^.*-//;
- $result = `$pkg_version -t '$newversion' '$oldversion'`;
- chomp $result;
- if ($result eq '<') {
- &perror("FATAL", $file, -1, "$makevar{PKGNAME} < $version. ".
- "Choose another PORTVERSION or bump PORTEPOCH.");
- # $backwards{$origin} = "$pkgname{$origin} < $version";
- }
- last;
- }
- }
- close VERSIONS;
- }
- # use INDEX (if present) to check for PKGBASE collisions
- if (-r "$indexfile") {
- open INDEX, "<$portsdir/$makevar{INDEXFILE}";
- while (<INDEX>) {
- my($origin, $pkgbase) = ('', '');
- chomp;
- next if /^(#|$)/;
- ($pkgbase, $origin) = split /\|/;
- $pkgbase =~ s,-[^-]+$,,;
- $origin =~ s,^.*/([^/]+/[^/]+)/?$,$1,;
- if ($pkgbase eq $makevar{PKGBASE} and $origin ne $makevar{PKGORIGIN}) {
- &perror("FATAL", $file, -1, "The package base name \"$makevar{PKGBASE}\" is already in use by the \"$origin\" port. ".
- "Choose another PORTNAME or use a PKGNAMEPREFIX or PKGNAMESUFFIX.");
- }
- }
- close INDEX;
- }
- # verify that all flavors have distinct names
- if ($makevar{FLAVORS}) {
- my %PKGFLAVOR;
- my @FLAVORS = split(/ /, $makevar{FLAVORS});
- my $makeenv_save = $makeenv;
- for my $flavor (@FLAVORS) {
- $makeenv = $makeenv_save . " FLAVOR=$flavor";
- my $pkgbase = &get_makevar("PKGBASE");
- if ($PKGFLAVOR{$pkgbase}) {
- &perror("FATAL", $file, -1, "The flavors \"$PKGFLAVOR{$pkgbase}\" and \"$flavor\" both generate a package named \"$pkgbase\". ".
- "Make the package names unique, e.g., with different PKGNAMEPREFIX or PKGNAMESUFFIX values for each flavor.");
- } else {
- $PKGFLAVOR{$pkgbase} = $flavor;
- }
- }
- my $makeenv = $makeenv_save;
- }
- # if DISTFILES have only single item, it is better to avoid DISTFILES
- # and to use combination of DISTNAME and EXTRACT_SUFX (unless USE_GITHUB
- # or USE_GITLAB is set to nodefault in which case it is fine).
- # example:
- # DISTFILES=package-1.0.tgz
- # should be
- # DISTNAME= package-1.0
- # EXTRACT_SUFX= .tgz
- if ($makevar{USE_GITHUB} ne 'nodefault' && $makevar{USE_GITLAB} ne 'nodefault') {
- if ($distfiles =~ /^\S+$/ && $distfiles !~ /:[^\/:]+$/) {
- $bogusdistfiles++;
- print "OK: seen DISTFILES with single item, checking value.\n"
- if ($verbose);
- &perror("WARN", $file, -1, "use of DISTFILES with single file ".
- "discouraged. distribution filename should be set by ".
- "DISTNAME and EXTRACT_SUFX.");
- if ($distfiles eq (($distname ne '') ? $distname : "$portname-$portversion") . $extractsufx) {
- &perror("WARN", $file, -1, "definition of DISTFILES not necessary. ".
- "DISTFILES is \${DISTNAME}/\${EXTRACT_SUFX} ".
- "by default.");
- }
- # display advice only in certain cases.
- #MICHAEL: will this work with multiple distfiles in this list? what about
- # doing the same sort of thing for DISTNAME, is it needed?
- if ($distfiles =~ /^\Q$i\E([\-.].+)$/) {
- &perror("WARN", $file, -1, "how about \"EXTRACT_SUFX=$1\"".
- ", instead of DISTFILES?");
- }
- }
- }
- push(@varnames, qw(
- PORTNAME PORTVERSION DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX
- PORTREVISION PORTEPOCH CATEGORIES MASTER_SITES MASTER_SITE_SUBDIR
- PROJECTHOST PKGNAMEPREFIX PKGNAMESUFFIX DISTNAME EXTRACT_SUFX DISTFILES(_\w+)?
- DIST_SUBDIR EXTRACT_ONLY
- ));
- #
- # section 3: PATCH_SITES/PATCHFILES(optional)
- #
- print "OK: checking second section of $file (PATCH*: optional).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- if ($tmp =~ /(PATCH_SITES|PATCH_SITE_SUBDIR|PATCHFILES|PATCH_DIST_STRIP)/) {
- &checkearlier($file, $tmp, @varnames);
- if ($tmp =~ /PATCH_SITES[?+]?=[^\n]+\n/) {
- print "OK: seen PATCH_SITES.\n" if ($verbose);
- $tmp =~ s/PATCH_SITES[?+]?=[^\n]+\n//;
- }
- if ($tmp =~ /PATCH_SITE_SUBDIR[?+]?=[^\n]+\n/) {
- print "OK: seen PATCH_SITE_SUBDIR.\n" if ($verbose);
- $tmp =~ s/PATCH_SITE_SUBDIR[?+]?=[^\n]+\n//;
- }
- if ($tmp =~ /PATCHFILES[?+]?=[^\n]+\n/) {
- print "OK: seen PATCHFILES.\n" if ($verbose);
- $tmp =~ s/PATCHFILES[?+]?=[^\n]+\n//;
- }
- if ($tmp =~ /PATCH_DIST_STRIP[?+]?=[^\n]+\n/) {
- print "OK: seen PATCH_DIST_STRIP.\n" if ($verbose);
- $tmp =~ s/PATCH_DIST_STRIP[?+]?=[^\n]+\n//;
- }
- &checkextra($tmp, 'PATCH_SITES', $file);
- $idx++;
- }
- push(@varnames, qw(
- PATCH_SITES PATCHFILES PATCH_DIST_STRIP
- ));
- #
- # section 4: MAINTAINER
- #
- print "OK: checking third section of $file (MAINTAINER).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- &checkearlier($file, $tmp, @varnames);
- &checkorder('MAINTAINER', $tmp, $file, qw(
- MAINTAINER COMMENT WWW
- ));
- $tmp = "\n" . $tmp;
- if ($tmp =~ /\nMAINTAINER(\?)?=([^\n]+)/) {
- my $addr = $2;
- if (defined $1 && $1 ne '') {
- &perror("WARN", $file, -1, "unless this is a master port, ".
- "MAINTAINER has to be set by \"=\", ".
- "not by \"$1=\".") unless ($masterport);
- }
- $addr =~ s/^\s*//;
- $addr =~ s/\s*$//;
- if ($addr =~ /[\s,<>()]/) {
- &perror("FATAL", $file, -1, "MAINTAINER should be a single address without comment.");
- }
- if ($addr !~ /^[^\@]+\@[\w\d\-\.]+$/) {
- &perror("FATAL", $file, -1, "MAINTAINER address, $addr, does not appear to be a valid email address.");
- }
- if ($newport && $addr =~ /ports\@freebsd.org/i) {
- &perror("WARN", $file, -1, "new ports should not be maintained by ".
- "ports\@FreeBSD.org.");
- }
- $tmp =~ s/\nMAINTAINER\??=[^\n]+//;
- } elsif ($whole !~ /\nMAINTAINER[?]?=/) {
- &perror("FATAL", $file, -1, "no MAINTAINER listed.") unless ($makevar{MAINTAINER} ne '');
- if (!$slaveport && $makevar{MAINTAINER} ne '') {
- &perror("WARN", $file, -1, "MAINTAINER is set externally to this port's Makefile, but this port is not configured as a slave port.");
- }
- }
- $tmp =~ s/\n\n+/\n/g;
- # check COMMENT
- if ($tmp !~ /\nCOMMENT(.)?=/) {
- &perror("FATAL", $file, -1, "COMMENT has to be there.") unless ($makevar{COMMENT} ne '');
- if (!$slaveport && $makevar{COMMENT} ne '') {
- &perror("WARN", $file, -1, "COMMENT is set externally to this port's Makefile, but this port is not configured as a slave port.");
- }
- } elsif (defined $1 && $1 ne '') {
- &perror("WARN", $file, -1, "unless this is a master port, COMMENT has to be set by \"=\", ".
- "not by \"$1=\".") unless ($masterport);
- } else { # check for correctness
- if (($makevar{COMMENT} !~ /^["\[0-9A-Z]/) || ($makevar{COMMENT} =~ m/\.$/)) { #"
- &perror("WARN", $file, -1, "COMMENT should begin with a capital, and end without a period");
- }
- if (length($makevar{COMMENT}) > 70) {
- &perror("WARN", $file, -1, "COMMENT exceeds 70 characters limit.");
- }
- }
- # check WWW
- if ($tmp !~ /\nWWW.?=\s*(\S+)/) {
- &perror("WARN", $file, -1, "WWW should exist and immediately follow COMMENT.") unless ($makevar{WWW} ne '');
- }
- # check for correctness
- {
- my $wwwurl = $1 // $makevar{WWW};
- if ($wwwurl and $wwwurl !~ m|^https?://|) {
- &perror("WARN", $file, -1, "WWW URL, $wwwurl should begin with \"http://\" or \"https://\".");
- }
- if ($wwwurl =~ m|search.cpan.org|) {
- if ($wwwurl =~ m|^http.?://search.cpan.org/~|) {
- &perror("WARN", $file, -1, "consider changing WWW URL to https://search.cpan.org/dist/$makevar{PORTNAME}/");
- }
- if ($wwwurl =~ m,/$,) {
- &perror("WARN", $file, -1, "end WWW CPAN URL with a \"/\"");
- }
- }
- }
- $idx++;
- push(@varnames, qw(
- MAINTAINER COMMENT WWW
- ));
- #
- # section 5: LICENSE
- #
- print "OK: checking fourth section of $file (LICENSE).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- if ($makevar{LICENSE}) {
- &checkorder('LICENSE', $tmp, $file, qw(
- LICENSE LICENSE_COMB LICENSE_GROUPS(_\w+)? LICENSE_NAME(_\w+)?
- LICENSE_TEXT(_\w+)? LICENSE_FILE(_\w+)? LICENSE_PERMS(_\w+)?
- LICENSE_DISTFILES(_\w+)?
- ));
- # check LICENSE
- if ($makevar{LICENSE} && $makevar{LICENSE} ne '') {
- my $comb = $makevar{LICENSE_COMB} // 'single';
- my @tokens = split(/ /, $makevar{LICENSE});
- if ($comb eq 'single' && scalar(@tokens) > 1) {
- &perror("FATAL", $file, -1, "LICENSE contains multiple licenses but LICENSE_COMB is not set to 'dual' or 'multi'");
- }
- }
- # check value of LICENSE_COMB
- if ($makevar{LICENSE_COMB} && $makevar{LICENSE_COMB} !~ /^(single|dual|multi$)/) {
- &perror("FATAL", $file, -1, "LICENSE_COMB contains invalid value '$1' - must be one of 'single', 'dual', 'multi'");
- }
- # Check for proper license file usage
- while ($tmp =~ /\nLICENSE_FILE_([^\s=]+)([\s=])/g) {
- my $lfn = $1;
- my $nchar = $2;
- if (!grep(/\b$lfn\b/, $makevar{LICENSE})) {
- &perror("FATAL", $file, -1, "license specified is $makevar{LICENSE}, ".
- "but found LICENSE_FILE for $lfn.");
- }
- if ($lfn =~ /\+$/ && $nchar eq '=') {
- &perror("WARN", $file, -1, "if license ends with a '+', make sure ".
- "LICENSE_FILE_$lfn is followed by a space before the '='.");
- }
- }
- # Last-ditch check to make sure the license is sanely defined.
- my $lic_check = system("make check-license 2>&1 >/dev/null");
- if ($lic_check) {
- &perror("FATAL", $file, -1, "Failed to validate port LICENSE '$makevar{LICENSE}' with ``make check-license''");
- }
- $idx++;
- push(@varnames, qw(
- LICENSE LICENSE_COMB LICENSE_GROUPS LICENSE_NAME
- LICENSE_TEXT LICENSE_FILE LICENSE_PERMS
- ));
- } else {
- &perror("WARN", $file, -1, "Consider defining LICENSE.");
- }
- #
- # section 6: BROKEN/IGNORE/DEPRECATED (may not be there)
- #
- print "OK: checking sixth section of $file (BROKEN/IGNORE/DEPRECATED).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- @linestocheck = qw(
- DEPRECATED EXPIRATION_DATE FORBIDDEN BROKEN(_\w+)? IGNORE(_\w+)?
- ONLY_FOR_ARCHS ONLY_FOR_ARCHS_REASON(_\w+)?
- NOT_FOR_ARCHS NOT_FOR_ARCHS_REASON(_\w+)? LEGAL_TEXT
- );
- my $brokenpattern = "^(" . join("|", @linestocheck) . ")[?+:]?=";
- if ($tmp =~ /$brokenpattern/) {
- $idx++;
- }
- foreach my $i (@linestocheck) {
- $tmp =~ s/$i[?+:]?=[^\n]+\n//g;
- }
- push(@varnames, @linestocheck);
- &checkearlier($file, $tmp, @varnames);
- #
- # section 7: *_DEPENDS (may not be there)
- #
- print "OK: checking seventh section of $file (*_DEPENDS).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- # Check for direct assignment of BUILD_DEPENDS to RUN_DEPENDS.
- if ($tmp =~ /\nRUN_DEPENDS=[ \t]*\$\{BUILD_DEPENDS}/) {
- &perror("FATAL", $file, -1, "RUN_DEPENDS should not be set to ".
- "\${BUILD_DEPENDS} as \${BUILD_DEPENDS} includes other ".
- "implicit dependencies. Instead, copy the explicit dependencies ".
- "from BUILD_DEPENDS to RUN_DEPENDS. See ".
- "http://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/makefile-depend.html#AEN2154 ".
- "for more details.");
- }
- @linestocheck = qw(
- EXTRACT_DEPENDS LIB_DEPENDS PATCH_DEPENDS BUILD_DEPENDS RUN_DEPENDS
- TEST_DEPENDS FETCH_DEPENDS DEPENDS_TARGET
- );
- if ($tmp =~ /^([\w\d]+_)?(PATCH_|EXTRACT_|LIB_|BUILD_|RUN_|TEST_|FETCH_)DEPENDS/m) {
- &checkearlier($file, $tmp, @varnames);
- check_depends_syntax($tmp, $file);
- foreach my $i (@linestocheck) {
- $tmp =~ s/^([\w\d]+_)?$i[?+:]?=[^\n]+\n//g;
- }
- # Remove any other *_DEPENDS lines as people may
- # use a macro for common depends as described in
- # section 5.9.2 of the Porter's Handbook.
- $tmp =~ s/.+_DEPENDS[?+:]?=[^\n]+\n//g;
- &checkextra($tmp, '*_DEPENDS', $file);
- $idx++;
- }
- push(@varnames, @linestocheck);
- &checkearlier($file, $tmp, @varnames);
- # section 8: FLAVORS/FLAVOR(optional)
- #
- print "OK: check eighth section of $file (FLAVORS: optional).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- if ($tmp =~ /(FLAVORS|FLAVOR)/) {
- &checkearlier($file, $tmp, @varnames);
- $idx++;
- }
- push(@varnames, qw(
- FLAVORS FLAVOR
- ));
- # section 9: USES/USE_x(optional)
- #
- print "OK: check ninth section of $file (USES: optional).\n"
- if ($verbose);
- $tmp = $sections[$idx] // '';
- my $use_github_set = 0;
- if ($tmp =~ /(USES|USE_)/) {
- &checkearlier($file, $tmp, @varnames);
- foreach my $line (split(/(USE(?:S[?+]|[_\w\d]+)?=[^\n]+\n)/, $tmp)) {
- if ($line =~ /USES[?+]?=[^\n]+\n/) {
- print "OK: seen USES.\n" if ($verbose);
- $tmp =~ s/USES[?+]?=[^\n]+\n//;
- next;
- }
- if ($line =~ /USE([_\w\d]+)=[^\n]+\n/) {
- print "OK: seen USE$1.\n" if ($verbose);
- if ($tmp =~ /USE_GITHUB/) {
- $use_github_set = 1;
- }
- print "OK: USE_GITHUB set\n" if($use_github_set && $verbose);
- $tmp =~ s/USE([_\w\d]+)=[^\n]+\n//;
- next;
- }
- }
- print "OK: check if GH_ options are in use\n"
- if ($verbose);
- foreach my $line (split(/(GH(?:S[?+]|[_\w\d]+)?=[^\n]+\n)/, $tmp)) {
- if ($line =~ /GH([_\w\d]+)=[^\n]+\n/) {
- print "OK: seen GH$1.\n" if ($verbose);
- print "No USE_GITHUB seen but GH$1 used\n"
- unless ($use_github_set);
- $tmp =~ s/GH([_\w\d]+)=[^\n]+\n//;
- next;
- }
- }
- # XXX: We should check this. But, one is allowed to add _related_ items to
- # a USE_ or USES item in this same section. Since this would be an ever-
- # moving target, remove the check.
- #&checkextra($tmp, 'USES/USE_x', $file);
- $idx++;
- }
- push(@varnames, qw(
- USES
- ));
- #
- # Makefile 10: check the rest of file
- #
- print "OK: checking the rest of the $file.\n" if ($verbose);
- $tmp = join("\n\n", @sections[$idx .. scalar(@sections)-1]);
- $tmp = "\n" . $tmp; # to make the begin-of-line check easier
- &checkearlier($file, $tmp, @varnames);
- # Check depends that might be specified based on the WITH_/WITHOUT_
- # arguments and other external variables.
- check_depends_syntax($tmp, $file);
- # check WRKSRC/NO_WRKSUBDIR
- #
- # do not use DISTFILES/DISTNAME to control over WRKSRC.
- # DISTNAME is for controlling distribution filename.
- # example:
- # DISTNAME= package
- # DISTFILES=package-1.0.tgz
- # should be
- # DISTNAME= package-1.0
- # EXTRACT_SUFX=.tgz
- # WRKSRC= ${WRKDIR}/package
- #
- print "OK: checking WRKSRC.\n" if ($verbose);
- $wrksrc = $nowrksubdir = '';
- $wrksrc = $1 if ($tmp =~ /\nWRKSRC[+?]?=[ \t]*([^\n]*)\n/);
- $nowrksubdir = $1 if ($tmp =~ /\nNO_WRKSUBDIR[+?]?=[ \t]*([^\n]*)\n/);
- if ($nowrksubdir eq '') {
- $realwrksrc = $wrksrc ? "$wrksrc/$distname"
- : "\${WRKDIR}/$distname";
- } else {
- $realwrksrc = $wrksrc ? $wrksrc : '${WRKDIR}';
- }
- print "OK: WRKSRC seems to be $realwrksrc.\n" if ($verbose);
- if ($nowrksubdir eq '') {
- print "OK: no NO_WRKSUBDIR, checking value of WRKSRC.\n"
- if ($verbose);
- if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) {
- &perror("WARN", $file, -1, "WRKSRC is set to meaningless value ".
- "\"$1\".".
- ($nowrksubdir eq ''
- ? " use \"NO_WRKSUBDIR=yes\" instead."
- : ""));
- }
- if ($bogusdistfiles) {
- if ($distname ne '' && $wrksrc eq '') {
- &perror("WARN", $file, -1, "do not use DISTFILES and DISTNAME ".
- "to control WRKSRC. how about ".
- "\"WRKSRC=\${WRKDIR}/$distname\"?");
- } else {
- &perror("WARN", $file, -1, "DISTFILES/DISTNAME affects WRKSRC. ".
- "take caution when changing them.");
- }
- }
- } else {
- print "OK: seen NO_WRKSUBDIR, checking value of WRKSRC.\n"
- if ($verbose);
- if ($wrksrc eq 'work' || $wrksrc =~ /^$[\{\(]WRKDIR[\}\)]/) {
- &perror("WARN", $file, -1, "definition of WRKSRC not necessary. ".
- "WRKSRC is \${WRKDIR} by default.");
- }
- }
- if ($tmp =~ /\nNO_PACKAGE[+?]?=/) {
- &perror("WARN", $file, -1, "NO_PACKAGE is obsolete. It should be ".
- "replaced with \"LICENSE_PERMS=no-pkg-mirror\"");
- }
- # check NO_STAGE
- if ($makevar{NO_STAGE}) {
- &perror("FATAL", $file, -1, "STAGE support is missing.");
- }
- # various MAN'uals related checks
- if ($makevar{USE_PERL5} =~ /\b(configure|modbuild|modbuildtiny)\b/
- && $tmp =~ /\nMAN3PREFIX=\s*\$\{PREFIX}\/lib\/perl5\/\$\{PERL_VER/) {
- &perror("WARN", $file, -1, "MAN3PREFIX is ".
- "\"\${PREFIX}/lib/perl5/\${PERL_VERSION}\" ".
- "when USE_PERL5=configure|modbuild|modbuildtiny is set. You do not need to specify it.");
- }
- if ($tmp =~ /\nMAN[1-9LN][?]?=/) {
- &perror("FATAL", $file, -1, "MAN[1-9LN] macro is not supported anymore. ".
- "Please list manpages in plist.");
- }
- # check INFO
- print "OK: checking INFO.\n" if ($verbose);
- if ($tmp =~ /\nINFO=\s*([^\n]*)\n/) {
- my @minfo = grep($_ !~ /^\s*$/, split(/\s+/, $1));
- if ($tmp =~ /[\/|\s]install-info\s/) {
- &perror("FATAL", $file, -1, "install-info is automatically run ".
- "when INFO is defined.");
- }
- foreach $i (@minfo) {
- if ($i =~ /\.info(-\d+)?$/) {
- &perror("FATAL", $file, -1, "do not include the .info extension ".
- "on files listed in the INFO macro.");
- }
- }
- } elsif ($tmp =~ /[\/|\s]install-info\s/) {
- &perror("WARN", $file, -1, "do not call install-info directly. Use the ".
- "INFO macro instead.");
- }
- # check for HAS_CONFIGURE or GNU_CONFIGURE
- if ($tmp =~ /\nGNU_CONFIGURE[?+]?=/
- && $tmp =~ /\n(HAS_CONFIGURE)[?+]?=/) {
- &perror("WARN", $file, -1, "since you already have GNU_CONFIGURE, ".
- "you do not need $1.");
- }
- # check direct use of important make targets.
- if ($tmp =~ /\n(fetch|extract|patch|configure|build|install):/) {
- &perror("FATAL", $file, -1, "direct redefinition of make target \"$1\" ".
- "discouraged. redefine \"do-$1\" instead.");
- }
- # check for incorrect use of the pre-everything target.
- if ($tmp =~ /\npre-everything:[^:]/) {
- &perror("FATAL", $file, -1, "use pre-everything:: instead of pre-everything:");
- }
- if ($tmp =~ /^pre-patch:/m && $use_gnome_hack) {
- &perror("FATAL", $file, -1, "pre-patch target overwrites gnomehack component. ".
- "use post-patch instead.");
- }
- if ($tmp =~ /^do-build:/m && $use_ant) {
- &perror("WARN", $file, -1, "USE_ANT is intended only for ports that ".
- "build with Ant. It is recommended not to override the default ".
- "'do-build:' target when defining USE_ANT");
- }
- #
- # check for deprecated use of USE_RC_SUBR, and current syntax
- #
- if ($tmp =~ /\nUSE_RC_SUBR=([\s]*)(.*)/) {
- my $subr_value = $makevar{USE_RC_SUBR};
- if ($subr_value eq '') {
- $subr_value = $2;
- }
- if (($subr_value =~ /^yes$/i) ||
- ($subr_value =~ /^true$/i) ||
- ($subr_value =~ /^1$/)) {
- &perror("FATAL", $file, -1, "The value of the USE_RC_SUBR variable ".
- "should be the name of the intended rc.d script, and there ".
- "should be a corresponding file in the files/ directory.");
- } else {
- foreach my $i (split(/\s/, $subr_value)) {
- if ($i ne '' && -f "files/$i.in") {
- if (open(RCIN, "< files/$i.in")) {
- my @rccontents = <RCIN>;
- my $found_provide = 0;
- foreach my $line (@rccontents) {
- if ($line =~ /^# PROVIDE:/) {
- $found_provide = 1;
- last;
- }
- }
- if (!$found_provide) {
- &perror("FATAL", "files/$i.in", -1, "rc.d script ".
- "$i.in must contain a '# PROVIDE:' line in ".
- "order to be started at boot time.");
- }
- close(RCIN);
- }
- }
- }
- }
- }
- # check for health of SUB_FILES
- if ($tmp =~ /\nSUB_FILES=([\s]*)(.*)/) {
- my $subr_value = $makevar{SUB_FILES};
- if ($subr_value eq '') {
- $subr_value = $2;
- }
- foreach my $i (split(/\s/, $subr_value)) {
- my $mvar;
- if ($i =~ /\$\{([^}]+)\}/) {
- $mvar = $1;
- if (defined($makevar{$mvar})) {
- $i = $makevar{$mvar};
- } else {
- $i = &get_makevar($mvar);
- }
- }
- if ($i ne '' && ! -f "files/$i.in") {
- &perror("FATAL", $file, -1, "$i listed in SUB_FILES/USE_RC_SUBR, ".
- "but files/$i.in is missing.");
- } elsif ($i eq '' && $mvar && $mvar ne '') {
- &perror("WARN", $file, -1, "possible undefined make variable ".
- "$mvar used as the value for SUB_FILES/USE_RC_SUBR.");
- }
- }
- }
- 1;
- }
- sub perror($$$$) {
- my($type, $file, $line, $msg) = @_;
- if ($type eq 'FATAL') {
- $err++;
- } else {
- $warn++;
- }
- if ($grouperrs) {
- $msg = '%%LINES%%' . $msg;
- if ($file ne "") {
- $msg = $file . ": " . $msg;
- }
- $msg = $type . ": " . $msg;
- if (!$errcache{$msg}) {
- push @errlst, $msg;
- }
- if ($line > -1) {
- push @{$errcache{$msg}}, $line;
- }
- } else {
- if ($line > -1) {
- $msg = "[$line]: " . $msg;
- }
- if ($file ne "") {
- $msg = $file . ": " . $msg;
- }
- $msg = $type . ": " . $msg;
- print $msg . "\n";
- }
- }
- sub checkextra {
- my($str, $section, $file) = @_;
- $str = "\n" . $str if ($str !~ /^\n/);
- $str =~ s/\n#[^\n]*/\n/g;
- $str =~ s/\n\.[^\n]+/\n/g;
- $str =~ s/\n\n+/\n/g;
- $str =~ s/^\s+//;
- $str =~ s/\s+$//;
- return if ($str eq '');
- if ($str =~ /^([\w\d]+)/) {
- &perror("WARN", $file, -1, "extra item placed in the ".
- "$section section, ".
- "for example, \"$1\".");
- } else {
- &perror("WARN", $file, -1, "extra item placed in the ".
- "$section section.");
- }
- }
- sub checkorder {
- my($section, $str, $file, @order) = @_;
- my(@items, $i, $j, $k, $invalidorder);
- print "OK: checking the order of $section section.\n" if ($verbose);
- $str //= '';
- @items = ();
- foreach my $i (split("\n", $str)) {
- $i =~ s/[+?]?=.*$//;
- push(@items, $i);
- }
- @items = reverse(@items);
- $j = -1;
- $invalidorder = 0;
- while (scalar(@items)) {
- $i = pop(@items);
- $k = 0;
- while ($k < scalar(@order) && $order[$k] ne $i) {
- if (defined $order[$k] &&
- $order[$k] =~ /[\.\*\+\?\{\}\[\]\^\$\|]/ &&
- $i =~ /$order[$k]/) {
- last;
- }
- $k++;
- }
- if (defined $order[$k] && $order[$k] =~ /[\.\*\+\?\{\}\[\]\^\$\|]/ &&
- $i =~ /$order[$k]/) {
- if ($k < $j) {
- &perror("FATAL", $file, -1, "$i appears out-of-order.");
- $invalidorder++;
- } else {
- print "OK: seen $i, in order.\n" if ($verbose);
- }
- $j = $k;
- } elsif (defined $order[$k] && $order[$k] eq $i) {
- if ($k < $j) {
- &perror("FATAL", $file, -1, "$i appears out-of-order.");
- $invalidorder++;
- } else {
- print "OK: seen $i, in order.\n" if ($verbose);
- }
- $j = $k;
- # This if condition tests for .if, .else (in all forms),
- # .for and .endfor and .include
- } elsif ($i !~ m/^\.(if|el|endif|for|endfor|include)/) {
- &perror("FATAL", $file, -1, "extra item \"$i\" placed in the ".
- "$section section.");
- }
- }
- if ($invalidorder) {
- &perror("FATAL", $file, -1, "order must be " . join('/', @order) . '.');
- } else {
- print "OK: $section section is ordered properly.\n"
- if ($verbose);
- }
- }
- sub checkearlier {
- my($file, $str, @varnames) = @_;
- $str //= '';
- print "OK: checking items that have to appear earlier.\n" if ($verbose);
- foreach my $i (@varnames) {
- if ($str =~ /\n($i)\??=/) {
- &perror("WARN", $file, -1, "\"$1\" has to appear earlier.");
- }
- }
- }
- sub linenumber {
- my $text = shift;
- my @lines;
- @lines = split /\n/, $text;
- return scalar(@lines) - 1;
- }
- sub abspathname {
- my($str, $file) = @_;
- my($s, $i, %cmdnames);
- my($pre);
- # trim all trailing backslash and newline
- $str =~ s/\\\n\s*/ /g;
- # ignore parameter string to reinplace command
- $str =~ s/([ \t][\@-]?(?:sed|\$[\{\(]SED[\}\)]|\$[\{\(]REINPLACE_CMD[\}\)]))((?:\s+\-\w+)*\s+(?:"(?:\\"|[^"\n])*"|'(?:\\'|[^'\n])*'))+(.*)/$1$3/g; #'
- # ignore parameter string to echo command
- # XXX: This next pattern crashes Perl 5.8.7.
- #$str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+("(\\'|\\"|[^"])*"|'(\\'|\\"|[^"])*')[ \t]*[;\n]//; #'
- $str =~ s/[ \t][\@-]?(echo|\$[\{\(]ECHO[\}\)]|\$[\{\(]ECHO_MSG[\}\)])[ \t]+.*(;|$)//m; #'
- print "OK: checking direct use of full pathnames in $file.\n"
- if ($verbose);
- foreach my $s (split(/\n+/, $str)) {
- $i = '';
- $s =~ s/#.*$//;
- if ($s =~ /(^|[ \t\@'"-])(\/[\w\d])/) { #'
- # suspected pathnames are recorded.
- $i = $2 . $';
- $pre = $` . $1;
- if ($pre =~ /MASTER_SITE_SUBDIR/) {
- # MASTER_SITE_SUBDIR lines are ok.
- $i = '';
- }
- if ($s =~ /\$\{[^}]*?\Q$i\E/) {
- # If we're inside a make variable, we probably do not have
- # an absolute path.
- $i = '';
- }
- }
- if ($i ne '' && ! grep {$i =~ m|^$_|} @ALLOWED_FULL_PATHS) {
- $i =~ s/\s.*$//;
- $i =~ s/['"].*$//; #'
- $i = substr($i, 0, 20) . '...' if (20 < length($i));
- &perror("WARN", $file, -1, "possible use of absolute pathname ".
- "\"$i\".");
- }
- }
- foreach my $s (split(/\n+/, $str)) {
- print "OK: checking direct use of pathnames, phase 1.\n" if ($verbose);
- %cmdnames = split(/\n|\t+/, <<EOF);
- /usr/opt \${PORTSDIR} instead
- $portsdir \${PORTSDIR} instead
- $localbase \${PREFIX} or \${LOCALBASE}, as appropriate
- EOF
- foreach my $i (keys %cmdnames) {
- if ($s =~ /^[^#]*$i/) {
- &perror("WARN", $file, -1, "possible direct use of \"$&\" ".
- "found. if so, use $cmdnames{$i}.");
- }
- }
- print "OK: checking direct use of pathnames, phase 2.\n" if ($verbose);
- %cmdnames = split(/\n|\t+/, <<EOF);
- distfiles \${DISTDIR} instead
- pkg \${PKGDIR} instead
- files \${FILESDIR} instead
- scripts \${SCRIPTDIR} instead
- patches \${PATCHDIR} instead
- work \${WRKDIR} instead
- EOF
- foreach my $i (keys %cmdnames) {
- # use (?![\w-]) instead of \b to exclude pkg-*
- if ($file =~ /^[^#]*(\.\/|\$[\{\(]\.CURDIR[\}\)]\/|[ \t])(\b$i)(?![\w-])/
- && $s !~ /^COMMENT(.)?=[^\n]+$i/m
- && $s !~ /^IGNORE(.)?=[^\n]+$i/m
- && $s !~ /^BROKEN(.)?=[^\n]+$i/m
- && $s !~ /^RESTRICTED(.)?=[^\n]+$i/m
- && $s !~ /^NO_PACKAGE(.)?=[^\n]+$i/m
- && $s !~ /^NO_CDROM(.)?=[^\n]+$i/m
- && $s !~ /^MAINTAINER(.)?=[^\n]+$i/m
- && $s !~ /^CATEGORIES(.)?=[^\n]+$i/m
- && $s !~ /^USES(.)?=[^\n]+$i/m
- && $s !~ /^WX_COMPS(.)?=[^\n]+$i/m
- && $s !~ /^SHEBANG_FILES(.)?=[^\n]+$i/m
- && $s !~ /^[A-Z0-9_]+_DESC=[^\n]+$i/m
- && $s !~ /^ONLY_FOR_ARCHS_REASON(.)?=[^\n]+$i/m
- && $s !~ /^NOT_FOR_ARCHS_REASON(.)?=[^\n]+$i/m) {
- &perror("WARN", $file, -1, "possible direct use of \"$i\" \"$s\" ".
- "found. if so, use $cmdnames{$i}.");
- }
- }
- }
- }
- sub get_makevar {
- my($cmd, $result);
- $cmd = join(' -V ', "make $makeenv MASTER_SITE_BACKUP=''", map { "'$_'" } @_);
- $result = `$cmd`;
- chomp $result;
- # This bit of magic is interesting and repeated in the get_make* functions.
- # It will ensure that all empty values for macros are replaced with a '\0' character
- # to preserve their "place in line" for future parsing. This is only needed when passing
- # multiple variables to these functions.
- no warnings 'uninitialized';
- $result =~ s/(?:^|(?<=\n))(?=\n|$)/$1\0$3/g;
- if (${^CHILD_ERROR_NATIVE} != 0) {
- die "\nFATAL ERROR: make(1) died with status ${^CHILD_ERROR_NATIVE} and returned '$result'";
- }
- # If the final value is just a '\0' strip it out.
- $result =~ s/^\0$//;
- return $result;
- }
- sub get_makevar_shallow {
- my($cmd, $result);
- $cmd = join(' -dV -V ', "make $makeenv MASTER_SITE_BACKUP=''", map { "'$_'" } @_);
- $result = `$cmd`;
- chomp $result;
- no warnings 'uninitialized';
- $result =~ s/(?:^|(?<=\n))(?=\n|$)/$1\0$3/g;
- if (${^CHILD_ERROR_NATIVE} != 0) {
- die "\nFATAL ERROR: make(1) died with status ${^CHILD_ERROR_NATIVE} and returned '$result'";
- }
- $result =~ s/^\0$//;
- return $result;
- }
- sub get_makevar_raw {
- my($cmd, $result);
- $cmd = join(' -XV ', "make $makeenv MASTER_SITE_BACKUP=''", map { "'$_'" } @_);
- $result = `$cmd`;
- chomp $result;
- no warnings 'uninitialized';
- $result =~ s/(?:^|(?<=\n))(?=\n|$)/$1\0$3/g;
- if (${^CHILD_ERROR_NATIVE} != 0) {
- die "\nFATAL ERROR: make(1) died with status ${^CHILD_ERROR_NATIVE} and returned '$result'";
- }
- $result =~ s/^\0$//;
- return $result;
- }
- # This uses a "null" makefile to extract options from /etc/make.conf without any overrides.
- sub get_makeconf_var {
- my($cmd, $result);
- $cmd = join(' -V ', "echo '' | make $makeenv -f -", map { "'$_'"} @_);
- $result =`$cmd`;
- chomp $result;
- no warnings 'uninitialized';
- $result =~ s/(?:^|(?<=\n))(?=\n|$)/$1\0$3/g;
- if (${^CHILD_ERROR_NATIVE} != 0) {
- die "\nFATAL ERROR: make(1) died with status ${^CHILD_ERROR_NATIVE} and returned '$result'";
- }
- $result =~ s/^\0$//;
- return $result;
- }
- sub is_predefined {
- my($url, $file) = @_;
- my($site, $site_re);
- my $subdir_re = quotemeta quotemeta '/%SUBDIR%/';
- for my $site (keys %predefined) {
- $site_re = quotemeta $site;
- $site_re =~ s,$subdir_re,/(.*)/,;
- if ($url =~ /$site_re/ && $file) {
- my $pe = "how about using \"\${MASTER_SITE_$predefined{$site}}\" ";
- if ($1) {
- $pe .= "with \"MASTER_SITE_SUBDIR=$1\", ";
- }
- $pe .= "instead of \"$url\"?";
- &perror("WARN", $file, -1, $pe);
- return &TRUE;
- } elsif ($url =~ /$site_re/ && !$file) {
- return &TRUE;
- }
- }
- undef;
- }
- sub urlcheck {
- my ($url, $file) = @_;
- if ($url !~ m#^\w+://#) {
- &perror("WARN", $file, -1, "\"$url\" doesn't appear to be a URL to me.");
- }
- if ($url !~ m#/(:[^/:]+)?$# && $url !~ m#:$#) {
- &perror("FATAL", $file, -1, "URL \"$url\" should ".
- "end with \"/\" or a group name (e.g. :something).");
- }
- if ($url =~ m#://[^/]*:/#) {
- &perror("FATAL", $file, -1, "URL \"$url\" contains ".
- "extra \":\".");
- }
- }
- sub TRUE {1;}
- # Local variables:
- # tab-width: 4
- # End:
|