[Slapt-get-user] How do I create a public slapt-get repository?

Roy Keene slapt at rkeene.org
Fri Jan 23 05:41:51 EST 2009


This is covered in the FAQ:
 	http://software.jaos.org/BUILD/slapt-get/FAQ.html#slgFAQ17

Additionally, the tools I use to maintain my repository are attached.

genpackages.tcl generates all the required package data for being a 
slapt-get source.

mkindex.tcl just produces an HTML index.

No warranty is provided, and no copyright is exerted (public domain).

On Thu, 22 Jan 2009, Xavian-Anderson Macpherson wrote:

> What commands do I have to use to create a publicly accessible slapt-get repository? What files must be present, and how do I create and update them?
> 
> Xavian-Anderson Macpherson
> Shingoshi
> --
> [IMAGE]
> 
>
-------------- next part --------------
#! /usr/bin/tclsh

if {[info command recursive_glob] == ""} {
	proc recursive_glob {dir pattern} {
		set ret ""
		foreach file [glob -nocomplain "${dir}/*"] {
			if {[file isdirectory $file]} {
				foreach res [recursive_glob $file $pattern] {
					lappend ret $res
				}
				continue
			}
			if {[string match $pattern $file]} {
				lappend ret $file
			}
		}
		return $ret
	}
}

proc packagename {file} {
	set ignore 1
	foreach part [split [file tail $file] -] {
		if {[string match {[0-9I]*} $part] && !$ignore} {
			break
		}

		lappend ret $part
		set ignore 0
	}

	if {![info exists ret]} {
		puts stderr "Weird package filename: $file"
		return [file tail $file]
	}

	return [join $ret -]
}

proc isslackpack {file} {
	set shortfile [file tail $file]
	if {![regexp {^[A-Za-z0-9]+.*-[0-9I]+.*-[0-9][^-]*\.tgz} $shortfile]} {
		return 0
	}

	# This is not a package, it just looks like one :-(
	if {[string match "INIT*.tgz" $shortfile]} {
		return 0
	}

	return 1
}

set pkgfd [open PACKAGES.TXT.TMP w]
set csumfd [open CHECKSUMS.md5.TMP w]

foreach pkgfile [recursive_glob . *.tgz] {
	set metafile [file rootname $pkgfile].meta
	set dirname [file dirname $pkgfile]
	set pkgname [packagename $pkgfile]
	set pkgshortfilename [file tail $pkgfile]

	# Skip things that aren't really slackware packages.
	if {![isslackpack $pkgfile]} {
		continue
	}

	# Skip unstable stuff from non-unstable entries.
	if {[string match "*-unstable" $dirname]} {
		continue
	}
	if {[string match "*/testing" $dirname] || [string match "*/testing/*" $dirname]} {
		continue
	}

	# Generate the metafile if it doesn't exist.
	if {![file exists $metafile]} {
		catch {
			set pkgreq ""
			set pkgdesc ""
			set pkgconflict ""
			set pkgfilesize [expr [file size $pkgfile] / 1024]
			set pkguncfilesize [expr [lindex [lindex [split [exec gunzip -l $pkgfile] \n] end] 1] / 1024]
			set pkgmd5 [lindex [split [exec md5sum $pkgfile]] 0]
			catch {
				set pkgreq [join [split [exec tar -zxOf $pkgfile install/slack-required] \n] ,]
			}
			catch {
				set pkgconflict [join [split [exec tar -zxOf $pkgfile install/slack-conflicts] \n] ,]
			}
			catch {
				foreach pkgdescline [split [exec tar -zxOf $pkgfile install/slack-desc] \n] {
					if {![string match "*:*" $pkgdescline] || [string match "#*" $pkgdescline]} {
						continue
					}
					lappend pkgdesc [string trim [join [lrange [split $pkgdescline :] 1 end] :]]
				}
			}
			
			set metafd [open $metafile w]
			puts $metafd "PACKAGE NAME:  $pkgshortfilename"
			puts $metafd "PACKAGE SIZE (compressed):  $pkgfilesize K"
			puts $metafd "PACKAGE SIZE (uncompressed):  $pkguncfilesize K"
			puts $metafd "PACKAGE REQUIRED:  $pkgreq"
			puts $metafd "PACKAGE CONFLICTS:  $pkgconflict"
			puts $metafd "PACKAGE CHECKSUM:  $pkgmd5"
			puts $metafd "PACKAGE DESCRIPTION:"
			foreach pkgdescline $pkgdesc {
				puts $metafd "$pkgname: $pkgdescline"
			}
			close $metafd
		}
	}

	catch {
		unset -nocomplain pkgmd5
		set metafd [open $metafile r]
		while 1 {
			gets $metafd line

			if {[eof $metafd]} {
				break
			}
			if {[string match "PACKAGE LOCATION: *" $line]} {
				continue
			}
			if {[string match "PACKAGE CHECKSUM: *" $line]} {
				set pkgmd5 [string trim [lindex [split $line :] 1]]
				continue
			}

			puts $pkgfd $line

			if {[string match "PACKAGE NAME: *" $line]} {
				puts $pkgfd "PACKAGE LOCATION:  $dirname"
			}
		}
		close $metafd
		puts $pkgfd ""

		if {![info exists pkgmd5]} {
			set pkgmd5 [lindex [split [exec md5sum $pkgfile]] 0]
		}

		puts $csumfd "$pkgmd5  $pkgfile"
	}
}

