;;; This file contains the needed macro to make a page with debian packages. 
;;; Licence: GPL 
;;; Authors: Martin Quinson (idea, preliminary coding)
;;; Authors: Vincent Danjean (proper, clean coding ;)

;;;;;;;;;;;;;
;;; Interface
;;;;;;;;;;;;;

;;; <pkgdeb:summary debroot="debian" components="main">
;;;    Makes a list of packages with short desc, and link to
;;;    #<pkgname> based on Packages files content
;;; <pkgdeb:details debroot="debian" components="main">
;;;    Makes a list of subframe containing the description of each
;;;    package based on Packages and Sources files content.

;;; Both accept following args [default]:
;;;  debroot [debian]: root of the debian archive (like debian)
;;;  dists [*]: newline separted list of distibutions (sid,...)
;;;  archs [*]: newline separted list of archs (i386,all,... or *)
;;;  components [*]: newline separted list of components (main,... or *)
;;;  names []: newline separted list of packages names (toto,... 
;;;            or '' that means all packages)
;;;  sections [.*]: regexp for section names (net,... or '.*')


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Implementation
;;;;;;;;;;;;;;;;;;

#include <download.tag>

;;;
;;; pkgdeb:PackagesFilesList
;;; 
;;; generate a list of 'Packages' files (used to retrieve informations)
;;;
<define-tag pkgdeb:PackagesFilesList whitespace=delete endtag=none>
  <preserve debroot dists pkgdist archs pkgarch
    components pkgcomponent pkgPackages />
  <set-var %attributes />

  <defvar debroot "debian" />
  <defvar dists "*" />
  <defvar archs "*" />
  <defvar components "*" />

  <ifeq <get-var type /> flat
    <compound>
      <ifeq <get-var dist /> "*"
        <error "dist mandatory when using flat type" />
      />
      <foreach pkgdist dists>
        <get-var debroot />/<get-var pkgdist />/Packages
      </foreach>
    </compound>
    <compound>

      <foreach pkgdist dists>
        <foreach pkgcomponent components>
          <foreach pkgarch archs>
            <get-var debroot />/dists/<get-var pkgdist/>/<get-var pkgcomponent/>/binary-<get-var pkgarch />/Packages
          </foreach>
        </foreach>
      </foreach>
    </compound>
  />
  <restore debroot dists pkgdist archs pkgarch 
    components pkgcomponent pkgPackages />
</define-tag>

;;;
;;; pkgdeb:SourcesFilesList
;;;
;;; generate a list of 'Sources.gz' files (used to retrieve informations)
;;;
<define-tag pkgdeb:SourcesFilesList whitespace=delete endtag=none>
  <preserve debroot dists pkgdist components pkgcomponent type />
  <set-var %attributes />

  <defvar debroot "debian" />
  <defvar dists "*" />
  <defvar components "*" />
  <set-var res="" />
  <ifeq <get-var type /> flat
    <compound>
      <ifeq <get-var dist /> "*"
        <error "dist mandatory when using flat type" />
      />
      <foreach pkgdist dists>
        <set-var res="<get-var res /> <get-var debroot />/<get-var pkgdist />/Sources.gz" />
      </foreach>
    </compound>
    <compound>
      <foreach pkgdist dists>
        <foreach pkgcomponent components>
          <set-var res="<get-var res /> <get-var debroot />/dists/<get-var pkgdist/>/<get-var pkgcomponent />/source/Sources.gz" />
        </foreach>
      </foreach>
    </compound>
  />

  <get-var res />
  <restore debroot dists pkgdist components pkgcomponent type />
</define-tag>

;;;
;;; pkgdeb:srcPackagesNamesList
;;; 
;;; generate a list of package names to manage based on user's args
;;; and Packages files. 
;;;
;;; Warning, that's the source package names.
;;;
<define-tag pkgdeb:srcPackagesNamesList whitespace=delete endtag=none>
  <preserve debroot dists components files list />

  <set-var %attributes />
  <set-var files="<pkgdeb:SourcesFilesList debroot="<get-var debroot />" dists="<get-var dists />" components="<get-var components />" type="<get-var type />"  />" />
  <subst-in-var files "\n" " " /><subst-in-var files " +" " " />
  <set-var list="<include command="zcat <get-var files /> | grep-available -Pe -n -s Package . - | sort | uniq" />" />
  <subst-in-var list "\n$" "" />
  <get-var list />
  <restore debroot dists components files list />
