aboutsummaryrefslogtreecommitdiff
path: root/ports-mgmt/portdowngrade/files/portdowngrade
blob: 005582995cd203d5c5181c59b314eed6eb20ce3c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/bin/sh

# portdowngrade

# Fetch a port directory from an older version;
# easy to use wrapper around Subversion

# This script is in the public domain

# $FreeBSD$

usage()
{
	<<EOF >/dev/stderr cat
Usage: $0 [-r] port-directory|port [revision/date]

When called without a revision to restore, svn log is called on the port's
directory so that relevant revisions can be identified.  Look for lines
containing "Update to X.X".  You may wish to filter it through ${PAGER:-less}.

When called with a port name instead of directory/origin, INDEX is grepped
for the correct origins and a list is presented.

When called with -r, make describe is called in the restored port and all
of the ports that the restored port depended on are also checked out at the
same date.

This software requires that a ports tree has been fetched and is present
in ${PORTSDIR:-/usr/ports}.
EOF
	exit 1
}

err()
{
	echo "${@:-An unknown error has occurred}" | fold -s > /dev/stderr
	exit 1
}

getport_recursive()
{
	# getport_recursive portorigin
	# "This function is recursive"
	echo -n "==> Fetching $1 ..."
	[ -d $tmpdir/${1%/*} ] || \
	    $svn -q up --depth files -r $rev "$tmpdir/${1%/*}" || \
	    	err "Something went wrong with fetching category for $1.  Ensure you have the correct revision!"
	$svn -q up -r $rev "$tmpdir/$1" || \
		err "Something went wrong with fetching port files for $1."
	echo " [DONE]"
	echo "$1" >> $tmpdir/portdowngrade.originlist
	deps=$(make PORTSDIR=$PWD/$tmpdir -C $tmpdir/$1 '-V_DEPEND_DIRS:N*/pkg:C,.*/([^/]*/[^/]*)$,\1,')
	if [ -n "$deps" ]; then
		for port in $deps; do
			if [ ! -d $tmpdir/$port ]; then
				echo "===> $1@$rev depends on $port."
				getport_recursive $port
			fi
		done
		echo "===> All dependencies of $1@$rev fetched."
	fi
}

svn=$(which svn 2>/dev/null || which svnlite 2>/dev/null) || err "Where is Subversion??"

PORTSDIR="$(make -f /usr/share/mk/bsd.port.mk -VPORTSDIR)"

[ -d $PORTSDIR ] || usage

args=$(getopt c:r $*) || usage

set -- $args

for arg; do
	case $arg in
	-r)
		recurse=true
		shift
		;;
	--)
		shift
		break
		;;
	-*)
		usage
		;;
	esac
done

case ${1-NULL} in
NULL)
	usage
	;;
*/*)
	# Contains a directory, so we're ready for the next stage
	# noop

	;;
*)
	# Probably a port name, get list of origins from INDEX
	INDEXFILE=$(make -C $PORTSDIR -VINDEXDIR)
	INDEXFILE="$INDEXFILE/$(make -C $PORTSDIR -VINDEXFILE)"

	[ -f $INDEXFILE ] || err You need to run make -C $PORTSDIR fetchindex

	sed -ne "s,^\([^|]*$1-[^|]*\)|/usr/ports/\([^|]*\)|.*,\1	-> \2,p" \
	    < $INDEXFILE
	<<EOF cat

Choose a port origin (directory) from the list
above, and then run ${0##*/} category/port

EOF
	exit 0
	;;
esac

: ${svnroot=https://svn.freebsd.org/ports/head}

# Get port directory
portdir="${1%$PORTSDIR}"
portdir="${portdir#/}"

[ -d "$PORTSDIR/$portdir" ] || err "$portdir does not exist in $PORTSDIR"

case ${2-NULL} in
NULL)
	# No revision/date provided, get log
	echo Choose a revision from this list and run $0 $1 revision
	$svn log $svnroot/$portdir
	echo Choose a revision from the above list and run $0 $1 revision
	exit 0
	;;
*)
	case ${2} in
	*-*-*)
		rev=\{$2\}
		;;
	r*)
		rev=$2
		;;
	*)
		# Number?
		echo $2 | grep -q '^[[:digit:]]*$' || \
		    err Revision argument must be a number or date
		rev=r$2
		;;
	esac

	case ${recurse:-false} in
	false)
		$svn co "$svnroot/$portdir@$rev" || \
		    err "Something went wrong with svn...  Ensure you have the correct revision!"
		destination=${portdir#*/}
		<<EOF cat
You should be done-- now cd into ${destination} and you can run
# make deinstall install clean

Please note that ${0##*/} no longer modifies the ports tree; the
checked out port is at
$(pwd)/${destination}
EOF
		;;
	true)
		tmpdir=$(mktemp -d portdowngrade.XXXXXXX)
		echo -n "=> Fetching empty ports tree... "
		$svn -q co --depth files "$svnroot@$rev" $tmpdir || \
		    err "Something went wrong with svn checkout... Ensure you have the correct revision!"
		echo "[DONE]"
		echo -n "=> Fetching important directories... "
		important=$($svn ls $tmpdir@$rev | \
		    sed -ne "s/^\([A-Z][^/]*\)\//$tmpdir\/\1@${rev}/p")
		$svn -q up $important || \
		    err "Could not fetch ^[A-Z] directories @$rev"
		echo "[DONE]"
		case x$(make -VWITH_PKGNG -f /usr/share/mk/bsd.port.mk) in
		x)
			;;
		*)
			echo -n "=> Fetching current pkg... "
			$svn -q up --depth empty $tmpdir/ports-mgmt
			$svn -q up $tmpdir/ports-mgmt/pkg@.
			echo "[DONE]"
			;;
		esac
		getport_recursive $portdir
		destination=$tmpdir/$portdir
		<< EOF cat > $tmpdir/portdowngrade.recurse
echo "This script will recursively reinstall all of the ports fetched"
echo "that $portdir depended on.  This is possibly dangerous and they may"
echo "not build."
echo "If you are sure that you know how to recover from this, answer 'yes'"
echo "to the following question."
echo
echo "Do you wish to remove all of the ports that $portdir depends on, and"
echo "reinstall with the versions just checked out?"
read var
[ "\$var" = "yes" ] || exit 1
for dir in \$(cat portdowngrade.originlist); do
	make PORTSDIR=\$(pwd) -C \$dir deinstall
done
make PORTSDIR=\$(pwd) -C $portdir install clean
EOF
		<< EOF fold -s
You should now be done-- now cd to $tmpdir, and check that the file portdowngrade.originlist has the correct ports in, then use

# sh portdowngrade.recurse

Really... only use this option if you are desperate!

EOF
		;;
	esac
esac

exit 0