close $pkgfd
close $csumfd

file delete PACKAGES.TXT.OLD
file delete CHECKSUMS.md5.OLD
catch { file rename PACKAGES.TXT PACKAGES.TXT.OLD }
catch { file rename CHECKSUMS.md5 CHECKSUMS.md5.OLD }
file rename PACKAGES.TXT.TMP PACKAGES.TXT
file rename CHECKSUMS.md5.TMP CHECKSUMS.md5
-------------- next part --------------
#! /usr/bin/tclsh

set defaultPkgs(glibc-solibs) 1
set defaultPkgs(aaa_elflibs) 1
set defaultPkgs(aaa_base) 1
set defaultPkgs(cxxlibs) 1
set defaultPkgs(glibc) 1

proc textdesc_arch {arch} {
	switch -- [string tolower $arch] {
		"i386" { return "386 or better" }
		"i486" { return "486 or better" }
		"i586" { return "Pentium or better" }
		"i686" { return "Pentium II or better" }
		"x86_64" { return "AMD64" }
		"noarch" { return "any CPU" }
	}

	return "(unknown)"
}

proc pkg_vers_comp {a b} {
	regsub -all {rc([0-9])} $a {.-\1} a
	regsub -all {rc([0-9])} $b {.-\1} b
	regsub -all {beta([0-9])} $a {.-\1} a
	regsub -all {beta([0-9])} $b {.-\1} b
	regsub -all {[^0-9\.\-]} $a {.} a
	regsub -all {[^0-9\.\-]} $b {.} b
	regsub -all {\.\.} $a {.} a
	regsub -all {\.\.} $b {.} b
	regsub -all {\.$} $a {} a
	regsub -all {\.$} $b {} b
	regsub -all {^\.} $a {} a
	regsub -all {^\.} $b {} b

	set a_l [split $a .]
	set b_l [split $b .]

	set a_len [llength $a_l]
	set b_len [llength $b_l]

	if {$a_len < $b_len} {
		set ab_len $b_len
		set ret -1
	} elseif {$b_len < $a_len} {
		set ab_len $a_len
		set ret 1
	} else {
		set ab_len $b_len
		set ret 0
	}																   

	for {set i 0} {$i < $ab_len} {incr i} {
		set a_i [lindex $a_l $i]
		set b_i [lindex $b_l $i]

		if {$a_i == ""} {
			set a_i 0
		}
		if {$b_i == ""} {
			set b_i 0
		}

		if {$a_i < $b_i} {
			set ret -1
			break
		}

		if {$b_i < $a_i} {
			set ret 1
			break
		}
	}

	return $ret
}