</define-tag>

;;;
;;; pkgdeb:binaryOfSource
;;;
;;; Retrieve all the binary packages of a given source package
;;;
<define-tag pkgdeb:binaryOfSource whitespace=delete endtag=none>
  <preserve debroot dists components source files list />
  <set-var %attributes />
  
  <set-var files="<pkgdeb:SourcesFilesList debroot="<get-var debroot />" dists="<get-var dists />" components="<get-var components />" type="<get-var type />"  />" />
  <subst-in-var files "\n" " "  />

  <set-var list="<include command="zcat <get-var files /> | grep-available -Pe -n -s Binary <get-var source /> - |sed 's/, */\\n/g' |sort | uniq" />" />
  <subst-in-var list "\n$" "" />
  <get-var list />
  <restore debroot dists components source files list />
</define-tag>

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; main functions
;;;;;;;;;;;;;;;;;;

;;;
;;; pkgdeb:details
;;; 
;;; Makes a list of subframe containing the description of each package.

<define-tag pkgdeb:details endtag=none>
  <preserve pkgname names debroot pkgdesc pkgdist dists pkgarch archs pkgcomponent components Packages sections pkgsection i ligne pkgarchs pkgfilearch pkgfilename localPackages localSources pkgsource pkgsdir pkgsfiles />
  <set-var %attributes />
  
  <defvar dists "*" />
;;;  <warning "Do details">

  <set-var Packages=<pkgdeb:PackagesFilesList
                         debroot=<get-var debroot />
			 dists=<get-var dists />
			 archs=<get-var archs />
			 components=<get-var components />
			 type="<get-var type />" />  />
  <subst-in-var Packages "\n" " " />

  <set-var sources="<pkgdeb:srcPackagesNamesList 
                          debroot="<get-var debroot />" 
			  dists="<get-var dists />" 
			  components="<get-var components />"
			  type="<get-var type />" />" />

  <foreach src sources>
    <set-var names="<pkgdeb:binaryOfSource 
                             debroot="<get-var debroot />" 
 	   		     dists="<get-var dists />" 
			     components="<get-var components />"
			     source="<get-var src />" />"
    />
;;;    <warning "Handle <get-var src/> (<get-var names />)" />
    <subframe title="Package <get-var src />"  name="<get-var src />"
            note="<a href="#summary">back</a>">
      <foreach pkg names>
	<dl class="pkgdeb">
        <if <gt <array-size names /> 1 />
	  <compound>
            <dt>Binary package:</dt><dd> <get-var pkg /></dd>
	  </compound>
        />
  	  <dt>Description:</dt>
          <dd>
          <set-var pkgdesc=<include command="grep-available -P -X '<get-var pkg />' -n -s Description <get-var Packages /> 2>/dev/null|
	                                     sed -e 's/^ //'" /> />
          <span class="pkgdeb_shortdesc"><get-var pkgdesc[0] /></span>
	  <span class="pkgdeb_longdesc">
;;;	  <table border=0><tr><td>  </td><td><font size=-1>
	  <set-var para="" />
	  <set-var i=1 />
	  <while <lt <get-var i /> <array-size pkgdesc /> /> >
	     <set-var line=<get-var pkgdesc[<get-var i />] /> />
	     ;;; avoid to get the description twice
	     <ifeq "<get-var line />" "<get-var pkgdesc[0] />"
               <compound>
		 <break />
