#Tc@sddlmZddlZddlZddlZddlZddlj j Z ddl m Z ddl mZddlZddlZddlZejddZde jfdYZd e jfd YZdS( i(tlint_fmri_successorN(t ActionError(t FileActiont ObsoleteFmrisis_obsolete, fmritPkgDupActionCheckercBsseZdZdZdZdZddZede_ddZ ed e _d d Z ed e _d dZ ede _ddZ ede _ddZ ede _ddZede_dedZddZede_ddZed e_d!d"Zed#e_ed$Zd%Zd&d'Zed(e_RS()s.A class to check duplicate actions/attributes.spkglint.dupactioncCstd|_i|_i|_i|_i|_i|_i|_i|_i|_ i|_ i|_ i|_ i|_ i|_i|_i|_i|_i|_i|_i|_i|_i|_i|_i|_i|_i|_g|_tt|j|dS(Ns!Checks for duplicate IPS actions.(t_t descriptiont ref_pathst lint_pathst ref_driverst lint_driverst ref_usernamestref_uidstlint_usernamest lint_uidstref_groupnamestlint_groupnamestref_gidst lint_gidstref_legacy_pkgstlint_legacy_pkgstprocessed_pathstprocessed_driverstprocessed_usernamestprocessed_uidstprocessed_groupnamestprocessed_gidstprocessed_refcount_pathstprocessed_refcount_legacy_pkgstprocessed_overlaystseen_dup_typestseen_mediated_linkstsuperRt__init__(tselftconfig((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyR!/s8                          cs+dtd}i}xQ|j|jd|jd|jD]+}|j|jjgj |jq:Wx6|j D]+}|j|jjgj |jqsW|j j t dx|j|jd|jD]tfd|jjjgDrqq|d|j|d|jdd |d |jdd |d |jdd |d|jdd |d|jdd|d|jddqW|j j t dx|j|jd|jd|jD]|d|j|d|jdd |d |jdd |d |jdd |d|jdd |d|jdd|d|jddqW|j j t dx|j D]|d|j|d|jdd |d |jdd |d |jdd |d|jdd |d|jdd|d|jddqW|j|jf|j|jf|j|jf|j|jf|j|jf|j|jf|j|jfg}x6|D].\}}|j||d|j i|_!qWdS(sSCalled to initialise a given checker using the supplied engine.c sj}fd}x||D]}|rI|j|krIq(n||jkr^q(n|j}|j|xL|jD]>\} } t| trt| |j| stpathtpkgR&tlegacyR+tdrivertusernametusertuidt groupnametgrouptgids,Seeding lint action duplicates dictionaries.s-Seeding local action duplicates dictionaries.t ignore_pubsN("tNonetFalset gen_manifestst lint_api_instR?R@t setdefaultR3tget_nameR4tlint_manifeststloggertdebugRt ref_api_insttanytgetRRR R R RRRRR R RRRt _merge_dictRMtlint_dic(R"tengineR>t lint_fmristmtdup_dictionariesR[tref_dic((RBs=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytstartupjs)##   "          t001c Cs;|jddgd|j|j|||jd|dS(s6Checks for duplicate paths on non-ref-counted actions.tfiletlicenseRCtmsgidN(tdup_attr_checkRRR*(R"R9RBR\t pkglint_id((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_pathss sPaths should be unique.t002c Cs8|jdgd|j|j|||jd|dS(s"Checks for duplicate driver names.RFR+ReN(RfR RR*(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_driverss sDriver names should be unique.t003c Cs8|jdgd|j|j|||jd|dS(s Checks for duplicate user names.RHRGReN(RfR RR*(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_usernamess sUser names should be unique.t004c Cs8|jdgd|j|j|||jd|dS(sChecks for duplicate uids.RHRIReN(RfR RR*(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_uids s sUIDs should be unique.t005c Cs8|jdgd|j|j|||jd|dS(s!Checks for duplicate group names.RKRJReN(RfRRR*(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_groupnamess sGroup names should be unique.t006c Cs8|jdgd|j|j|||jd|dS(sChecks for duplicate gids.RKR+ReN(RfRRR*(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_gidss sGIDs should be unique.t007c Cs|js dSxrd|j|jfd|j|jfgD]F\}}}|jj|d}|shq8n||krt||dkrq8n||krq8nd|j |f} t } |} t } x||D]\} }|j d|d|d| rqn| j | x|j | D]}|jd s%|jd s%|jd s%|jd s%|jd r|q%n|j|| g|j\}}|sq%n| j |q%WqWg}| rtt }xt| D]}i}x||D]\} }|j d|d|d| r*qn|j |j ||jkr|j|}||krv||j| q| g|| %st sx%(type)s action for %(attr)s is reference-counted but has different attributes across %(count)s duplicates: %(suspects)sttypeR5tcounttsuspectsRet ignore_linted(t refcountableRRRRR,RYRNtlenR+R1tlintedtaddt differencest startswithtconflicting_variantsR*tsortedR4tjoinRStTrueterrorR(R"R9RBR\RgR5R`t processed_dicR=RttfmristtargRtpfmriR'tkeyt conflict_varstconflict_actionsR|t action_typestval((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytduplicate_refcount_path_attrs(s  "           6   's@Duplicated reference counted actions should have the same attrs.tc  Cs||jkrdS|j|kr&dS|j|} | |krCdS| |krit|| dkridSt} t} xV|| D]J\} }|jdkrd|jkrqn| j|| j| qW|j| |\}}|dkr|jdkr|j|||\}}| rpx7|D]/\}}|j|dd |j||fq/Wt||        %   s2Paths should be delivered by one action type only.t009c CsQ|jdkrdS|jdgd|j|j|||jd|dtdS(sChecks that any duplicate file actions which specify overlay attributes do so according to the rules. Much of the implementation here is done by _prune_overlays(..), called by dup_attr_check.RcNRCReR(R+RfRRR*R(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytoverlayss  s#Overlaying actions should be valid.t010cs|jdkrdS|jjdds2dSjkrEdStjdkrbdS|jjdd}g}g}dj|f}dj|f} d j|f} xjD]\} }|jjdd} | s"j|d | r qn|j| |fq| |krj|d | rIqn|j| |fqqWfd } t g}| || }|r%g}x:|D]2\} }|jt | |j || fqWt t |}j td id j|d6d6d| n|r| || }|rg}t g}xJ|D]B\} }|jt | |j || f|j |jqYWt|dkrt t |}j tdid j|d6d6d| qqntt g|D]\}} |j^q dkrt g}x?|D]7\}} j|d |sG|j t | qGqGW|sjjdSt |}j tdid j|d6d6d|njjdS(sChecks that groups of mediated-links are valid. We perform minimal validation of mediated links here, since the generic action-validation check, pkglint.action009, will run the validate() method on each action. We check that all mediators for a given path are part of the same mediation namespace, and that all links for a given path have a 'mediator' attribute to declare that namespace. We also check, that if mediators are being used, that all actions deliver the same type of action for that mediated link. There is some overlap with duplicate_path_types here, in that duplicate reference-counted actions with a path attribute where that list of actions contains link or hardlink actions will be reported here instead, in case the user simply got the type of action wrong. RRNRCiRws%s%s.1s%s%s.2s%s%s.3Rtc sg}x|D]\}}xjD]{\}}||krEq'nj|d|r`q'nj||gi\}}x!|D]} |j|| fqWq'Wq W|S(s}Look for conflicting variants across the given list, allowing for pkg.linted values matching lint_id.Rt(RRRR4( t mediator_listRtt conflictsRR9tpfmtactconf_vartconf_actconf(R\R=R"(s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytvariant_conflictsgs  sLpath %(path)s uses different mediator namespaces across actions in %(fmris)sRyRResIpath %(path)s has missing mediator attributes across actions in %(fmris)sscpath %(path)s uses multiple action types for potentially mediated links across actions in %(fmris)s(slinkshardlink(R+R,RYRNRRRRR4R1tstrRRRRR(R"R9RBR\Rgt ref_mediatortdifferent_namespacestmissing_mediatorsttypes_idt missing_idtdiff_idRRwRRtseen_conflictsRtac_namesR((R\R=R"s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytmediated_links0s     4  sMediated-links should be valid.cCsx|D] }||kr-||||, ), ... ] iRCcSsdtj|}xH|jjD]7}|dkr7qq|jdrLqq|j|=qWt|S(sreturns a string representation of the given action with all non-variant attributes other than path and overlay removed. Used for comparison of overlay actions. RCtoverlayRu(spathsoverlay(RtdeepcopyR,tkeysRR(R9t action_copyR((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyt _remove_attrss cSs+x$|D]\}}||kr|SqWdS(s#return the fmri for a given action.N((R9t action_fmrisR3R((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyt _get_fmri s RtallowtpreservesQpath %(path)s missing 'preserve' attribute for 'overlay=allow' action in %(fmri)sR3t1ttruecSs[t}x<|D]4}x+|D]#\}}|jd||fqWqWdjt|S(s pretty print a group of variantss%s=%ss, (R1RRR2(RRRKRR((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyt_render_variants0s   cSsIi}x<tjD]1}|dkr(qn|jj|d|||jtd i|d 6|jd6d d |j|fq>q>Wd|jkr|j|jdd|j}|r|j|||||qnd |jkr=d|jd kr=|j td|jd d|j|fq=ndS(sCross-check that the 'pkg' attribute points to a package that depends on the package containing this legacy action. Also check that all the required tags are present on this legacy action.RENtcategorytdescthotlineR+RDtvendortversions.%(attr)s missing from legacy action in %(pkg)sR5Res%s%s.1t search_typesREV=s2legacy action in %s does not contain a REV= strings%s%s.3( R+R3RSR,RRt get_manifesttLATEST_SUCCESSORtcheck_legacy_renameR(R"R9RBR\RgR+trequiredRE((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyRE~s.      cCsTd|krP|djdkrPd }y/|j|jdd|jdgdt}WnGtjk r}|jt dt |dd |j |fd SX|d kr|jt d i|jd6|jd6dd |j |fqPt |j|jd |j sP|jt di|jd6|jd6dd|j |fqPnd S(sFPart of the legacy(..) check, not an individual check. Given a legacy action, if the package pointed to by the 'pkg' attribute of that action exists (say pkg=SUNWlegacy), we check that a user who types: pkg install SUNWlegacy gets the package containing the legacy action installed on their system, possibly following renames along the way. legacy A package manifest with the same name as the 'pkg' attribute of the legacy action action The legacy action we're investigating manifest The manifest we're investigating engine Our lint engine lint_id The id of this check s pkg.renamedRRDRxtold_mfsREslegacy renaming: %sRes%s%s.5Nsblegacy package %(legacy)s did not result in a dependency on %(pkg)s when following package renamess%s%s.4RMsClegacy package %(legacy)s did not result in a dependency on %(pkg)ss%s%s.2(RRNtfollow_renamesR,R3Rtbaset LintExceptionRRRR+RRM(R"RER9RBR\RtR(te((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyRs0      s.'legacy' actions should have valid attributes.RmcCsC|jdkr?|jtd|jdd|j|fndS(s.We should never have actions called 'unknown'.tunknownsunknown action found in %sRes%s%sN(R+RRR3(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyR&s s%'unknown' actions should never occur.RocCstd}|jdkrdS|jddkr6dSd|kr\|djdkr\dSd}d}|jd}|jd sd |}ny(tjj|d d }|j }WnJtjj k ry(tjj|d d }|j }WqdSXnX||j krdS|r||j kr|j |j s|j |j} |js^dSt| |d |jr}dSqnd|j|f} d} t} y|j|dgdt} Wn@tjk r} t} |jd||j| fd| nX|jd| d|d|}|r8|jd}ng}| r| r|j j|||krldSd|kr|jdd|krdS|jtdi|d6|jd6dd| ndS(sDWe should not have a require dependency on a package that has been marked as obsolete. This check also produces warnings when it is unable to find manifests marked as dependencies for a given package in order to check for their obsoletion. This can help to detect errors in the fmri attribute field of the depend action, though can be noisy if all dependencies are intentionally not present in the repository being linted or referenced. The pkglint paramter pkglint.action005.1.missing-deps can be used to declare which fmris we know could be missing, and for which we should not emit a warning message if those manifests are not available. s%dependency on obsolete package in %s:tdependNRztrequires pkg.renamedRR3spkg:/spkg:/%st build_releases5.11RMs%s%sR!twarn_on_obsoletes%s %sRes%s.1.missing-depsR9RBRyt@isPobsolete dependency check skipped: unable to find dependency %(dep)s for %(pkg)stdepRDs%s.1(RR+R,RRNRRDR3tPkgFmriRSt IllegalFmriRRt is_obsoletet has_versionRRMROR"RR#R$Rt get_paramtsplitR4R(R"R9RBR\RgtmsgR+t declared_fmritdep_fmrit found_fmriRtR(tfound_obsoleteterrtknown_missing_deps((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyt dep_obsoletesz              s;Packages should not have dependencies on obsolete packages.RqcCsd|jkrdS|jd}t|tr;|g}nx|D]}ytjj|dd}WqBtjjk rytjj|dd}Wqtjjk r|jdi|jd6|d6dd |j|fqXqBXqBWdS( ssWe should be given a valid FMRI as a dependency, allowing for a potentially missing component valueR3NR)s5.11s,invalid FMRI in action %(action)s in %(pkg)sRDR9Res%s%s( R,R0t basestringRDR3R-R.RR+(R"R9RBR\RgRR3R((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyt valid_fmri]s&        spkg(5) FMRIs should be valid.RscCsg|jdkrcd|jkrc|jtdi|jd6|jdd6dd|j|fndS(s0License actions should not have path attributes.RdRCs8license action in %(pkg)s has a path attribute, %(path)sRDRes%s%sN(R+R,RRR3(R"R9RBR\Rg((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyRd{s   s('license' actions should not have paths.Rc Csgt|jjD](}|jdr||j|f^q}|r|jtdi|jd6t|d6djg|D]\}}d||f^qd6dd |j |fd t nd S( sLog an INFO message with the key/value pairs of all pkg.linted* attributes set on this action. Essentially this exists to prevent users from adding pkg.linted values to manifests that don't really need them.s pkg.lintedsApkg.linted attributes detected for %(pkg)s %(action)s: %(linted)sRDR9s, s%s=%sRRes%s%sR}N( RR,RRtinfoRR3RRR+R(R"R9RBR\RgRt linted_attrsR((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyRs(   .s(Show actions with pkg.linted attributes.RcCs|js dSy|jWntk r}djgt|jdD]}|j^qI}|jtdi|j d6|d6dd|j |fnXdS( sValidate all actions.Ns; s s5Publication error with action in %(pkg)s: %(details)sRDtdetailsRes%s%s( t do_pub_checkstvalidateRRRR2tlstripRRR3R+(R"R9RBR\RgR8RR?((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyRAs  . sPublication checks for actions.RcCs+|jdk rdS|jd}t|dkrp|jtdi|d6|jd6dd |j|fnt|d kstjd |d  r|jtd i|d6|jd6dd |j|fntjd|s'|jtdi|d6|jd6dd|j|fndS(s#Checks username length, and format.RHNRGis&Username %(name)s in %(pkg)s > 8 charsR+RDRes%s%s.1is[a-z]sWUsername %(name)s in %(pkg)s does not have an initial lower-case alphabetical characters%s%s.2s^[a-z]([a-zA-Z1-9._-])*$s7Username %(name)s in %(pkg)s is invalid - see passwd(4)s%s%s.3(R+R,RRRR3tretmatch(R"R9RBR\RgRG((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytusername_formats*   )    sUser names should be valid.RcCs|jdkrdS|jjddkr/dS|jd}tjj|dd}|js|jtdi|d6|jd 6d d |j|fndS( s6Checks that 'incorporate' dependencies have a version.R'NRzt incorporateR3R)s5.11sK'incorporate' depend action on %(fmri)s in %(pkg)s does not have a version.RDRes%s%s( R+R,RYRDR3R-RRR(R"R9RBR\RgR3R((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytversion_incorporates    s1'incorporate' dependencies should have a version.t012cCsx|jjD]u}|jdr|j|j}|d kr|jtdi|d6|jd6dd |j|fqqqWd S( s5facet values should be set to a valid value in pkg(5)RvRRtalls[facet value should be set to 'true', 'false' or 'all' in attribute name %(key)s in %(fmri)sRR3Res%s%sN(struesfalsesall(R,RRRRRR3R+(R"R9RBR\RgRtvalue((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyt facet_values    sAfacet value should be set to a valid value in an action attributet013c Csd}|d|dg}d|jks@|jdj| rDdS|jd|kr|jtdjd|jdd|jd d j|d d j|j|n|jd|dkrEx~|jd D]j}t jj |dd}|j sqn|jdjdt |d|jd d j|j|qWn|jd|dkrx~|jd D]j}t jj |dd}|j rqln|jdjdt |d|jd d j|j|qlWndS(s6pkg_actuators should be set to a valid value in pkg(5)spkg.additional-supdate-on-uninstallsuninstall-on-uninstallR+NsGinvalid package actuator name {attr} in {fmri} supported values: {sact}R5R3tsacts, Res{0}{1}RJR)s5.11sUinvalid package-triggered uninstall FMRI {tf} in {fmri}: should not contain a versionttfsWinvalid package-triggered update FMRI {tf} in {fmri}: should contain a specific version( R,RRRtformatR3RR+tattrlistRDR-RR( R"R9RBR\Rgt start_patterntsupported_actuatorsR<R((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pytsupported_pkg_actuatorsJ                 s/package actuator should be set to a valid value(RRR+R!RaR RRRRERR&R:R<RdRRARERGRKRS(((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyRsD % 7  ?  ' 3   u         4(tpkg.lint.engineRt collectionsRtos.pathRtpkg.fmriRDt pkg.lint.basetlintR#t pkg.actionsRtpkg.actions.fileRRCR Rt namedtupleRt ActionCheckerRR(((s=/usr/lib/python2.7/vendor-packages/pkg/lint/pkglint_action.pyts