├── LICENSES └── BSD-2-Clause.tcberner.adridg ├── README.md ├── UPDATING.md └── bin ├── bump_revision.rb ├── instant-workstation ├── pkg-dependency-graph.pl ├── pkg-dependency-graph.py ├── show-explicit-ports └── sparse-ports-checkout.sh /LICENSES/BSD-2-Clause.tcberner.adridg: -------------------------------------------------------------------------------- 1 | Copyright 2017 Tobias C. Berner 2 | Copyright 2017 Adriaan de Groot 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FreeBSD (new) Committer's Tools 2 | 3 | > This repo contains notes from my new-committer period, as well as links 4 | > to useful FreeBSD resources (mostly for new committers) and some tools 5 | > of mixed parentage. 6 | 7 | ## Links 8 | 9 | * [Committer's Guide](https://www.freebsd.org/doc/en_US.ISO8859-1/articles/committers-guide/) -- [log messages](https://www.freebsd.org/doc/en_US.ISO8859-1/articles/committers-guide/commit-log-message.html) 10 | * [Porter's Handbook](https://www.freebsd.org/doc/en_US.ISO8859-1/books/porters-handbook/book.html) 11 | * [FreeBSD bugzilla](https://bugs.freebsd.org/) 12 | * [FreeBSD phab](https://reviews.freebsd.org/) 13 | * [FreeBSD package builders](https://pkg-status.freebsd.org/) 14 | 15 | ## Tools 16 | 17 | * [instant-workstation](bin/instant-workstation) 18 | > This script uses `dialog(1)` to ask a few questions, and then 19 | > installs the software and configuration needed for that workstation-use. 20 | > It is tailored to my needs, but accepts PRs for other uses. 21 | * [sparse-checkout](bin/sparse-ports-checkout.sh) 22 | > This script checks out a (writable) ports-tree suitable for working 23 | > on individual ports. The ports tree is checked out in *sparse* 24 | > mode, which means that you only get the bits needed to modify 25 | > and build the ports you ask for. Can also be used to create 26 | > a ports tree from a Phab review. Joint work with tcberner@ 27 | > 28 | > Typical use is to create a writable checkout (that is, one over 29 | > ssh which you can commit from) with a particular name, for one 30 | > or more ports that need to be modified: 31 | > sparse-ports-checkout.sh -w -n ports-tree-name -p category/portname 32 | * [bump_revision](bin/bump_revision.rb) 33 | > This script bumps the `PORTREVISION` value in each named 34 | > port, by editing the Makefile. If no `PORTREVISION` exists, 35 | > adds one with value 1. 36 | * Ports graphs [perl](bin/pkg-dependency-graph.pl) [python](bin/pkg-dependency-graph.py) 37 | > Both scripts use dot (`graphics/graphviz`) to produce a graph of the 38 | > dependencies for a given port. Both use the output from `pkg` to 39 | > obtain the dependency tree. 40 | 41 | 42 | ## Instructions 43 | 44 | * [New Install](UPDATING.md#new-install) 45 | * [Updating with jails](UPDATING.md#updating-jails) 46 | * [Updating home Certificate Authority](UPDATING.md#ssl-certs) 47 | 48 | ## Contributors 49 | 50 | The work in this repository is not only my own. Other contributors 51 | alphabetically by first name or nickname are: 52 | 53 | - natethegreat44 54 | - Tobias Berner 55 | -------------------------------------------------------------------------------- /UPDATING.md: -------------------------------------------------------------------------------- 1 | # New Install 2 | 3 | > These are instructions for getting a system up-and-running for **me**. 4 | 5 | Fetch the instant-workstation script, as root, and then run it. 6 | ``` 7 | # fetch https://raw.githubusercontent.com/adriaandegroot/FreeBSDTools/main/bin/instant-workstation 8 | # sh instant-workstation 9 | ``` 10 | 11 | # Updating Jails 12 | 13 | > These are the instructions for **my** update process, written 14 | > down mostly so I can cut-and-paste them in future. 15 | > Since I have a host (running 11-STABLE) which has some 16 | > jails managed by ezjail and some jails managed by poudriere, 17 | > it all takes a little bit of messing around to do one round 18 | > of updating. I generally do this together with a big update 19 | > of all my packages. 20 | 21 | ``` 22 | # Make sure sources are up-to-date 23 | cd /usr/src 24 | svn up 25 | # Do build on host 26 | make -j6 buildworld && make -j6 buildkernel 27 | make installkernel && mergemaster -p -FU 28 | make installworld && mergemaster -FU 29 | # Update the jails 30 | ezjail-admin update -i 31 | # Update the poudriere jail 32 | poudriere jail -u -j 111amd64 -m src=/usr/src 33 | # Reboot and resume into new environment 34 | reboot 35 | # Build all packages that are needed for the "roots" (not-autoinstall) 36 | poudriere bulk -j 111amd64 -p github-kde -t -c `pkg-dependency-graph.py --roots` 37 | ``` 38 | 39 | ## SSL Certs 40 | 41 | > Since I have a home "Certificate Authority" with which I sign 42 | > my SSL certificates for in-home use (e.g. for my IMAP server), 43 | > I need to make the CA certificate acceptable system-wide. 44 | 45 | Sources: 46 | - https://forums.freebsd.org/threads/adding-certificate-to-ca_root_nss.51945/ 47 | - https://blog.socruel.nu/freebsd/how-to-install-private-CA-on-freebsd.html (mostly this one) 48 | 49 | After updating ca-nss or reinstalling, I need to tell clients about 50 | my home CA. I have the public certificate from my home CA as `ca.crt`, and: 51 | 52 | - Copy `ca.crt` into `/etc/ssl/` 53 | - Append the contents of `ca.crt` to `/etc/ssl/cert.pem` (this is the 54 | big list of root-CAs, generated by *ca_root_nss*). When the certs update 55 | normally, this needs to be re-done. 56 | ``` 57 | cat /etc/ssl/ca.crt >> /etc/ssl/cert.pem 58 | ``` 59 | - Link `ca.crt` into the hashes directory by finding the hash and soft-linking. 60 | The `.0` at the end is important. 61 | ``` 62 | cd /etc/ssl/certs 63 | ln -s ../ca.crt `openssl x509 -noout -hash -in ../ca.crt`.0 64 | ``` 65 | -------------------------------------------------------------------------------- /bin/bump_revision.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | # License-Filename: LICENSES/BSD-2-Clause.tcberner.adridg 5 | # 6 | ### USAGE 7 | # 8 | # Bumps the PORTREVISION in named directories. 9 | # bump_revision ... 10 | # For each named , tries to bump the PORTREVISION 11 | # in the Makefile in dir. Generally, call this with 12 | # paths relative to a ports tree checkout, e.g. 13 | # bump_revision devel/cmake devel/cmake-doc 14 | # 15 | ### END USAGE 16 | 17 | 18 | def get_revision(makefile) 19 | File.readlines(makefile).each do |line| 20 | if line =~ /\APORTREVISION.*[0-9]+/ 21 | return line.strip.split(/\s+/).last 22 | end 23 | end 24 | return nil 25 | end 26 | 27 | def next_revision(num) 28 | num ||= 0 29 | return num.to_i + 1 30 | end 31 | 32 | def add_portrevision(makefile) 33 | lines = File.readlines makefile 34 | # Order according to portlint: 35 | # PORTNAME PORTVERSION DISTVERSIONPREFIX DISTVERSION DISTVERSIONSUFFIX PORTREVISION 36 | pn = lines.index{|l| l =~ /\APORTNAME.?=.*[A-Za-z]+/} || 0 37 | pv = lines.index{|l| l =~ /\APORTVERSION.?=/} || 0 38 | dvp = lines.index{|l| l =~ /\ADISTVERSIONPREFIX.?=/} || 0 39 | dv = lines.index{|l| l =~ /\ADISTVERSION.?=/} || 0 40 | dvs = lines.index{|l| l =~ /\ADISTVERSIONSUFFIX.?=/} || 0 41 | no = [pn, pv, dvp, dv, dvs].sort.last 42 | 43 | puts "adding PORTERVISION=1 to #{makefile}" 44 | lines.insert no+1, "PORTREVISION=\t1\n" 45 | File.open(makefile,'wb'){|f| f.write(lines.join)} 46 | end 47 | 48 | def bump_revision(makefile) 49 | lines = File.readlines makefile 50 | rev = get_revision makefile 51 | if rev 52 | pr = lines.index{|l| l =~ /\APORTREVISION.?=.*[0-9]+/} 53 | line = lines[pr] 54 | nrev = next_revision rev 55 | puts "bumping #{makefile} from #{rev} to #{nrev}" 56 | newline = line.gsub(rev.to_s, nrev.to_s) 57 | lines[pr] = newline 58 | File.open(makefile,'wb'){|f| f.write(lines.join)} 59 | else 60 | add_portrevision makefile 61 | end 62 | end 63 | 64 | args = ARGV 65 | if args.length == 0 66 | puts "no arguments given" 67 | return 1 68 | end 69 | 70 | args.each do |arg| 71 | makefile = File.join arg, "Makefile" 72 | next unless File.directory?(arg) 73 | unless File.exist?(makefile) 74 | puts "skipping #{arg}" 75 | next 76 | end 77 | revision = get_revision(makefile) 78 | nextrevision = next_revision(revision) 79 | bump_revision makefile 80 | end 81 | -------------------------------------------------------------------------------- /bin/instant-workstation: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # SPDX-FileCopyrightText: 2019 Adriaan de Groot 4 | # SPDX-License-Identifier: BSD-2-Clause 5 | # 6 | ### USAGE 7 | # 8 | # This shell script can be run on a freshly-installed FreeBSD system 9 | # to create an "instant-workstation". It uses dialog(1) for user-input, 10 | # and does a best-effort to install what's needed. 11 | # - a desktop environment 12 | # - a display manager (and X and the rest) 13 | # - graphics drivers 14 | # - tooling for various tasks 15 | # 16 | # 17 | # Usage: 18 | # instant-workstation [-h] [--selfupdate|-U] 19 | # 20 | # Usage: 21 | # -h show this help 22 | # -U, --selfupdate update the script and run it again 23 | # 24 | # Run with --selfupdate to update the script from its canonical source 25 | # (useful for testing updates to the script itself). 26 | # 27 | ### END USAGE 28 | 29 | if test "x$1" = "x-h" ; then 30 | sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" 31 | exit 0 32 | fi 33 | 34 | # Get a temporary location for dialog output 35 | base=`basename $0` 36 | CONFIG=`mktemp /tmp/${base}.XXXXXX` || { echo "! Cannot create temporary file." ; exit 1 ; } 37 | 38 | setup_polkit=false 39 | 40 | ### SELF-UPDATE 41 | # 42 | # 43 | if test "x$1" = "x--selfupdate" -o "x$1" = "x-U" 44 | then 45 | /usr/bin/fetch -o "${CONFIG}" https://raw.githubusercontent.com/adriaandegroot/FreeBSDTools/main/bin/instant-workstation 46 | /bin/mv "${CONFIG}" "$0" ; exit 0 47 | fi 48 | 49 | 50 | ### USER INPUT 51 | # 52 | # Pick one or more DE's, and exactly one DM 53 | # NOTE: each ID should be distinct 54 | # 55 | /usr/bin/dialog --no-tags --separate-output \ 56 | --checklist "Desktop Environment" 0 0 0 \ 57 | kde5 "KDE Plasma Desktop" 0 \ 58 | gnome3 "GNOME Desktop" 0 \ 59 | xfce4 "XFCE Desktop" 0 \ 60 | mate "MATE Desktop" 0 \ 61 | stump "STUMP WM" 0 \ 62 | twm "TWM, X like the '90s" 0 \ 63 | --checklist "Extra Software for .." 0 0 0 \ 64 | kdedevel "C++ Development" 0 \ 65 | telegram "Telegram" 0 \ 66 | matrix "Matrix" 0 \ 67 | irc "IRC" 0 \ 68 | latex "LaTeX" 0 \ 69 | management "Host Management" 0 \ 70 | --radiolist "Display Manager" 0 0 0 \ 71 | sddm "SDDM" 1 2> ${CONFIG} 72 | 73 | ### PACKAGE SELECTION 74 | # 75 | # Turn the user input into specific packages and sysrc 76 | # commands to execute. 77 | # 78 | packages="" 79 | sysrc="" 80 | sysctl="" 81 | for line in `cat "${CONFIG}"` 82 | do 83 | case "x$line" in 84 | "xkde5") 85 | packages="$packages x11/kde5 devel/dbus www/falkon" 86 | sysrc="$sysrc dbus_enable=YES" 87 | sysctl="$sysctl net.local.stream.recvspace=65536 net.local.stream.sendspace=65536" 88 | ;; 89 | "xgnome3") 90 | packages="$packages x11/gnome3" 91 | ;; 92 | "xxfce4") 93 | packages="$packages x11-wm/xfce4" 94 | ;; 95 | "xmate") 96 | packages="$packages x11/mate-desktop" 97 | ;; 98 | "xstump") 99 | packages="$packages x11-wm/stumpwm" 100 | ;; 101 | "xtwm") 102 | packages="$packages x11-wm/twm x11/xterm x11-fonts/xfontsel" 103 | ;; 104 | "xsddm") 105 | packages="$packages x11/sddm" 106 | sysrc="$sysrc sddm_enable=YES" 107 | setup_polkit=true 108 | ;; 109 | "xkdedevel") 110 | # TODO: distinguish DE and install matching gitk and IDE? 111 | packages="$packages devel/ccache devel/cmake devel/git devel/kdevelop devel/qgit devel/ninja" 112 | ;; 113 | "xtelegram") 114 | packages="$packages net-im/telegram-desktop" 115 | ;; 116 | "xmatrix") 117 | packages="$packages net-im/nheko" 118 | ;; 119 | "xirc") 120 | packages="$packages irc/quassel irc/irssi" 121 | ;; 122 | "xlatex") 123 | packages="$packages print/texlive-base print/tex-basic-engines print/tex-formats" 124 | ;; 125 | "xmanagement") 126 | packages="$packages sysutils/screen sysutils/ezjail" 127 | ;; 128 | "*") 129 | echo "! Unrecognized tag '${line}' in ${CONFIG}" 130 | exit 1 131 | ;; 132 | esac 133 | done 134 | 135 | rm "${CONFIG}" 136 | 137 | ### HARDWARE SUPPORT 138 | # 139 | # Best-guess for necessary hardware drivers 140 | # 141 | fbsd_version=$( /usr/bin/uname -r | /usr/bin/sed 's/-.*//' ) 142 | 143 | # The reporting from pciconf has changed, too 144 | case "x${fbsd_version}" in 145 | "x1[12]."*) 146 | vga_product=$( /usr/sbin/pciconf -l | /usr/bin/awk '/^vgapci/{ print substr($4,length($4)-3); }' ) 147 | vga_vendor=$( /usr/sbin/pciconf -l | /usr/bin/awk '/^vgapci/{ print substr($4,8,4); }' ) 148 | ;; 149 | "x13."*) 150 | vga_product=$( /usr/sbin/pciconf -l | /usr/bin/awk '/^vgapci/{ for(i=2; i<=NF; i++) { if ( substr($i,0,7)=="device=" ) print substr($i,10); } }' ) 151 | vga_vendor=$( /usr/sbin/pciconf -l | /usr/bin/awk '/^vgapci/{ for(i=2; i<=NF; i++) { if ( substr($i,0,7)=="vendor=" ) print substr($i,10); } }' ) 152 | ;; 153 | *) 154 | echo "Unrecognized FreeBSD version '${fbsd_version}'" 155 | exit 1 156 | ;; 157 | esac 158 | 159 | # Look for Intel graphics 160 | if test 8086 = "${vga_product}" 161 | then 162 | case "x${fbsd_version}" in 163 | "x12."[012]) 164 | packages="$packages graphics/drm-fbsd12.0-kmod" 165 | ;; 166 | "x11."[234]) 167 | packages="$packages graphics/drm-fbsd11.2-kmod" 168 | ;; 169 | "x13."*) 170 | : 171 | ;; 172 | *) 173 | echo "Unrecognized FreeBSD version '${fbsd_version}'" 174 | exit 1 175 | ;; 176 | esac 177 | fi 178 | 179 | # Look for NVidia graphics 180 | if test 10de = "${vga_vendor}" 181 | then 182 | packages="nvidia-driver nvidia-xconfig" 183 | fi 184 | 185 | ### VIRTUALBOX 186 | # 187 | # 188 | if test beef = "${vga_vendor}" 189 | then 190 | # Virtualbox Support 191 | packages="$packages emulators/virtualbox-ose-additions" 192 | sysrc="$sysrc vboxguest_enable=YES vboxservice_enable=YES" 193 | fi 194 | 195 | ### VMWARE 196 | # 197 | # 198 | if test 0405 = "${vga_vendor}" 199 | then 200 | # VMWare Workstation Support 201 | packages="$packages open-vm-tools xf86-input-vmmouse xf86-video-vmware" 202 | sysrc="$sysrc dbus_enable=YES moused_enable=YES vmware_guest_vmblock_enable=YES vmware_guest_vmhgfs_enable=YES vmware_guest_vmmemctl_enable=YES vmware_guest_vmxnet_enable=YES vmware_guestd_enable=YES" 203 | fi 204 | 205 | ### X11 206 | # 207 | # 208 | packages="$packages x11/xorg" 209 | 210 | ### INSTALLATION 211 | # 212 | # 213 | if test -z "$packages" 214 | then 215 | echo "! No packages selected for installation." 216 | exit 1 217 | fi 218 | 219 | command="/usr/sbin/pkg install $packages" 220 | if test -n "$sysrc" 221 | then 222 | command="$command ; /usr/sbin/sysrc $sysrc"; 223 | fi 224 | if test -n "$sysctl" 225 | then 226 | for l in $sysctl ; do 227 | command="$command ; echo \"$l\" >> /etc/sysctl.conf" 228 | done 229 | fi 230 | 231 | echo "su root for installation and configuration" 232 | su root -c "$command" 233 | 234 | ### VMWARE Post installation 235 | # 236 | # 237 | if test 0405 = "${vga_vendor}" 238 | then 239 | echo 'Updating vmware X configuration' 240 | mkdir -p /usr/local/etc/X11/xorg.conf.d 241 | 242 | # X11 configuration 243 | echo '# Temporary fix to set vmmouse 244 | Section "ServerFlags" 245 | Option "AutoAddDevices" "false" 246 | EndSection 247 | 248 | Section "InputDevice" 249 | Identifier "Mouse0" 250 | Driver "vmmouse" 251 | Option "Device" "/dev/sysmouse" 252 | EndSection 253 | 254 | Section "Device" 255 | Identifier "Card0" 256 | Driver "vmware" 257 | EndSection' > /usr/local/etc/X11/xorg.conf.d/vmware.conf 258 | 259 | # Enable 3D acceleration when available 260 | echo 'To enable 3D acceleration, add your username(s) to the ''video'' group with:' 261 | echo ' pw groupmod video -m ' 262 | fi 263 | 264 | ### SDDM Post installation 265 | # 266 | # 267 | if $setup_polkit ; then 268 | echo 'Allowing the ''operator'' group to shut modify system state from SDDM.' 269 | polkit_file="/usr/local/etc/polkit-1/rules.d/40-operator-group-sddm.rules" 270 | su root -c "cat > $polkit_file" < \"$dep_name\";"; 92 | } 93 | } 94 | say "}"; 95 | -------------------------------------------------------------------------------- /bin/pkg-dependency-graph.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3.6 2 | # 3 | # A script to generate a .dot file (Graphviz) from installed 4 | # packages, to show what depends on what. Prints the dot code 5 | # to standard output. 6 | # 7 | # Use the option --root to print out, one per line, the roots 8 | # of the forest of installed packages (this suppresses regular 9 | # dot output). 10 | 11 | import argparse 12 | import os 13 | import subprocess 14 | import sys 15 | 16 | if sys.version_info < (3, 5): 17 | raise ValueError("Python 3.5 or later is required.") 18 | 19 | def collect_pkg(): 20 | """ 21 | Run pkg, and returns a dictionary 22 | where the keys are names of packages, 23 | and the values are lists of packages that the key depends on. 24 | """ 25 | deps = {} 26 | PKG = "/usr/sbin/pkg" 27 | QUERY = "query" 28 | 29 | # Gather all packages, init deps to an empty dependency list per package 30 | r = subprocess.run( 31 | [PKG, QUERY, "%o"], 32 | stdout=subprocess.PIPE) 33 | output = r.stdout.split(b"\n") 34 | for line in output: 35 | if line: 36 | line = line.decode("ascii") 37 | deps[line] = [] 38 | 39 | # Now build up the dependency graph 40 | r = subprocess.run( 41 | [PKG, QUERY, "%o::%do"], 42 | stdout=subprocess.PIPE) 43 | output = r.stdout.split(b"\n") 44 | for line in output: 45 | if line: 46 | line = line.decode("ascii") 47 | package, dep = line.split("::") 48 | deps[package].append(dep) 49 | 50 | return deps 51 | 52 | def normalize_deps(deps): 53 | """ 54 | Normalize the dependencies. 55 | 56 | A package in @p deps now has a dependency list that contains 57 | all the transitive dependencies; prune it down to only the 58 | first-level dependencies. 59 | """ 60 | normalized_deps = {} 61 | for key in deps.keys(): 62 | all_deps = set(deps[key]) 63 | second_deps = set() 64 | for k in all_deps: 65 | second_deps.update(set(deps[k])) 66 | 67 | l = list(all_deps - second_deps) 68 | l.sort() 69 | 70 | normalized_deps[key] = l 71 | 72 | return normalized_deps 73 | 74 | def count_reverse(deps): 75 | """ 76 | For a dependency graph pkg -> [pkgs], returns a dictionary 77 | with pkg as key, and the number of *other* packages that depend 78 | on this one. May be done with a normalized, or not-normalized graph. 79 | 80 | The keys that keep count 0 are the "root" nodes of the forest of 81 | installed packages. 82 | """ 83 | reverse_count = {} 84 | for key in deps.keys(): 85 | reverse_count[key] = 0 86 | for key in deps.keys(): 87 | for d in deps[key]: 88 | # These are the packages that k depends on, so they all get +1 89 | reverse_count[d] += 1 90 | 91 | return reverse_count 92 | 93 | def parse_args(): 94 | parser = argparse.ArgumentParser(description="pkg(8) graphing tool") 95 | parser.add_argument("--roots", "-r", dest="roots", action="store_true", default=False) 96 | return parser.parse_args() 97 | 98 | def do_graph(dependency_graph): 99 | packages = list(dependency_graph.keys()) 100 | packages.sort() 101 | 102 | print("### Root nodes:\n###\n#") 103 | count = count_reverse(dependency_graph) 104 | for k in packages: 105 | if count[k] == 0: 106 | print("# p%d %s" % (packages.index(k), k)) 107 | 108 | print("digraph {") 109 | for k in packages: 110 | print(" p%d [label=\"%s\"];" % (packages.index(k), str(k))) 111 | 112 | c = 1 113 | for k in packages: 114 | for dep in dependency_graph[k]: 115 | print(" p%d -> p%d;" % (packages.index(k), packages.index(dep)) ) 116 | 117 | print("}") 118 | 119 | def do_roots(dependency_graph): 120 | count = count_reverse(dependency_graph) 121 | packages = list(dependency_graph.keys()) 122 | packages.sort() 123 | for k in packages: 124 | if count[k] == 0: 125 | print(k) 126 | 127 | if __name__ == "__main__": 128 | args = parse_args() 129 | dependency_graph = normalize_deps(collect_pkg()) 130 | 131 | if args.roots: 132 | do_roots(dependency_graph) 133 | else: 134 | do_graph(dependency_graph) 135 | 136 | -------------------------------------------------------------------------------- /bin/show-explicit-ports: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # Shows the "explicit" ports, that is, shows the ports that the 4 | # user has installed via "pkg install" and ignores all the 5 | # automatic ports. This is useful to rebuild "all the stuff 6 | # I specifically want" in poudriere. Use -n to print only 7 | # port names (for instance, to "pkg install" elsewhere). 8 | # Otherwise, full origins are printed (for "poudriere bulk"). 9 | 10 | if test "x$1" = "x-n" ; then 11 | postprocess() { 12 | cut -d / -f 2 - 13 | } 14 | else 15 | postprocess() { 16 | cat - 17 | } 18 | fi 19 | 20 | pkg query '%o:%a' | grep ':0$' | cut -d : -f 1 | postprocess 21 | -------------------------------------------------------------------------------- /bin/sparse-ports-checkout.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-License-Identifier: BSD-2-Clause 4 | # License-Filename: LICENSES/BSD-2-Clause.tcberner.adridg 5 | # 6 | ### USAGE 7 | # 8 | # Checkout a shallow copy of the FreeBSD ports tree with only the 9 | # ports given as arguments filled in. Also checks out .arcconfig 10 | # (for convenient reviews) and Mk/ (so that there's a chance of using 11 | # the checked-out ports tree to build something) and other ports- 12 | # infrastructure. For a single port, that's still about 7MB. 13 | # 14 | # Usage: 15 | # sparse-ports-checkout <-n name|-a name> [-w] [-R path] ... 16 | # 17 | # Usage: 18 | # -n is for checking out a new sparse tree 19 | # -a is for working on an existing tree 20 | # -w writable checkout (svn+ssh) instead of read-only (https) 21 | # -R provide a repo-path to use 22 | # -h show this help 23 | # Ports-spec names ports to check out: 24 | # -p names a port to check out 25 | # -f names a file to read a list of ports from 26 | # -d checks out paths named in differential revision 27 | # (no option) names a port to check out 28 | # 29 | # Example: 30 | # # Ports in several categories, all named 31 | # sparse-ports-checkout.sh -n ports-amarok \ 32 | # -p audio/amarok-kde4 \ 33 | # -p audio/libofa \ 34 | # -p devel/qtscriptgenerator 35 | # # Ports from a review, and devel/cmake too 36 | # sparse-ports-checkout.sh -n ports-kgraph \ 37 | # -w -d 12530 devel/cmake 38 | # 39 | ### END USAGE 40 | 41 | ### LICENSES/BSD-2-Clause.tcberner.adridg 42 | # 43 | # Copyright 2017 Tobias C. Berner 44 | # Copyright 2017 Adriaan de Groot 45 | # 46 | # Redistribution and use in source and binary forms, with or without 47 | # modification, are permitted provided that the following conditions 48 | # are met: 49 | # 50 | # 1. Redistributions of source code must retain the above copyright 51 | # notice, this list of conditions and the following disclaimer. 52 | # 2. Redistributions in binary form must reproduce the above copyright 53 | # notice, this list of conditions and the following disclaimer in the 54 | # documentation and/or other materials provided with the distribution. 55 | # 56 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 57 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 58 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 59 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 60 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 61 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 62 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 63 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 64 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 65 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 66 | # POSSIBILITY OF SUCH DAMAGE. 67 | # 68 | ### END LICENSES 69 | 70 | # Writable vs non-writable SVN base 71 | REP_w=svn+ssh://repo.freebsd.org/ports/head 72 | REP=https://svn.FreeBSD.org/ports/head 73 | 74 | unique_line () 75 | { 76 | echo `echo "$*" | tr ' ' '\n' | sort -u | tr ' ' '\n'` 77 | } 78 | 79 | category_makefiles () 80 | { 81 | echo `echo "$*" | awk 'BEGIN{RS=" "; OFS="/"}{print $1,"Makefile"}'` 82 | } 83 | 84 | main () 85 | { 86 | local tree="" 87 | local categories="" 88 | local ports="" 89 | 90 | while getopts "ha:n:p:f:wR:d:" opt ; do 91 | case $opt in 92 | h|\?) 93 | sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" 94 | return 0 95 | ;; 96 | w) 97 | REP="${REP_w}" 98 | ;; 99 | R) 100 | REP="${OPTARG}" 101 | ;; 102 | d) 103 | diffnum="${OPTARG}" 104 | # Digits come before char 'D', extend 12296 to D12296 105 | if test 'D' '>' "${diffnum}" ; then 106 | diffnum="D${diffnum}" 107 | fi 108 | echo "Loading differential revision ${diffnum}" 109 | tmplist=/tmp/$$.portlist 110 | fetch -o - "https://reviews.freebsd.org/${diffnum}?download=true" | egrep '^[+-]{3} [^/]' | cut -d' ' -f2 | cut -d/ -f1,2 | sort -u > ${tmplist} 111 | category=`awk -F '/' '($1 && $2){print $1}' < ${tmplist} | sort | uniq` 112 | port=`awk -F '/' '($1 && $2){print $1"/"$2}' < ${tmplist} | sort | uniq` 113 | categories="${category} ${categories}" 114 | ports="${port} ${ports}" 115 | echo " .. loaded" `wc -l < ${tmplist}` "ports from differential revision ${diffnum}" 116 | rm -f $$.portlist 117 | ;; 118 | n) 119 | if [ "x${tree}y" == "xy" ] ; then 120 | tree="${OPTARG}" 121 | if [ -e "${tree}" ] ; then 122 | echo "argument -n '${tree}' already exists in working directory" 123 | return 1 124 | fi 125 | else 126 | echo "multiple -n or -a arguments given: ${tree}, ${OPTARG}" 127 | return 1 128 | fi 129 | ;; 130 | a) 131 | if [ "x${tree}y" == "xy" ] ; then 132 | tree="${OPTARG}" 133 | if [ ! -d "${tree}" ] ; then 134 | echo "argument to -a '${tree}' does not exist in working directory, you need -n" 135 | return 1 136 | fi 137 | else 138 | echo "multiple -n or -a arguments given: ${tree}, ${OPTARG}" 139 | return 1 140 | fi 141 | ;; 142 | p) 143 | category=`echo "${OPTARG}" | awk -F '/' '{print $1}'` 144 | port=`echo "${OPTARG}" | awk -F '/' '{print $2}'` 145 | if [ "x${category}y" != "xy" -a "x${port}y" != "xy" ] ; then 146 | categories="${category} ${categories}" 147 | ports="${category}/${port} ${ports}" 148 | else 149 | echo "could not understand -p argument '${OPTARG}'" 150 | return 1 151 | fi 152 | ;; 153 | f) 154 | if [ -f "${OPTARG}" ] ; then 155 | category=`cat "${OPTARG}" | awk -F '/' '($1 && $2){print $1}' | sort | uniq` 156 | port=`cat "${OPTARG}" | awk -F '/' '($1 && $2){print $1"/"$2}' | sort | uniq` 157 | categories="${category} ${categories}" 158 | ports="${port} ${ports}" 159 | else 160 | echo "could not read ports list from -f file '${OPTARG}'" 161 | return 1 162 | fi 163 | ;; 164 | esac 165 | done 166 | 167 | if [ "x${tree}y" == "xy" ] ; then 168 | echo "Need a tree argument -a, or -n" 169 | return 1 170 | fi 171 | 172 | _used_opt=`expr "$OPTIND" - 1` 173 | if [ "$_used_opt" -lt "$#" ] ; then 174 | shift "$_used_opt" 175 | for OPTARG in "$@" ; do 176 | category=`echo "${OPTARG}" | awk -F '/' '{print $1}'` 177 | port=`echo "${OPTARG}" | awk -F '/' '{print $2}'` 178 | if [ "x${category}y" != "xy" -a "x${port}y" != "xy" ] ; then 179 | categories="${category} ${categories}" 180 | ports="${category}/${port} ${ports}" 181 | else 182 | echo "could not understand argument '${OPTARG}'" 183 | return 1 184 | fi 185 | done 186 | fi 187 | 188 | if [ ! -d ${tree} ] ; then 189 | svn co --depth empty "${REP}" "${tree}" 190 | else 191 | svn up "${tree}" 192 | fi 193 | 194 | categories=`unique_line "${categories}"` 195 | category_mfs=`category_makefiles "${categories}"` 196 | ports=`unique_line "${ports}"` 197 | 198 | echo -e "Checking out cats: \033[33m${categories}\033[0m" 199 | echo -e "Checking out catms: \033[33m${category_mfs}\033[0m" 200 | echo -e "Chekcout out ports: \033[33m${ports}\033[0m" 201 | 202 | if [ -d ${tree} ] ; then 203 | cd ${tree} 204 | echo -e "\033[32mChecking out CATEGORIES\033[0m" 205 | svn update --set-depth=empty ${categories} 206 | echo -e "\033[32mCheckout out CATEGORY Makefile\033[0m" 207 | svn update --set-depth=infinity ${category_mfs} 208 | echo -e "\033[32mChecking out PORTS\033[0m" 209 | svn update --set-depth=infinity ${ports} 210 | echo -e "\033[32mChecking out Mk\033[0m" 211 | svn update --set-depth=infinity Mk Keywords Templates .arcconfig MOVED UPDATING 212 | fi 213 | } 214 | 215 | main $* 216 | --------------------------------------------------------------------------------