;;;		 <warning "Avoiding to display the description twice on pkg <get-var pkg />." />
;;;                 <warning "Remove '<get-var line />' and after" />
	       </compound>
	       <compound>
	       ;;; group paragraph together
	       <ifeq <get-var line /> "."
	         <compound> ;;; Got "." => Change paragraph
	           <ifneq <get-var para /> "" 
		     <compound>
	               <p><get-var para /></p>
		       <set-var para="" />
		     </compound>
		   />
	         </compound>
	         <compound> ;;; Got something else than WMLSEP => add to paragraph if !indented
	           <ifeq "<match <get-var line /> "^ " />" "true"
 	 	     <compound>
		       <preserve start end />
		         <set-var start="<match <get-var line /> "^ *" action=extract />" />
		         <set-var start="<subst-in-string <get-var start /> " " " " />" />
	                 <ifneq <get-var para /> "" 
		            <set-var start="<br /><get-var start />" />
	                 />
		         <set-var line="<get-var start /><subst-in-string <get-var line /> "^ *" /> " />
		       <restore start end />
		     </compound>
		   />
		   <set-var para="<get-var para /> <get-var line />" />
	         </compound>
	       />
	       </compound>
	     /> ;;; trick to get the description only once
          <increment i />
	  </while> ;;; foreach line in the description
          ;;; Display the last block of the description, if any
	  <ifneq <get-var para /> "" 
	     <compound>
	       <subst-in-var para "^ *Homepage: (.*[^ ]) *$" "Homepage: <a href="\\1">\\1</a>" singleline=false />
	       <p><get-var para /></p>
	     </compound>
	  />
;;;	  </font></td></tr></table>
	  </span>
          </dd>
          ;;; Partie download des binaires
          <foreach pkgdist dists>
            <set-var localPackages=<pkgdeb:PackagesFilesList
                                    debroot=<get-var debroot />
		    	            dists=<get-var pkgdist />
			            archs=<get-var archs />
			            components=<get-var components /> /> />
	    <subst-in-var localPackages "\n" " " />


            ;;; search all the arch for this binary on that dist
            <set-var pkgarchs=<include command="grep-available -P -X '<get-var pkg />' -n -s Architecture <get-var localPackages /> | sort | uniq" /> />
	    <foreach arch pkgarchs>
	      ;;; search the file names for this binary on that dist under this arch
	      <set-var files=<include command="grep-available -P -X '<get-var pkg />' <get-var localPackages /> | grep-dctrl -n -X -F Architecture '<get-var arch />' -s Filename  |sort | uniq" /> />
              ;;; output the result
	      <foreach file files>
	        <ifneq <get-var file /> ""
		  <compound>
                    <dt>Package for <get-var arch /><ifneq
  	              "*" <get-var pkgdist /> <group " " (<get-var pkgdist />) /> 
	            />:</dt><dd>
	            <download file="<get-var file />" dir="<get-var debroot />/" ext="" />
		    </dd>
		  </compound>
	        />
              </foreach> ;;; files
            </foreach> ;;; archs
	    
          </foreach> ;;; foreach dist
          </dl>
          <if <gt <array-size names /> 1 /> <hr /> />
      </foreach> ;;; foreach binary package
      
      ;;; Output the source package
      <dl class="pkgdebsrc">
      <foreach pkgdist dists>
        <dt>Source package<ifneq "*" <get-var pkgdist />
            <group " " (<get-var pkgdist />) />
        />:</dt><dd>
        <set-var localSources=<pkgdeb:SourcesFilesList
                                    debroot=<get-var debroot />
		 	            dists=<get-var pkgdist />
			            components=<get-var components />
				    type="<get-var type />" /> />
	<subst-in-var localSources "\n" " " />

        <set-var sources=<include command="zcat <get-var localSources /> | grep-available -P -X <get-var src /> -n -s Files - | sort -t _ -k 2 -r | uniq" /> />
        <set-var dir=<include command="zcat <get-var localSources /> | grep-available -P -X <get-var src /> -n -s Directory - |head -n 1" /> />
	<foreach file sources>
	  <subst-in-var file "^.*[^ ]  *[^ ]*  *([^ ]*)$" "\\1" />
;;;	  <warning "file=<get-var file />" />
	  <if <get-var file />
	    <download file="<get-var file />" dir="<get-var debroot />/<get-var dir />" />
	  />
	</foreach>
	</dd>
	;;; Output the patches, if any
	<foreach file sources>
	  <subst-in-var file "^.*[^ ]  *[^ ]*  *([^ ]*)$" "\\1" />
	  <if <match <get-var file /> "diff.gz" />
	    <compound>
	      <set-var file="<get-var debroot />/<get-var dir />/<get-var file />" />
	      <subst-in-var file "\n" ""  />