proc mkindex_html {dir} {
	set indexfile index.html

	file stat $dir/.. finfo
	lappend filelist [list ".." $finfo(type) $finfo(ctime) $finfo(size) $finfo(nlink)]

	foreach file [lsort -dictionary [glob -nocomplain -tails -directory $dir *]] {
		if {$file == $indexfile} {
			continue
		}
		unset -nocomplain finfo
		catch {
			file stat $dir/$file finfo
		}
		if {![info exists finfo]} {
			continue
		}

		set pkgdata ""
		if {$finfo(type) == "directory"} {
			mkindex_html $dir/$file
		}

		if {[string match "*.tgz" $file] && $finfo(type) == "file"} {
			set metafile "[file rootname $dir/$file].meta"
			if {![file exists $metafile]} {
				continue
			}
			set mfd [open $metafile r]
			set pkgdata [read $mfd]
			close $mfd

			set pkginfowork [split [string range $file 0 end-4] -]
			set pkgname [join [lrange $pkginfowork 0 end-3] -]
			set pkgvers [lindex $pkginfowork end-2]
			set pkgarch [lindex $pkginfowork end-1]
			set pkgrelv [lindex $pkginfowork end]

			set isNewer 0
			if {[info exists pkgInfo($pkgname)]} {
				set chk_pkgvers [lindex $pkgInfo($pkgname) 0]
				set chk_pkgrelv [lindex $pkgInfo($pkgname) 1]
				switch -- [pkg_vers_comp $pkgvers $chk_pkgvers] {
					"1" {
						set isNewer 1
					}
					"0" {
						if {[pkg_vers_comp $pkgrelv $chk_pkgrelv] == 1} {
							set isNewer 1
						}
					}
				}
			} else {
				set isNewer 1
			}

			if {$isNewer} {
				set pkgInfo($pkgname) [list $pkgvers $pkgrelv $file]
			}
		}

		lappend filelist [list $file $finfo(type) $finfo(ctime) $finfo(size) $finfo(nlink) $pkgdata]
	}

	set indexpath "$dir/$indexfile"
	catch {
		set fd [open $indexpath w]
		puts $fd {<html>
  <head>
    <title>Slackware Packages</title>
    <style type="text/css">
<!--
      body,td,th,p,div { font-family: Verdana,Geneva,Arial,Sans-serif; font-size: 14px; color: #000000; background: #ffffff; }
      small { font-family: Verdana,Geneva,Arial,Sans-serif; font-size: 10px; color: #000000; }
      h1 { font-family: Verdana,Geneva,Arial,Sans-serif; font-size: 18px; color: #000000; text-align: center; }
      a { color: #000000; text-decoration: underline; }
      .dir_container { background: #eeeeee; border: 1px solid #000000; margin-left: 5px; margin-right: 5px; }
      .dir_hdr { background: #eeeeee; margin-left: 2px; margin-right: 2px; }
      .pkg_hdr { background: #a5d5ff; font-size: 14px; border-collapse: collapse; border: 1px solid #000000; border-bottom: 1px dashed #000000; margin-left: 5px; margin-right: 5px; }
      .pkg_hdr div { background: #a5d5ff; font-size: 14px; margin-left: 2px; margin-right: 5px;  }
      .info_hdr { background: #eeeeee; font-size: 12px; border-collapse: collapse; border: 1px solid #000000; border-top: none; margin-left: 5px; margin-right: 5px; }
      .info_hdr div { background: #eeeeee; font-size: 12px; margin-left: 2px; margin-right: 5px; }
      .info_hdr_req { background: #eeeeee; font-size: 12px; margin-top: 6px; }
      .pkg_link { background: #eeeeee; font-size: 9px; }
      .spacer { font-size: 6px; }
      .note { font-family: Verdana,Geneva,Arial,Sans-serif; font-size: 10px; color: #000000; }
      .hidden { visibility: hidden; }
-->
    </style>
  </head>
  <body>
    <h1>Slackware Packages</h1>
}

		puts $fd "    <div class=\"dir_container\">"
    		foreach filedata [lsort -dictionary $filelist] {
			set file [lindex $filedata 0]
			set type [lindex $filedata 1]
			set ctime [lindex $filedata 2]
			set size [lindex $filedata 3]
			set nlink [lindex $filedata 4]
			set pkgdata [lindex $filedata 5]
			if {$type != "directory"} {
				continue
			}

			switch -- $file {
				".." {
					puts $fd "    <div class=\"dir_hdr\">Go <a href=\"$file/\">up</a> a directory</div>"
				}
				default {
					puts $fd "    <div class=\"dir_hdr\">Go to the <a href=\"$file/\">$file</a> directory</div>"
				}
			}

		}
		puts $fd "    </div>"


		puts $fd "    <hr>"

		set pkgItemsDisplayed 0
    		foreach filedata [lsort -dictionary $filelist] {
			set file [lindex $filedata 0]
			set type [lindex $filedata 1]
			set ctime [lindex $filedata 2]
			set size [lindex $filedata 3]
			set pkgdata [lindex $filedata 5]
			if {$type != "file"} {
				continue
			}
			if {![string match "*.tgz" $file]} {
				continue
			}

			set pkginfowork [split [string range $file 0 end-4] -]
			set pkgname [join [lrange $pkginfowork 0 end-3] -]

			if {[info exists pkgInfo($pkgname)]} {
				set chk_file [lindex $pkgInfo($pkgname) 2]
				if {$file != $chk_file} {
					continue
				}
			}

			set pkgvers [lindex $pkginfowork end-2]
			set pkgarch [lindex $pkginfowork end-1]
			set pkgrelv [lindex $pkginfowork end]

			set pkgdesc ""
			set pkgreqs [list]
			set descmode 0
			set desclineno 0
			foreach line [split $pkgdata \n] {
				if {[string match "PACKAGE REQUIRED: *" $line]} {
					set pkgreqs_in [split [string trim [join [lrange [split $line :] 1 end] :]] ,]
					foreach req $pkgreqs_in {
						set req [string trim $req]

						set altreqs_in [split $req |]
						set altreqs [list]
						foreach altreq $altreqs_in {
							set altreq [string trim $altreq]

							if {[info exists ::defaultPkgs($altreq)]} {
								set altreqs [list]
								break
							}

							lappend altreqs $altreq
						}
						if {[llength $altreqs] != 0} {
							lappend pkgreqs [join $altreqs |]
						}
					}

				}
				if {[string match "PACKAGE DESCRIPTION:*" $line]} {
					set descmode 1
					continue
				}
				if {$descmode} {
					set pkgdescline [string trim [join [lrange [split $line :] 1 end] :]]
					if {$pkgdescline == ""} {
						continue
					}

					if {$desclineno > 0} {
						append pkgdesc " $pkgdescline"
					}

					incr desclineno
				}
			}
			set pkgdesc [string trim $pkgdesc]
			if {$pkgdesc == ""} {
				set pkgdesc "(No Description Available)"
			}

			if {$ctime > ([clock seconds]-(86400*5))} {
				set newnote " <small>(new)</small>"
			} else {
				set newnote ""
			}

			incr pkgItemsDisplayed

			puts $fd "    <div>"
			puts $fd "      <div class=\"pkg_hdr\" id=\"$pkgname\"><div><a href=\"$file\">$pkgname</a> v$pkgvers-$pkgrelv for [textdesc_arch $pkgarch] ($size bytes, [clock format $ctime -format {%d%b%y}])$newnote</div></div>"
			puts $fd "      <div class=\"info_hdr\">"
			puts $fd "        <div>$pkgdesc</div>"
			if {[llength $pkgreqs] > 0} {
				puts -nonewline $fd "      <div class=\"info_hdr_req\">Requires"
				set pkgreqslen [llength $pkgreqs]
				for {set ridx 0} {$ridx < $pkgreqslen} {incr ridx} {
					set req [string trim [lindex $pkgreqs $ridx]]

					set altreqs [split $req |]
					set altreqslen [llength $altreqs]
					for {set aridx 0} {$aridx < $altreqslen} {incr aridx} {
						set altreq [string trim [lindex $altreqs $aridx]]

						if {[info exists pkgInfo($altreq)]} {
							puts -nonewline $fd " <a href=\"#$altreq\">$altreq</a>"
							puts -nonewline $fd " <a class=\"pkg_link\" href=\"[lindex $pkgInfo($altreq) 2]\">\[pkg\]</a>"
						} else {
							puts -nonewline $fd " $altreq"
						}

						if {$aridx != ($altreqslen - 1)} {
							puts -nonewline $fd " or"
						}
					}
					if {$ridx == ($pkgreqslen - 2)} {
						puts -nonewline $fd ", and"
					} elseif {$ridx != ($pkgreqslen -1)} {
						puts -nonewline $fd ","
					}
				}
				puts $fd ".</div>"
			}
			puts $fd "    </div>"
			puts $fd "    <div class=\"spacer\">&nbsp;</div>"
		}

		if {$pkgItemsDisplayed != 0} {
			puts $fd "    <hr>"
		}
		puts $fd "    <span>Updated: [clock format [clock seconds]]</span><br>"
		puts $fd {    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
      <input type="hidden" name="cmd" value="_xclick">
      <input type="hidden" name="business" value="slackware at rkeene.org">
      <input type="hidden" name="item_name" value="Slackware Devel System">
      <input type="hidden" name="no_note" value="1">
      <input type="hidden" name="currency_code" value="USD">
      <input type="hidden" name="tax" value="0">
      <input type="hidden" name="lc" value="US">
      <input type="image" src="/images/x-click-but21.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
    </form>}
puts $fd "  <div class=\"note\">SOURCE=[regsub {^/web/static/} [file normalize $dir] {http://}]</div>"
puts $fd {  <div class="hidden"><a href="PACKAGES.TXT">PACKAGES.TXT</a>, <a href="CHECKSUMS.md5">CHECUKSUMS.md5</a></div>}
puts $fd {  </body>
</html>}
		close $fd
	} err

	if {[string trim $err] != ""} {
		puts $err
	}

	return
}

if {[llength $argv] == 0} {
	puts stderr "Usage: mkindex <dir>"
	exit 1
}

foreach dir $argv {
	mkindex_html $dir
}


More information about the Slapt-get-user mailing list