diff options
Diffstat (limited to 'Tools')
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" |