;;;	      <warning "diff=<get-var file />(dir=<get-var dir />)"  />
	      <set-var serie="<include command="filterdiff --remove-timestamps --strip=3 -z -i */debian/patches/series <get-var file /> | sed 's/^\+//'" />" />
              <if <gt <array-size serie /> 1 />
	        <compound>
		 <dt>Patches applied to the upstream tarball:</dt>
		 <dd>
		 <ul>
                 <array-shift serie -3 />
 	         <subst-in-var file "^ *$" "" singleline=false  />
		 <set-var out=<include command="rm -rf <get-var debroot/>/patches/<get-var src/>"/> />
		 <ifneq "<get-var out/>" "" <warning <get-var out /> /> />
		 <set-var out=<include command="mkdir -p <get-var debroot/>/patches/<get-var src/>"/> />
		 <ifneq "<get-var out/>" "" <warning <get-var out /> /> />
		 <foreach patchname serie>
  	           <subst-in-var patchname "#.*$" "" />
  	           <subst-in-var patchname " *" "" />
		   <ifneq <get-var patchname /> ""
		     <compound>
;;;		      <warning "file=<get-var patchname/> dir=<get-var debroot/>/patches/<get-var src/>" />
		      <li><download file="<get-var patchname/>" dir="<get-var debroot/>/patches/<get-var src/>" ext=""/>:
	              <set-var out=<include command="filterdiff --remove-timestamps --strip=3 -z -i */debian/patches/<get-var patchname/> <get-var file/> | sed 's/^\+//' | (read l; read l; read l; cat) > <get-var debroot/>/patches/<get-var src/>/<get-var patchname/>"/>/>
		      <ifneq "<get-var out/>" "" <warning <get-var out /> /> />
;;;		      <warning "look patch <get-var debroot/>/patches/<get-var src/>/<get-var patchname/>" />
		      <set-var patch=<include command="head -n 1 <get-var debroot/>/patches/<get-var src/>/<get-var patchname/>"/>/>
		      <if <match <get-var patch[0] /> "^%title" />
		        <compound>
			  <set-var title=<get-var patch[0] /> />
			  <subst-in-var title "%title " "" />
			  <get-var title />
			</compound>
			<compound>
			  (no description available)
			</compound>
		      />
		      </li>
                     </compound>
		   />
		 </foreach>
		 </ul>
                 </dd>
		</compound>
	      />
            </compound>
	  />
	</foreach> ;;; src file to extract the patches
      </foreach> ;;; dist
      </dl>
    </subframe>
  </foreach> ;;; foreach source package
  <restore pkgname names debroot pkgdesc pkgdist dists pkgarch archs pkgcomponent components Packages sections pkgsection i ligne pkgarchs pkgfilearch pkgfilename localPackages localSources pkgsource pkgsdir pkgsfiles />
</define-tag>

;;;
;;; pkgdeb:summary
;;; 
;;; Makes a list of packages with short desc, and link to #<pkgname>

<define-tag pkgdeb:summary endtag=none>
  <preserve pkgname pkgdesc debroot dists archs components names sections />
  <set-var %attributes />
  <defvar dists "*" />
 
;;;  <warning "Do summary" >
  <set-var Packages=<pkgdeb:PackagesFilesList
                         debroot=<get-var debroot />
			 dists=<get-var dists />
			 archs=<get-var archs />
			 components=<get-var components />
			 type="<get-var type />" />  />
  <subst-in-var Packages "\n" " " />
  
  <set-var sources="<pkgdeb:srcPackagesNamesList 
                          debroot="<get-var debroot />" 
			  dists="<get-var dists />" 
			  components="<get-var components />"
			  type="<get-var type />"  />"  />


  <foreach src sources>
    <b><a href="#<get-var src />"><get-var src /></a /></b />:
    <set-var bins="<pkgdeb:binaryOfSource 
                        debroot="<get-var debroot />" 
 	   		dists="<get-var dists />" 
			components="<get-var components />"
			source="<get-var src />" />"
    />
    <foreach pkg bins>
      <if <gt <array-size bins /> 1 />
	<compound>
          <br />  <b><get-var pkg /></b />:
	</compound>
      />
      <set-var pkgdesc=<include command="grep-available -P -X '<get-var pkg/>' -n -s Description <get-var Packages /> 2>/dev/null|sed 's/^ \\.$/<br />/'" /> />
      <get-var pkgdesc[0] />

    </foreach> ;;; binaries
    <br />
  </foreach> ;;; src

  <restore pkgname pkgdesc debroot dists archs components names sections />
</define-tag>