1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
- <html>
- <head>
- <title>Graft</title>
- </head>
- <body>
- <center>
- <h1><em>Graft</em> - a package management utility</h1>
- </center>
- <h4>Prepared by Peter Samuel
- <a href="mailto:peter.r.samuel@gmail.com"><tt><peter.r.samuel@gmail.com></tt></a></h4>
- <h4>$Revision: 2.16 $</h4>
- <h4>$Date: 2018/04/16 14:54:07 $</h4>
- <blockquote>
- <p> <em><strong>graft:</strong> To insert (a graft) in a branch or stem
- of another tree; to propagate by insertion in another stock; also, to
- insert a graft upon. To implant a portion of (living flesh or skin) in
- a lesion so as to form an organic union. To join (one thing) to another
- as if by grafting, so as to bring about a close union.</em> </p>
- </blockquote>
- <hr>
- <h2><a name="contents">Contents</a></h2>
- <ul>
- <li> <a href="#intro">Introduction</a>
- <li> <a href="#rationale">Rationale</a>
- <li> <a href="#research">Research</a>
- <li> <a href="#design">Design</a>
- <ul>
- <li> <a href="#precedence">Control file precedence & conflict resolution</a>
- </ul>
- <li> <a href="#history">History</a>
- <li> <a href="#installation">Installation</a>
- <ul>
- <li> <a href="#rpm_and_deb">Creating RPM and DEB packages</a>
- <li> <a href="#gotchas">Grafting <em>Graft</em> and
- <em>Perl</em> - the bootstrap problem</a>
- </ul>
- <li> <a href="#using-graft">Using <em>Graft</em></a>
- <ul>
- <li> <a href="#compiling-packages">Compiling
- Packages</a>
- <li><a href="#usage"><em>Graft</em> command line
- options</a>
- <ol>
- <li><a href="#graft-i">Install</a>
- <li><a href="#graft-d">Delete</a>
- <li><a href="#graft-p">Prune</a>
- <li><a href="#graft-L">Information</a>
- </ol>
- <li> <a href="#testing">Testing the <em>Graft</em>
- Installation</a>
- <li> <a href="#installing-packages">Installing
- Packages</a>
- <li> <a href="#bypass">Bypassing package
- directories</a>
- <li> <a href="#include">Including specific files
- and/or directories</a>
- <li> <a href="#exclude">Excluding specific files
- and/or directories</a>
- <li> <a href="#config_dirs">Grafting configuration files</a>
- <li><a href="#partial-graft">Grafting part of a
- package</a>
- <li> <a href="#deleting-packages">Deleting and/or
- Upgrading Packages</a>
- <li><a href="#transitioning">Transitioning a package to
- <em>Graft</em> control</a>
- <li> <a href="#conflicts">Conflict Processing</a>
- <li> <a href="#exitstatus">Exit Status</a>
- </ul>
- <li> <a href="#other-pkg-tools">Using <em>Graft</em> with
- other package management tools</a>
- <li> <a href="#availability">Availability</a>
- <li> <a href="#license">License</a>
- </ul>
- <hr>
- <h2><a name="intro">Introduction</a></h2>
- <p> <em>Graft</em> provides a mechanism for managing multiple packages
- under a single directory hierarchy. It was inspired by both <em>Depot</em>
- (Carnegie Mellon University) and <em>Stow</em> (Bob Glickstein). </p>
- <p> For the purposes of this discussion a <em>package</em> is defined as
- a suite of programs and files that make up an individual product. For
- example, the <em>package</em> known as <em>gcc</em> consists of the compiler
- and preprocessor programs, include files, manual pages and any other
- associated file or program. The concept of a <em>package</em> should not be
- confused with some vendor's definitions that are - by this definition -
- actually collections of <em>packages</em>. </p>
- <p> Special thanks to Gordon Rowell, Charles Butcher, Charlie Brady,
- Robert Maldon and Matias A. Fonzo for design suggestions and contributions.
- </p>
- <hr>
- <h2><a name="rationale">Rationale</a></h2>
- <p> In any reasonably large environment, many software packages will be
- installed. The installation location for these packages usually follows
- one of three rationales - each with its own advantages and drawbacks: </p>
- <ol>
- <li> <p> Each package is isolated from all other packages by
- installing it into a self contained directory tree. All binaries,
- manual pages, library and configuration files are stored under
- a single directory tree. This directory tree contains NO other
- files which are not the exclusive domain of the package in
- question. </p>
- <p> This method makes package demarcation obvious. As each
- package is self contained, identification of any file within a
- package is immediately apparent. </p>
- <p> Multiple versions of packages can be installed fairly easily
- to accommodate acceptance testing of new versions and/or legacy
- systems. </p>
- <p> However, the use of individual package directories can
- lead to VERY long <strong>$PATH</strong> and <strong>$MANPATH</strong> environment
- variables. Some shells may not be able to handle such long
- variables. Whenever a new package is added, each user MUST
- update their <strong>$PATH</strong> and <strong>$MANPATH</strong> to make the package
- available. </p>
- <li> <p> Packages are installed under a common directory tree.
- Binaries for all packages are grouped in a single directory,
- manual pages for all packages in another directory and so on.
- </p>
- <p> This method eliminates the need for continually updating long
- <strong>$PATH</strong> variables for each user. As soon as a package is
- placed into the common '<tt>bin</tt>' directory it is immediately
- available to all users (after a shell rehash if necessary). </p>
- <p> However, when a package is to be updated it is often very
- difficult to isolate all the files related to a particular
- package if they are intermingled with unrelated files. </p>
- <li> <p> A combination of methods (1) and (2). </p>
- </ol>
- <p> In an effort to maximise the advantages and minimise the
- disadvantages, <em>Depot</em>, <em>Stow</em> and <em>Graft</em> adopt a similar
- philosophy: </p>
- <blockquote>
- <p> Packages are installed in self contained directory trees and
- symbolic links from a common area are made to the package files. </p>
- </blockquote>
- <p> This approach allows multiple versions of the same package to co-exist
- on the one system. One version is the commonly available version and
- symbolic links will be made to this version. New versions can be tested
- and once acceptable can replace the current commonly available version.
- Older versions can still be used for legacy systems by using the
- '<em>real</em>' path name to the package instead of the '<em>common</em>'
- path name. </p>
- <p> The size and complexity of environment variables such as <strong>$PATH</strong>
- and <strong>$MANPATH</strong> is minimised because only the common area is
- required. Any special cases can also be accommodated but these will
- usually be in the minority when compared with the number of commonly
- available packages. </p>
- <hr>
- <h2><a name="research">Research</a></h2>
- <p> <strong>Note:</strong> Development of <em>Graft</em> began in late 1996. The
- comments regarding the packages listed below reflect their functionality
- and behaviour at that time and may not necessarily reflect their current
- functionality and behaviour. </p>
- <p> As stated earlier, <em>Graft</em> was inspired by <em>Depot</em> and
- <em>Stow</em>. Both these systems were examined and finally rejected for
- the following reasons: </p>
- <dl>
- <dt> <em>Depot</em>
- <a href="ftp://ftp.andrew.cmu.edu/pub/depot/depot.tar.gz">ftp://ftp.andrew.cmu.edu/pub/depot/depot.tar.gz</a>
- <dd> <p> <em>Depot</em> is very flexible yet cumbersome. </p>
- <p> It requires a database file to be created which
- provides a snapshot of the current state of both the package
- repository and the <em>Depot</em> target. It is possible to
- inadvertently destroy the package repository if the database
- is damaged. </p>
- <p> <em>Depot</em> assumes "<em>ownership</em>" of the
- target area, making it almost impossible to accommodate
- packages that are not under the control of <em>Depot</em>.
- ("<em>Ownership</em>" in this case means that <em>Depot</em>
- assumes ALL files in the target area will be under the
- control of <em>Depot</em>. It does not imply that <em>Depot</em>
- modifies Unix file permissions). </p>
- <p> Because of <em>Depot</em>'s assumed <em>ownership</em> it is
- difficult for other packages not under the control of
- <em>Depot</em> to be placed in the same target area. </p>
- <p> <em>Depot</em> attempts to impose a fixed package repository
- relative to the package target. It assumes that all
- packages will be stored under
- '<tt><em>dir</em>/depot/<em>package</em></tt>' and the target
- will be '<tt><em>dir</em></tt>'. This can be overridden on
- the command line but the internals of <em>Depot</em> make
- this mechanism cumbersome. </p>
- <p> <em>Depot</em> is written in C and there are many source
- files in its distribution. Local modifications would be
- difficult to quickly implement and test. </p>
- <dt> <em>Stow</em>
- <a href="https://www.gnu.org/software/stow/">https://www.gnu.org/software/stow/</a>
- <dd> <p> <em>Stow</em> is a stateless system. It requires no
- database or configuration information. </p>
- <p> Like <em>Depot</em>, it assumes that the package repository
- will be stored under '<tt><em>dir</em>/stow/<em>package</em></tt>'
- and the target will be '<tt><em>dir</em></tt>'. This can be
- overridden on the command line and works well during the
- install phase. </p>
- <p> <em>Stow</em> assumes "<em>ownership</em>"
- of the target area, making it difficult to accommodate
- packages that are not under the control of <em>Stow</em>.
- ("<em>Ownership</em>" in this case means that <em>Stow</em>
- assumes ALL files in the target area will be under the
- control of <em>Stow</em>. It does not imply that <em>Stow</em>
- modifies Unix file permissions). </p>
- <p> Because of <em>Stow</em>'s assumed <em>ownership</em>
- it is difficult for other packages not under the control
- of <em>Stow</em> to be placed in the same target area. When
- deleting packages, <em>Stow</em> examines everything in the
- target directory - whether it is associated with the package
- it is trying to delete or not. This can be time consuming and
- potentially dangerous as empty directories are also removed
- - even empty directories that do not belong to the package
- being removed. </p>
- <p> <em>Stow</em> has a clever feature of <em>folding</em> and
- <em>unfolding</em> directories. It attempts to optimise the
- number of symbolic links by making links to directories if
- the directory is only associated with a single package. If
- at a later date <em>Stow</em> discovers another package that
- needs that directory it will <em>unfold</em> that directory
- into a collection of symbolic links to files rather than
- a single symbolic link to the directory. <em>Stow</em> will
- <em>fold</em> the directory when removing packages if the
- remainder of the directory is only concerned with a single
- package. While clever, this feature is probably a waste of
- time and effort. It means that the entire package target
- must be scanned to determine package ownership of links and
- as packages will usually be replaced by newer versions a
- directory <em>fold</em> will probably be short lived. </p>
- <p> <em>Stow</em> will sometimes miss potential conflicts when
- run in <em>show only</em> mode. The conflicts may occur when a
- directory is unfolded and will not show up in <em>show only</em>
- mode. </p>
- <p> <em>Stow</em>'s author suggests that packages be compiled
- such that they refer to files in the target location rather
- than the actual package installation directory. This approach
- precludes the use of multiple versions of packages with
- different configuration and/or library files. </p>
- <p> <em>Stow</em> is written in <em>Perl</em> and is only a
- few hundred lines of code so local modifications can be
- accommodated. However there are very few comments in the
- code which makes the process of modification difficult. </p>
- </dl>
- <p> Since the release of <em>Graft</em> 1.6, the existence of yet another
- packaging program has been brought to the author's attention. </p>
- <dl>
- <dt> <em>Encap</em>
- <a href="http://www.ks.uiuc.edu/Development/Computers/docs/sysadmin/Build/encap.html">http://www.ks.uiuc.edu/Development/Computers/docs/sysadmin/Build/encap.html</a>
- <dd> <p> <em>Encap</em> grew out of work begun at the University
- of Illinois Champaign-Urbana. It has the same underlying
- philosophy as <em>Depot</em>, <em>Stow</em> and <em>Graft</em> -
- encapsulate packages into self contained directories and use
- symbolic links to make them visible in a common location. </p>
- <p> <em>Encap</em> uses a combination of a <em>csh</em> wrapper
- and a <em>Perl</em> program to accomplish its work. Like both
- <em>Depot</em> and <em>Stow</em>, <em>Encap</em> assumes that all
- compiled packages will live under a single directory hierarchy
- - by default '<tt><em>dir</em>/encap/<em>package</em></tt>'. It
- then attempts to create a symbolic link tree for ALL the
- packages under this area. There doesn't appear to be any
- easy way to support the quick addition or removal of a single
- package. </p>
- <p> A new release of <em>Encap</em> incorporating many new
- features was expected to be available in early 1997, however
- no release greater than version 1.2 has been forthcoming. </p>
- <p> One good feature of <em>Encap</em> is the ability to exclude
- specific files from the package tree. This concept has been
- incorporated into <em>Graft</em> 1.7 and above. </p>
- </dl>
- <p> Since the release of <em>Graft</em> 2.3, the existence of
- several another packaging programs have been brought to the author's
- attention. Rather than outline their features and whether or not the
- author feels they are superior (or inferior) to <em>Graft</em>, a reference
- to each package and a brief description is given and further research
- is left as an exercise for the reader: </p>
- <dl>
- <dt> <em>stowES</em>
- <dd>
- <pre>
- <a href="https://os.inf.tu-dresden.de/~adam/stowES/">https://os.inf.tu-dresden.de/~adam/stowES/</a>
- </pre>
- <p> "<em>stowES (stow Enhancement Script) is
- a Perl script which tries to ease the use of the "stow"
- packaging program and software which can be compiled and
- installed with autoconf. It automates the compilation and
- installation of software packages and provides some useful
- functions to maintain your stow packages (e.g., list packages,
- check packages for integrity, etc.).</em>" </p>
- <dt> <em>opt_depot</em>
- <dd>
- <pre>
- <a href="https://github.com/jonabbey/opt_depot">https://github.com/jonabbey/opt_depot</a>
- </pre>
- <p> "<em>opt_depot is a suite of Perl scripts which makes
- it easy to manage installed software across a wide range
- of client systems. opt_depot makes it possible to keep all
- files associated with a program together in one directory,
- so installation and de-installation is simple. opt_depot is
- easy to manage, and provides a scheme for installing software
- in a truly portable fashion; packages may be installed locally
- on client systems, or kept in a central package archive for
- NFS access. </em>"</p>
- <p> This site also has links to several other package
- management utilities, including <em>Graft</em>. </p>
- <dt> <em>relink</em>
- <dd>
- <pre>
- <a href="http://sourceforge.net/projects/relink/">http://sourceforge.net/projects/relink/</a>
- </pre>
- <p> "<em>relink is a package management tool for
- organization and management of software packages. It should
- run on any UNIX platform that runs PERL. Similar tools
- include: rpm(REDHAT/Mandrake), pkgadd(Slackware/SUN),
- stow(GNU) and depot(CMU)</em>" </p>
- <dt> <em>univSrcPkg</em>
- <dd>
- <pre>
- <a href="http://freecode.com/articles/the-universal-source-package">http://freecode.com/articles/the-universal-source-package</a>
- </pre>
- <p> <a href="mailto:bud@sistema.it">Bud Bruegger</a> has written
- a brief paper outlining his thoughts on a "<em>Universal Source
- Package</em>" solution. </p>
- <p> This site also has links to other package management
- programs and similar items of interest. </p>
- </dl>
- <hr>
- <h2><a name="design">Design</a></h2>
- <p> This brings us to <em>Graft</em>. <em>Graft</em> has been designed to
- use the best features of <em>Depot</em>, <em>Stow</em> and <em>Encap</em>
- while maintaining as simple a mechanism as possible. The principles of
- <em>Graft</em> are: </p>
- <ul>
- <li> <p> <em>Graft</em> will allow packages to be <em>grafted</em>
- from any directory to any other directory. Default
- <tt>installation</tt> and <tt>target</tt> directories will be
- used but can easily be overridden on the command line. </p>
- <li> <p> <em>Graft</em> will log its actions to a log file. The
- log file can be specified on the command line. If not specified
- on the command line a default log file will be used. </p>
- <li> <p> <em>Graft</em> will NOT create symbolic links to
- directories. If a directory does not exist in the target tree
- it will be created (with the same ownership and permissions as
- the original if desired). </p>
- <li> <p> <em>Graft</em> will create symbolic links with full
- pathnames rather than relative pathnames. This allows easy
- identification of true package locations and facilitates block
- movement of a target tree without the need for <em>Graft</em>
- deletion and re-installation. </p>
- <li> <p> <em>Graft</em> will cease installation of a package if a
- conflict arises. A conflict is defined as one of the following
- conditions: </p>
- <ul>
- <li> If the package object is a directory and the
- target object exists but is not a directory.
- <li> If the package object is not a directory and the
- target object exists and is not a symbolic link.
- <li> If the package object is not a directory and the
- target object exists and is a symbolic link to
- something other than the package object.
- <li> If the package directory contains a
- <tt>.graft-config</tt> file and the target object exists
- but does not match the 32-bit CRC of the package object.
- </ul>
- <li> <p> Installation conflicts will always be reported. Conflicts
- will be reported to standard error. </p>
- <li> <p> <em>Graft</em> will attempt to display all possible
- operations when asked, even when asked not to perform the
- operations. </p>
- <li> <p> <em>Graft</em> will not delete directories when
- uninstalling. <em>Graft</em> will print an appropriate message if an
- empty directory results and leave the deletion for the operator
- to perform outside the scope of <em>Graft</em>'s operations. This
- ensures that <em>place holder</em> directories that may be
- used by other packages are not inadvertently removed. This
- feature can be permanently disabled by setting a flag in the
- <tt>Makefile</tt>. It can also be temporarily disabled using a
- command line option. </p>
- <li> <p> <em>Graft</em> will continue to delete the remainder of
- a package after a conflict arises. This maximises the amount of
- deletion that can be performed. </p>
- <li> <p> Deletion conflicts will always be reported. Conflicts
- will be reported to standard error. </p>
- <li> <p> <em>Graft</em> will only concern itself with files
- relating to the package at hand. This will allow other packages
- to be placed in the target area without fear of intervention by
- <em>Graft</em>. </p>
- <li> <p> <em>Graft</em> will only allow the superuser to install
- or delete packages. This feature can be permanently disabled by
- setting a flag in the <tt>Makefile</tt> or it may be overridden
- by a command line option. </p>
- <li> <p> If the file <tt>.nograft</tt> exists in any package
- directory, <em>Graft</em> will bypass that directory and any
- subdirectories during installation. The name of this file is
- specified in the <tt>Makefile</tt>. </p>
- <li> <p> When installing a directory tree, if the file
- <tt>.graft-exclude</tt> exists in any package directory,
- <em>Graft</em> will assume that the file contains a list of
- file and/or directory names - one per line - which correspond
- to files and/or directories in the directory containing the
- <tt>.graft-exclude</tt> file. These files and/or directories
- will NOT be <em>grafted</em>. The name of this file is specified
- in the <tt>Makefile</tt>. </p>
- <p> The <tt>.nograft</tt> file takes priority over the
- <tt>.graft-exclude</tt> file. </p>
- <li> <p> When installing a directory tree, if the file
- <tt>.graft-include</tt> exists in any package directory,
- <em>Graft</em> will assume that the file contains a list of
- file and/or directory names - one per line - which correspond
- to files and/or directories in the directory containing the
- <tt>.graft-include</tt> file. ONLY the files and/or directories
- listed in the <tt>.graft-include</tt> will be <em>grafted</em>. The
- name of this file is specified in the <tt>Makefile</tt>. </p>
- <p> The <tt>.graft-exclude</tt> file takes priority over the
- <tt>.graft-include</tt> file. </p>
- <li> <p> When installing a directory tree, if the file
- <tt>.graft-config</tt> exists in a package directory, the contents
- of the directory will be <strong>copied</strong> to the target
- directory. If the target files exists and is in conflict with the
- package file then the package file will be copied into the target
- directory as <tt>file<em>.new</em></tt>. </p>
- <p> The <tt>.graft-include</tt> file takes priority over the
- <tt>.graft-config</tt> file. </p>
- <li> <p> If the file <tt>.nograft</tt> exists in any package
- directory, it will be ignored and <em>Graft</em> will continue
- processing the directory and any subdirectories during
- deletion. </p>
- <li> <p> If the file <tt>.graft-exclude</tt> exists in any
- package directory, its contents will be ignored and <em>Graft</em>
- will continue processing the directory and any subdirectories
- during deletion. </p>
- <li> <p> If the file <tt>.graft-include</tt> exists in any
- package directory, its contents will be ignored and <em>Graft</em>
- will continue processing the directory and any subdirectories
- during deletion. </p>
- <li> <p> If the file <tt>.graft-config</tt> exists in any
- package directory, during deletion matching files in the target
- directory will not be deleted however any
- <tt>file<em>.new</em></tt> files will be deleted. </p>
- <li> <p> As an aid to transitioning systems to <em>Graft</em>,
- <em>Graft</em> will allow conflicting files to be pruned. This
- pruning can take the form of a file rename or a file removal
- depending on either a <tt>Makefile</tt> flag or a command line
- option. If file removal is selected and the file is a non-empty
- directory, it will be renamed instead. </p>
- <li> <p> If the file <tt>.nograft</tt> exists in any package
- directory, it will be ignored and <em>Graft</em> will continue
- processing the directory and any subdirectories during
- pruning. </p>
- <li> <p> If the file <tt>.graft-exclude</tt> exists in any
- package directory, its contents will be ignored and <em>Graft</em>
- will continue processing the directory and any subdirectories
- during pruning. </p>
- <li> <p> If the file <tt>.graft-include</tt> exists in any
- package directory, its contents will be ignored and <em>Graft</em>
- will continue processing the directory and any subdirectories
- during pruning. </p>
- <li> <p> If the file <tt>.graft-config</tt> exists in any
- package directory, the files in the directory will be ignored
- during pruning. Sub-directories will continue to be processed
- appropriately. </p>
- </ul>
- <h3><a name="precedence">Control file precedence & conflict resolution</a></h3>
- <p> As stated above, the various <em>Graft</em> control files have the
- following precedence, from highest to lowest: </p>
- <pre>
- .nograft > .graft-exclude > .graft-include > .graft-config
- </pre>
- <p> The following table summarises the activities of <em>Graft</em> when
- various control files are present: </p>
- <center>
- <table summary="Control File Precedence" border=2 cellpadding=3>
- <tr>
- <th colspan=5>
- Install
- </th>
- </tr>
- <tr>
- <th>
- <em>Target</em>
- </th>
- <th>
- <em>.nograft</em>
- </th>
- <th>
- <em>.graft-exclude</em>
- </th>
- <th>
- <em>.graft-include</em>
- </th>
- <th>
- <em>.graft-config</em>
- </th>
- </tr>
- <tr>
- <td>
- does not exist
- </td>
- <td>
- IGNORE
- </td>
- <td>
- IGNORE
- </td>
- <td>
- SYMLINK
- </td>
- <td>
- COPY
- </td>
- </tr>
- <tr>
- <td>
- symlink to source
- </td>
- <td>
- IGNORE
- </td>
- <td>
- IGNORE
- </td>
- <td>
- NOP
- </td>
- <td>
- DELETE & COPY
- </td>
- </tr>
- <tr>
- <td>
- symlink to other
- </td>
- <td>
- IGNORE
- </td>
- <td>
- IGNORE
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- symlink to other (crc match)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- NOP
- </td>
- </tr>
- <tr>
- <td>
- symlink to other (crc diff)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- COPY.new
- </td>
- </tr>
- <tr>
- <td>
- file
- </td>
- <td>
- IGNORE
- </td>
- <td>
- IGNORE
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- file (crc match)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- NOP
- </td>
- </tr>
- <tr>
- <td>
- file (crc diff)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- COPY.new
- </td>
- </tr>
- <tr>
- <td>
- not a file
- </td>
- <td>
- IGNORE
- </td>
- <td>
- IGNORE
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- CONFLICT
- </td>
- </tr>
- <tr>
- <th colspan=5>
- Delete
- </th>
- </tr>
- <tr>
- <th>
- <em>Target</em>
- </th>
- <th>
- <em>.nograft</em>
- </th>
- <th>
- <em>.graft-exclude</em>
- </th>
- <th>
- <em>.graft-include</em>
- </th>
- <th>
- <em>.graft-config</em>
- </th>
- </tr>
- <tr>
- <td>
- does not exist
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- </tr>
- <tr>
- <td>
- symlink to source
- </td>
- <td>
- DELETE
- </td>
- <td>
- DELETE
- </td>
- <td>
- DELETE
- </td>
- <td>
- DELETE & DELETE.new
- </td>
- </tr>
- <tr>
- <td>
- symlink to other
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- symlink to other (crc match)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- DELETE.new
- </td>
- </tr>
- <tr>
- <td>
- symlink to other (crc diff)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- NOP
- </td>
- </tr>
- <tr>
- <td>
- file
- </td>
- <td>
- NOTE
- </td>
- <td>
- NOTE
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- file (crc match)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- DELETE.new
- </td>
- </tr>
- <tr>
- <td>
- file (crc diff)
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- N/A
- </td>
- <td>
- NOP
- </td>
- </tr>
- <tr>
- <td>
- not a file
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- CONFLICT
- </td>
- <td>
- CONFLICT
- </td>
- </tr>
- <tr>
- <th colspan=5>
- Prune
- </th>
- </tr>
- <tr>
- <th>
- <em>Target</em>
- </th>
- <th>
- <em>.nograft</em>
- </th>
- <th>
- <em>.graft-exclude</em>
- </th>
- <th>
- <em>.graft-include</em>
- </th>
- <th>
- <em>.graft-config</em>
- </th>
- </tr>
- <tr>
- <td>
- does not exist
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- symlink to source
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- <td>
- NOP
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- symlink to other
- </td>
- <td>
- PRUNE
- </td>
- <td>
- PRUNE
- </td>
- <td>
- PRUNE
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- file
- </td>
- <td>
- PRUNE
- </td>
- <td>
- PRUNE
- </td>
- <td>
- PRUNE
- </td>
- <td>
- N/A
- </td>
- </tr>
- <tr>
- <td>
- not a file
- </td>
- <td>
- PRUNE
- </td>
- <td>
- PRUNE
- </td>
- <td>
- PRUNE
- </td>
- <td>
- N/A
- </td>
- </tr>
- </table>
- </center>
- <hr>
- <h2><a name="history">History</a></h2>
- <p> Development on <em>Graft</em> began in October 1996. The initial design
- used a configuration file to map the installed location of each package to
- its target directory (that is the directory in which the symbolic links
- would be created). Work proceeded at a regular pace and by November 1997
- <em>Graft</em> version <em>2.1</em> was released. In this, and all
- subsequent versions, the configuration file had been removed in favour of
- using default source and target directories. </p>
- <p> No further work was performed until September 2000 when the concept of
- bypassing or including files and directories using <tt>.nograft</tt> or
- <tt>.graft-include</tt> files was introduced in <em>Graft</em> version
- <em>2.3</em>. </p>
- <p> Again nothing changed until February 2002 when Rod Whitby identified a
- bug in the handling of <tt>.graft-include</tt> files. Several other users
- (Peter Bray, Robert Maldon and others) also reported some deprecation
- warnings when using <em>Graft</em> with <em>Perl</em> version
- <em>5.6.0</em>. <em>Graft</em> version <em>2.4</em> was the end of
- <em>Graft</em> development for over a decade. </p>
- <p> In May 2015 Matias A. Fonzo contacted the author wishing to use
- <em>Graft</em> in the
- <a href="http://www.dragora.org/">Dragora GNU/Linux</a>
- distribution. Matias' usage of <em>Graft</em> lead to <em>Graft</em>
- version <em>2.5</em> in June 2015 whereby the <tt>-P</tt> command line
- option was silently ignored if the effective user was not root. </p>
- <p> Since the release of <em>Graft</em> version <em>2.4</em> the author's
- <em>Perl</em> code had improved somewhat so <em>Graft</em> version
- <em>2.6</em> released in July 2015 represented a major clean up of coding
- style and internals. No new behaviours or features were added to the
- <em>2.6</em> release. </p>
- <p> Matias made some more suggestions and improvements up to and including
- <em>Graft</em> version <em>2.16</em> in April 2018. These changes added
- the <tt>.graft-config</tt> control file, the <tt>-r /rootdir</tt> option for
- specifying a new root directory, the <tt>-L</tt> option for displaying
- default locations as well as introducing some tighter controls on the
- messages and exit status of <em>Graft</em> under various conditions. </p>
- <hr>
- <h2><a name="installation">Installation</a></h2>
- <p> Before installing <em>Graft</em> you'll need <em>Perl</em>
- 5.<em>x</em>. <em>Graft</em> version 2.<em>x</em> requires features only
- available with <em>Perl</em> 5.<em>x</em> and will not run with
- <em>Perl</em> 4.<em>x</em>. </p>
- <p> Your operating system and its file system(s) should also support
- symbolic links. If you can't make symbolic links then you can't use
- <em>Graft</em>! <em>Graft</em> will exit gracefully if your version of
- <em>Perl</em> does not support symbolic links. It will also exit gracefully
- if you attempt to <em>graft</em> a package into a file system that does not
- support symbolic links - from a Linux <tt>ext4</tt> file system into an
- <tt>vfat</tt> file system for example. </p>
- <p> <em>Graft</em> has been written to ensure it uses <em>Perl</em> modules
- that are considered part of the core <em>Perl</em> distribution. However it
- may be possible that you're using a home grown installation of
- <em>Perl</em> or some distribution that doesn't have the same <em>Perl</em>
- modules as the author's development environment. </p>
- <p> If this is the case you'll see compile failures for the following modules
- if they are unavailable: </p>
- <pre>
- File::Basename
- Getopt::Long
- </pre>
- <p> You will not be able to install <em>Graft</em> until these modules are
- available. </p>
- <p> You may also see run-time failures when using <em>Graft</em> with
- <tt>.graft-config</tt> files if the following modules are unavailable: </p>
- <pre>
- Compress::Raw::Zlib (<em>used in install and delete modes</em>)
- File::Copy (<em>only used in install mode</em>)
- </pre>
- <p> If you don't have these modules and you do not intend to use
- <tt>.graft-config</tt> files then you can continue to use <em>Graft</em>
- without issue. </p>
- <p> Follow these instructions to install <em>Graft</em>: </p>
- <ol>
- <li> <p> Unpack the gzipped <em>Graft</em> distribution: </p>
- <pre>
- gunzip -c graft-2.16.tar.gz | tar xvf -
- </pre>
- <li> <p> change directories to the <em>Graft</em> distribution
- directory: </p>
- <pre>
- cd graft-2.16
- </pre>
- <li> <p> Create an writable version of the <tt>Makefile</tt> by
- running the command </p>
- <pre>
- make -f Makefile.dist
- </pre>
- <p> You'll see output similar to </p>
- <pre>
- cp Makefile.dist Makefile
- chmod 644 Makefile
- ######################################################
- # #
- # You'll now need to modify the Makefile #
- # variables to suit your local conditions. #
- # #
- ######################################################
- make: *** [Makefile] Error 1
- </pre>
- <p> You can ignore the error message. That is just there to
- prevent the creation of the <em>graft</em> executable before you've
- made your site specific configurations to the <tt>Makefile</tt>.
- </p>
- <li> <p> Edit the <tt>Makefile</tt>. The following variables should be
- modified to suit your local requirements: </p>
- <dl>
- <dt>
- <pre>
- <strong>PACKAGEDIR</strong> = /usr/local/pkgs
- <strong>TARGETDIR</strong> = /usr/local
- </pre>
- <dd> <p> These two variables control your default
- package <tt>installation</tt> and <tt>target</tt>
- directories. Most sites will probably choose to
- install packages under a common <tt>installation</tt>
- directory and then <em>graft</em> them into a common
- <tt>target</tt> directory. </p>
- <p> If no specific <tt>target</tt> directory is
- given on the command line, <em>Graft</em> will use
- the default value specified by <strong>TARGETDIR</strong>. If
- a <tt>target</tt> directory is given on the command
- line but is not fully qualified, the value specified
- by <strong>TARGETDIR</strong> will be prepended to the command
- line argument. </p>
- <p> Package names provided to <em>Graft</em> that are
- not fully qualified will have the value specified
- by <strong>PACKAGEDIR</strong> prepended to the command line
- arguments. </p>
- <dt>
- <pre>
- <strong>TOP</strong> = $(PACKAGEDIR)/graft-$(VERSION)
- <strong>BIN</strong> = $(TOP)/bin
- <strong>MAN</strong> = $(TOP)/man
- <strong>DOC</strong> = $(TOP)/doc
- </pre>
- <dd> <p> There should be no need to modify these
- values unless you wish to install <em>Graft</em> into
- a directory that is different from your default
- package installation directory. If you do modify
- <strong>TOP</strong> you should not change the values of
- <strong>BIN</strong>, <strong>MAN</strong> and <strong>DOC</strong>. If you feel
- you must change these values then perhaps you've
- misunderstood the concept behind <em>Graft</em> so a
- re-read of this document may be in order. </p>
- <dt>
- <pre>
- <strong>PERL</strong> = /usr/bin/perl
- </pre>
- <dd> <p> This variable refers to the location
- of the <em>Perl</em> 5.<em>x</em> that will be used by
- the <em>Graft</em> executable. If you plan on
- <em>grafting</em> <em>Perl</em> then this value should
- be the <em>grafted</em> location of <em>Perl</em>
- rather than the installation location of <em>Perl</em>.
- If you are using an operating system that comes with
- <em>Perl</em> 5.<em>x</em> - such as RedHat or Ubuntu
- Linux - then you don't need to worry about
- <em>grafting</em> <em>Perl</em> so the value of
- <strong>PERL</strong> should reflect its installed
- location. </p>
- <p> Most Unix, Linux and other Unix like operating
- systems ship with <em>Perl</em> these days so
- modifying this value is probably unnecessary. </p>
- <dt>
- <pre>
- <strong>BUILDPERL</strong> = $(PERL)
- </pre>
- <dd> <p> <em>Perl</em> is required during the
- <tt>make</tt>. You'll only need to change this if
- the current installed location of <em>Perl</em> is
- different to the future <em>grafted</em> location of
- <em>Perl</em>. </p>
- <dt>
- <pre>
- <strong>LOGFILE</strong> = /var/log/graft
- </pre>
- <dd> <p> <em>Graft</em> logs all of its actions to a log
- file. Modify the value of <strong>LOGFILE</strong> to suit
- your local needs. An alternative name can be
- specified on the command line. </p>
- <p> If you want logging disabled by default, set the
- value of <strong>LOGFILE</strong> to <tt>/dev/null</tt>. </p>
- <dt>
- <pre>
- <strong>GRAFT-IGNORE</strong> = .nograft
- <strong>GRAFT-EXCLUDE</strong> = .graft-exclude
- <strong>GRAFT-INCLUDE</strong> = .graft-include
- <strong>GRAFT-CONFIG</strong> = .graft-config
- </pre>
- <dd> <p> These variables hold the names of the
- special <em>Graft</em> files that control whether or
- not subdirectories or files are <em>grafted</em>. If
- you change these values, try to choose obvious names.
- If you want the files to appear in a simple directory
- listing, do not use file names that begin with a
- dot "." character. </p>
- <dt>
- <pre>
- <strong>GRAFT-NEVER</strong> =
- </pre>
- <dd> <p> This variable holds the names of the
- files and/or directories that should never be
- <em>grafted</em>. Typically these may be source code
- repositories as used by systems such as
- <em>CVS</em>, or perhaps lockfiles. The default
- value is empty but if you wish to specify values,
- simply add them to the variable using only
- whitespace as a separator. For example: </p>
- <pre>
- GRAFT-NEVER = CVS RCS SCCS .lock
- </pre>
- <dt>
- <pre>
- <strong>NEVERGRAFT</strong> = 0
- </pre>
- <dd> <p> If this variable is set to <strong>1</strong>,
- the files and/or directories specified by
- <strong>GRAFT-NEVER</strong> will be automatically excluded
- from the <em>grafted</em> directory. </p>
- <p> If this variable is set to <strong>0</strong>, the files
- and/or directories specified by <strong>GRAFT-NEVER</strong>
- will be not be excluded from the <em>grafted</em>
- directory. </p>
- <p> The sense of this value is reversed by use of
- the <strong>-C</strong> command line option.
- <p> The automatic exclusion is bypassed completely
- if the <em>grafted</em> directory contains either
- a <tt>.nograft</tt> or <tt>.graft-include</tt>
- file. </p>
- <dt>
- <pre>
- <strong>PRUNED-SUFFIX</strong> = .pruned
- </pre>
- <dd> <p> This variable sets the suffix name of
- <em>pruned</em> files. <em>Pruned</em> files will be
- renamed <em>filename</em><tt>.pruned</tt>. </p>
- <dt>
- <pre>
- <strong>CONFIG-SUFFIX</strong> = .new
- </pre>
- <dd> <p> This variable sets the suffix name of configuration
- files that will be copied to the target directory when
- the target object is in conflict with the package
- object. The files will be copied as
- <em>filename</em><tt>.new</tt>. </p>
- <dt>
- <pre>
- <strong>SUPERUSER</strong> = 1
- </pre>
- <dd> <p> If this variable is set to <strong>1</strong> only
- the superuser can <em>install</em>, <em>delete</em>
- or <em>prune</em> packages. This can be overridden
- by the use of the <strong>-u</strong> command line
- option. If this variable is set to <strong>0</strong>,
- superuser privileges are not required and the
- <strong>-u</strong> override command line option is
- disabled. </p>
- <p> If you are installing a private copy of
- <em>Graft</em> to manage packages in your home
- directory you should set <strong>SUPERUSER</strong> to
- <strong>0</strong>. </p>
- <p> If you're using <em>Graft</em> to manage a global
- set of packages you should set <strong>SUPERUSER</strong>
- to <strong>1</strong>. </p>
- <dt>
- <pre>
- <strong>PRESERVEPERMS</strong> = 0
- </pre>
- <dd> <p> When <em>grafting</em> packages, <em>Graft</em>
- will create new directories as required. By setting
- <strong>PRESERVEPERMS</strong> to <strong>1</strong>,
- the original user id, group id and file modes will be
- carried over to the new directory. This variable is
- used only if <strong>SUPERUSER</strong> is set to
- <strong>1</strong>. The sense of this variable can be
- reversed using the <strong>-P</strong> command line
- option. </p>
- <dt>
- <pre>
- <strong>DELETEOBJECTS</strong> = 0
- </pre>
- <dd> <p> When deleting <em>grafted</em> packages,
- <em>Graft</em> may leave empty directories. Setting
- <strong>DELETEOBJECTS</strong> to <strong>1</strong>
- will allow <em>Graft</em> to delete these directories.
- If <strong>DELETEOBJECTS</strong> is <strong>0</strong>
- then <em>Graft</em> will display an appropriate message
- reminding the user that a directory has been emptied.
- The sense of this variable can be reversed using the
- <strong>-D</strong> command line option. </p>
- <p> It's probably not good practise to set this value
- to <strong>1</strong> as some directories may be used
- as place holders by a number of different packages. If
- the value is set to <strong>0</strong> deletion of
- directories can be forced via the <strong>-D</strong>
- command line option. </p>
- <p> When pruning packages, <em>graft</em> can either
- remove conflicting files or rename them. If
- <strong>DELETEOBJECTS</strong> is set to
- <strong>1</strong> the default prune action will be to
- delete conflicting objects. If
- <strong>DELETEOBJECTS</strong> is set to
- <strong>0</strong> the default prune action will be to
- rename conflicting objects. The sense of this variable
- can be reversed using the <strong>-D</strong> command
- line option. </p>
- </dl>
- <p> Save your changes and exit from the editor. </p>
- <li> <p> Remove any existing executables by running: </p>
- <pre>
- make clean
- </pre>
- <p> You should see output similar to: </p>
- <pre>
- rm -f graft
- </pre>
- <li> <p> Create the <em>Graft</em> executable by running: </p>
- <pre>
- make
- </pre>
- <p> You should see output similar to: </p>
- <pre>
- /usr/bin/perl -wc graft.pl
- graft.pl syntax OK
- sed \
- -e 's#xCONFIG-SUFFIXx#.new#g' \
- -e 's#xDELETEOBJECTSx#0#g' \
- -e 's#xGRAFT-CONFIGx#.graft-config#g' \
- -e 's#xGRAFT-EXCLUDEx#.graft-exclude#g' \
- -e 's#xGRAFT-IGNOREx#.nograft#g' \
- -e 's#xGRAFT-INCLUDEx#.graft-include#g' \
- -e 's#xGRAFT-NEVERx##g' \
- -e 's#xLOGFILEx#/var/log/graft#g' \
- -e 's#xNEVERGRAFTx#0#g' \
- -e 's#xPACKAGEDIRx#/usr/local/pkgs#g' \
- -e 's#xPERLx#/usr/bin/perl#g' \
- -e 's#xPRESERVEPERMSx#0#g' \
- -e 's#xPRUNED-SUFFIXx#.pruned#g' \
- -e 's#xSUPERUSERx#1#g' \
- -e 's#xTARGETDIRx#/usr/local#g' \
- < graft.pl > graft
- chmod +x graft
- /usr/bin/perl -wc graft
- graft syntax OK
- if [ -n "" ]; \
- then \
- AUTOIGNORE=1; \
- else \
- AUTOIGNORE=0; \
- fi; \
- sed \
- -e "s#xAUTOIGNOREx#$AUTOIGNORE#g" \
- -e 's#xCONFIG-SUFFIXx#.new#g' \
- -e 's#xDELETEOBJECTSx#0#g' \
- -e 's#xDOCx#/usr/local/pkgs/graft-2.16/doc#g' \
- -e 's#xGRAFT-CONFIGx#.graft-config#g' \
- -e 's#xGRAFT-EXCLUDEx#.graft-exclude#g' \
- -e 's#xGRAFT-IGNOREx#.nograft#g' \
- -e 's#xGRAFT-INCLUDEx#.graft-include#g' \
- -e 's#xGRAFT-NEVERx##g' \
- -e 's#xLOGFILEx#/var/log/graft#g' \
- -e 's#xNEVERGRAFTx#0#g' \
- -e 's#xPACKAGEDIRx#/usr/local/pkgs#g' \
- -e 's#xPERLx#/usr/bin/perl#g' \
- -e 's#xPRESERVEPERMSx#0#g' \
- -e 's#xPRUNED-SUFFIXx#.pruned#g' \
- -e 's#xSUPERUSERx#1#g' \
- -e 's#xTARGETDIRx#/usr/local#g' \
- -e 's#xVERSIONx#2.16#g' \
- < graft.man > graft.1
- </pre>
- <li> <p> If you're using the <em>automounter</em> under Solaris
- 2.<em>x</em>, the installation process may not be able to directly
- create the directory specified by <strong>TOP</strong>. If this is the case
- then manually create this directory using whatever procedures
- are appropriate for your operating system. </p>
- <p> For example, if the <tt>/usr/local</tt> mount point is under the
- control of the <em>automounter</em> via an entry in the
- <tt>auto_pkgs</tt> map: </p>
- <pre>
- * nfshost:/export/sparc-SunOS-5.5.1/usr/local/&
- </pre>
- <p> you'll need to create the <em>Graft</em> installation directory
- by executing the following command on the machine <em>nfshost</em>:
- </p>
- <pre>
- mkdir /export/sparc-SunOS-5.5.1/usr/local/pkgs/graft-2.16
- </pre>
- <li> <p> Install the <em>Graft</em> executable, manual page and
- documentation by executing: </p>
- <pre>
- make install
- </pre>
- <p> You should see output similar to: </p>
- <pre>
- mkdir -p /usr/local/pkgs/graft-2.16/bin
- cp graft /usr/local/pkgs/graft-2.16/bin
- for i in graft.1; \
- do \
- manpage=`basename $i`; \
- man=`expr $i : '.*\.\(.\)'`; \
- mkdir -p /usr/local/pkgs/graft-2.16/man/man$man; \
- cp $i /usr/local/pkgs/graft-2.16/man/man$man/$manpage; \
- chmod 644 /usr/local/pkgs/graft-2.16/man/man$man/$manpage; \
- done
- for i in graft.html graft.pdf graft.ps graft.txt; \
- do \
- mkdir -p /usr/local/pkgs/graft-2.16/doc; \
- cp doc/$i /usr/local/pkgs/graft-2.16/doc; \
- chmod 644 /usr/local/pkgs/graft-2.16/doc/$i; \
- touch /usr/local/pkgs/graft-2.16/doc/.nograft; \
- done
- </pre>
- </ol>
- <p> <em>Graft</em> is now installed and ready to be used. </p>
- <p> <strong>NOTE:</strong> If you make changes to your <em>Graft</em> installation at a
- later date, please run the following commands: </p>
- <pre>
- make clean
- make install
- </pre>
- <p> Failure to do this may result in a <em>Graft</em> manual page that does
- NOT reflect your current configuration. </p>
- <h3><a name="rpm_and_deb">Creating RPM and DEB packages</a></h3>
- <p> Beginning with <em>Graft</em> 2.11 there is now the ability to create
- RPM and Debian installation packages. Obviously you'll need one or more of
- the <em>rpmbuild</em> and <em>dpkg-deb</em> packages installed on your
- system. </p>
- <p> After editing the <tt>Makefile</tt> to suit your environment simply run
- the appropriate <tt>make</tt> command to create the binary installation
- package in the current directory: </p>
- <pre>
- make rpm
- </pre>
- <p> or </p>
- <pre>
- make deb
- </pre>
- <p> The creation of these packages is somewhat experimental. Please let the
- author know if you have issues. </p>
- <hr>
- <h3><a name="gotchas">Grafting <em>Graft</em> and <em>Perl</em> - the
- bootstrap problem</a></h3>
- <p> <strong>If you are using an operating system that comes with <em>Perl</em>
- 5.<em>x</em> - such as RedHat or Ubuntu Linux - then you don't need to worry
- about <em>grafting</em> <em>Perl</em>, so this section can be ignored.</strong> </p>
- <p> <strong>However if you are a creator of an operating system
- distribution then this section may be relevant.</strong> </p>
- <p> Embedded into the <em>Graft</em> executable is the location of the
- <em>Perl</em> executable. If you've understood the concept behind
- <em>Graft</em> then this location may be the <em>grafted</em> location of
- <em>Perl</em> rather than the true location of <em>Perl</em>. </p>
- <p> This presents a dilemma when you come to <em>graft</em> both <em>Graft</em>
- and <em>Perl</em>. You can't run the <em>grafted</em> location of the
- <em>Graft</em> executable because it doesn't exist yet, and you can't run
- the real location of the <em>Graft</em> executable because <em>Perl</em>
- hasn't been <em>grafted</em> yet. </p>
- <p> Assuming that <em>Graft</em> and <em>Perl</em> are installed in </p>
- <pre>
- /usr/local/pkgs/graft-2.16
- /usr/local/pkgs/perl-5.18.2
- </pre>
- <p> you can resolve this dilemma by executing the following commands:
- </p>
- <pre>
- /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i graft-2.16
- /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i perl-5.18.2
- </pre>
- <p> This will <em>graft</em> both <em>Graft</em> and <em>Perl</em> from the
- default package installation directory (as specified by
- <strong>PACKAGEDIR</strong> in the <tt>Makefile</tt>) into your default target
- directory (as specified by <strong>TARGETDIR</strong> in the <tt>Makefile</tt>).
- </p>
- <p> If you don't wish to use the default directories you can use the
- following commands to <em>graft</em> the packages into <tt>/pkgs</tt>
- instead of <tt>/usr/local</tt> for example: </p>
- <pre>
- /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i -t /pkgs /usr/local/pkgs/graft-2.16
- /usr/local/pkgs/perl-5.18.2/bin/perl /usr/local/pkgs/graft-2.16/bin/graft -i -t /pkgs /usr/local/pkgs/perl-5.18.2
- </pre>
- <p> Now both <em>Graft</em> and <em>Perl</em> have been <em>grafted</em> and any
- other package can be <em>grafted</em> by executing the simpler command:
- </p>
- <pre>
- graft -i <em>package</em>
- </pre>
- <p> The <em>Graft</em> distribution includes a program called
- <tt>graftBootStrap.sh</tt> which allows you to easily <em>graft</em> both
- <em>Graft</em> and <em>Perl</em>. It can be found in the <em>contrib</em>
- directory of the distribution. Thanks to Gordon Rowell for providing it.</p>
- <p> You may also find the <tt>-L</tt> command line option to be useful to
- programmatically determine where <em>Graft</em> expects to find
- <em>Perl</em> along with the default locations of its log file, target and
- package directories. See the <a href="#graft-L">Information</a> section
- below for details. </p>
- <hr>
- <h2><a name="using-graft">Using <em>Graft</em></a></h2>
- <h3><a name="compiling-packages">Compiling Packages</a></h3>
- <p> Any packages you wish to place under the control of <em>Graft</em> should
- be compiled and installed in such a way that any package dependent
- files are referenced with the ACTUAL package installation directory
- rather than the common area in which <em>Graft</em> will be creating
- symbolic links. For example, ensure that <em>Perl</em> version
- <em>5.18.2</em> is looking for its library files in
- <tt>/usr/local/pkgs/perl-5.18.2/lib/perl5</tt> instead of
- <tt>/usr/local/lib/perl5</tt>. This approach will allow you to easily
- separate multiple versions of the same package without any problems. </p>
- <hr width="25%">
- <h3><a name="usage"><em>Graft</em> command line options</a></h3>
- <p> All of the details concerning actions, package locations and target
- directories are passed to <em>Graft</em> on the command line.
- (<em>Graft</em> 1.<em>x</em> used a configuration file. This has now been
- deprecated in favour of a log file). </p>
- <p> <em>Graft</em>'s command line options can be summarised as: </p>
- <pre>
- graft -i [-P|u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
- graft -d [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
- graft -p [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
- graft -L
- </pre>
- <p> <em>Graft</em> has four basic actions: </p>
- <ol>
- <li> <p> <a name="graft-i"><strong>Install</strong></a> </p>
- <pre>
- graft -i [-C] [-P|u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
- </pre>
- <dl>
- <dt> <strong>-i</strong>
- <dd>
- <p> Install symbolic links from the package
- installation directory to the target directory.
- Requires superuser privileges if
- <strong>SUPERUSER</strong> was set to <strong>1</strong> in the
- <tt>Makefile</tt>. </p>
- <dt> <strong>-C</strong>
- <dd>
- <p> If <strong>NEVERGRAFT</strong> was set to <strong>1</strong>
- in the <tt>Makefile</tt>, disable the automatic
- exclusion of files and/or directories whose
- names exactly match the values specified by
- <strong>GRAFT-NEVER</strong> in the <tt>Makefile</tt>. </p>
- <p> If <strong>NEVERGRAFT</strong> was set to <strong>0</strong>
- in the <tt>Makefile</tt>, force the automatic
- exclusion of files and/or directories whose
- names exactly match the values specified by
- <strong>GRAFT-NEVER</strong> in the <tt>Makefile</tt>. </p>
- <p> Can only be used with the -i option. </p>
- <p> This option is ignored for each <em>grafted</em>
- directory, if the directory contains a
- <tt>.nograft</tt> or <tt>.graft-include</tt>
- file. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. If there
- are no objects specified for
- <strong>GRAFT-NEVER</strong> then this option will
- be silently ignored and will not appear in the help
- message nor in the manual page. </p>
- <dt> <strong>-P</strong>
- <dd>
- <p> Preserve modes and ownerships when creating new
- directories or copying files if
- <strong>PRESERVEPERMS</strong> was set to
- <strong>0</strong> in the <tt>Makefile</tt>. Do not
- preserve modes and ownerships if the option is not
- provided on the command line. </p>
- <p> Do not preserve modes and ownerships when
- creating new directories or copying files if
- <strong>PRESERVEPERMS</strong> was set to
- <strong>1</strong> in the <tt>Makefile</tt>.
- Preserve modes and ownerships if the option is not
- provided on the command line. </p>
- <p> Cannot be used with the <strong>-u</strong> option. </p>
- <p> This option will be silently ignored if the
- effective user of <em>Graft</em> is not root. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. This
- option will be silently ignored and will not appear
- in the help message nor in the manual page if
- <strong>SUPERUSER</strong> was set to
- <strong>0</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-u</strong>
- <dd>
- <p> Superuser privileges are not required when
- installing packages. </p>
- <p> Cannot be used with the <strong>-P</strong> option. </p>
- <p> This option is only available if
- <strong>SUPERUSER</strong> was set to
- <strong>1</strong> in the <tt>Makefile</tt>. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. This
- option will be silently ignored and will not appear
- in the help message nor in the manual page if
- <strong>SUPERUSER</strong> was set to
- <strong>0</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-l <em>log</em></strong>
- <dd>
- <p> Specify an alternate log file instead of the
- default specified by <strong>LOGFILE</strong> in the
- <tt>Makefile</tt>. No logging is performed if
- the <strong>-n</strong> option is used. </p>
- <p> Log entries have the form: </p>
- <pre>
- 878790215 1.10+ I /usr/local/pkgs/cpio-2.4.2 /usr/local
- 878888916 2.1 I /usr/local/pkgs/gzip-1.2.4 /usr/local
- 878888916 2.1 IC /usr/local/pkgs/gzip-1.2.4/bin/gzip invalid symlink
- </pre>
- <p> This shows that a development version of
- <em>graft</em> (1.10+) was used to install
- symbolic links from <tt>/usr/local/pkgs/cpio-2.4.2</tt>
- to <tt>/usr/local</tt>. A new version of
- <em>graft</em> (2.1) was used to install symbolic
- links from <tt>/usr/local/pkgs/gzip-1.2.4</tt> to
- <tt>/usr/local</tt>. The <tt>IC</tt> entry indicates
- that a conflict occurred during this
- installation - the file <tt>/usr/local/pkgs/bin/gzip</tt>
- was a symbolic link to something other than
- <tt>/usr/local/pkgs/gzip-1.2.4/bin/gzip</tt>. </p>
- <dt> <strong>-n</strong>
- <dd>
- <p> List actions but do not perform them. Implies
- the very verbose option. Does not require
- superuser privileges regardless of the value of
- <strong>SUPERUSER</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-v</strong>
- <dd>
- <p> Be verbose. </p>
- <dt> <strong>-V</strong>
- <dd>
- <p> Be very verbose. </p>
- <dt> <strong>-r <em>/rootdir</em></strong>
- <dd>
- <p> Use the fully qualified named directory as the
- root directory for all graft operations. The source
- directory, target directory and log file will all
- be relative to this specific directory. </p>
- <p> Can only be used by the superuser. </p>
- <dt> <strong>-s</strong>
- <dd>
- <p> <em>Stow</em>/<em>Depot</em> compatibility mode.
- Infer the <em>Graft</em> target directory from
- each package installation directory in the
- manner of <em>Stow</em> and <em>Depot</em>. </p>
- <p> Target directory is the <tt>dirname</tt> of the
- <tt>dirname</tt> of the package installation
- directory. (Yes that really is two
- <tt>dirname</tt>s). So if the package
- installation directory is </p>
- <pre>
- /usr/local/depot/gzip-1.2.4
- </pre>
- <p> the package will be <em>grafted</em> into
- </p>
- <pre>
- /usr/local
- </pre>
- <p> Cannot be used with the <strong>-t</strong> option. </p>
- <dt> <strong>-t <em>target</em></strong>
- <dd>
- <p> Override the default <em>graft</em> target
- directory with <strong><em>target</em></strong>. The value
- of <strong><em>target</em></strong> must be a fully
- qualified directory and it must exist. </p>
- <p> Cannot be used with the <strong>-s</strong> option. </p>
- <dt> <strong>package</strong>
- <dd>
- <p> Install the named package. If <strong>package</strong> is
- a fully qualified directory, use it as the
- package installation directory. If
- <strong>package</strong> is not a fully qualified
- directory, prepend it with the value of
- <strong>PACKAGEDIR</strong> as specified in the
- <tt>Makefile</tt>. </p>
- </dl>
- <hr width="10%">
- <li> <p> <a name="graft-d"><strong>Delete</strong></a> </p>
- <pre>
- graft -d [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
- </pre>
- <dl>
- <dt> <strong>-d</strong>
- <dd>
- <p> Delete symbolic links from the package target
- directory to the package installation
- directory. Requires superuser privileges if
- <strong>SUPERUSER</strong> was set to <strong>1</strong> in the
- <tt>Makefile</tt>. </p>
- <dt> <strong>-D</strong>
- <dd>
- <p> Delete empty directories if
- <strong>DELETEOBJECTS</strong> was set to <strong>0</strong> in the
- <tt>Makefile</tt>. If the option is not
- provided on the command line, notify the user
- that a directory has been emptied. </p>
- <p> Do not delete empty directories if
- <strong>DELETEOBJECTS</strong> was set to <strong>1</strong> in the
- <tt>Makefile</tt>. Notify the user that a
- directory has been emptied. If the option is
- not provided on the command line, delete empty
- directories. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. </p>
- <dt> <strong>-u</strong>
- <dd>
- <p> Superuser privileges are not required when
- deleting packages. </p>
- <p> This option is only available if
- <strong>SUPERUSER</strong> was set to
- <strong>1</strong> in the <tt>Makefile</tt>. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. This
- option will be silently ignored and will not appear
- in the help message nor in the manual page if
- <strong>SUPERUSER</strong> was set to
- <strong>0</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-l <em>log</em></strong>
- <dd>
- <p> Specify an alternate log file instead of the
- default specified by <strong>LOGFILE</strong> in the
- <tt>Makefile</tt>. No logging is performed if
- the <strong>-n</strong> option is used. </p>
- <p> Log entries have the form: </p>
- <pre>
- 879126278 1.10+ D /usr/local/pkgs/weblint-1.017 /usr/local
- 879126278 1.10+ DC /usr/local/pkgs/weblint-1.017/bin/weblint file exists
- 879126278 1.10+ DC /usr/local/pkgs/weblint-1.017/man/man1/weblint.1 file exists
- </pre>
- <p> This shows that a development version of
- <em>graft</em> (1.10+) was used to delete
- symbolic links from <tt>/usr/local</tt> to
- <tt>/usr/local/pkgs/weblint-1.017</tt>. The <tt>DC</tt>
- entries indicate that conflicts occurred during
- this action - the files
- <tt>/usr/local/bin/weblint</tt> and
- <tt>/usr/local/man/man1/weblint.1</tt> already
- exist. </p>
- <dt> <strong>-n</strong>
- <dd>
- <p> List actions but do not perform them. Implies
- the very verbose option. Does not require
- superuser privileges regardless of the value of
- <strong>SUPERUSER</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-v</strong>
- <dd>
- <p> Be verbose. </p>
- <dt> <strong>-V</strong>
- <dd>
- <p> Be very verbose. </p>
- <dt> <strong>-r <em>/rootdir</em></strong>
- <dd>
- <p> Use the fully qualified named directory as the
- root directory for all graft operations. The source
- directory, target directory and log file will all
- be relative to this specific directory. </p>
- <p> Can only be used by the superuser. </p>
- <dt> <strong>-s</strong>
- <dd>
- <p> <em>Stow</em>/<em>Depot</em> compatibility mode.
- Infer the <em>Graft</em> target directory from
- each package installation directory in the
- manner of <em>Stow</em> and <em>Depot</em>. </p>
- <p> Target directory is the <tt>dirname</tt> of the
- <tt>dirname</tt> of the package installation
- directory. (Yes that really is two
- <tt>dirname</tt>s). So if the package
- installation directory is </p>
- <pre>
- /usr/local/depot/gzip-1.2.4
- </pre>
- <p> the package will be <em>grafted</em> into
- </p>
- <pre>
- /usr/local
- </pre>
- <p> Cannot be used with the <strong>-t</strong> option. </p>
- <dt> <strong>-t <em>target</em></strong>
- <dd>
- <p> Override the default <em>graft</em> target
- directory with <strong><em>target</em></strong>. The value
- of <strong><em>target</em></strong> must be a fully
- qualified directory and it must exist. </p>
- <p> Cannot be used with the <strong>-s</strong> option. </p>
- <dt> <strong>package</strong>
- <dd>
- <p> Delete the named package. If <strong>package</strong> is
- a fully qualified directory, use it as the
- package installation directory. If
- <strong>package</strong> is not a fully qualified
- directory, prepend it with the value of
- <strong>PACKAGEDIR</strong> as specified in the
- <tt>Makefile</tt>. </p>
- </dl>
- <hr width="10%">
- <li> <p> <a name="graft-p"><strong>Prune</strong></a> </p>
- <pre>
- graft -p [-D] [-u] [-l log] [-n] [-v|V] [-r /rootdir] [-s|-t target] package(s)
- </pre>
- <dl>
- <dt> <strong>-p</strong>
- <dd>
- <p> Prune objects (files, links or directories)
- from the package target directory that are in
- conflict with the package installation
- directory. Requires superuser privileges if
- <strong>SUPERUSER</strong> was set to <strong>1</strong> in the
- <tt>Makefile</tt>. </p>
- <dt> <strong>-D</strong>
- <dd>
- <p> Remove conflicting objects if
- <strong>DELETEOBJECTS</strong> was set to <strong>0</strong> in the
- <tt>Makefile</tt>. Rename conflicting objects
- as <tt><em>object</em>.pruned</tt> if the option
- is not provided on the command line. </p>
- <p> Rename conflicting objects to
- <tt><em>object</em>.pruned</tt> if
- <strong>DELETEOBJECTS</strong> was set to <strong>1</strong> in the
- <tt>Makefile</tt>. Remove conflicting objects
- if the option is not provided in the command
- line. </p>
- <p> If a directory is to be removed and it is not
- empty, it will be renamed as
- <tt><em>dir</em>.pruned</tt> and a suitable
- warning message will be given regardless of the
- sense of this flag. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. </p>
- <dt> <strong>-u</strong>
- <dd>
- <p> Superuser privileges are not required when
- pruning packages. </p>
- <p> This option is only available if
- <strong>SUPERUSER</strong> was set to
- <strong>1</strong> in the <tt>Makefile</tt>. </p>
- <p> The <em>Graft</em> manual page will correctly
- reflect the behaviour of this option based on the
- values specified in the <tt>Makefile</tt>. This
- option will be silently ignored and will not appear
- in the help message nor in the manual page if
- <strong>SUPERUSER</strong> was set to
- <strong>0</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-l <em>log</em></strong>
- <dd>
- <p> Specify an alternate log file instead of the
- default specified by <strong>LOGFILE</strong> in the
- <tt>Makefile</tt>. No logging is performed if
- the <strong>-n</strong> option is used. </p>
- <p> Log entries have the form: </p>
- <pre>
- 879126283 1.10+ P /usr/local/pkgs/weblint-1.017 /usr/local
- </pre>
- <p> This shows that a development version of
- <em>graft</em> (1.10+) was used to delete objects
- from <tt>/usr/local</tt> that were in conflict with
- <tt>/usr/local/pkgs/weblint-1.017</tt>. </p>
- <dt> <strong>-n</strong>
- <dd>
- <p> List actions but do not perform them. Implies
- the very verbose option. Does not require
- superuser privileges regardless of the value of
- <strong>SUPERUSER</strong> in the <tt>Makefile</tt>. </p>
- <dt> <strong>-v</strong>
- <dd>
- <p> Be verbose. </p>
- <dt> <strong>-V</strong>
- <dd>
- <p> Be very verbose. </p>
- <dt> <strong>-r <em>/rootdir</em></strong>
- <dd>
- <p> Use the fully qualified named directory as the
- root directory for all graft operations. The source
- directory, target directory and log file will all
- be relative to this specific directory. </p>
- <p> Can only be used by the superuser. </p>
- <dt> <strong>-s</strong>
- <dd>
- <p> <em>Stow</em>/<em>Depot</em> compatibility mode.
- Infer the <em>Graft</em> target directory from
- each package installation directory in the
- manner of <em>Stow</em> and <em>Depot</em>. </p>
- <p> Target directory is the <tt>dirname</tt> of the
- <tt>dirname</tt> of the package installation
- directory. (Yes that really is two
- <tt>dirname</tt>s). So if the package
- installation directory is </p>
- <pre>
- /usr/local/depot/gzip-1.2.4
- </pre>
- <p> the package will be <em>grafted</em> into
- </p>
- <pre>
- /usr/local
- </pre>
- <p> Cannot be used with the <strong>-t</strong> option. </p>
- <dt> <strong>-t <em>target</em></strong>
- <dd>
- <p> Override the default <em>graft</em> target
- directory with <strong><em>target</em></strong>. The value
- of <strong><em>target</em></strong> must be a fully
- qualified directory and it must exist. </p>
- <p> Cannot be used with the <strong>-s</strong> option. </p>
- <dt> <strong>package</strong>
- <dd>
- <p> Prune the named package. If <strong>package</strong> is
- a fully qualified directory, use it as the
- package installation directory. If
- <strong>package</strong> is not a fully qualified
- directory, prepend it with the value of
- <strong>PACKAGEDIR</strong> as specified in the
- <tt>Makefile</tt>. </p>
- </dl>
- <li> <p> <a name="graft-L"><strong>Information</strong></a> </p>
- <pre>
- graft -L
- </pre>
- <dl>
- <dt> <strong>-L</strong>
- <dd>
- <p> This is a special mode and it overrides all
- other command line arguments. When present
- <strong>graft</strong> will display the
- <strong>default</strong> locations for Perl, the
- graft log file, the target directory, and the
- package directory in a form suitable for creating
- environment variables for Bourne like shells. The
- output will appear on <strong>STDOUT</strong> as
- follows: </p>
- <pre>
- GRAFT_PERL=/usr/bin/perl
- GRAFT_LOGFILE=/var/log/graft
- GRAFT_TARGETDIR=/usr/local
- GRAFT_PACKAGEDIR=/usr/local/pkgs
- </pre>
- <p> You can set these environment variables using
- one of the following methods. </p>
- <pre>
- eval "$(graft -L)" # modern shells such as bash, zsh etc
- eval "`graft -L`" # older shells such as sh etc
- </pre>
- </dl>
- </ol>
- <hr width="25%">
- <h3><a name="testing">Testing the <em>Graft</em> Installation</a></h3>
- <p> Before creating the symbolic links from the target directory to
- the package directory, you may wish to see what actions <em>Graft</em>
- will perform. Execute the following command: </p>
- <pre>
- graft -i -n <em>package-name</em>
- </pre>
- <p> The <tt>-i</tt> option tells <em>Graft</em> to install the package and
- the <tt>-n</tt> option tells <em>Graft</em> to report on its actions
- without actually performing them. The default <em>Graft</em> target
- directory will be used and the package installation directory will be
- taken from the fully qualified package argument or the default value
- will be prepended to the package argument if it is not fully qualified.
- </p>
- <p> <em>Graft</em> will report on the following actions: </p>
- <ul>
- <li> <p> Installing links to <em>package-location</em> in
- <em>package-target</em> </p>
- <p> Indicates the real package location and its <em>grafted</em>
- target. </p>
- <li> <p> Processing <em>package-directory</em> </p>
- <p> Indicates which package directory is being processed. </p>
- <li> <p> MKDIR <em>dirname</em> </p>
- <p> This destination directory will be created. </p>
- <li> <p> SYMLINK <em>dest-package-file</em> -> <em>package-file</em>
- </p>
- <p> This symbolic link will be created. </p>
- <li> <p> NOP <em>string</em> </p>
- <p> No action was necessary for this package object. </p>
- <li> <p> BYPASS <em>dirname</em> - .nograft file found</p>
- <p> This directory contains a file called <tt>.nograft</tt> so its
- contents and any subdirectories will be bypassed by
- <em>Graft</em>. </p>
- <li> <p> READING include file
- <em>package-dir</em><tt>/.graft-include</tt> </p>
- <p> The directory currently being processed by <em>Graft</em>
- contains a file called <tt>.graft-include</tt> which contains
- a list of file and/or directory names from the directory that
- should only be <em>grafted</em>. The contents of this file are
- being read by <em>Graft</em>. </p>
- <li> <p> INCLUDE file <em>package-file</em> - listed in
- <em>package-dir</em><tt>/.graft-include</tt> </p>
- <p> The file name mentioned in this message appears in the
- <em>.graft-include</em> file and the file exists in the directory
- currently being processed. It will be <tt>grafted</tt>. </p>
- <li> <p> IGNORE file <em>package-file</em> - not listed in
- <em>package-dir</em><tt>/.graft-include</tt> </p>
- <p> The file name mentioned in this message does not appear in the
- <em>.graft-include</em> file and the file exists in the directory
- currently being processed. It will not be <tt>grafted</tt>. </p>
- <li> <p> INCLUDE directory <em>package-directory</em> - listed in
- <em>package-dir</em><tt>/.graft-include</tt> </p>
- <p> The directory name mentioned in this message appears
- in the <em>.graft-include</em> file and the directory exists
- in the directory currently being processed. It will be
- <tt>grafted</tt>. </p>
- <li> <p> IGNORE directory <em>package-file</em> - not listed in
- <em>package-dir</em><tt>/.graft-include</tt> </p>
- <p> The directory name mentioned in this message does not
- appear in the <em>.graft-include</em> file and the directory
- exists in the directory currently being processed. It will not
- be <tt>grafted</tt>. </p>
- <li> <p> READING exclude file
- <em>package-dir</em><tt>/.graft-exclude</tt> </p>
- <p> The directory currently being processed by <em>Graft</em>
- contains a file called <tt>.graft-exclude</tt> which contains
- a list of file and/or directory names from the directory that
- should not be <em>grafted</em>. The contents of this file are
- being read by <em>Graft</em>. </p>
- <li> <p> IGNORE include file
- <em>package-dir</em><tt>/.graft-include</tt>, overridden by exclude
- file <em>package-dir</em><tt>/.graft-exclude</tt> </p>
- <p> The directory currently being processed by <em>Graft</em>
- contains a file called <tt>.graft-exclude</tt> as well as a file
- called <tt>.graft-include</tt>. The <tt>.graft-exclude</tt>
- file takes precedence over the <tt>.graft-include</tt> file,
- so the latter file will be ignored. </p>
- <li> <p> EXCLUDE file <em>package-file</em> - listed in
- <em>package-dir</em><tt>/.graft-exclude</tt> </p>
- <p> The file name mentioned in this message appears in the
- <em>.graft-exclude</em> file and the file exists in the directory
- currently being processed. It will not be <tt>grafted</tt>. </p>
- <li> <p> EXCLUDE directory <em>package-directory</em> - listed in
- <em>package-dir</em><tt>/.graft-exclude</tt> </p>
- <p> The directory name mentioned in this message appears
- in the <em>.graft-exclude</em> file and the directory exists
- in the directory currently being processed. It will not be
- <tt>grafted</tt>. </p>
- <li> <p> CONFLICT <em>message</em> </p>
- <p> <em>Graft</em> could not successfully process a package object.
- One of the following conditions was encountered: </p>
- <ul>
- <li> The package object is a directory and the
- target object exists but it not a directory.
- <li> The package object is not a directory and the
- target object exists and is not a symbolic
- link.
- <li> The package object is not a directory and the
- target object exists and is a symbolic link to
- something other than the package object.
- </ul>
- <p> Conflicts are ALWAYS reported on standard error. If you wish
- to see if the installation of a package will have any
- conflicts, you can execute: </p>
- <pre>
- graft -i -n <em>package-name</em> > /dev/null
- </pre>
- <p> Only <tt>CONFLICT</tt> messages will be displayed. If nothing
- is displayed then you can safely conclude that this package
- can be installed using <em>Graft</em> without any conflicts.
- </p>
- </ul>
- <p> If you were to test the installation of the <em>kermit-5A190</em>
- package you would execute the command: </p>
- <pre>
- graft -i -n kermit-5A190
- </pre>
- You should see output resembling:
- <pre>
- Installing links to /usr/local/pkgs/kermit-5A190 in /usr/local
- Processing /usr/local/pkgs/kermit-5A190
- SYMLINK /usr/local/README -> /usr/local/pkgs/kermit-5A190/README
- NOP /usr/local/pkgs/kermit-5A190/bin and /usr/local/bin are both directories
- Processing /usr/local/pkgs/kermit-5A190/bin
- SYMLINK /usr/local/bin/kermit -> /usr/local/pkgs/kermit-5A190/bin/kermit
- SYMLINK /usr/local/bin/wart -> /usr/local/pkgs/kermit-5A190/bin/wart
- NOP /usr/local/pkgs/kermit-5A190/man and /usr/local/man are both directories
- Processing /usr/local/pkgs/kermit-5A190/man
- NOP /usr/local/pkgs/kermit-5A190/man/man1 and /usr/local/man/man1 are both directories
- Processing /usr/local/pkgs/kermit-5A190/man/man1
- SYMLINK /usr/local/man/man1/kermit.1 -> /usr/local/pkgs/kermit-5A190/man/man1/kermit.1
- MKDIR /usr/local/doc
- Processing /usr/local/pkgs/kermit-5A190/doc
- SYMLINK /usr/local/doc/ckccfg.doc -> /usr/local/pkgs/kermit-5A190/doc/ckccfg.doc
- SYMLINK /usr/local/doc/ckuins.doc -> /usr/local/pkgs/kermit-5A190/doc/ckuins.doc
- SYMLINK /usr/local/doc/ckc190.upd -> /usr/local/pkgs/kermit-5A190/doc/ckc190.upd
- SYMLINK /usr/local/doc/ckcker.upd -> /usr/local/pkgs/kermit-5A190/doc/ckcker.upd
- SYMLINK /usr/local/doc/ckaaaa.hlp -> /usr/local/pkgs/kermit-5A190/doc/ckaaaa.hlp
- SYMLINK /usr/local/doc/ckuaaa.hlp -> /usr/local/pkgs/kermit-5A190/doc/ckuaaa.hlp
- NOP /usr/local/pkgs/kermit-5A190/lib and /usr/local/lib are both directories
- Processing /usr/local/pkgs/kermit-5A190/lib
- SYMLINK /usr/local/lib/ckedemo.ini -> /usr/local/pkgs/kermit-5A190/lib/ckedemo.ini
- SYMLINK /usr/local/lib/ckeracu.ini -> /usr/local/pkgs/kermit-5A190/lib/ckeracu.ini
- SYMLINK /usr/local/lib/ckermit.ini -> /usr/local/pkgs/kermit-5A190/lib/ckermit.ini
- SYMLINK /usr/local/lib/ckermod.ini -> /usr/local/pkgs/kermit-5A190/lib/ckermod.ini
- SYMLINK /usr/local/lib/cketest.ini -> /usr/local/pkgs/kermit-5A190/lib/cketest.ini
- SYMLINK /usr/local/lib/ckevt.ini -> /usr/local/pkgs/kermit-5A190/lib/ckevt.ini
- SYMLINK /usr/local/lib/ckurzsz.ini -> /usr/local/pkgs/kermit-5A190/lib/ckurzsz.ini
- </pre>
- <p> This output shows you that most of the directories already exist
- (indicated by the <tt>NOP</tt> flags). A symbolic link will be created
- in the relevant target directory to each of the files in the
- <em>kermit-5A190</em> package. One directory exists in the
- <em>kermit-5A190</em> package that does not exist in the target -
- <tt>doc</tt>. This directory will be created by <em>Graft</em>. </p>
- <p> <strong>NOTE</strong>: If you are using the <em>automounter</em> you may not be
- able to create the directory <tt>/usr/local/doc</tt>. You'll have to create
- the directory on the NFS server under the file system in which it
- really lives. You should be familiar with the peculiarities of the
- <em>automounter</em> and your specific site configuration before creating
- any directories directly under mount points used by the
- <em>automounter</em>. </p>
- <hr width="25%">
- <h3><a name="installing-packages">Installing Packages</a></h3>
- <p> Once you have ensured that <em>Graft</em> will perform the correct
- actions, you can execute: </p>
- <pre>
- graft -i <em>package-name</em>
- </pre>
- <p> So to install <em>kermit</em> you would execute: </p>
- <pre>
- graft -i kermit-5A190
- </pre>
- <p> There will be no output from <em>Graft</em> unless it encounters a
- conflict. If you wish to see more information you can specify one of
- the verbose flags. For a minimum of output you can execute: </p>
- <pre>
- graft -i -v kermit-5A190
- </pre>
- <p> You should see the following output: </p>
- <pre>
- Processing /usr/local/pkgs/kermit-5A190
- Processing /usr/local/pkgs/kermit-5A190/bin
- Processing /usr/local/pkgs/kermit-5A190/man
- Processing /usr/local/pkgs/kermit-5A190/man/man1
- Processing /usr/local/pkgs/kermit-5A190/doc
- Processing /usr/local/pkgs/kermit-5A190/lib
- </pre>
- <p> If you choose the very verbose option by executing: </p>
- <pre>
- graft -i -V kermit-5A190
- </pre>
- <p> the output will be the same as that when the <tt>-n</tt> option was
- used, however this time <em>Graft</em> will actually create the symbolic
- links. </p>
- <pre>
- Installing links to /usr/local/pkgs/kermit-5A190 in /usr/local
- Processing /usr/local/pkgs/kermit-5A190
- SYMLINK /usr/local/README -> /usr/local/pkgs/kermit-5A190/README
- NOP /usr/local/pkgs/kermit-5A190/bin and /usr/local/bin are both directories
- Processing /usr/local/pkgs/kermit-5A190/bin
- SYMLINK /usr/local/bin/kermit -> /usr/local/pkgs/kermit-5A190/bin/kermit
- SYMLINK /usr/local/bin/wart -> /usr/local/pkgs/kermit-5A190/bin/wart
- NOP /usr/local/pkgs/kermit-5A190/man and /usr/local/man are both directories
- Processing /usr/local/pkgs/kermit-5A190/man
- NOP /usr/local/pkgs/kermit-5A190/man/man1 and /usr/local/man/man1 are both directories
- Processing /usr/local/pkgs/kermit-5A190/man/man1
- SYMLINK /usr/local/man/man1/kermit.1 -> /usr/local/pkgs/kermit-5A190/man/man1/kermit.1
- NOP /usr/local/pkgs/kermit-5A190/doc and /usr/local/doc are both directories
- Processing /usr/local/pkgs/kermit-5A190/doc
- SYMLINK /usr/local/doc/ckccfg.doc -> /usr/local/pkgs/kermit-5A190/doc/ckccfg.doc
- SYMLINK /usr/local/doc/ckuins.doc -> /usr/local/pkgs/kermit-5A190/doc/ckuins.doc
- SYMLINK /usr/local/doc/ckc190.upd -> /usr/local/pkgs/kermit-5A190/doc/ckc190.upd
- SYMLINK /usr/local/doc/ckcker.upd -> /usr/local/pkgs/kermit-5A190/doc/ckcker.upd
- SYMLINK /usr/local/doc/ckaaaa.hlp -> /usr/local/pkgs/kermit-5A190/doc/ckaaaa.hlp
- SYMLINK /usr/local/doc/ckuaaa.hlp -> /usr/local/pkgs/kermit-5A190/doc/ckuaaa.hlp
- NOP /usr/local/pkgs/kermit-5A190/lib and /usr/local/lib are both directories
- Processing /usr/local/pkgs/kermit-5A190/lib
- SYMLINK /usr/local/lib/ckedemo.ini -> /usr/local/pkgs/kermit-5A190/lib/ckedemo.ini
- SYMLINK /usr/local/lib/ckeracu.ini -> /usr/local/pkgs/kermit-5A190/lib/ckeracu.ini
- SYMLINK /usr/local/lib/ckermit.ini -> /usr/local/pkgs/kermit-5A190/lib/ckermit.ini
- SYMLINK /usr/local/lib/ckermod.ini -> /usr/local/pkgs/kermit-5A190/lib/ckermod.ini
- SYMLINK /usr/local/lib/cketest.ini -> /usr/local/pkgs/kermit-5A190/lib/cketest.ini
- SYMLINK /usr/local/lib/ckevt.ini -> /usr/local/pkgs/kermit-5A190/lib/ckevt.ini
- SYMLINK /usr/local/lib/ckurzsz.ini -> /usr/local/pkgs/kermit-5A190/lib/ckurzsz.ini
- </pre>
- <p> <strong>NOTE</strong>: In this case the <tt>/usr/local/doc</tt> directory was not
- created by <em>Graft</em> because <tt>/usr/local</tt> is a mount point
- controlled by the <em>automounter</em>. The <tt>doc</tt> directory was
- created manually prior to executing <em>Graft</em>. </p>
- <hr width="25%">
- <h3><a name="bypass">Bypassing package directories</a></h3>
- <p> You may have the need to place only part of a package under the control
- of <em>Graft</em>. Examples of such occasions may be: </p>
- <ul>
- <li> <p> The contents of one package conflict with another package.
- For example <tt>/usr/local/pkgs/gcc-2.7.2.1/lib/libiberty.a</tt> and
- <tt>/usr/local/pkgs/gdb-4.16/lib/libiberty.a</tt>. </p>
- <li> <p> A package directory is obviously the exclusive domain of
- the package and no benefit will be gained by creating symbolic
- links to its files. For example
- <tt>/usr/local/pkgs/perl-5.18.2/lib/perl5</tt>. </p>
- <p> <strong>NOTE</strong>: This will ONLY work if you originally compiled and
- installed the package such that it refers to its files by their
- '<em>real</em>' pathnames and NOT by the virtual pathnames
- provided by <em>Graft</em>. </p>
- </ul>
- <p> You can force <em>Graft</em> to bypass a directory by creating the file </p>
- <pre>
- <em>package-name/dir/dir/</em>.nograft
- </pre>
- <p> Using the second example above, if you were to create the file: </p>
- <pre>
- /usr/local/pkgs/perl-5.18.2/lib/perl5/.nograft
- </pre>
- <p> <em>Graft</em> would create directories and symbolic links for every file
- and directory down to <tt>/usr/local/pkgs/perl-5.18.2/lib</tt>. The <tt>perl5</tt>
- directory and anything below it would not be created. </p>
- <hr width="25%">
- <h3><a name="include">Including specific files and/or directories</a></h3>
- <p> There may be the occasional need to include specific files and/or
- directories in a directory, rather than the entire directory tree itself. An
- example of such an occurrence would be the case where a package
- contains a number of subdirectories, only one of which is required to
- be <em>grafted</em>. </p>
- <p> You can force <em>Graft</em> to only include any number of files and/or
- directories in a package directory by creating the file </p>
- <pre>
- .graft-include
- </pre>
- <p> in the same directory. </p>
- <p> <tt>.graft-include</tt> will contain a list of file and/or directory names
- - one per line - of the files and/or directories you wish to include. </p>
- <p> Consider the <em>a2ps</em> package for example. When installed it
- contains the following directories: </p>
- <pre>
- /usr/local/pkgs/a2ps-4.13b/bin
- /usr/local/pkgs/a2ps-4.13b/etc
- /usr/local/pkgs/a2ps-4.13b/include
- /usr/local/pkgs/a2ps-4.13b/info
- /usr/local/pkgs/a2ps-4.13b/lib
- /usr/local/pkgs/a2ps-4.13b/man
- /usr/local/pkgs/a2ps-4.13b/share
- </pre>
- <p> The only directory you wish to <em>graft</em> is the <tt>bin</tt>
- directory. You could place a <tt>.nograft</tt> file in each of the other
- directories, <strong>OR</strong> you could create a single <tt>.graft-include</tt>
- file in <tt>/usr/local/pkgs/a2ps-4.13b/.graft-include</tt>. This file would
- contain </p>
- <pre>
- bin
- </pre>
- <p> Now only the <tt>bin</tt> directory will be <em>grafted</em>. </p>
- <hr width="25%">
- <h3><a name="exclude">Excluding specific files and/or directories</a></h3>
- <p> There may be the occasional need to exclude specific files and/or
- directories from a directory, rather than the entire directory itself. An
- example of such an occurrence would be the case where files from different
- packages have the same name. <em>Emacs</em> and <em>Xemacs</em> use the same
- names for a number of their configuration files for example. </p>
- <p> You can force <em>Graft</em> to exclude any number of files and/or
- directories from a package directory by creating the file </p>
- <pre>
- .graft-exclude
- </pre>
- <p> in the same directory. </p>
- <p> <tt>.graft-exclude</tt> will contain a list of file and/or directory names
- - one per line - of the files and/or directories you wish to exclude. </p>
- <p> For example, if you did not wish the file </p>
- <pre>
- /usr/local/pkgs/sudo-1.5.3/etc/sudoers
- </pre>
- <p> to be <em>grafted</em> as </p>
- <pre>
- /usr/local/etc/sudoers
- </pre>
- <p> but you did want </p>
- <pre>
- /usr/local/pkgs/sudo-1.5.3/etc/visudo
- </pre>
- <p> to be <em>grafted</em> as </p>
- <pre>
- /usr/local/etc/visudo
- </pre>
- <p> you would create the file </p>
- <pre>
- /usr/local/pkgs/sudo-1.5.3/etc/.graft-exclude
- </pre>
- <p> and ensure its contents contained the line: </p>
- <pre>
- sudoers
- </pre>
- <p> <strong>NOTE:</strong> Any entries made in a <tt>.graft-exclude</tt> file will
- override the same entries made in a <tt>.graft-include</tt> file. That is,
- if a file or directory name is listen in both a <tt>.graft-exclude</tt>
- and a <tt>.graft-include</tt> file, it will be <strong>excluded</strong> from the
- <em>graft</em>. </p>
- <hr width="25%">
- <h3><a name="config_dirs">Grafting configuration files</a></h3>
- <p> Beginning with <em>Graft</em> 2.11 there is now the ability to treat a
- package directory as a repository for configuration files. In this case you
- would place a <tt>.graft-config</tt> file in the package directory and any
- files in that directory would be <strong>copied</strong> to the target
- directory. Files in conflict would also be copied but would have a default
- suffix of <em>.new</em> to ensure the existing file is not clobbered.
- Conflict discovery is achieved using a simple 32-bit CRC check. This
- feature has been added to assist operating system distributors manage
- system configuration files, specifically it was added at the request of the
- maintainer of the <a href="http://www.dragora.org/">Dragora GNU/Linux</a>
- distribution. </p>
- <p> Consider the following example. You may wish to upgrade the
- <em>openssh</em> server as part of an upgrade to your distribution. In
- order to preserve any local user modifications to the relevant
- configuration files you would add a <tt>.graft-config</tt> file to the
- package as follows: </p>
- <pre>
- /usr/local/pkgs/openssh-server-6.61/etc/default/.graft-config
- /usr/local/pkgs/openssh-server-6.61/etc/init.d/.graft-config
- /usr/local/pkgs/openssh-server-6.61/etc/init/.graft-config
- /usr/local/pkgs/openssh-server-6.61/etc/network/if-up.d/.graft-config
- /usr/local/pkgs/openssh-server-6.61/etc/pam.d/.graft-config
- /usr/local/pkgs/openssh-server-6.61/etc/ufw/applications.d/.graft-config
- /usr/local/pkgs/openssh-server-6.61/lib/systemd/system/.graft-config
- </pre>
- <p> The other directories in the distribution would not require any control
- files. </p>
- <p> Imagine that the local administrator has made some changes to
- <tt>/etc/pam.d/sshd</tt> such as adding additional authentication methods
- to support two-factor authentication for example. As the distribution
- maintainer you do not want to reverse this local change so when the local
- administrator upgrades the distribution, <em>Graft</em>
- <strong>copies</strong> the new <tt>/etc/pam.d/sshd</tt> file to
- <tt>/etc/pam.d/sshd.new</tt> which allows the local administrator to merge
- their changes with any new features supported by the upgrade. </p>
- <p> To take full advantage of this feature you may need to explicitly set the
- target directory as follows: </p>
- <pre>
- graft -i -t / openssh-server-6.61
- </pre>
- <hr width="25%">
- <h3><a name="partial-graft">Grafting part of a package</a></h3>
- <p> Some packages can be successfully used when only part of their
- installation directory is <em>grafted</em>. Other packages are
- recalcitrant and need some special hand holding which can only be
- solved by <em>grafting</em> each section of the package separately. </p>
- <p> The first scenario can be handled by either <tt>.nograft</tt> files or
- partial <em>grafts</em>. Consider <em>Perl</em> version <em>5.18.2</em>.
- When installed in its own directory </p>
- <pre>
- /usr/local/pkgs/perl-5.18.2
- </pre>
- <p> there are three subdirectories </p>
- <pre>
- drwxr-sr-x 2 psamuel bisg 512 Oct 30 1996 bin
- drwxr-sr-x 3 psamuel bisg 512 Oct 30 1996 lib
- drwxr-sr-x 4 psamuel bisg 512 Oct 30 1996 man
- </pre>
- <p> Everything in the <tt>lib</tt> directory is exclusive to <em>Perl</em>
- and does not require <em>grafting</em>. Therefore, <em>perl-5.18.2</em> can
- be <em>grafted</em> using either of the following two methods: </p>
- <pre>
- touch /usr/local/pkgs/perl-5.18.2/lib/.nograft
- graft -i perl-5.18.2
- </pre>
- or
- <pre>
- graft -it /usr/local/bin perl-5.18.2/bin
- graft -it /usr/local/man perl-5.18.2/man
- </pre>
- <p> Now let's consider a recalcitrant package - <em>ObjectStore</em> version
- 4.0.2.a.0. When installed in </p>
- <pre>
- /usr/local/pkgs/ostore-4.0.2.a.0
- </pre>
- <p> the following files and directories are available: </p>
- <pre>
- -rwxrwxr-x 1 pauln one3 1089 Oct 31 1996 Copyright
- drwxrwxrwx 8 pauln one3 512 Oct 2 1996 common
- drwxrwxrwx 6 pauln one3 512 Oct 31 1996 sunpro
- -rw-r----- 1 root one3 1900544 Apr 29 1997 txn.log
- </pre>
- <p> The executable programs that need to be <em>grafted</em> are in
- <tt>sunpro/bin</tt> and the manual pages that need to be <em>grafted</em>
- are in <tt>common/man</tt>. Everything else in the package does not
- need to be <em>grafted</em>. If the entire package was to be
- <em>grafted</em> the result would be two directories that are not in the
- regular <strong>$PATH</strong> and <strong>$MANPATH</strong> environment variables - namely
- <tt>/usr/local/common/man</tt> and <tt>/usr/local/sunpro/bin</tt>, plus a host of
- other directories that are not relevant for <em>grafting</em>. No amount
- of <tt>.nograft</tt> and <tt>.graft-exclude</tt> juggling will solve
- this problem. </p>
- <p> The solution is to use two partial <em>grafts</em>: </p>
- <pre>
- graft -it /usr/local/bin ostore-4.0.2.a.0/sunpro/bin
- graft -it /usr/local/man ostore-4.0.2.a.0/common/bin
- </pre>
- <p> Using this approach, the correct executables and manual pages are
- available without the need to <em>graft</em> unnecessary files and
- directories. </p>
- <hr width="25%">
- <h3><a name="deleting-packages">Deleting and/or Upgrading
- Packages</a></h3>
- <p> If you wish to upgrade a package - let's assume you wish to upgrade
- <em>kermit</em> from version 5A190 to version 6.0.192 - you'd follow
- these steps. </p>
- <p> Firstly, you'd compile and install <em>kermit-6.0.192</em> in </p>
- <pre>
- /usr/local/pkgs/kermit-6.0.192
- </pre>
- <p> Once you'd tested it to your satisfaction, you'd need to delete the
- symbolic links to the current <em>grafted</em> version. You can check
- which actions <em>Graft</em> will perform by executing: </p>
- <pre>
- graft -d -n kermit-5A190
- </pre>
- <p> You'll see output similar to </p>
- <pre>
- Uninstalling links from /usr/local to /usr/local/pkgs/kermit-5A190
- Processing /usr/local/pkgs/kermit-5A190
- Processing /usr/local/pkgs/kermit-5A190/bin
- UNLINK /usr/local/bin/kermit
- UNLINK /usr/local/bin/wart
- Processing /usr/local/pkgs/kermit-5A190/man
- Processing /usr/local/pkgs/kermit-5A190/man/man1
- UNLINK /usr/local/man/man1/kermit.1
- Processing /usr/local/pkgs/kermit-5A190/doc
- UNLINK /usr/local/doc/ckccfg.doc
- UNLINK /usr/local/doc/ckuins.doc
- UNLINK /usr/local/doc/ckc190.upd
- UNLINK /usr/local/doc/ckcker.upd
- UNLINK /usr/local/doc/ckaaaa.hlp
- UNLINK /usr/local/doc/ckuaaa.hlp
- Processing /usr/local/pkgs/kermit-5A190/lib
- UNLINK /usr/local/lib/ckedemo.ini
- UNLINK /usr/local/lib/ckeracu.ini
- UNLINK /usr/local/lib/ckermit.ini
- UNLINK /usr/local/lib/ckermod.ini
- UNLINK /usr/local/lib/cketest.ini
- UNLINK /usr/local/lib/ckevt.ini
- UNLINK /usr/local/lib/ckurzsz.ini
- UNLINK /usr/local/lib/.testing
- </pre>
- <p> If you're happy with the output from the test deletion you can delete
- the <em>grafted</em> package. Once again, you'll only see output if a
- failure occurs unless you use one of the verbose options. </p>
- <p> If you execute: </p>
- <pre>
- graft -dV kermit-5A190
- </pre>
- <p> you'll see: </p>
- <pre>
- Uninstalling links from /usr/local to /usr/local/pkgs/kermit-5A190
- Processing /usr/local/pkgs/kermit-5A190
- Processing /usr/local/pkgs/kermit-5A190/bin
- UNLINK /usr/local/bin/kermit
- UNLINK /usr/local/bin/wart
- Processing /usr/local/pkgs/kermit-5A190/man
- Processing /usr/local/pkgs/kermit-5A190/man/man1
- UNLINK /usr/local/man/man1/kermit.1
- Processing /usr/local/pkgs/kermit-5A190/doc
- UNLINK /usr/local/doc/ckccfg.doc
- UNLINK /usr/local/doc/ckuins.doc
- UNLINK /usr/local/doc/ckc190.upd
- UNLINK /usr/local/doc/ckcker.upd
- UNLINK /usr/local/doc/ckaaaa.hlp
- UNLINK /usr/local/doc/ckuaaa.hlp
- EMPTY /usr/local/doc is now empty. Delete manually if necessary.
- Processing /usr/local/pkgs/kermit-5A190/lib
- UNLINK /usr/local/lib/ckedemo.ini
- UNLINK /usr/local/lib/ckeracu.ini
- UNLINK /usr/local/lib/ckermit.ini
- UNLINK /usr/local/lib/ckermod.ini
- UNLINK /usr/local/lib/cketest.ini
- UNLINK /usr/local/lib/ckevt.ini
- UNLINK /usr/local/lib/ckurzsz.ini
- </pre>
- <p> <strong>NOTE</strong>: In this case the existence of an empty directory has been
- discovered. If <em>Graft</em> empties a directory during a package
- deletion, it will either notify you or delete the directory depending
- on the combination of variables in the <tt>Makefile</tt> and command
- line options. It's probably better practise not to automatically
- delete empty directories as they may be used by other packages - such
- as lock file directories for example. </p>
- <p> Now you can remove the <em>real</em> package contents. (You may not wish
- to do this immediately as some legacy systems may depend on features
- provided by the older version or you may feel the need for further
- testing before feeling confident that the old version can be removed):
- </p>
- <pre>
- rm -rf /usr/local/pkgs/kermit-5A190
- </pre>
- <p> Now you can <em>graft</em> the new version of <em>kermit</em>. Execute: </p>
- <pre>
- graft -i -n kermit-6.0.192
- </pre>
- <p> to ensure that the <em>grafting</em> will proceed without error. Once
- you are satisfied that this is the case you can <em>graft</em> the new
- package by executing: </p>
- <pre>
- graft -i kermit-6.0.192
- </pre>
- <hr width="25%">
- <h3><a name="transitioning">Transitioning a package to <em>Graft</em>
- control</a></h3>
- <p> <em>Graft</em> can be used to easily transition a package from its
- current installation in your target directory to a <em>grafted</em>
- installation. </p>
- <p> As an example, let's consider the package <em>weblint</em> version 1.017.
- It consists of three files installed in: </p>
- <pre>
- /usr/local/bin/weblint
- /usr/local/lib/global.weblintrc
- /usr/local/man/man1/weblint.1
- </pre>
- <p> The first step is to create a new copy of the package in its own
- directory: </p>
- <pre>
- /usr/local/pkgs/weblint-1.017
- </pre>
- <p> Ensure that any references to library files are now made to
- <tt>/usr/local/pkgs/weblint-1.017/lib</tt> instead of <tt>/usr/local/lib</tt>.
- </p>
- <p> Test the new installation to ensure it behaves as expected. </p>
- <p> Then prune the old files from <tt>/usr/local/*</tt> using: </p>
- <pre>
- graft -pV weblint-1.017
- </pre>
- <p> You'd expect to see output similar to: </p>
- <pre>
- Pruning files in /usr/local which conflict with /usr/local/pkgs/weblint-1.017
- Processing /usr/local/pkgs/weblint-1.017
- Processing /usr/local/pkgs/weblint-1.017/man
- Processing /usr/local/pkgs/weblint-1.017/man/man1
- RENAME /usr/local/man/man1/weblint.1
- Processing /usr/local/pkgs/weblint-1.017/bin
- RENAME /usr/local/bin/weblint
- Processing /usr/local/pkgs/weblint-1.017/lib
- RENAME /usr/local/lib/global.weblintrc
- </pre>
- <p> If you elected to delete conflicting files instead of renaming them
- you'd use: </p>
- <pre>
- graft -pDV weblint-1.017
- </pre>
- <p> and you'd see output similar to: </p>
- <pre>
- Pruning files in /usr/local which conflict with /usr/local/pkgs/weblint-1.017
- Processing /usr/local/pkgs/weblint-1.017
- Processing /usr/local/pkgs/weblint-1.017/man
- Processing /usr/local/pkgs/weblint-1.017/man/man1
- UNLINK /usr/local/man/man1/weblint.1
- Processing /usr/local/pkgs/weblint-1.017/bin
- UNLINK /usr/local/bin/weblint
- Processing /usr/local/pkgs/weblint-1.017/lib
- UNLINK /usr/local/lib/global.weblintrc
- </pre>
- <p> Now the new version of <em>weblint</em> 1.017 can be <em>grafted</em> in
- place: </p>
- <pre>
- graft -i weblint-1.017
- </pre>
- <p> The <em>grafted</em> version of <em>weblint</em> can now be tested. </p>
- <p> If we renamed conflicting files, they can be removed once the
- <em>grafted</em> <em>weblint</em> has been satisfactorily tested: </p>
- <pre>
- rm /usr/local/man/man1/weblint.1.pruned
- rm /usr/local/bin/weblint.pruned
- rm /usr/local/lib/global.weblintrc.pruned
- </pre>
- <hr width="25%">
- <h3><a name="conflicts">Conflict Processing</a></h3>
- <p> Occasionally <em>Graft</em> will fail to completely install a package. This
- occurs because <em>Graft</em> encounters a conflict. A conflict is defined as
- one of the following possibilities: </p>
- <center>
- <table summary="Conflcits" border=2 cellpadding=3>
- <tr>
- <th>
- Package Object
- </th>
- <th>
- Target Object
- </th>
- </tr>
- <tr>
- <td>
- directory
- </td>
- <td>
- not a directory
- </td>
- </tr>
- <tr>
- <td>
- file
- </td>
- <td>
- directory
- </td>
- </tr>
- <tr>
- <td>
- file
- </td>
- <td>
- file
- </td>
- </tr>
- <tr>
- <td>
- file
- </td>
- <td>
- symbolic link to something other than the package object
- </td>
- </tr>
- </table>
- </center>
- <p> If <em>Graft</em> encounters such a conflict during the installation of a
- package it will report the conflict and exit. </p>
- <p> Resolving the conflict depends on the nature of the conflict and is
- beyond the scope of this discussion - however most conflicts will
- either be the result of attempting to <em>graft</em> a package on top of
- the same package actually installed in the target directory or a file
- name clash between two (or more) different packages. </p>
- <p> Conflicts arising from the pre-existence of a package in the target
- directory can be resolved using <em>graft</em>'s prune mechanism
- described above in <a href="#transitioning">"Transitioning a
- package to <em>Graft</em> control"</a>. </p>
- <p> File name clash conflicts can be resolved by the use of either a
- <a href="#bypass"><tt>.nograft</tt></a> or
- <a href="#exclude"><tt>.graft-exclude</tt></a> file or by
- <em>grafting</em> only part of a package as described above in
- <a href="#partial-graft">"Grafting part of a package"</a>.
- </p>
- <p> If <em>Graft</em> encounters a conflict while deleting a package, it will
- report the conflict and continue deleting the remainder of the package.
- In this way <em>Graft</em> will delete as much of the package as
- possible. Conflicts that arise during deletion will probably be the
- result of an incorrectly installed package or the installation of other
- components of the same package without the use of <em>Graft</em>. </p>
- <p> Conflict messages are written to standard error. All other messages
- are written to standard output. To quickly determine if a package will
- have any conflicts when <em>grafted</em>, redirect standard output to
- <tt>/dev/null</tt> </p>
- <pre>
- graft -i -n <em>package</em> > /dev/null
- </pre>
- <p> If you don't see any output then you can safely assume that there will
- be no conflicts when <em>grafting</em> this package. </p>
- <p> See the comprehensive table above describing how
- <a href="#precedence">conflicts are handled</a> for more details. </p>
- <hr width="25%">
- <h3><a name="exitstatus">Exit Status</a></h3>
- <p> <em>Graft</em> will terminate with an exit status of either 0, 1, 2, 3 or 4
- under the following conditions: </p>
- <center>
- <table summary="Exit Status" border=2 cellpadding=3>
- <tr>
- <th>
- Exit Status
- </th>
- <th>
- Condition
- </th>
- </tr>
- <tr>
- <td>
- <center>
- <strong>0</strong>
- </center>
- </td>
- <td>
- All operations succeeded.
- </td>
- </tr>
- <tr>
- <td>
- <center>
- <strong>1</strong>
- </center>
- </td>
- <td>
- A conflict occurred during installation.
- </td>
- </tr>
- <tr>
- <td>
- <center>
- <strong>2</strong>
- </center>
- </td>
- <td>
- Command line syntax was incorrect.
- </td>
- </tr>
- <tr>
- <td>
- <center>
- <strong>3</strong>
- </center>
- </td>
- <td>
- One or more packages listed on the command line does not
- exist. Other valid packages listed on the command line were
- processed correctly.
- </td>
- </tr>
- <tr>
- <td>
- <center>
- <strong>4</strong>
- </center>
- </td>
- <td>
- The log file <tt>/var/log/graft</tt> could not be updated. Usually a
- result of a permission error. Any other error condition will
- override this condition.
- </td>
- </tr>
- </table>
- </center>
- <hr>
- <h2><a name="other-pkg-tools">Using <em>Graft</em> with other package
- management tools</a></h2>
- <p> Most Unix vendors have released their own package management tools with
- their operating systems. Examples of this are Solaris 2.<em>x</em> with its
- <em>SVR4 Package Manager</em> <tt>pkgadd</tt>, RedHat Linux with its
- <em>RedHat Package Manager</em> <tt>rpm</tt>, Ubuntu Linux (and other Debian
- Linux derivatives) with its <tt>dpkg</tt> system and HP-UX 10.<em>x</em> with
- its <tt>swinstall</tt> suite. <em>Graft</em> has been designed as an adjunct
- to these package managers rather than a competitor. The author has used
- <em>Graft</em> successfully with all of the operating systems mentioned here.
- </p>
- <ul>
- <li> <p> Many useful packages available in the public domain and from
- other commercial sources are not shipped with most flavours of
- Unix. <em>Graft</em> can be used to maintain a rich package
- environment beyond the set of packages provided by your vendor.
- Vendor based packages can still be maintained using the vendor's
- tools and <em>Graft</em> can be used to maintain your own packages.
- </p>
- <li> <p> The vendor based management tools are usually used to maintain
- single instances of a package on each machine. It is often
- difficult to have multiple versions of the same package coexisting
- on the same machine. <em>Graft</em> can be used to maintain multiple
- versions of a package to support legacy, production and development
- requirements simultaneously. </p>
- <li> <p> Another common problem with vendor supplied software is
- the speed at which upgrades are available. The large vendors are not
- known for providing quick fixes to many of their packages. (Notable
- exceptions to this are the vendors of operating systems based on
- open source software who can draw on the enormous number of users
- who submit patches because the source code is available). Using
- <em>Graft</em> you can obtain a working public domain version of
- a package (if one exists of course) and install it in a different
- location to the vendor copy. When the vendor releases a new version of
- the package, it can be installed using the vendor's package management
- tool and your <em>grafted</em> copy can be removed (only if the vendor's
- version of the package is better than the public domain version). </p>
- <li> <p> Sometimes, a vendor's package doesn't quite perform in the
- manner you'd like. It may be making assumptions about your file
- system(s) that are incorrect for your environment or it may not
- have all the features you'd like. If an alternative package is
- available - either in the public domain or from other commercial
- sources - it can be installed and <em>grafted</em> accordingly. </p>
- </ul>
- <hr>
- <h2><a name="availability">Availability</a></h2>
- <p> The latest version of <em>Graft</em> should always be available from: </p>
- <pre>
- <a href="http://peters.gormand.com.au/Home/tools/graft">http://peters.gormand.com.au/Home/tools/graft</a>
- </pre>
- <hr>
- <h2><a name="license">License</a></h2>
- <p> <em>Graft</em> is licensed under the terms of the GNU General Public
- License, Version 2, June 1991. </p>
- <p> You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA, or download
- it from the Free Software Foundation's web site: </p>
- <pre>
- <a href="http://www.gnu.org/copyleft/gpl.html">http://www.gnu.org/copyleft/gpl.html</a>
- <a href="http://www.gnu.org/copyleft/gpl.txt">http://www.gnu.org/copyleft/gpl.txt</a>
- </pre>
- <hr>
- </body>
- </html>
|