aboutsummaryrefslogtreecommitdiff
path: root/Tools
diff options
context:
space:
mode:
Diffstat (limited to 'Tools')
-rwxr-xr-xTools/scripts/MOVEDlint.awk51
-rw-r--r--Tools/scripts/README62
-rwxr-xr-xTools/scripts/add-port-to-category-makefile.sh50
-rwxr-xr-xTools/scripts/addport626
-rw-r--r--Tools/scripts/ai-master-prompt.md53
-rwxr-xr-xTools/scripts/bump_revision.pl182
-rwxr-xr-xTools/scripts/find-work-for-installed-ports.sh64
-rw-r--r--Tools/scripts/gen-compat.sh85
-rwxr-xr-xTools/scripts/git-diff-ports.sh31
-rwxr-xr-xTools/scripts/git-get-latest-remote-version.sh46
-rwxr-xr-xTools/scripts/gnomedepends.py126
-rwxr-xr-xTools/scripts/hackage-get-latest-version.sh49
-rwxr-xr-xTools/scripts/npmjs-get-latest-version.sh45
-rwxr-xr-xTools/scripts/port_conflicts_check.lua507
-rwxr-xr-xTools/scripts/portsearch4
-rwxr-xr-xTools/scripts/pypi-get-latest-version.sh48
-rwxr-xr-xTools/scripts/rmport67
-rwxr-xr-xTools/scripts/search_lib_depends_and_bump.sh4
-rwxr-xr-xTools/scripts/tindex9
-rwxr-xr-xTools/scripts/update-patches102
-rwxr-xr-xTools/scripts/update-rust-port.sh86
-rwxr-xr-xTools/scripts/update_crates62
22 files changed, 1336 insertions, 1023 deletions
diff --git a/Tools/scripts/MOVEDlint.awk b/Tools/scripts/MOVEDlint.awk
index 3cbec030cb5c..d589b1768989 100755
--- a/Tools/scripts/MOVEDlint.awk
+++ b/Tools/scripts/MOVEDlint.awk
@@ -36,21 +36,36 @@ BEGIN {
portsdir = ENVIRON["PORTSDIR"] ? ENVIRON["PORTSDIR"] : "/usr/ports"
if (ARGC == 1) {
ARGV[ARGC++] = portsdir "/MOVED"
- if (ENVIRON["BLAME"]) {
- if (!system("test -r " portsdir "/.git")) {
- blame = "cd " portsdir "; git blame MOVED 2>/dev/null"
- }
-
+ }
+ if (ENVIRON["BLAME"]) {
+ blame=1
+ }
+ if (blame) {
+ if (!system("test -r " portsdir "/.git")) {
+ blame = "cd " portsdir "; git blame MOVED 2>/dev/null"
}
}
sort = "/usr/bin/sort -n"
- lastdate="1999-12-31"
+ if (!lastdate) {
+ lastdate="1999-12-31"
+ } else if (lastdate !~ /^20[0-3][0-9]-[01][0-9]-[0-3][0-9]$/) {
+ printf "Invalid date format '%s' expecting YYYY-MM-DD\n", lastdate
+ exit(1)
+ }
}
/^(#|$)/ {
next
}
+!started && $3 < lastdate {
+ next
+}
+
+!started && $3 >= lastdate {
+ started = 1
+}
+
NF != 4 {
printf "%5d: format is from|to|date|reason, detected %d field(s) \n", NR, NF | sort
error[NR] = 1
@@ -69,6 +84,18 @@ $3 !~ /^20[0-3][0-9]-[01][0-9]-[0-3][0-9]$/ {
next
}
+$1 ~ /[ \t]/ {
+ printf "%5d: '%s' contains spaces\n", NR, $1 | sort
+ error[NR] = 1
+ next
+}
+
+$2 ~ /[ \t]/ {
+ printf "%5d: '%s' contains spaces\n", NR, $2 | sort
+ error[NR] = 1
+ next
+}
+
{
if ($1 in srcs) {
printf "%5d: %s has duplicate entries\n", NR, $1 | sort
@@ -96,13 +123,17 @@ $3 !~ /^20[0-3][0-9]-[01][0-9]-[0-3][0-9]$/ {
delete missing[$1]
} else {
if (from_flavor != "") {
- if (!system("test \"" from_flavor "\" = \"`make -C " portsdir "/" $1 " -VFLAVORS:M" from_flavor "`\"")) {
+ if (!system("test \"" from_flavor "\" = \"`make -C " portsdir "/" $1 " -VFLAVORS:M" from_flavor " __MAKE_CONF=/dev/null`\"")) {
printf "%5d: %s still has the %s flavor\n", NR, $1, from_flavor | sort
}
# No else because the port is there but does not have the flavor,
# so it should be ok.
} else {
- printf "%5d: %s must be marked as resurrected\n", NR, $1 | sort
+ if ($2 ~ $1 "@") {
+ printf "%5d: %s is a flavor of %s, the line should be removed\n", NR, $2, $1 | sort
+ } else {
+ printf "%5d: %s must be marked as resurrected\n", NR, $1 | sort
+ }
}
}
@@ -118,7 +149,7 @@ $3 !~ /^20[0-3][0-9]-[01][0-9]-[0-3][0-9]$/ {
missing[$2] = NR
else
if (to_flavor != "") {
- if (system("test \"" to_flavor "\" = \"`make -C " portsdir "/" $2 " -VFLAVORS:M" to_flavor "`\"")) {
+ if (system("test \"" to_flavor "\" = \"`make -C " portsdir "/" $2 " -VFLAVORS:M" to_flavor " __MAKE_CONF=/dev/null`\"")) {
printf "%5d: %s does not have the %s flavor\n", NR, $2, to_flavor | sort
error[NR] = 1
}
@@ -154,4 +185,6 @@ END {
}
close(sort)
+ if (length(error) > 0)
+ exit(1)
}
diff --git a/Tools/scripts/README b/Tools/scripts/README
index 1b7d2b838270..71e4ae1ac963 100644
--- a/Tools/scripts/README
+++ b/Tools/scripts/README
@@ -5,7 +5,6 @@ NOTE: These scripts need work and are *NOT* safe to use unless you know
MOVEDlint.awk - checks MOVED for common errors
ardiff - compare two archives easily
-addport - replacement for easy-import
bad-pkgdescrs.sh - locate identical pkg descriptions
bump_revision.pl - Small script to bump the PORTREVISION variable of ports
which are depending on a port with a changed shared lib
@@ -13,23 +12,24 @@ bump_revision.pl - Small script to bump the PORTREVISION variable of ports
checkcats.py - verify that master categories in all ports are correct and
report any problems. Beware that the full check takes quite
some time.
-checknewvers - checks for availability for a newest version of distfiles on
+checknewver.sh - checks for availability for a newest version of distfiles on
MASTER_SITES (ftp only).
-checksum - allows checking of ports to see if their checksums
+checksum.sh - allows checking of ports to see if their checksums
match, and if they don't, give a diff against the older version to
help discover why the checksum didn't match.
chkorigin.sh - checks all ports in the tree for a wrong PKGORIGIN.
Run this tool after every repocopy.
doportlint - run portlint on every port and return the results
-distclean - compare md5 sums of distfiles in ports/distfiles with currently
+distclean.sh - compare sha256 sums of distfiles in ports/distfiles with currently
installed ports collection in ports/* and prompt to remove
unmatched entries
getpatch - downloads patch attachments from a Bug Tracking Systems
getpatch.sh - downloads patch attachments from a Bug Tracking Systems (plain shell script)
-gnomedepends - Analyse pkg/PLIST and give an advice as to which GNOME ports
- should be listes in {RUN,LIB}_DEPENDS for this port
mark_safe.pl - utility to set subsets of ports to MAKE_JOBS_(UN)SAFE=yes
neededlibs.sh - Extract direct library dependencies from binaries.
+port_conflicts_check.lua - Verify that files installed by more than 1 port are covered
+ in CONFLICTS or CONFLICTS_INSTALL entries (and generate portedit commands
+ to fix those issues)x
portsearch - A utility for searching the ports tree. It allows more detailed
search criteria than ``make search key=<string>'' and accepts
all perl(1) regular expressions.
@@ -40,42 +40,11 @@ splitpatch.pl - A small script to convert multi-file patches to several
tindex - script used to build INDEXes for supported FreeBSD branches, which
are the source of the 'make fetchindex' INDEXes, and the build
failure reports on ports@FreeBSD.org
-update-patches - generates updated patches.
+update_crates - script used to generate an updated Makefile using make cargo-crates
+ output
----------------------------------------------------------------------
-gnomedepends is a script, which analyses pkg/PLIST and gives an advice as to
-which GNOME ports should be listes in {RUN,LIB}_DEPENDS for the port to ensure
-correct removal of GNOME shared directories. Usage is simple:
- % cd /usr/ports/CATEGORY/PORT
- % gnomedepends.py
- According to the contents of PLIST the port depends on the following GNOME
- port(s):
-
- /usr/ports/audio/gnomeaudio, for directories:
- share/gnome/sounds
-
- /usr/ports/sysutils/gnomecontrolcenter, for directories:
- share/gnome/apps
-
- /usr/ports/x11/gnomecore, for directories:
- share/gnome/apps/Games
-
- /usr/ports/x11/gnomelibs, for directories:
- etc/sound/events
- etc/sound
- share/gnome/games
- share/gnome/pixmaps
- share/gnome
-
-The example above means that you need to have ${PORTSDIR}/audio/gnomeaudio,
-${PORTSDIR}/sysutils/gnomecontrolcenter, ${PORTSDIR}/x11/gnomecore and
-${PORTSDIR}/x11/gnomelibs listed in {RUN,LIB}_DEPENDS for this port.
-Please be warned, that the this only means that the ports listed by the script
-required for correct removal of GNOME shared directories, not for the port
-functionality, so actual {RUN,LIB}_DEPENDS may have more entries.
-
-----------------------------------------------------------------------
portsearch - A utility for searching the ports tree.
portsearch is a utility to for searching of the ports tree. It permits
@@ -113,18 +82,3 @@ portsearch - A utility for searching the ports tree.
All searches are case-insensitive
See the file README.portsearch for further information.
-
-----------------------------------------------------------------------
-
-The update-patches script looks for files in $WRKSRC (if unset, this defaults
-to the work/ subdirectory of the current directory) which have a matching .orig
-file. It also looks in $PATCHDIR (if unset, this defaults to the files/
-subdirectory of the current directory) for patches that correspond to the first
-set. If the changes in an existing patch do not reflect the changes in the
-files in $WRKSRC, the script renames the existing patch by adding the suffix
-.orig and generates a new patch in its place. If no patch existed, the new one
-is created with a name that contains the path and filename of the file being
-patched, except that "/" separators and "." characters are replaced by
-underscores: for example, a new patch to $WRKSRC/foo/bar.c would be created as
-$PATCHDIR/patch-foo_bar_c. If you save a .orig backup of a file, but don't
-change the file, update-patches will generate an empty patch.
diff --git a/Tools/scripts/add-port-to-category-makefile.sh b/Tools/scripts/add-port-to-category-makefile.sh
new file mode 100755
index 000000000000..f77c46b0c90c
--- /dev/null
+++ b/Tools/scripts/add-port-to-category-makefile.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+PORT="$1"
+
+set -e
+set -o pipefail
+
+export LC_ALL=C
+
+##
+## add-port-to-category-makefile.sh: adds a new port to {category}/Makefile
+##
+
+
+# sanity checks
+[ -z "$PORT" ] && echo "this command requires the <port> argument" && exit 1
+(echo "$PORT" | grep -q "/") && echo "port's name can't contain slash" && exit 1
+! [ -f Makefile ] && echo "no Makefile found, are you in the ports tree?" && exit 1
+! grep -q "^ SUBDIR += " Makefile && echo "this command can only be run from the ports tree category directory" && exit 1
+! grep -q "^\\.include <bsd\\.port\\.subdir\\.mk>$" Makefile && echo "this command can only be run from the ports tree category directory" && exit 1
+! [ -d "$PORT" ] && echo "the '$PORT' directory is missing" && exit 1
+! [ -f "$PORT/Makefile" ] && echo "'$PORT/Makefile' is missing" && exit 1
+grep -q "^ SUBDIR += $PORT$" Makefile && echo "port '$PORT' is already added" && exit 1
+
+
+# add port to Makefile
+/usr/bin/awk '
+BEGIN {
+ done = 0
+ seen = 0
+ str = " SUBDIR += '$PORT'"
+}
+/^ SUBDIR \+= / {
+ if (!done && str < $0) {
+ print str
+ done = 1
+ }
+ print $0;
+ seen = seen + 1
+}
+!/^ SUBDIR \+= / {
+ if (seen > 0 && !done) {
+ print str
+ done = 1
+ }
+ print $0
+}' < Makefile > Makefile.new &&
+/bin/mv Makefile.new Makefile
diff --git a/Tools/scripts/addport b/Tools/scripts/addport
deleted file mode 100755
index 48e6d006ff38..000000000000
--- a/Tools/scripts/addport
+++ /dev/null
@@ -1,626 +0,0 @@
-#!/usr/bin/env perl
-#
-# addport - perl script that adds new ports to the
-# FreeBSD Ports Collection. Replaces easy-import.
-#
-# Copyright (c) 2000 Will Andrews and Michael Haro
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# Original shell script & idea: Will Andrews <will@FreeBSD.org>
-# Original conversion to Perl : Michael Haro <mharo@FreeBSD.org>
-# Maintainer alumni : Renato Botelho <garga@FreeBSD.org>
-#
-# Id: addport,v 1.2 2000/04/02 06:21:13 will Exp (original shell script)
-# Id: addport,v 1.5 2000/04/22 22:19:43 mharo Exp (perl conversion)
-#
-# MAINTAINER= crees@FreeBSD.org
-#
-
-# Smartmatch operator (~~) used
-require 5.10.1;
-
-use Cwd "abs_path";
-use Getopt::Std;
-use Sys::Hostname;
-use locale;
-use strict;
-
-# Subroutine prototypes
-sub warnx($);
-sub err($$);
-sub errx($$);
-sub prompt($);
-sub query($);
-sub usage();
-sub contains($@);
-sub lsports();
-sub lastcomment();
-
-my %opts;
-
-getopts('ac:d:fh:il:L:mns:tu:y', \%opts);
-
-my $autofill_l = $opts{'l'};
-my $autofill_L = $opts{'L'};
-my $autofill = ($autofill_l ? $autofill_l : $autofill_L);
-my $c = $opts{'c'} if ($opts{'c'} ne "");
-my $distdir = $opts{'s'} if ($opts{'s'} ne "");
-my $dir = $opts{'d'};
-my $h = "repo.FreeBSD.org";
-$h = $opts{'h'} if ($opts{'h'} ne "");
-my $u = $ENV{USER};
-$u = $opts{'u'} if ($opts{'u'} ne "");
-my $more_testing = $opts{'t'};
-my $interactive = $opts{'i'};
-my $nomkdir = $opts{'m'};
-my $addlchk = $opts{'a'};
-my $nofetch = $opts{'f'};
-my $checkexist = $opts{'y'};
-my $currentdir = abs_path(".");
-my %l10nprefix = (
- 'chinese' => 'zh-',
- 'french' => 'fr-',
- 'german' => 'de-',
- 'hebrew' => 'iw-',
- 'hungarian' => 'hu-',
- 'japanese' => 'ja-',
- 'korean' => 'ko-',
- 'portuguese' => 'pt-',
- 'russian' => 'ru-',
- 'ukrainian' => 'uk-',
- 'vietnamese' => 'vi-',
-);
-
-my $tmpdir;
-my $repo;
-my $portsdir = $ENV{PORTSDIR} ? $ENV{PORTSDIR} : '/usr/ports';
-my $repo = $ENV{ADDPSVNROOT}? $ENV{ADDPSVNROOT} : "svn+ssh://$u\@$h/ports/head";
-my $make = "make";
-my $portlint = `which portlint`; chomp $portlint;
-my $plint_args = "-N -a -c -t";
-my $perl = "perl";
-my $cp = "cp";
-my $mv = "mv";
-my $rm = "rm";
-chomp(my $svnlite = `which svnlite`);
-my $svn = ($svnlite ? $svnlite : "svn");
-my $keyword = '\$FreeBSD\\\$';
-# vars required for commitfile
-my $descr; my $portversion; my $pkgcomment;
-my $tmp; my $pkgcommentlen; my $comment; my $maintainer = "";
-my $maintaineraddr; my $tmp2; my $offset; my $commitfile = "";
-my $moved = "";
-$tmp = $tmp2 = $offset = 0;
-
-# Check the editor.
-my $edit = "/usr/bin/vi";
-$edit = $ENV{EDITOR} if ($ENV{EDITOR} ne "");
-
-# Check svn version
-my $svnversion = `$svn --version --quiet 2>/dev/null`;
-chomp $svnversion;
-if ($svnversion eq "") {
- errx(1, "Subversion binary not found in \$PATH, aborting.");
-}
-my @svnversion = split(/\./, $svnversion);
-if ($svnversion[0] == 1 && $svnversion[1] < 7) {
- errx(1, "minimum Subversion version of 1.7 not met, aborting.");
-}
-
-# stuff that always happens when we start
-BEGIN {
- $tmpdir=`mktemp -d -t ap`;
- chomp $tmpdir;
- if ($tmpdir eq "") {
- errx(1,"making random tmpdir didn't work, aborting.");
- }
-}
-
-# stuff that always happens when we exit
-END {
- # only remove $tmpdir if it points to something in /tmp
- # this is a silly little security thing
- if (defined($rm) && defined($tmpdir)) {
- system("$rm -rf $tmpdir") if ($tmpdir =~ m,/tmp/,);
- }
-}
-
-# setup the list of commands to run on the new port(s).
-my @commands;
-my $passenv = "";
-if ($addlchk && -f $portlint) {
- $passenv = "DISTDIR=\"$distdir\"" if -d $distdir;
- $passenv = $passenv . " PORTSDIR=\"$portsdir\"" if !$nomkdir;
- push(@commands, "$make $passenv clean check-categories");
- push(@commands, "$portlint $plint_args");
- push(@commands, "$make $passenv FETCH_BEFORE_ARGS='-A' checksum") if !$nofetch;
- if ($more_testing) {
- push(@commands, "$make $passenv distclean");
- push(@commands, "$make $passenv build");
- push(@commands, "$make $passenv distclean");
- }
- if (!$nomkdir) {
- chdir $tmpdir;
- print "Checking out Mk directory to ensure portlint correctness.\n";
- system("$svn co $repo/Mk Mk") && errx(1, "Could not checkout Mk directory");
- system("$svn co $repo/Templates Templates") && errx(1, "Could not checkout Templates directory");
- chdir $currentdir;
- }
-}
-
-if ($dir eq "") {
- warnx("Need to specify a directory with -d argument!");
- usage();
- exit 1;
-}
-
-# check the port doesn't exist already
-
-if ($checkexist) {
- my $found = 0;
- print ">> Fetching INDEX to scan for duplicates...\n";
- my $indexfile = "$tmpdir/" . `$make -C $portsdir -V INDEXFILE`;
- system("$make -C /usr/ports INDEXDIR=$tmpdir fetchindex") && errx(1, "Could not fetch INDEX file.");
- my @namepart;
- foreach (split(/\,/, $dir)) {
- s/^.*\///;
- foreach (split(/[-_]/)) {
- next if length () <=2 or /^rubygem$/;
- push(@namepart, $_);
- }
- }
- open(INDEXFILE, "< $indexfile") or errx(1, "$indexfile unreadable.");
- while (my $line = <INDEXFILE>) {
- $line =~ m,^[^|]*\|/usr/ports/[^/]*/([^|]*)\|,;
- $line = $1;
- foreach my $dpart (@namepart) {
- if ($line =~ /^[^ ]*\b$dpart\b/i) {
- $line =~ s/\s+/ /g;
- print "$dpart matches $line\n";
- $found = 1;
- }
- }
- }
- if ($found) {
- prompt ("Possible duplicates found -- still OK?")
- and errx(1, "Investigating duplicates");
- }
-}
-
-# make sure we're in the right place.
-chdir $currentdir;
-my @dirs = split(/\,/, $dir);
-foreach my $i (@dirs) { $i = abs_path($i); }
-my $portname; my $wrapat;
-foreach my $thisdir (@dirs) {
- # make double sure where we are..
- chdir $thisdir;
- # do some dir sanity checking first
- errx(1, "Please specify valid directories to import new ports from.") if $thisdir eq "";
- errx(1, "$thisdir is either not a directory or does not exist.") if (! -d $thisdir);
-
- print "Working with port directory $thisdir.\n";
-
- $portname = `basename $thisdir`; # avoid problems with dirs containing `/' in cvs
- chomp $portname;
- warnx("Port directory contains upper-case character! Please try using an all lower-case name to make everybody's life a bit easier.") if ($portname =~ /[A-Z]/);
- if ($interactive) {
- if (prompt("Port directory name will be $portname in SVN Repo. OK? ")) {
- do {
- $portname = query("Preferred name for port directory? ");
- } while (prompt("Is the new name $portname OK? "));
- }
- }
-
- chdir $thisdir or err(1, "$thisdir");
-
- # now run the tests on this baby.
- for (@commands) {
- system("$_") && errx(1, "'$_' had problems. aborting.");
- }
-
- # Get the category name and make it suitable for use with svn
- my @categories = split(/ /, `$make -VCATEGORIES`);
- my $category = $categories[0];
- if ($interactive) {
- if (prompt("Port $portname will be put in category $category. OK? " )) {
- do {
- $category = query("Preferred category for $portname? ");
- } while (prompt("Is the new category $category OK? "));
- }
- }
- chomp $category;
-
- # Do commitfile checking but only if the user did not request automatic filling.
- if (!$autofill) {
- if (-f $c) {
- system("$mv $c $tmpdir/commitfile") && errx(1, "Oops, can't move commitfile!");
- print "\nRemember, you asked to use a commit file to read for the commit log.\n";
- print "This means you'll get a message saying the log message was unchanged or\n";
- print "not specified. Just tell it to continue and it will be committed.\n\n";
- $commitfile = "--file $tmpdir/commitfile";
- }
- } else {
- ## Set up the autofill file.
- # Read COMMENT for part of the commit message.
- if ($autofill_l) {
- chomp($pkgcomment = `$make $passenv -V COMMENT`);
- # Change the first character to lowercase to make it fit with the
- # rest of the commit message, only if the second is not upper case.
- $pkgcomment =~ s/(^.)(?![A-Z])/\l$1/;
- $pkgcomment .= ".";
- $pkgcomment .= "\n\n" if ($autofill != -1);
- } else {
- $pkgcomment = `cat pkg-descr`;
- $pkgcomment .= "\n" if ($autofill != -1);
- }
- chomp($maintaineraddr = `$make $passenv -V MAINTAINER`);
- chomp($portversion = `$make $passenv -V PORTVERSION`);
- # Read Makefile to find necessary variables.
- open(MAKEFILE, "Makefile") or die("Can't open Makefile for reading: $!");
- while(<MAKEFILE>) {
- chomp;
- die ("Old style Makefile headers detected") if (/^# (?:[Nn]ew )?[Pp]orts collection [Mm]akefile/);
- ($maintainer) = (m/^# Created by:\s+(\w.*)$/) if (/^# Created by/);
- }
- close(MAKEFILE);
- $maintainer = $maintaineraddr unless ($maintainer);
- # Write out the data to the comment file.
- open(AUTOFILL, "> $tmpdir/commitfile") or die("Can't open $tmpdir/commitfile for writing: $!");
- if ($autofill_l) {
- # pretty print; wrap @ 72 characters
- $tmp = "Add $portname $portversion, $pkgcomment";
- $wrapat = 72;
- while($wrapat > 1) {
- $tmp2 = $tmp;
- $tmp =~ s/(.{$wrapat}([^ ]+)?) /$1\n/g;
- last unless $tmp =~ /^[^\n]{73}/;
- $wrapat--;
- $tmp = $tmp2;
- }
- } else {
- $tmp = $pkgcomment;
- }
- print AUTOFILL $tmp;
- print AUTOFILL "PR: $autofill\n" if ($autofill != -1);
- print AUTOFILL "Submitted by: $maintainer" if ($maintainer && $autofill != -1);
- close(AUTOFILL);
- print "Okay, a commit log message was automatically generated for you.\n";
- print "Now you will have a chance to edit it to make sure it's OK to use.\n";
- print "Here's the contents of the file:\n--start--\n";
- open(AUTOFILL, "$tmpdir/commitfile") or die("Can't open $tmpdir/commitfile for reading: $!");
- print while (<AUTOFILL>);
- close(AUTOFILL);
- $tmp = prompt("\n--end--\nDo you wish to edit the file before continuing? ");
- system("$edit $tmpdir/commitfile") if ($tmp == 0);
- print "\nRemember, you asked to use a commit file to read for the commit log.\n";
- print "This means you'll get a message saying the log message was unchanged or\n";
- print "not specified. Just tell it to continue and it will be committed.\n\n";
- $commitfile = "--file $tmpdir/commitfile";
- }
-
- print "We're ready to commit.\n";
- print "Source directory: $thisdir\n";
- print "Target SVN Repo directory: ports/$category/$portname\n";
- prompt("Adding port $portname to $category OK? ") && errx(1, "user abort requested");
-
- chdir $tmpdir or err(1, "$tmpdir");
-
- # let's get our hands dirty.
- if (! -d "ports") {
- system("$svn co --depth empty $repo ports") && errx(1, "can't get ports root, aborting.");
- }
- chdir "ports" or err(1,"ports");
- if (! -d "$category") {
- system("$svn up --depth files $category") && errx(1, "can't get temporary category directory, aborting.");
- }
- chdir $category or err(1,"$category");
-
- # check for previous existence of port -- on the way use filthy
- # home-made XML parser.
- # Until svn revs are in the database, we'll use dates.
- print "Checking for previous versions of $category/$portname... \n";
- my $previous_incarnation = "bogus";
- my $oldportlist = `/usr/bin/fetch -qo - http://people.FreeBSD.org/~crees/removed_ports/index.xml`;
- if ($oldportlist !=~ /^fetch:[^:]+: Not Found/) {
- foreach (split("\n", $oldportlist)) {
- if (/^ +\<port\>$category\/$portname(?:\<removed_revision\>r([0-9]*)\<\/removed_revision\>)?\<removed_date\>([^<]*)/) {
- print "Found one!\n";
- if ($1 == "") {
- $previous_incarnation = $2;
- $previous_incarnation =~ s,/,-,g;
- print "This port was last alive on $previous_incarnation.\n";
- $previous_incarnation = "\{$previous_incarnation\}";
- } else {
- $previous_incarnation = $1 - 1;
- print "The last living revision of this port was r$previous_incarnation.\n";
- }
- last;
- }
- }
- } else {
- print "Could not fetch list-- perhaps the site is down.";
- }
- if ($previous_incarnation ne "bogus") {
- print "Fetching older version... ";
- system("$svn cp -q '$repo/$category/$portname\@$previous_incarnation' .");
- print "[DONE]\n";
- print "Removing irrelevant files and directories... ";
- my @oldfiles = split("\0", `cd $portname && find . -type f -print0`);
- my @olddirs = split("\0", `cd $portname && find . -type d -print0 | sort -r`);
- my @newfiles = split("\0", `cd $thisdir && find . -type f -print0`);
- my @newdirs = split("\0", `cd $thisdir && find . -type d -print0| sort -r`);
-
- foreach my $file (@oldfiles) {
- system("cd $portname && $svn rm $file")
- if !($file ~~ @newfiles)
- }
-
- foreach my $directory (@olddirs) {
- system("cd $portname && $svn rm $directory")
- if !($directory ~~ @newdirs);
- }
-
- print "[DONE]\n";
-
- # Remove cvs2svn props if present
- print "Removing cvs2svn props...\n";
- system("$svn propdel -qR cvs2svn:cvs-rev $portname");
-
- $moved = "MOVED";
- print "Removing port's entry from $moved...\n";
- system("cd .. && $svn up -q $moved && sed -i '' -e '\\,^$category/$portname\|\|,d' $moved");
-
- # Add note to log about readdition
- system("echo '(Readdition of $category/$portname which was removed on $previous_incarnation)\n' > $tmpdir/commitfile.tmp && cat $tmpdir/commitfile >> $tmpdir/commitfile.tmp && mv $tmpdir/commitfile.tmp $tmpdir/commitfile") unless ($commitfile eq "");
-
- } else {
- print "[none found]\n";
- }
- system("$cp -PRp $thisdir .");
- system("$svn add --force --depth empty `find $portname -type d | grep -v '^$portname/work'`") && errx(1, "svn add for dirs failed, aborting.");
-
- system("$svn add --force `find $portname -type f | grep -v '^$portname/work'`") && errx(1, "svn add for files failed, aborting.");
-
- # Find keywords in old files and strip
- print "Stripping any keywords...\n";
- system("sed -i '' -e 's,\\\$Free" . "BSD:[^\$]*\\\$,\$Free" . "BSD\$,' \$(find $portname -type f)");
-
- # find files with keywords in and propset
-
- print "Setting correct properties on files...\n";
-
- my @portfiles = split("\0", `find $portname -type f -print0`);
- my $portfiles = join(" ", @portfiles);
- my @keywordfiles = split("\n", `grep -l $keyword $portfiles`);
- foreach (@portfiles) {
- if ($_ ~~ @keywordfiles) {
- system("$svn -q propset svn:keywords FreeBSD=%H $_");
- system("$svn -q propdel fbsd:nokeywords $_");
- } else {
- system("$svn -q propset fbsd:nokeywords on $_");
- system("$svn -q propdel svn:keywords $_");
- }
- }
-
- # strip svn:executable if added-- not allowed
-
- system("cd $portname && $svn -qR propdel svn:executable");
-
- # figure out where the port name belongs in category Makefile
- my ($spaces, @ports) = &lsports;
- errx(1, "Error: $portname already exists in $category\'s Makefile") if (&contains($portname, @ports));
- my $port = "";
- foreach my $tmp (sort(@ports)) {
- if ($tmp gt $portname) {
- $port = $tmp;
- last;
- }
- }
-
- # now let's insert it
- my $cmd;
- if (scalar @ports == 0) {
- # there were no previous SUBDIR += lines, so we're going to
- # put ourselves after the last comment (we can't be after a
- # .include <bsd.port.subdir.mk> for example).
- my $lastcommentnum = &lastcomment;
- $cmd = "$lastcommentnum\n+\ni\n";
- } else {
- if ($port eq "") {
- # there were previous SUBDIR lines, but none was greater than we are,
- # means, we're the last port, so, add ourselves after the last port
- $port = $ports[$#ports];
- $cmd = "/^" . $spaces . "SUBDIR += $port/\na\n";
- } else {
- # OK, append ourselves in the right place, so things *stay* sorted.
- $cmd = "/^" . $spaces . "SUBDIR += $port/\ni\n";
- }
- }
- print "Inserting new port into $category/Makefile...\n";
- open(ED, "|ed Makefile") || die "Cannot start ed to actually insert module\n";
- print ED "$cmd" . $spaces . "SUBDIR += $portname\n.\nw\nq\n";
- close(ED);
-
- # commit the actual port.
- chdir "$tmpdir/ports" or err(1, "$tmpdir/ports");
- if ($opts{'n'}) {
- print "Faking commit....\n";
- } else {
- system("$svn ci $commitfile $moved $category/Makefile $category/$portname") && errx(1, "svn commit failed, aborting.");
- }
-}
-
-print <<EOF;
-You're done! The new port $portname has been completely imported in
-the tree. Don't forget to add the creator's name and email address to
-the Contributors' List if they are not already there. To do this, edit
-documentation/content/en/articles/contributors/contrib-additional.adoc.
-EOF
-
-sub warnx($) {
- my ($msg) = @_;
- print STDERR $0 . ": " . $msg . "\n";
-}
-
-sub err($$) {
- my ($ex, $msg) = @_;
-
- warnx("WARNING: err called incorrectly") if (($ex !~ m/^\d+/) || ($msg eq ""));
- print STDERR $0 . ": " . $msg . ": $!\n";
- exit $ex;
-}
-
-sub errx($$) {
- my ($ex,$msg) = @_;
-
- warnx("WARNING: errx called incorrectly") if (($ex !~ m/^\d+/) || ($msg eq ""));
- print STDERR $0 . ": " . $msg . "\n";
- exit $ex;
-}
-
-sub prompt($) {
- my ($msg) = @_;
- my $reply = query($msg);
- return 0 if ($reply =~ m/^[Yy]/);
- return 1 if ($reply =~ m/^[Nn]/);
-}
-
-sub query($) {
- my ($msg) = @_;
-
- print "$msg";
- my $reply = <>;
- chomp $reply;
- return $reply;
-}
-
-sub usage() {
-#addport,v \$Revision: 1.21 $
-print <<EOF;
-authors: <will\@FreeBSD.org>, <mharo\@FreeBSD.org>
-
-SYNOPSIS
- $0 [-c commitfile] [-h host] [-l PR number | -L PR number]
- [-s distdir] [-u user] [-afimnty] -d directory
-
- Where "directory" contains the comma-delimited list
- of root directories of new ports that you wish to
- add to the Ports Collection. The name of this directory
- *WILL* matter in regards to the repository!
-
-OPTIONS
- -a Perform checks on the port to make sure
- there are no problems. Recommended.
- -c file Use file in place of normal log message.
- -f Do not fetch the distfile.
- -h host Use a svnhost besides repo.FreeBSD.org.
- -i Interactive mode; allow more control over
- where things are placed.
- -l PR# Attempts to autogenerate a commit message by
- reading the Makefile file.
- The PR number must be passed to -l. If there is
- no PR (i.e., self-created or submitted in
- private email), use PR# -1.
- -L PR# Like -l but it'll generate commit message based
- on pkg-descr
- -m Do not checkout ports/Mk (needed for support
- of portlinting etc).
- -n Do not actually commit anything.
- -s distdir Use a different directory besides the default,
- for downloading distfiles.
- -t Do more port testing. Requires -a.
- -u user Use a different username (default: $u).
- -y Check for similarly named ports.
-
-ENVIRONMENT VARIABLES
- $0 supports the following environment variables:
-
- ADDPSVNROOT - Location of SVN repository.
- USER - Username of user invoking $0.
-
-EXAMPLES
- % addport -n -d greatgame,helpfuldev,shoot
- Will show what happens but not actually commit ports
- named "greatgame", "helpfuldev", and "shoot".
-
- % addport
- Displays this message. :-)
-
-EOF
-}
-
-sub contains($@) {
- # look if the first parameter is contained in the list following it
- my ($item, @list) = @_;
-
- foreach my $i (@list) {
- return 1 if $i eq $item;
- }
- return 0;
-}
-
-sub lsports() {
- my @rv = ();
- my $spaces;
-
- open(F, "Makefile") || die "can't open Makefile: $!";
- while(<F>) {
- chomp;
- chomp;
- next if $_ !~ m/SUBDIR/;
-
- if ( !defined($spaces) ) {
- m/^([\s\t]+)[^\s\t]/;
- $spaces = $1;
- }
-
- s/^[ \t]+SUBDIR[ \t]+\+?=[\ \t]+//;
- push(@rv, $_);
- }
- close(F);
-
- return ($spaces, @rv);
-}
-
-# this finds the last comment in the Makefile
-sub lastcomment() {
- my $num = 0;
- my $diff = 0;
-
- open(F, "Makefile");
- while(<F>) {
- chomp;
- if ($_ =~ m/^#/) {
- $num += $diff;
- $num++;
- $diff = 0;
- } else {
- $diff += 1;
- }
- next;
- }
- return $num;
-}
-
diff --git a/Tools/scripts/ai-master-prompt.md b/Tools/scripts/ai-master-prompt.md
new file mode 100644
index 000000000000..e14f45c92651
--- /dev/null
+++ b/Tools/scripts/ai-master-prompt.md
@@ -0,0 +1,53 @@
+<!--
+ai-master-prompt.md: master prompt file for AI assistants to know how to perform
+ various simple operations on ports and ports tree.
+ AI assistants find it by using the .env file in the root of
+ the repository, or by using relevant environment variables.
+ For example, the Google's gemini AI assistant can use
+ GEMINI_SYSTEM_MD to find this file.
+
+MAINTAINER: yuri@FreeBSD.org
+-->
+
+# Project Context: FreeBSD ports
+
+## General Instructions
+- Individual port directories are under category directories: {category}/{port directory}
+- In order to perform operations on an individual port you need to change directory into this port.
+- In every port's directory there is a Makefile.
+- WRKDIR of every port can be determined by the command 'make -V WRKDIR'
+- WRKSRC of every port can be determined by the command 'make -V WRKSRC'
+- When any port is updated, the distinfo file can be regenerated using the 'make makesum' command.
+- Any port can download and extract the source files using the 'make patch' command.
+- Working directory can be removed (cleaned) using the 'make clean' command.
+- PORTREVISION should be removed when DISTVERSION or PORTVERSION is updated.
+- Any FreeBSD package that is needed can be installed using the command 'sudo pkg install -A {package name}'.
+- In case if any work* directories are present in the port directory before the port update such directories should be removed by the 'make clean' command.
+- The USES variable in port's Makefile defines what type of port this is.
+ - When USES contains the word 'gmake' this is a port that is built using GNU Make (using the the gmake executable).
+ - When USES contains the word 'cmake' this is a port that is built using cmake.
+ - When USES contains the word 'python' this is a Python based port.
+ - When USES contains the word 'cargo' this is a Rust based port.
+ - When USES contains the word 'cabal' this is a Haskell based port.
+- Port uses GitHub to fetch distfiles if it has the USE_GITHUB=yes line.
+- Every port has a maintainer, maintainer's e-mail address is in the MAINTAINER variable.
+
+### Instructions for ports that use GitHub to fetch distfiles
+- GitHub account name of such ports is in GH_ACCOUNT, or otherwise PORTNAME is used as an account name.
+- GitHub project name of such ports is in GH_PROJECT, or otherwise PORTNAME is used as a project name.
+- The GitHub git URL is constructed as https://github.com/{GH_ACCOUNT}/{GH_PROJECT}.git
+- The latest released version of a git URL can be determined using the command '../../Tools/scripts/git-get-latest-remote-version.sh {Git-URL} {DISTVERSIONPREFIX}'
+
+### Instructions for Python based ports
+- The latest released version of the software can be determined using the command '../../Tools/scripts/pypi-get-latest-version.sh {python project name}'
+- Dependencies need to be updated when the port is updated. They need to be compared with the dependency requirements set in the project.
+- setuptools build dependency should never be added to BUILD_DEPENDS, and instead the distutils element should be present in USE_PYTHON.
+- numpy dependency should be added as ${PYNUMPY} instead of the usual syntax. No version information should be added in this case.
+- pillow dependency should be added as ${PY_PILLOW} instead of the usual syntax. No version information should be added in this case.
+- The cython build dependency should never be added to BUILD_DEPENDS. Instead, the cython element should be added to USE_PYTHON for cython dependencies of versions 1.x or 2.x, and the cython3 element should be added to USE_PYTHON for cython dependencies of versions 3.x
+- Do not add upper version limits for Python based ports.
+- Always replace exact version comparison in dependencies with >=.
+
+### Instructions for Haskell based ports
+- Directories of all Haskell ports have the prefix "hs-".
+- The latest released version of the software can be determined using the command '../../Tools/scripts/haskell-get-latest-version.sh {haskell project name}'
diff --git a/Tools/scripts/bump_revision.pl b/Tools/scripts/bump_revision.pl
index ff7eb5d07e09..da306eca6097 100755
--- a/Tools/scripts/bump_revision.pl
+++ b/Tools/scripts/bump_revision.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/env -S perl -wT
+#!/usr/bin/env -S perl -wt
#
# This script helps with bumping the PORTREVISION of all ports that depend on a
@@ -20,10 +20,13 @@ use strict;
use Getopt::Std;
use Carp 'verbose';
use Cwd;
-use Data::Dumper;
use File::Basename;
+use Data::Dumper;
+$Data::Dumper::Indent = 1; # simple indent
+$Data::Dumper::Purity = 1; # Perl syntax
+my $debug = 0;
-use vars qw/$opt_n $opt_f $opt_i $opt_u $opt_l $opt_g $opt_p/;
+use vars qw/$opt_n $opt_f $opt_i $opt_u $opt_l $opt_g $opt_p $opt_h/;
# launder environment
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
@@ -34,8 +37,8 @@ sub usage {
Usage: $0 [options] [<category>/]<portname>
Options:
- -l - shaLlow, only bump ports with direct dependencies.
- -g - Grandchildren, also bump for indirect dependencies (default).
+ -l - shaLlow, only bump ports with direct dependencies. (default).
+ -g - Grandchildren, also bump for indirect dependencies.
-n - Check only (dry-run), do not change Makefiles.
-f - No tmpdir, just use the directory where INDEX resides.
-i <filename> - Use this for INDEX name. Defaults to \${PORTSDIR}/INDEX-n,
@@ -51,51 +54,58 @@ EOF
$| = 1;
sub bumpMakefile {
+ my ($taintedorigin) = @_;
+ my $origin;
+
+ if ($taintedorigin =~ /^([-\@\w.\/]+)$/) {
+ $origin = $1;
+ } else {
+ Carp::carp "cannot untaint $taintedorigin - invalid characters";
+ return;
+ }
- my ($p) = @_;
-
- my $makefile = "$p/Makefile";
+ my $makefile = "$origin/Makefile";
my $fin;
- unless(open($fin, $makefile)) {
- print "-- Cannot open Makefile of $p, ignored.\n";
- next;
- }
- my @lines = <$fin>;
- if ($!) { die "Error while reading $makefile: $!. Aborting"; }
- close($fin) or die "Can't close $makefile b/c $!";
- chomp(@lines);
+ unless(open($fin, $makefile)) {
+ print "-- Cannot open Makefile of $origin, ignored.\n";
+ return;
+ }
+ my @lines = <$fin>;
+ if ($!) { die "Error while reading $makefile: $!. Aborting"; }
+ close($fin) or die "Can't close $makefile b/c $!";
+ chomp(@lines);
- my $revision = 1;
+ my $revision = 1;
- foreach my $line (@lines) {
- last if ($line =~ /^MAINTAINER/);
- $revision += $1 if ($line =~ /PORTREVISION\??=[ \t]*(\d+)$/);
- }
+ foreach my $line (@lines) {
+ last if ($line =~ /^MAINTAINER/);
+ $revision += $1 if ($line =~ /PORTREVISION\??=[ \t]*(\d+)$/);
+ }
- my $printedrev = 0;
- open(my $fout, '>', "$makefile.bumped");
- foreach my $line (@lines) {
- if (!$printedrev) {
- if ($line =~ /^CATEGORIES??=/ || $line =~ /^PORTEPOCH??=/) {
- print $fout "PORTREVISION= $revision\n";
- $printedrev = 1;
- # Fall through!
- }
- if ($line =~ /^PORTREVISION\?=/) {
- print $fout "PORTREVISION?= $revision\n";
- $printedrev = 1;
- next;
- }
- if ($line =~ /^PORTREVISION=/) {
- print $fout "PORTREVISION= $revision\n";
- $printedrev = 1;
- next;
- }
+ my $printedrev = 0;
+ open(my $fout, '>', "$makefile.bumped");
+ foreach my $line (@lines) {
+ if (!$printedrev) {
+ if ($line =~ /^CATEGORIES??=/ || $line =~ /^PORTEPOCH??=/) {
+ print $fout "PORTREVISION= $revision\n";
+ $printedrev = 1;
+ # Fall through!
+ }
+ if ($line =~ /^PORTREVISION\?=/) {
+ print $fout "PORTREVISION?= $revision\n";
+ $printedrev = 1;
+ next;
+ }
+ if ($line =~ /^PORTREVISION=/) {
+ print $fout "PORTREVISION= $revision\n";
+ $printedrev = 1;
+ next;
}
- print $fout "$line\n";
}
- close($fout) or die "Can't close $makefile b/c $!";
- rename "$makefile.bumped", $makefile or die "Can't rename $makefile.bumped to $makefile: $!";
+ print $fout "$line\n";
+ }
+ close($fout) or die "Can't close $makefile b/c $!";
+ rename "$makefile.bumped", $makefile or die "Can't rename $makefile.bumped to $makefile: $!";
}
my $osversion = `uname -r`;
@@ -107,14 +117,16 @@ my ($portsdir, $INDEX);
{
$opt_i = "";
$opt_u = "";
- getopts("fgi:lnu:p:") or die "Aborting";
+ getopts("fghi:lnu:p:") or die "Aborting";
+ usage() if $opt_h;
+ if ($ENV{'DEBUG'}) { $debug = $ENV{'DEBUG'}; }
$shallow = $opt_l if $opt_l;
if ($opt_l and $opt_g) {
die "Options -g and -l given, which are mutually exclusive. Pick either.";
}
if (not $opt_l and not $opt_g) {
- warn "Neither -g nor -l given. Defaulting to -g";
- $opt_g = 1;
+ warn "Neither -g nor -l given. Defaulting to -l";
+ $opt_l = 1;
}
$portsdir = $opt_p ? $opt_p : '/usr/ports';
@@ -132,8 +144,8 @@ my $TMPDIR = File::Basename::dirname($INDEX);
#
# Sanity checking
#
-if (-d "$TMPDIR/.svn" and not $opt_f and not $opt_n) {
- die "$TMPDIR/.svn exists, cowardly refusing to proceed.\n";
+if (-d "$TMPDIR/.git" and not $opt_f and not $opt_n) {
+ die "$TMPDIR/.git exists, cowardly refusing to proceed.\n";
}
@@ -160,49 +172,52 @@ my %index = ();
my @a;
my @b;
- my $port;
+ my $origin;
+ my $cat_port;
+ my $pkgname;
map {
- @a = split(/\|/, $_);
+ @a = split(/\|/, $_); # columns per PORTINDEX(5) aka INDEX(5)
@b = split(/\//, $a[1]);
- $port = $b[-2]."/".$b[-1];
+ $cat_port = $b[-2]."/".$a[0];
+ $cat_port =~ s/-[^-]+$//;
+ $origin = $b[-2]."/".$b[-1];
+
+ unless ($b[-1]) { die "undefined portname"; }
+ unless ($origin) { die "undefined origin"; }
- @{ $index{$port} }{'portname', 'portnameversion', 'origin', 'comment', 'deps'}
- = ($b[-1], $a[0], $port, $a[3], ());
+ @{ $index{$a[0]} }{'portname', 'origin', 'comment', 'deps'}
+ = ($b[-1], $origin, $a[3], ());
- if ($a[8]) {
+ if ($a[8]) { # run dependencies
@b = split(" ", $a[8]);
- @{ $index{$port}{deps} }{@b} = (1) x @b;
+ @{ $index{$a[0]}{deps} }{@b} = (1) x @b;
}
-
+ undef;
} @lines;
+
print "- Processed ", scalar keys(%index), " entries.\n";
+ if ($debug and $debug > 1) {
+ print STDERR Dumper(\%index);
+ }
}
my %DEPPORTS = ();
+my %byorigin = map { ($index{$_}{'origin'} => $_) } keys %index;
+my %byportname = map { ($index{$_}{'portname'} => $_) } keys %index;
+
foreach my $PORT (@ARGV) {
#
# See if the port really exists.
# If specified as category/portname, that should be enough.
# If specified as portname, check all categories for existence or duplicates.
#
- unless (defined $index{$PORT}) {
- my @found = grep /\/$PORT$/, keys(%index);
- my $count = @found;
-
- if ($count == 0) {
- die "Cannot find ${PORT} in ${INDEX}.";
- } elsif ($count == 1) {
- $PORT = $found[0];
- } else {
- my $n = join(" ", @found);
- die "Found ${PORT} more than once in ${INDEX}: $n. Try category/$PORT.\nAborting";
- }
- }
-
- my $PORTNAMEVERSION = $index{$PORT}{portnameversion};
- print "Found $PORT as $PORTNAMEVERSION\n";
+ my $r = $index{$PORT};
+ if (!defined $r) { $r = $byportname{$PORT}; }
+ if (!defined $r) { $r = $byorigin{$PORT}; }
+ if (defined $r) { print "Found $PORT as $r.\n"; $PORT = $r; }
+ else { die "Cannot find $PORT in $INDEX! Aborting"; }
#
# Figure out all the ports depending on this one.
@@ -212,7 +227,8 @@ foreach my $PORT (@ARGV) {
my $count = 0;
foreach my $p (keys(%index)) {
- if (defined $index{$p}{'deps'}{$PORTNAMEVERSION}) {
+ my $q = $index{$p}{'deps'}{$PORT};
+ if ($q) {
$DEPPORTS{$p} = 1;
++$count;
}
@@ -225,6 +241,7 @@ foreach my $PORT (@ARGV) {
# In shallow mode, strip all those who don't have a direct dependency
#
sub direct_dependency($@) {
+ if ($debug) { print STDERR Dumper \@_; }
my ($port, @requisites) = @_;
open F, '-|', '/usr/bin/make', '-C', $port, qw/-V _RUN_DEPENDS -V _LIB_DEPENDS/ or die "cannot launch make: $!";
my @lines = <F>;
@@ -232,7 +249,7 @@ sub direct_dependency($@) {
my $deps = join(" ", @lines);
my %deps = map { $_ =~ s[/usr/ports/][]; $_ =~ s[$portsdir/][]; ($_ => 1) } split " ", $deps;
if ($!) { die "cannot read depends from make: $!"; }
- close F or die "cannot read depends from make: $!";
+ close F or Carp::carp "cannot read depends from make: $!";
my $required = grep { $_ } map { defined $deps{$_} } @requisites;
return $required;
}
@@ -241,9 +258,11 @@ if ($shallow) {
my $n = keys %DEPPORTS;
my $idx = 1;
foreach my $p (keys %DEPPORTS) {
- print "- Checking requisites of port $idx/$n...\r";
+ print "- Checking requisites of port $idx/$n... \r";
+ print "\n" if $debug;
++$idx;
- unless (direct_dependency($p, @ARGV)) {
+ my $pp = $index{$p}->{'origin'};
+ unless (direct_dependency($pp, map { $index{$_}{origin} } @ARGV)) {
delete $DEPPORTS{$p};
}
}
@@ -258,6 +277,7 @@ my $ports = join(" ", keys %DEPPORTS);
#
unless ($opt_f or $opt_n) {
$TMPDIR = ".bump_revision_pl_tmpdir.$$";
+ die "This code fragment has not been updated for Git yet.";
print "svn checkout into $TMPDIR...\n";
mkdir($TMPDIR, 0755);
chdir($TMPDIR);
@@ -272,9 +292,11 @@ unless ($opt_f or $opt_n) {
{
print "Updating Makefiles\n";
foreach my $p (sort keys(%DEPPORTS)) {
- print "- Updating Makefile of $p\n";
- next if $opt_n;
- bumpMakefile "$p";
+ my $origin = $index{$p}->{'origin'};
+ print "- Updating Makefile of $origin\n";
+ unless($opt_n) {
+ bumpMakefile "$origin";
+ }
}
}
@@ -288,7 +310,7 @@ thing remains: Committing to the ports tree. This program is not
going to do that for you, you have to do it manually.
\$ cd $TMPDIR
-\$ svn commit
+\$ git commit
Then, remove the temp directory ($TMPDIR).
EOF
diff --git a/Tools/scripts/find-work-for-installed-ports.sh b/Tools/scripts/find-work-for-installed-ports.sh
new file mode 100755
index 000000000000..e9ad442aca88
--- /dev/null
+++ b/Tools/scripts/find-work-for-installed-ports.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+# Tool to find work (such as unassigned Bugzilla PRs) to port committers or
+# perhaps other developers based on the list of locally installed ports.
+# More sources can be added later (such as GitHub pull requests).
+#
+# SPDX-License-Identifier: BSD-2-Clause
+# Copyright (c) 2025 René Ladan <rene@FreeBSD.org>
+# MAINTAINER=rene@FreeBSD.org
+
+set -eu
+
+# Look for PRs in Bugzilla having $1 in the summary line (as opposed to the full
+# PR content), and add each such PR to the output (PR number, assignee, summary)
+# if it is not assigned some FreeBSD.org, with the exception of
+# ports-bugs@FreeBSD.org. The matching is case-insensitive.
+get_PRs()
+{
+ catport=${1}
+ category="$(echo "${catport}" | cut -f 1 -d /)"
+ port="$(echo "${catport}" | cut -f 2 -d /)"
+ timeout=20 # seconds
+
+ echo "getting Bugzilla PRs having ${catport} in the synopsis" >&2
+ # content= looks for the search string in all of the pr content,
+ # summary= only looks in the summary line
+ url="https://bugs.freebsd.org/bugzilla/rest/bug?bug_status=__open__&product=Ports%20%26%20Packages&summary=${category}%2f${port}"
+ raw="$(fetch -q -T ${timeout} -o - "${url}")"
+ # Enable the next line to get full JSON output in per-port files for debugging
+ # echo "${raw}" > "${category}-${port}.json"
+ if [ -z "${raw}" ] ; then
+ echo "${catport}: no REST reply within ${timeout} seconds from URL: ${url}" >&2
+ exit 67
+ fi
+ pr_list="$(echo "${raw}" | jq '[.bugs | map(select(.assigned_to | test("ports-bugs@freebsd.org";"i") or test("@freebsd.org";"i") == false)).[] | {id,assigned_to,summary}]')"
+
+ # The below code is just to get one line per PR in the output.
+ num_prs=$(echo "${pr_list}" | jq length)
+ if [ ${num_prs} -gt 0 ] ; then
+ for i in $(jot ${num_prs} 0) ; do
+ echo "${pr_list}" | jq -r --argjson i ${i} '[.[$i].id,.[$i].assigned_to,.[$i].summary] | @tsv'
+ done
+ fi
+}
+
+if ! which jq >/dev/null ; then
+ echo "Please install textproc/jq" >&2
+ exit 66
+fi
+
+# Iterate through all installed ports which are not maintained by a FreeBSD.org
+# address (this includes ports-bugs and possibly you), and for each such port
+# see if there is output from get_PR() and if so, report it grouped by the port
+# maintainer.
+for p in $(pkg query -e '%m !~ *@FreeBSD.org' %o,%m) ; do
+ origin=$(echo "${p}" | cut -f 1 -d ,)
+ maintainer=$(echo "${p}" | cut -f 2 -d ,)
+
+ # see if there is a Bugzilla report for ${origin}
+ bz="$(get_PRs "${origin}")"
+ if [ -n "${bz}" ] ; then
+ printf "** %s\n%s\n" "${maintainer}" "${bz}"
+ fi
+done
diff --git a/Tools/scripts/gen-compat.sh b/Tools/scripts/gen-compat.sh
new file mode 100644
index 000000000000..3f36e97f601d
--- /dev/null
+++ b/Tools/scripts/gen-compat.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+set -eu
+set -o pipefail
+
+prog=${0##*/}
+
+usage()
+{
+ echo "Usage $prog <version> <arch> <filelist>" >&2
+ exit 1
+}
+
+if [ $# -ne 3 ]; then
+ usage
+fi
+
+version=${1}
+arch=${2}
+filelist=${3}
+
+if [ ! -f ${filelist} ]; then
+ echo "filelist if not a file" >&2
+ usage
+fi
+
+case $arch in
+amd64 | powerpc64)
+ sets="base lib32" ;;
+aarch64)
+ case $version in
+ 13.*)
+ sets="base" ;;
+ *)
+ sets="base lib32" ;;
+ esac
+ ;;
+*)
+ sets="base" ;;
+esac
+tarch=${arch}
+if [ $tarch = "arm64" ]; then
+ tarch="aarch64"
+fi
+if [ $tarch = "aarch64" ]; then
+ arch="arm64"
+fi
+if [ $tarch = "powerpc64" ] || [ $tarch = "powerpc64le" ]; then
+ arch="powerpc"
+fi
+if [ $tarch = "riscv64" ]; then
+ arch="riscv"
+fi
+
+flist=""
+while read l ; do
+ flist="$flist */$l"
+done <$filelist
+
+tmpdir=$(mktemp -d)
+trap "rm -rf $tmpdir" 0 1 2 3 15
+mkdir -p ${tmpdir}/base
+set -o noglob
+for s in $sets; do
+ echo "Fetching $s for ${version}"
+ extract_list="$flist"
+ if [ $s = "base" ]; then
+ extract_list="${extract_list} */sys/param.h"
+ fi
+ fetch -o - https://download.freebsd.org/releases/${arch}/${tarch}/${version}-RELEASE/${s}.txz | tar -C ${tmpdir}/base -x -f - $extract_list
+done
+set +o noglob
+fbsd_version=$(awk '/#define __FreeBSD_version/ { print $3 }' ${tmpdir}/base/usr/include/sys/param.h)
+maj_version=${version%%.*}
+date=$(date "+%Y%m%d")
+compatdir="compat${maj_version}x-${tarch}-${version}.${fbsd_version}.${date}"
+mkdir -p ${tmpdir}/${compatdir}/lib
+case $sets in
+*lib32*)
+ mkdir -p ${tmpdir}/${compatdir}/lib32
+ find ${tmpdir}/base/usr/lib32/ -name "*.so.*" -exec mv -v {} ${tmpdir}/${compatdir}/lib32/ \;
+ ;;
+esac
+find ${tmpdir}/base -name "*.so.*" -exec mv -v {} ${tmpdir}/${compatdir}/lib/ \;
+tar -cvJf ${compatdir}.tar.xz -C ${tmpdir} ${compatdir}
diff --git a/Tools/scripts/git-diff-ports.sh b/Tools/scripts/git-diff-ports.sh
new file mode 100755
index 000000000000..f13ed0779064
--- /dev/null
+++ b/Tools/scripts/git-diff-ports.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+set -e
+set -o pipefail
+
+export LC_ALL=C
+
+##
+## git-diff-ports.sh: returns the list of ports with uncommitted changes in the repository
+##
+
+# check that packaged dependencies are installed
+
+for dep in git; do
+ if ! which -s $dep; then
+ echo "error: the '$dep' dependency is missing"
+ if [ $dep = "git" ]; then
+ echo "... please install the 'git' package"
+ fi
+ exit 1
+ fi
+done
+
+
+# MAIN
+
+git diff HEAD "$@" |
+ awk -F / '/^diff/ && $2 !~ /[[:upper:]]/ && $3 !~ /^Makefile/ { print $2 "/" $3 }' |
+ sort -u
diff --git a/Tools/scripts/git-get-latest-remote-version.sh b/Tools/scripts/git-get-latest-remote-version.sh
new file mode 100755
index 000000000000..692a4fb1c8ef
--- /dev/null
+++ b/Tools/scripts/git-get-latest-remote-version.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+set -e
+set -o pipefail
+
+export LC_ALL=C
+
+##
+## git-get-latest-remote-version.sh: retrieves the latest version of a remote project at the given Git URL
+##
+
+# args
+
+REPOSITORY_URL="$1" # mandatory
+TAG_PREFIX="$2" # optional
+
+if [ -z "$REPOSITORY_URL" ]; then
+ echo "Usage: $0 <repository-url> <tag-prefix>"
+ exit 1
+fi
+
+# check that packaged dependencies are installed
+
+for dep in git version_sort; do
+ if ! which -s $dep; then
+ echo "error: the '$dep' dependency is missing"
+ if [ $dep = "git" ]; then
+ echo "... please install the 'git' package"
+ elif [ $dep = "version_sort" ]; then
+ echo "... please install the 'libversion' package"
+ fi
+ exit 1
+ fi
+done
+
+
+# MAIN
+
+git ls-remote --refs --tags $REPOSITORY_URL 2>/dev/null |
+ grep "refs/tags/$TAG_PREFIX" |
+ sed -e "s|.*refs/tags/$TAG_PREFIX||" |
+ version_sort |
+ tail -1 ||
+ ! echo "failed to find the git project '$REPOSITORY_URL' or tags in it"
diff --git a/Tools/scripts/gnomedepends.py b/Tools/scripts/gnomedepends.py
deleted file mode 100755
index 2c5da9c7fc29..000000000000
--- a/Tools/scripts/gnomedepends.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python
-#
-# gnomedepends
-# Analyse pkg/PLIST and give an advice as to which GNOME
-# ports should be listes in {RUN,LIB}_DEPENDS for this port
-#
-# ----------------------------------------------------------------------------
-# "THE BEER-WARE LICENSE" (Revision 42, (c) Poul-Henning Kamp):
-# Maxim Sobolev <sobomax@FreeBSD.org> wrote this file. As long as you retain
-# this notice you can do whatever you want with this stuff. If we meet some
-# day, and you think this stuff is worth it, you can buy me a beer in return.
-#
-# Maxim Sobolev
-# ----------------------------------------------------------------------------
-#
-# MAINTAINER= gnome@FreeBSD.org
-#
-# TODO:
-# - analyse actual {RUN,LIB}_DEPENDS and give an advice about what should be
-# added;
-# - analyse results and remove redundant dependencies (for example if gnomecore
-# has gnomecontrolcenter listed as dependency, and it is found that the port
-# requires both gnomecontrolcenter and gnomecore do not list
-# gnomecontrolcenter then);
-# - parse ports/INDEX directly.
-#
-
-import os, os.path, sys, string, re
-
-def getcmdout(cmdline):
- results = []
- pipe = os.popen(cmdline)
- buffer = pipe.readlines()
- for result in buffer:
- result = string.strip(result)
- if len(result) > 0:
- results.append(result)
- pipe.close()
- return results
-
-def readfile(filename):
- file = open(filename)
- result = file.readlines()
- file.close()
- return result
-
-def filter(lines, regobj):
- results = []
- for line in lines:
- match = regobj.match(line)
- if match != None:
- result = string.strip(match.group(1))
- try:
- tmp = results.index(result)
- except ValueError:
- results.append(result)
- return results
-
-gnomeports = getcmdout('cd /usr/ports && make search key=gnome | grep ^Path:')
-newgnomeports = []
-for i in gnomeports:
- newgnomeports.append(string.split(i)[1])
-gnomeports = newgnomeports
-newgnomeports = []
-
-regobj = re.compile('^@dirrm (?P<dirname>\S+).*$')
-for portdir in gnomeports:
- try:
- lines = readfile(os.path.join(portdir, 'pkg-plist'))
- lines = list(filter(lines, regobj))
- if len(lines) > 0:
- newgnomeports.append([portdir, lines])
- except IOError:
- pass
-gnomeports = newgnomeports
-newgnomeports = []
-
-try:
- currplist = readfile('pkg-plist')
-except IOError as errmsg:
- print(errmsg)
- sys.exit(1)
-
-regobj = re.compile('^(?!@)(?P<dirname>\S+)/.*')
-currdirs = list(filter(currplist, regobj))
-regobj = re.compile('^@dirrm (?P<dirname>\S+).*$')
-currdirs.extend(list(filter(currplist, regobj)))
-currportdir = os.getcwd()
-
-newcurrdirs = []
-for dir in currdirs:
- incremental = ''
- for component in string.split(dir, '/'):
- if incremental != '':
- incremental = incremental + '/'
- incremental = incremental + component
- try:
- tmp = newcurrdirs.index(incremental)
- except ValueError:
- newcurrdirs.append(incremental)
-currdirs = newcurrdirs
-
-depends = []
-for gnomeport in gnomeports:
- if (currportdir == gnomeport[0]):
- continue
- matches = []
- for gnomedir in gnomeport[1]:
- for dir in currdirs:
- if (gnomedir == dir):
- matches.append(dir)
- if len(matches) > 0:
- depends.append([gnomeport[0], matches])
-
-if len(depends) == 0:
- sys.stdout.writelines(['No dependencies found (maybe it is not a GNOME port).\n'])
- sys.exit(0)
-
-sys.stdout.writelines(['According to the contents of pkg-plist the port depends on the following GNOME\n', 'port(s):\n\n'])
-for depend in depends:
- sys.stdout.writelines([depend[0], ', for directories:\n'])
- for dir in depend[1]:
- sys.stdout.writelines(['\t', dir, '\n'])
- sys.stdout.writelines(['\n'])
-
-
diff --git a/Tools/scripts/hackage-get-latest-version.sh b/Tools/scripts/hackage-get-latest-version.sh
new file mode 100755
index 000000000000..3ad21fcbd73a
--- /dev/null
+++ b/Tools/scripts/hackage-get-latest-version.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+set -e
+set -o pipefail
+
+export LC_ALL=C
+
+##
+## hackage-get-latest-version.sh: retrieves the latest version of a given Haskell package as registered on https://hackage.haskell.org
+##
+
+# args
+
+PACKAGE_NAME="$1"
+
+if [ -z "$PACKAGE_NAME" ]; then
+ echo "Usage: $0 <package-name>"
+ echo "Example: $0 cryptol"
+ echo "Example: $0 ShellCheck"
+ exit 1
+fi
+
+# check that packaged dependencies are installed
+
+for dep in curl jq version_sort; do
+ if ! which -s $dep; then
+ echo "error: the '$dep' dependency is missing"
+ if [ $dep = "curl" ]; then
+ echo "... please install the 'curl' package"
+ elif [ $dep = "jq" ]; then
+ echo "... please install the 'jq' package"
+ elif [ $dep = "version_sort" ]; then
+ echo "... please install the 'libversion' package"
+ fi
+ exit 1
+ fi
+done
+
+
+# MAIN
+
+curl -H "Accept: application/json" https://hackage.haskell.org/package/$PACKAGE_NAME 2>/dev/null |
+ grep -v "Package not found: No such package in package index" |
+ jq -r 'keys[]' |
+ version_sort |
+ tail -1 ||
+ ! echo "failed to find the Haskell package '$PACKAGE_NAME'"
diff --git a/Tools/scripts/npmjs-get-latest-version.sh b/Tools/scripts/npmjs-get-latest-version.sh
new file mode 100755
index 000000000000..122211f03df8
--- /dev/null
+++ b/Tools/scripts/npmjs-get-latest-version.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+set -e
+set -o pipefail
+
+export LC_ALL=C
+
+##
+## npmjs-get-latest-version.sh: retrieves the latest version of a given Node.js package as registered on https://registry.npmjs.org
+##
+
+# args
+
+PACKAGE_NAME="$1"
+
+if [ -z "$PACKAGE_NAME" ]; then
+ echo "Usage: $0 <package-name>"
+ echo "Example: $0 @github/copilot"
+ echo "Example: $0 express"
+ exit 1
+fi
+
+# check that packaged dependencies are installed
+
+for dep in curl jq; do
+ if ! which $dep >/dev/null 2>&1; then
+ echo "error: the '$dep' dependency is missing"
+ if [ $dep = "curl" ]; then
+ echo "... please install the 'curl' package"
+ elif [ $dep = "jq" ]; then
+ echo "... please install the 'jq' package"
+ fi
+ exit 1
+ fi
+done
+
+
+# MAIN
+
+curl -H "Accept: application/json" https://registry.npmjs.org/$PACKAGE_NAME/latest 2>/dev/null |
+ grep -v "Not Found" |
+ jq -r '.version' ||
+ ! echo "failed to find the Node.js package '$PACKAGE_NAME'"
diff --git a/Tools/scripts/port_conflicts_check.lua b/Tools/scripts/port_conflicts_check.lua
new file mode 100755
index 000000000000..c5265af19a5a
--- /dev/null
+++ b/Tools/scripts/port_conflicts_check.lua
@@ -0,0 +1,507 @@
+#!/usr/libexec/flua
+
+--[[
+SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+
+Copyright (c) 2022 Stefan Esser <se@FreeBSD.org>
+
+Generate a list of existing and required CONFLICTS_INSTALL lines
+for all ports (limited to ports for which official packages are
+provided).
+
+This script depends on the ports-mgmt/pkg-provides port for the list
+of files installed by all pre-built packages for the architecture
+the script is run on.
+
+The script generates a list of ports by running "pkg provides ." and
+a mapping from package base name to origin via "pkg rquery '%n %o'".
+
+The existing CONFLICTS and CONFLICTS_INSTALL definitions are fetched
+by "make -C $origin -V CONFLICTS -V CONFLICTS_INSTALL". This list is
+only representative for the options configured for each port (i.e.
+if non-default options have been selected and registered, these may
+lead to a non-default list of conflicts).
+
+The script detects files used by more than one port, than lists by
+origin the existing definition and the list of package base names
+that have been detected to cause install conflicts followed by the
+list of duplicate files separated by a hash character "#".
+
+This script uses the "hidden" LUA interpreter in the FreeBSD base
+systems and does not need any port except "pkg-provides" to be run.
+
+The run-time on my system checking the ~32000 packages available
+for -CURRENT on amd64 is less than 250 seconds.
+
+Example output:
+
+# Port: games/sol
+# Files: bin/sol
+# < aisleriot gnome-games
+# > aisleriot
+portedit merge -ie 'CONFLICTS_INSTALL=aisleriot # bin/sol' /usr/ports/games/sol
+
+The output is per port (for all flavors of the port, if applicable),
+gives examples of conflicting files (mostly to understand whether
+different versions of a port could co-exist), the current CONFLICTS
+and CONFLICTS_INSTALL entries merged, and a suggested new entry.
+This information is followed by a portedit command line that should
+do the right thing for simple cases, but the result should always
+be checked before the resulting Makefile is committed.
+--]]
+
+require "lfs"
+
+-------------------------------------------------------------------
+local file_pattern = "."
+local database = "/var/db/pkg/provides/provides.db"
+local max_age = 1 * 24 * 3600 -- maximum age of database file in seconds
+
+-------------------------------------------------------------------
+local function table_sorted_keys(t)
+ local result = {}
+ for k, _ in pairs(t) do
+ result[#result + 1] = k
+ end
+ table.sort(result)
+ return result
+end
+
+-------------------------------------------------------------------
+local function table_sort_uniq(t)
+ local result = {}
+ if t then
+ local last
+ table.sort(t)
+ for _, entry in ipairs(t) do
+ if entry ~= last then
+ last = entry
+ result[#result + 1] = entry
+ end
+ end
+ end
+ return result
+end
+
+-------------------------------------------------------------------
+local function fnmatch(name, pattern)
+ local function fnsubst(s)
+ s = string.gsub(s, "%%", "%%%%")
+ s = string.gsub(s, "%+", "%%+")
+ s = string.gsub(s, "%-", "%%-")
+ s = string.gsub(s, "%.", "%%.")
+ s = string.gsub(s, "%?", ".")
+ s = string.gsub(s, "%*", ".*")
+ return s
+ end
+ local rexpr = ""
+ local left, middle, right
+ while true do
+ left, middle, right = string.match(pattern, "([^[]*)(%[[^]]+%])(.*)")
+ if not left then
+ break
+ end
+ rexpr = rexpr .. fnsubst(left) .. middle
+ pattern = right
+ end
+ rexpr = "^" .. rexpr .. fnsubst(pattern) .. "$"
+ return string.find(name, rexpr)
+end
+
+-------------------------------------------------------------------
+local function fetch_pkgs_origins()
+ local pkgs = {}
+ local pipe = io.popen("pkg rquery '%n %o'")
+ for line in pipe:lines() do
+ local pkgbase, origin = string.match(line, "(%S+) (%S+)")
+ pkgs[origin] = pkgbase
+ end
+ pipe:close()
+ pipe = io.popen("pkg rquery '%n %o %At %Av'")
+ for line in pipe:lines() do
+ local pkgbase, origin, tag, value = string.match(line, "(%S+) (%S+) (%S+) (%S+)")
+ if tag == "flavor" then
+ pkgs[origin] = nil
+ pkgs[origin .. "@" .. value] = pkgbase
+ end
+ end
+ pipe:close()
+ return pkgs
+end
+
+-------------------------------------------------------------------
+local BAD_FILE_PATTERN = {
+ "^[^/]+$",
+ "^lib/python[%d%.]+/site%-packages/examples/[^/]+$",
+ "^lib/python[%d%.]+/site%-packages/samples/[^/]+$",
+ "^lib/python[%d%.]+/site%-packages/test/[^/]+$",
+ "^lib/python[%d%.]+/site%-packages/test_app/[^/]+$",
+ "^lib/python[%d%.]+/site%-packages/tests/[^/]+$",
+ "^lib/python[%d%.]+/site%-packages/tests/unit/[^/]+$",
+}
+
+local BAD_FILE_PKGS = {}
+
+local function check_bad_file(pkgbase, file)
+ for _, pattern in ipairs(BAD_FILE_PATTERN) do
+ if string.match(file, pattern) then
+ BAD_FILE_PKGS[pkgbase] = BAD_FILE_PKGS[pkgbase] or {}
+ table.insert(BAD_FILE_PKGS[pkgbase], file)
+ break
+ end
+ end
+end
+
+-------------------------------------------------------------------
+local function read_files(pattern)
+ local files_table = {}
+ local now = os.time()
+ local modification_time = lfs.attributes(database, "modification")
+ if not modification_time then
+ print("# Aborting: package file database " .. database .. " does not exist.")
+ print("# Install the 'pkg-provides' package and add it as a module to 'pkg.conf'.")
+ print("# Then fetch the database with 'pkg update' or 'pkg provides -u'.")
+ os.exit(1)
+ end
+ if now - modification_time > max_age then
+ print("# Aborting: package file database " .. database)
+ print("# is older than " .. max_age .. " seconds.")
+ print("# Use 'pkg provides -u' to update the database.")
+ os.exit(2)
+ end
+ local pipe = io.popen("locate -d " .. database .. " " .. pattern)
+ if pipe then
+ for line in pipe:lines() do
+ local pkgbase, file = string.match(line, "([^*]+)%*([^*]+)")
+ if file:sub(1, 11) == "/usr/local/" then
+ file = file:sub(12)
+ end
+ check_bad_file(pkgbase, file)
+ local t = files_table[file] or {}
+ t[#t + 1] = pkgbase
+ files_table[file] = t
+ end
+ pipe:close()
+ end
+ return files_table
+end
+
+-------------------------------------------------------------------
+local DUPLICATE_FILE = {}
+
+local function fetch_pkg_pairs(pattern)
+ local pkg_pairs = {}
+ for file, pkgbases in pairs(read_files(pattern)) do
+ if #pkgbases >= 2 then
+ DUPLICATE_FILE[file] = true
+ for i = 1, #pkgbases -1 do
+ local pkg_i = pkgbases[i]
+ for j = i + 1, #pkgbases do
+ local pkg_j = pkgbases[j]
+ if pkg_i ~= pkg_j then
+ local p1 = pkg_pairs[pkg_i] or {}
+ local p2 = p1[pkg_j] or {}
+ p2[#p2 + 1] = file
+ p1[pkg_j] = p2
+ pkg_pairs[pkg_i] = p1
+ end
+ end
+ end
+ end
+ end
+ return pkg_pairs
+end
+
+-------------------------------------------------------------------
+local function conflicts_delta(old, new)
+ local old_seen = {}
+ local changed
+ for i = 1, #new do
+ local matched
+ for j = 1, #old do
+ if new[i] == old[j] or fnmatch(new[i], old[j]) then
+ new[i] = old[j]
+ old_seen[j] = true
+ matched = true
+ break
+ end
+ end
+ changed = changed or not matched
+ end
+ if not changed then
+ for j = 1, #old do
+ if not old_seen[j] then
+ changed = true
+ break
+ end
+ end
+ end
+ if changed then
+ return table_sort_uniq(new)
+ end
+end
+
+-------------------------------------------------------------------
+local function fetch_port_conflicts(origin)
+ local dir, flavor = origin:match("([^@]+)@?(.*)")
+ if flavor ~= "" then
+ flavor = " FLAVOR=" .. flavor
+ end
+ local seen = {}
+ local portdir = "/usr/ports/" .. dir
+ local pipe = io.popen("make -C " .. portdir .. flavor .. " -V CONFLICTS -V CONFLICTS_INSTALL 2>/dev/null")
+ for line in pipe:lines() do
+ for word in line:gmatch("(%S+)%s?") do
+ seen[word] = true
+ end
+ end
+ pipe:close()
+ return table_sorted_keys(seen)
+end
+
+-------------------------------------------------------------------
+local function conflicting_pkgs(conflicting)
+ local pkgs = {}
+ for origin, pkgbase in pairs(fetch_pkgs_origins()) do
+ if conflicting[pkgbase] then
+ pkgs[origin] = pkgbase
+ end
+ end
+ return pkgs
+end
+
+-------------------------------------------------------------------
+local function collect_conflicts(pkg_pairs)
+ local pkgs = {}
+ for pkg_i, p1 in pairs(pkg_pairs) do
+ for pkg_j, _ in pairs(p1) do
+ pkgs[pkg_i] = pkgs[pkg_i] or {}
+ table.insert(pkgs[pkg_i], pkg_j)
+ pkgs[pkg_j] = pkgs[pkg_j] or {}
+ table.insert(pkgs[pkg_j], pkg_i)
+ end
+ end
+ return pkgs
+end
+
+-------------------------------------------------------------------
+local function split_origins(origin_list)
+ local port_list = {}
+ local flavors = {}
+ local last_port
+ for _, origin in ipairs(origin_list) do
+ local port, flavor = string.match(origin, "([^@]+)@?(.*)")
+ if port ~= last_port then
+ port_list[#port_list + 1] = port
+ if flavor ~= "" then
+ flavors[port] = {flavor}
+ end
+ else
+ table.insert(flavors[port], flavor)
+ end
+ last_port = port
+ end
+ return port_list, flavors
+end
+
+-------------------------------------------------------------------
+local PKG_PAIR_FILES = fetch_pkg_pairs(file_pattern)
+local CONFLICT_PKGS = collect_conflicts(PKG_PAIR_FILES)
+local PKGBASE = conflicting_pkgs(CONFLICT_PKGS)
+local ORIGIN_LIST = table_sorted_keys(PKGBASE)
+local PORT_LIST, FLAVORS = split_origins(ORIGIN_LIST)
+
+local function conflicting_files(pkg_i, pkgs)
+ local files = {}
+ local all_files = {}
+ local f
+ local p1 = PKG_PAIR_FILES[pkg_i]
+ if p1 then
+ for _, pkg_j in ipairs(pkgs) do
+ f = p1[pkg_j]
+ if f then
+ table.sort(f)
+ files[#files + 1] = f[1]
+ table.move(f, 1, #f, #all_files + 1, all_files)
+ end
+ end
+ end
+ for _, pkg_j in ipairs(pkgs) do
+ p1 = PKG_PAIR_FILES[pkg_j]
+ f = p1 and p1[pkg_i]
+ if f then
+ table.sort(f)
+ files[#files + 1] = f[1]
+ table.move(f, 1, #f, #all_files + 1, all_files)
+ end
+ end
+ return table_sort_uniq(files), table_sort_uniq(all_files)
+end
+
+---------------------------------------------------------------------
+local version_pattern = {
+ "^lib/python%d%.%d/",
+ "^share/py3%d%d%?-",
+ "^share/%a+/py3%d%d%?-",
+ "^lib/lua/%d%.%d/",
+ "^share/lua/%d%.%d/",
+ "^lib/perl5/[%d%.]+/",
+ "^lib/perl5/site_perl/mach/[%d%.]+/",
+ "^lib/ruby/gems/%d%.%d/",
+ "^lib/ruby/site_ruby/%d%.%d/",
+}
+
+local function generalize_patterns(pkgs, files)
+ local function match_any(str, pattern_array)
+ for _, pattern in ipairs(pattern_array) do
+ if string.match(str, pattern) then
+ return true
+ end
+ end
+ return false
+ end
+ local function unversioned_files()
+ for i = 1, #files do
+ if not match_any(files[i], version_pattern) then
+ return true
+ end
+ end
+ return false
+ end
+ local function pkg_wildcards(from, ...)
+ local to_list = {...}
+ local result = {}
+ for i = 1, #pkgs do
+ local orig_pkg = pkgs[i]
+ for _, to in ipairs(to_list) do
+ result[string.gsub(orig_pkg, from, to)] = true
+ end
+ end
+ pkgs = table_sorted_keys(result)
+ end
+ local pkg_pfx_php = "php[0-9][0-9]-"
+ local pkg_sfx_php = "-php[0-9][0-9]"
+ local pkg_pfx_python2
+ local pkg_sfx_python2
+ local pkg_pfx_python3
+ local pkg_sfx_python3
+ local pkg_pfx_lua
+ local pkg_pfx_ruby
+ pkgs = table_sort_uniq(pkgs)
+ if unversioned_files() then
+ pkg_pfx_python2 = "py3[0-9]-" -- e.g. py39-
+ pkg_sfx_python2 = "-py3[0-9]"
+ pkg_pfx_python3 = "py3[0-9][0-9]-" -- e.g. py311-
+ pkg_sfx_python3 = "-py3[0-9][0-9]"
+ pkg_pfx_lua = "lua[0-9][0-9]-"
+ pkg_pfx_ruby = "ruby[0-9][0-9]-"
+ else
+ pkg_pfx_python2 = "${PYTHON_PKGNAMEPREFIX}"
+ pkg_sfx_python2 = "${PYTHON_PKGNAMESUFFIX}"
+ pkg_pfx_python3 = nil
+ pkg_sfx_python3 = nil
+ pkg_pfx_lua = "${LUA_PKGNAMEPREFIX}"
+ pkg_pfx_ruby = "${RUBY_PKGNAMEPREFIX}"
+ end
+ pkg_wildcards("^php%d%d%-", pkg_pfx_php)
+ pkg_wildcards("-php%d%d$", pkg_sfx_php)
+ pkg_wildcards("^phpunit%d%-", "phpunit[0-9]-")
+ pkg_wildcards("^py3%d%-", pkg_pfx_python2, pkg_pfx_python3)
+ pkg_wildcards("-py3%d%$", pkg_sfx_python2, pkg_sfx_python3)
+ pkg_wildcards("^py3%d%d%-", pkg_pfx_python2, pkg_pfx_python3)
+ pkg_wildcards("-py3%d%d%$", pkg_sfx_python2, pkg_sfx_python3)
+ pkg_wildcards("^lua%d%d%-", pkg_pfx_lua)
+ pkg_wildcards("-emacs_[%a_]*", "-emacs_*")
+ pkg_wildcards("^ghostscript%d%-", "ghostscript[0-9]-")
+ pkg_wildcards("^bacula%d%-", "bacula[0-9]-")
+ pkg_wildcards("^bacula%d%d%-", "bacula[0-9][0-9]-")
+ pkg_wildcards("^bareos%d%-", "bareos[0-9]-")
+ pkg_wildcards("^bareos%d%d%-", "bareos[0-9][0-9]-")
+ pkg_wildcards("^moosefs%d%-", "moosefs[0-9]-")
+ pkg_wildcards("^ruby%d+-", pkg_pfx_ruby)
+ return table_sort_uniq(pkgs)
+end
+
+-------------------------------------------------------------------
+for _, port in ipairs(PORT_LIST) do
+ local function merge_table(t1, t2)
+ table.move(t2, 1, #t2, #t1 + 1, t1)
+ end
+ local port_conflicts = {}
+ local files = {}
+ local msg_files = {}
+ local conflict_pkgs = {}
+ local function merge_data(origin)
+ local pkgbase = PKGBASE[origin]
+ if not BAD_FILE_PKGS[pkgbase] then
+ local pkg_confl_file1, pkg_confl_files = conflicting_files(pkgbase, CONFLICT_PKGS[pkgbase])
+ merge_table(msg_files, pkg_confl_file1) -- 1 file per flavor
+ merge_table(files, pkg_confl_files) -- all conflicting files
+ merge_table(conflict_pkgs, CONFLICT_PKGS[pkgbase])
+ merge_table(port_conflicts, fetch_port_conflicts(origin))
+ end
+ end
+ local flavors = FLAVORS[port]
+ if flavors then
+ for _, flavor in ipairs(flavors) do
+ merge_data(port .. "@" .. flavor)
+ end
+ else
+ merge_data(port)
+ end
+ files = table_sort_uniq(files)
+ msg_files = table_sort_uniq(msg_files)
+ conflict_pkgs = generalize_patterns(conflict_pkgs, files)
+ if #port_conflicts then
+ port_conflicts = table_sort_uniq(port_conflicts)
+ conflict_pkgs = conflicts_delta(port_conflicts, conflict_pkgs)
+ end
+ if conflict_pkgs then
+ local conflicts_string_cur = table.concat(port_conflicts, " ")
+ local conflicts_string_new = table.concat(conflict_pkgs, " ")
+ local file_list = table.concat(msg_files, " ")
+ print("# Port: " .. port)
+ print("# Files: " .. file_list)
+ if conflicts_string_cur ~= "" then
+ print("# < " .. conflicts_string_cur)
+ end
+ print("# > " .. conflicts_string_new)
+ print("portedit merge -ie 'CONFLICTS_INSTALL=" .. conflicts_string_new ..
+ " # " .. file_list .. "' /usr/ports/" .. port)
+ print()
+ end
+end
+
+-------------------------------------------------------------------
+local BAD_FILES_ORIGINS = {}
+
+for _, origin in ipairs(ORIGIN_LIST) do
+ local pkgbase = PKGBASE[origin]
+ local files = BAD_FILE_PKGS[pkgbase]
+ if files then
+ for _, file in ipairs(files) do
+ if DUPLICATE_FILE[file] then
+ local port = string.match(origin, "([^@]+)@?")
+ BAD_FILES_ORIGINS[port] = BAD_FILES_ORIGINS[origin] or {}
+ table.insert(BAD_FILES_ORIGINS[port], file)
+ end
+ end
+ end
+end
+
+-------------------------------------------------------------------
+local bad_origins = table_sorted_keys(BAD_FILES_ORIGINS)
+
+if #bad_origins > 0 then
+ print ("# Ports with badly named files:")
+ print ()
+ for _, port in ipairs(bad_origins) do
+ print ("# " .. port)
+ local files = BAD_FILES_ORIGINS[port]
+ table.sort(files)
+ for _, file in ipairs(files) do
+ print ("#", file)
+ end
+ print()
+ end
+end
diff --git a/Tools/scripts/portsearch b/Tools/scripts/portsearch
index ee394ab58325..5c153aae9b73 100755
--- a/Tools/scripts/portsearch
+++ b/Tools/scripts/portsearch
@@ -24,8 +24,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
-# $Id$
-#
# Each port record in INDEX contains 10 fields, delimited by ``|'', some
@@ -50,7 +48,7 @@ my $portsdir = "/usr/ports";
$portsdir = $ENV{PORTSDIR} if ( defined $ENV{'PORTSDIR'} );
my $VERSION = "1.0";
-my $file = "$portsdir/INDEX" . ($osrel <= 4 ? "" : "-$osrel");
+my $file = "$portsdir/INDEX-$osrel";
my $match = 1;
my $count = 0;
my $fulldesc = 0;
diff --git a/Tools/scripts/pypi-get-latest-version.sh b/Tools/scripts/pypi-get-latest-version.sh
new file mode 100755
index 000000000000..580aa282248d
--- /dev/null
+++ b/Tools/scripts/pypi-get-latest-version.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+set -e
+set -o pipefail
+
+export LC_ALL=C
+
+##
+## pypi-get-latest-version.sh: retrieves the latest version of a given Python package as registered on https://pypi.org
+##
+
+# args
+
+PACKAGE_NAME="$1"
+
+if [ -z "$PACKAGE_NAME" ]; then
+ echo "Usage: $0 <package-name>"
+ echo "Example: $0 numpy"
+ echo "Example: $0 scipy"
+ exit 1
+fi
+
+# check that packaged dependencies are installed
+
+for dep in jq version_sort; do
+ if ! which -s $dep; then
+ echo "error: the '$dep' dependency is missing"
+ if [ $dep = "jq" ]; then
+ echo "... please install the 'jq' package"
+ elif [ $dep = "version_sort" ]; then
+ echo "... please install the 'libversion' package"
+ fi
+ exit 1
+ fi
+done
+
+
+# MAIN
+
+fetch -o - https://pypi.python.org/pypi/$PACKAGE_NAME/json 2>/dev/null |
+ jq -r '.releases | keys[]' |
+ grep -v dev |
+ grep -v -E ".*(a|b|rc)[0-9]*$" |
+ version_sort |
+ tail -1 ||
+ ! echo "failed to find the Python package '$PACKAGE_NAME'"
diff --git a/Tools/scripts/rmport b/Tools/scripts/rmport
index b8757712bacf..26e0ad332418 100755
--- a/Tools/scripts/rmport
+++ b/Tools/scripts/rmport
@@ -4,7 +4,7 @@
#
# Copyright 2006-2007 Vasil Dimov
# Copyright 2012-2018 Chris Rees
-# Copyright 2016-2021 René Ladan
+# Copyright 2016-2025 René Ladan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -113,7 +113,7 @@ find_expired()
for port in $(make -C ${PORTSDIR}/${category} -V SUBDIR); do
DATE="$(make -C ${PORTSDIR}/${category}/${port} -V EXPIRATION_DATE)"
# shellcheck disable=SC2039
- if [ -n "${DATE}" ] && [ ! "${DATE}" \> "$${TODAY}" ] ; then
+ if [ -n "${DATE}" ] && [ ! "${DATE}" \> "${TODAY}" ] ; then
if [ "$1" = 1 ] ; then
echo -n "${DATE} ${category}/${port}: "
make -C ${PORTSDIR}/${category}/${port} -V DEPRECATED
@@ -127,7 +127,7 @@ find_expired()
# check if some ports depend on the given port
# XXX Very Little Chance (tm) for breaking INDEX exists:
-# /usr/ports/INDEX may be outdated and not contain recently added dependencies
+# INDEX may be outdated and not contain recently added dependencies
check_dep_core()
{
catport=${1}
@@ -145,9 +145,22 @@ check_dep_core()
err=0
deps=$(grep -E "${pkgname}" ${INDEX} |grep -vE "^(${rmpkgs})" || :)
- if [ -n "${deps}" ] ; then
+ # Try to avoid false positives from INDEX when a port has just been
+ # removed but INDEX has not yet been updated.
+ # XXX this needs more work, we must look for the dependencies of catport in MOVED
+ in_MOVED=0
+ #MOVED_line="$(grep "${catport}" "${PORTSDIR}/MOVED")"
+ #if [ -z "${MOVED_line}" ] ; then
+ # in_MOVED=2 # dependent port not found
+ #elif [ "${TODAY}" = "$(echo "${MOVED_line}" | cut -d \| -f 3)" ] ; then
+ # in_MOVED=1 # dependent port just removed
+ #fi
+ if [ -n "${deps}" ] && [ ${in_MOVED} -eq 0 ] ; then
log "${catport}: some port(s) depend on ${pkgname}:"
- echo "${deps}" >&2
+ # Skip dependencies in on-screen listing to avoid excessively
+ # long lines. Note that WWW should be field 13 according to
+ # Mk/bsd.port.mk:4492
+ echo "${deps}" | cut -d \| -f -7,10 >&2
err=1
fi
@@ -203,11 +216,10 @@ check_dep()
get_PRs()
{
catport=${1}
- synopsis=${2}
- log "${catport}: getting PRs having ${synopsis} in the synopsis"
+ log "${catport}: getting PRs having ${catport} in the synopsis"
- url="https://bugs.freebsd.org/bugzilla/buglist.cgi?quicksearch=${synopsis}"
+ url="https://bugs.freebsd.org/bugzilla/buglist.cgi?quicksearch=${catport}"
raw="$(fetch -q -T 20 -o - "${url}")"
@@ -225,12 +237,11 @@ get_PRs()
check_PRs()
{
catport=${1}
- synopsis=${2}
- PRs="$(get_PRs ${catport} "${synopsis}")" || exit
+ PRs="$(get_PRs ${catport})" || exit
if [ -n "${PRs}" ] ; then
- log "${catport}: PRs found, related to ${synopsis}:"
+ log "${catport}: related PRs found:"
printf "%s\n" "${PRs}" >&2
echo "you can skip ${catport} and continue with the rest or remove it anyway" >&2
@@ -251,7 +262,7 @@ edit_MOVED()
catport=${1}
DEPRECATED="$(make -C ${PORTSDIR}/${catport} -V DEPRECATED)"
- DEPRECATED=${DEPRECATED:+: ${DEPRECATED}}
+ DEPRECATED=${DEPRECATED:+: ${DEPRECATED%.}}
if [ -n "$(make -C ${PORTSDIR}/${catport} -V EXPIRATION_DATE)" ] ; then
REASON="Has expired${DEPRECATED}"
else
@@ -316,7 +327,7 @@ commit()
answer=$(ask "Do you want to tweak the commit message")
if [ "${answer}" = "y" ] ; then
${GIT} pull --ff-only --rebase 2>&1
- ${GIT} commit 2>&1 # modify final commit message
+ ${GIT} commit --amend # modify final commit message
echo "All done, check the result and push when everything is OK."
fi
}
@@ -352,6 +363,8 @@ usage()
# main
+trap cleanup 1 2 3 15
+
if [ ! -r ${INDEX} ] ; then
echo "${INDEX} not readable, exiting" >&2
exit 66
@@ -366,7 +379,7 @@ else
cd "${git_dir}/.." || exit 1
fi
if ! ${GIT} diff --exit-code remotes/origin/main ; then
- echo "you have local commits, exiting" >&2
+ echo "you have local commits or are behind origin/main, exiting" >&2
exit 65
fi
@@ -387,7 +400,7 @@ if [ ${1} = "-p" ] ; then
if [ ${#} -ne 2 ] ; then
usage
fi
- get_PRs "dummy" ${2}
+ get_PRs ${2}
exit
fi
@@ -410,7 +423,18 @@ fi
gitlog=$(mktemp -t gitlog)
gitrmlist=$(mktemp -t gitrmlist)
-echo "cleanup: Remove expired ports:" > ${gitlog}
+if [ $# -eq 1 ] ; then
+ topic="${1%/}"
+ plural=""
+ colon=""
+else
+ log "/!\\ Removing multiple ports at once, commit topic will be generic /!\\"
+ topic="cleanup"
+ plural="s"
+ colon=":"
+fi
+
+echo "${topic}: Remove expired port${plural}${colon}" > ${gitlog}
echo "" >> ${gitlog}
for catport in $* ; do
@@ -426,12 +450,19 @@ for catport in $* ; do
continue
fi
- if ! check_PRs ${catport} ${port} ; then
+ if ! check_PRs ${catport} ; then
continue
fi
# everything seems ok, edit the files
+ if [ -z "${catport##www/node*}" ] ; then
+ node_version="${catport##www/node}"
+ if [ -n "${node_version}" ] ; then
+ echo "You are removing a node port, do not forget www/npm-node${node_version} and www/yarn-node${node_version}"
+ fi
+ fi
+
edit_MOVED ${catport}
edit_Makefile ${cat} ${port}
@@ -464,5 +495,3 @@ done
commit
cleanup
-
-# EOF
diff --git a/Tools/scripts/search_lib_depends_and_bump.sh b/Tools/scripts/search_lib_depends_and_bump.sh
index 408e4e72d287..479fada9bd0c 100755
--- a/Tools/scripts/search_lib_depends_and_bump.sh
+++ b/Tools/scripts/search_lib_depends_and_bump.sh
@@ -4,7 +4,7 @@
# The script will search for this port over the complete directory you are located now
# and will bump all ports using `Tools/scripts/bump-revision.sh`
#
-# Version 0.1
+# Version 0.2
# License: MIT
# Matthias Fechner <mfechner@FreeBSD.org>
@@ -33,7 +33,7 @@ PORT_TO_SEARCH=${1}
BASEDIR=$(pwd)
# Get a list of all ports
echo "Prepare a list of all ports"
-ports=$(find . -name Makefile ! -path "./Tools/* | sort")
+ports=`find . -name Makefile -maxdepth 3 -not \( -path "./distfiles/*" -prune \) -not \( -path "./Tools/*" -prune \) -not \( -path "./Templates/*" -prune \) -print | sort`
echo "done."
echo
diff --git a/Tools/scripts/tindex b/Tools/scripts/tindex
index 8d6819fa6302..a14cda9e60e2 100755
--- a/Tools/scripts/tindex
+++ b/Tools/scripts/tindex
@@ -123,7 +123,10 @@ ${GIT} -C ${SRCDIR14} pull --rebase -q
OSVERSION14=$(awk '/^#define[[:blank:]]__FreeBSD_version/ {print $3}' < ${SRCDIR14}/sys/sys/param.h)
cd ${PORTSDIR}
-rm -f INDEX-12 INDEX-12.bz2 INDEX-13 INDEX-13.bz2 INDEX-14 INDEX-14.bz2
+for ver in 12 13 14; do
+ rm -f INDEX-${ver} INDEX-${ver}.bz2 INDEX-${ver}.xz INDEX-${ver}.zst
+done
+
OLD_HEAD=$(${GIT} rev-parse HEAD)
if ! ${GIT} pull --ff-only > git.log 2>&1 ; then
(echo "Git update failed with conflicts:";
@@ -148,7 +151,9 @@ for branch in 12.x 13.x 14.x; do
checkfixed ${branch}
bzip2 -kf ${PORTSDIR}/INDEX-${release}
- mv ${PORTSDIR}/INDEX-${release} ${PORTSDIR}/INDEX-${release}.bz2 ${OUTDIR}
+ zstd -qf --ultra -22 -k ${PORTSDIR}/INDEX-${release}
+ xz -9e -kf ${PORTSDIR}/INDEX-${release}
+ mv ${PORTSDIR}/INDEX-${release} ${PORTSDIR}/INDEX-${release}.bz2 ${PORTSDIR}/INDEX-${release}.zst ${PORTSDIR}/INDEX-${release}.xz ${OUTDIR}
done
# All indexes built successfully, clear the hook
diff --git a/Tools/scripts/update-patches b/Tools/scripts/update-patches
deleted file mode 100755
index 0d92905f6428..000000000000
--- a/Tools/scripts/update-patches
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/bin/sh
-
-# $OpenBSD: update-patches,v 1.3 2000/06/09 17:08:37 espie Exp $
-# Copyright (c) 2000
-# Marc Espie. All rights reserved.
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Neither the name of OpenBSD nor the names of its contributors
-# may be used to endorse or promote products derived from this software
-# without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY ITS AUTHOR AND THE OpenBSD project ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-
-# Find out all .orig files and strip the name to what diff will use
-cd $PATCH_WRKSRC && find . -type f -name '*.orig' | fgrep -v $DISTORIG | \
-sed -e "s,^./\(.*\)\.orig\$,\1," | {
-while read file
-do
- echo 1>&2 "Processing $file"
- # look in patchdir for an existing patchfile matching this
- mkdir -p $PATCHDIR
- cd $PATCHDIR
- for i in ${PATCH_LIST}
- do
- # Ignore non-files, or old backup
- [ -f $i ] || continue
- case $i in \
- *.orig|*.rej|*~) ;;
- *) # Patch found. Is this the one ?
- if grep "^--- $file.orig" $i >/dev/null
- then
- accounted="$accounted $i"
- # found it, splice before diff part with diff
- esc=`echo $file | sed -e 's,/,\\\\/,g'`
- { sed -e "/^--- $esc.orig/,\$ d" <$i
- (cd $PATCH_WRKSRC && diff -p ${DIFF_ARGS} -u $file.orig $file) } >$i.new
- # did it change ? mark it as changed
- if diff ${DIFF_ARGS} -u --ignore-matching-lines="^--- $file.orig .*" \
- --ignore-matching-lines="^+++ $file .*" $i $i.new 1>&2
- then
- rm $i.new
- else
- echo 1>&2 "Patch $i for $file updated"
- mv $i $i.orig
- mv $i.new $i
- edit="$edit $i"
- fi
- continue 2
- fi;;
- esac
- done
- # Build a sensible name for the patch file
- patchname=patch-`echo $file|sed -e s,/,_,g`
- echo 1>&2 "No patch-* found for $file, creating $patchname"
- (cd $PATCH_WRKSRC && diff -p ${DIFF_ARGS} -u $file.orig $file) >$patchname
- edit="$edit $patchname"
- accounted="$accounted $patchname"
-done
-
-# Verify all patches accounted for
-for i in ${PATCHDIR}/*
-do
- [ -f $i ] || continue
- case $i in \
- *.orig|*.rej|*~) ;;
- *)
- for j in $accounted
- do
- if [ $j = $i ]
- then
- continue 2
- fi
- done
- echo 1>&2 "*** Patch $i not accounted for.";;
- esac
-done
-
-# Check for $Id and similar bugs in all those patch files.
-for i in $accounted
-do
- if sed -e '/1,^---/ d' $i|egrep '$(Id|FreeBSD)'
- then
- echo 1>&2 "Problem with $i: CVS tag found in patch"
- fi
-done
-
-echo $edit
-}
-exit 0
diff --git a/Tools/scripts/update-rust-port.sh b/Tools/scripts/update-rust-port.sh
new file mode 100755
index 000000000000..57d8f0641f9c
--- /dev/null
+++ b/Tools/scripts/update-rust-port.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# MAINTAINER: yuri@FreeBSD.org
+
+# CAVEAT: ports with Makefile.crates are not yet supported
+
+## args
+
+VERSION="$1"
+
+## set strict mode
+
+STRICT="set -euo pipefail"
+$STRICT
+
+## checks
+
+for dep in portedit rustc; do
+ if ! which -s $dep; then
+ echo "error: $dep dependency is missing, $0 requires lang/rust and ports-mgmt/portfmt to be installed" >&2
+ exit 1
+ fi
+done
+if [ -z "$VERSION" ]; then
+ echo "Usage: $0 <new-version>"
+ exit 1
+fi
+if ! [ -f Makefile ] || ! [ -f pkg-descr ] || ! grep -q "CARGO_CRATES=" Makefile; then
+ echo "$0 should be run in a Rust-based port directory"
+ exit 1
+fi
+
+## MAIN
+
+# copy Makefile
+cp Makefile Makefile.new
+
+# substitute version tag PORTVERSION or DISTVERSION
+sed -i '' -E "s/^(PORT|DIST)(VERSION=[\t ]*)[0-9.-]+/\1\2${VERSION}/" Makefile.new
+
+# reset PORTREVISION if present
+if grep -q "PORTREVISION=" Makefile; then
+ echo PORTREVISION=0 | portedit merge -i Makefile.new
+fi
+
+# replace CARGO_CRATES with a placeholder
+/usr/bin/awk '
+BEGIN {
+ in_cargo_crates = 0
+}
+/^CARGO_CRATES=.*/ {
+ in_cargo_crates = 1
+ print "#@@@PLACEHOLDER@@@"
+}
+/^\t.*/ {
+ if (in_cargo_crates) {
+ // skip line
+ } else {
+ print $0
+ }
+}
+!/^CARGO_CRATES=.*|^\t.*/ {
+ if (in_cargo_crates) {
+ in_cargo_crates = 0
+ }
+ print $0
+}' < Makefile.new > Makefile
+
+# update distinfo
+make makesum
+
+# replace the placeholder
+while IFS= read -r line; do
+ if [ "$line" = "#@@@PLACEHOLDER@@@" ]; then
+ make cargo-crates | grep -v '^='
+ else
+ echo "$line"
+ fi
+done < Makefile > Makefile.new &&
+mv Makefile.new Makefile
+
+# clean
+make clean
+
+# update distinfo
+make makesum
diff --git a/Tools/scripts/update_crates b/Tools/scripts/update_crates
new file mode 100755
index 000000000000..c95b4bbec6af
--- /dev/null
+++ b/Tools/scripts/update_crates
@@ -0,0 +1,62 @@
+#!/bin/sh
+# Copyright (c) 2021 Rodrigo Osorio
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# MAINTAINER= rodrigo@FreeBSD.org
+#
+
+usage() {
+ echo "usage: update_crates <makefile>"
+ echo
+ exit 1
+}
+
+if [ "$#" -ne 1 ]; then
+ usage
+ exit 1
+fi
+
+newcrates() {
+ while IFS= read -r nline
+ do
+ echo "$nline"
+ done < "/dev/stdin"
+}
+
+infile=$1
+incrates=0
+while IFS= read -r line <&3
+do
+ match=$(echo "${line}" | grep "^CARGO_CRATES=")
+ [ -n "${match}" ] && incrates=1
+ if [ "${incrates}" -eq 1 ]; then
+ if [ -z "$line" ]; then
+ incrates=0
+ newcrates
+ echo "$line"
+ fi
+ else
+ echo "${line}"
+ fi
+done 3< "$infile"