Merge ~jarnos/ppa-purge:master into ppa-purge:master

Proposed by Jarno Suni on 2016-12-12
Status: Needs review
Proposed branch: ~jarnos/ppa-purge:master
Merge into: ppa-purge:master
Diff against target: 900 lines (+567/-175) (has conflicts)
5 files modified
debian/control (+4/-5)
debian/copyright (+2/-0)
debian/ppa-purge.1 (+77/-24)
debian/ppa-purge.bash-completion (+80/-66)
ppa-purge (+404/-80)
Conflict in ppa-purge
Reviewer Review Type Date Requested Status
ppa-purge 2016-12-12 Pending
Review via email: mp+313001@code.launchpad.net

Description of the change

Uses apt-get, not aptitude at all.

Aims to fix:
Under https://bugs.launchpad.net/ppa-purge
Bug #1614160
Bug #802853
Bug #1121325 (since it does not use aptitude)

Under https://bugs.launchpad.net/ubuntu/+source/ppa-purge
Bug #1408031
Bug #1548881
Bug #995113

+some fixes told in git log.

Please donate to me on contributing to this project: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YYXVNC3L8QSQA

To post a comment you must log in.
~jarnos/ppa-purge:master updated on 2016-12-15
f302251... by Jarno Suni on 2016-12-14

Move check for not removing this package.

Now allow downgrading, though.

41b8698... by Jarno Suni on 2016-12-14

Read package lists to /dev/shm to avoid writing to permanent storage.

Rename PPA_PKGS -> PKGS. Empty the files after use. Do not sort
while reading PKGS.

dcbd763... by Jarno Suni on 2016-12-14

Do not display revert list (=$REINSTALL).

Reverts will be shown as part of executing the apt-get install
command.

7d5a2cf... by Jarno Suni on 2016-12-15

Simplify by using bash regex and variable expansion.

Get rid of some variables at the same time.

Tim Lunn (darkxst) wrote :

Turns out this is pretty hard to review, launchpad doesnt help but you also have several commits that revert or fix changes you made in subsequent commits.

Have made a couple of inline comments below.

Will also go through and cherry-pick some of the more trivial commits, but you will need to rebase your branch once done.

Tim Lunn (darkxst) wrote :

s/subsequent/previous/ commits

Jarno Suni (jarnos) wrote :

Unfortunately development was not completely straight-forward.

Tim Lunn (darkxst) wrote :

there are still commits you could squash to clean things up a bit

&&
complete

you remove then add back

there 2 commits that deal with escaping ppa string?

etc

Jarno Suni (jarnos) wrote :

Is there an easy way to cancel the removing of && so that there is no mention of it in git log disturbing your mind?

Is it a problem that there are 2 commits that deal with escaping ppa string? If you want less commits I could just commit the final code as one commit. But you did not accept that either.

~jarnos/ppa-purge:master updated on 2016-12-18
65fb9fb... by Jarno Suni on 2016-12-18

Simplify messaging. No folding used.

5bece79... by Jarno Suni on 2016-12-18

Ask user whether to continue or not after changing repositories.

60a3ad1... by Jarno Suni on 2016-12-18

Make apt-get show version info on revert.

9e7bb54... by Jarno Suni on 2016-12-18

Add long opitions; new --version, --remove, --verbose, remove -dq

Use getopt to parse options. Add long options. Options may also be
after arguments.

Remove -d option, but user may set environment variable RELEASE to
override automaticly determined release name.

Remove -q, but new -v alias --verbose is used to control the same
thing.

New options:
--remove, -r: Remove repository entries or list files. LP: #945473
--verbose, -v: Control output of "apt-get update". LP: #1293507
--version, -V: Print standard GNU version information.

Manual page was generated by command
"help2man -N ./ppa-purge >debian/ppa-purge.1".

Tim Lunn (darkxst) wrote :
Download full text (9.9 KiB)

It is very easy

you need to use `git rebase -i HEAD~40` the last number is the amount of
commits to go back.

then you can group the commits you want to merge (cut and paste the line
and put it where it needs to go)

set the second commits action (first column) to s (squash)

It will then merge those commits, if there are any conflicts in the auto
merge it might leave little snippets in the code that you need to
manually correct. These will look something like

 >>>>>>>>>> HEAD

old code

========

new code

<<<<<<<<<< later commit

Fix those, then "git add <file>"

git rebase --continue

update the commit message for the merged commit and its done!

If you want to just remove commits (for example the commit that adds
check ubuntu dists, then the other that subsequently removes it)

use the same "git rebase -i" command and then just delete the lines for
any commits to remove.

you can also you the e (edit) action if you ever need to make any change
to a particular commit!

On 19/12/16 00:31, Jarno Suni wrote:
> Is there an easy way to cancel the removing of && so that there is no mention of it in git log disturbing your mind?
>
> Is it a problem that there are 2 commits that deal with escaping ppa string? If you want less commits I could just commit the final code as one commit. But you did not accept that either.
>
>
> Diff comments:
>
>> diff --git a/ppa-purge b/ppa-purge
>> index a0b5e42..f197c2c 100755
>> --- a/ppa-purge
>> +++ b/ppa-purge
>> @@ -23,116 +38,196 @@ warn() {
>> write_msg "Warning: $*" 1>&2
>> }
>>
>> +error() {
>> + write_msg "Error: $*" 1>&2
>> +}
>> +
>> +apt_update() {
>> + msg "Updating package lists. This might take a while..."
>> + $APT $quiet_arg update
>> + exit_status=$?
>> + [[ $exit_status -eq 0 ]] &&
>> + msg "Updating package lists finished successfully." || {
>> + local -r text="Updating package lists failed; error code $exit_status."
>> + if [[ $yes ]]; then
>> + error "$text"
>> + [[ $quit ]] || exit 5
>> + else
>> + warn "$text"
>> + [[ $quit ]] || {
>> + read -p "Continue anyway (y/n)? " -n 1 -r
> Yes, I could remove it, I suppose.
>
>> + echo
>> + [[ $REPLY =~ ^[Yy]$ ]] || exit 5
>> + }
>> + fi
>> + }
>> +}
>> +
>> +finish() {
>> + quit=t
>> + rm $PPA_PKGS $REVERTS
>> + if [[ $restore && ((${#lists[@]} > 0)) ]]; then
>> + msg 'Restoring .list file(s):'
>> + for file in "${lists[@]}"; do
>> + cp -va "$file".save "$file"
>> + done
>> + apt_update
>> + fi
>> +}
>> +
>> +trap finish 0
>> +
>> usage() {
>> - echo "Usage: sudo ppa-purge [options] <ppa:ppaowner>[/ppaname]"
>> - echo
>> - echo "ppa-purge will reset all packages from a PPA to the standard"
>> - echo "versions released for your distribution."
>> - echo
>> - echo "Options:"
>> - echo " -p [ppaname] PPA name to be disabled (default: ppa)"
>> - echo " -o [ppaowner] PPA owner"
>> - echo " -s [host] Repository server (default: ppa.launchpad.net)"
>> - echo " -d [distribution] Override the default distribution choice."
>> - echo " -y Pass "-y --force-yes" to apt-get or "-y" to aptitude"
>> - echo " -i Reverse preference of apt-get upon aptitude."
>> - echo " -h Display this help text"
>> -...

~jarnos/ppa-purge:master updated on 2016-12-23
2db960c... by Jarno Suni on 2016-12-20

Be more strict when checking, if apt-get fails to update all repositories.

Regard even warnings in "apt-get update" as fatal errors.
Fixes LP: #1514839

4744e12... by Jarno Suni on 2016-12-21

Add option --figure-soname-bumps to optionally enable old default.

Disable the explicit figuring by default; let apt-get handle
installing soname bumped packages automatically. If the option
is used, do the figuring, and display the list of packages that are
going to be explicitly installed due to (figured) soname bump.

b51c9e1... by Jarno Suni on 2016-12-22

Instead of matching all components, match only distribution name.

If source distribution name is given, purge repository only, if
the distribution name matches.

The previous approach of matching all components is tricky: The
first component in deb line is actually source distribution name
and it should be treated differently. If there is a deb line
containing many components, specifying one in command line would
purge all of them (in the respective repository), so removing
only that component in the respective deb line should be done
instead of disabling the whold line. Removing components can be
done relatively easy by other tools, so it was dropped here to
keep it simple.

3e937ff... by Jarno Suni on 2016-12-23

Fine-tune bash completions

Do not always complete options, except when the word begins with -.
As for other words, complete only what could be used to avoid long
lists.

Do not use "command" with sed. If you were paranoid, you would use
it with compgen and complete, too, but it is not usually done.

Jarno Suni (jarnos) wrote :

I did the changes you suggested, but I was in another branch, and to my surprise, the changes do not show in master. BTW I also changed the first commit to include (all?) remarkable authors, but that again does not show in master.

Jarno Suni (jarnos) wrote :

I thought the changes would go to each branch since all of them were same up to those commits before changing.

Tim Lunn (darkxst) wrote :

you need to push a new branch after rebasing!

Jarno Suni (jarnos) wrote :

On Sat, 24 Dec 2016 04:38:45 -0000
Tim <email address hidden> wrote:

> you need to push a new branch after rebasing!

You mean the feature branch I created for enabling long options and
removing distributions? Where could I push that one or do you mean I
merge it to my local master and then push?

--
Jarno Ilari Suni - http://www.iki.fi/8/

Tim Lunn (darkxst) wrote :

any branch in general, when you rebase it destroys the history and needs to be re-pushed. you can force overwrite an existing branch but if
anyone is using that, they will have issues!

On 25/12/16 07:12, Jarno Suni wrote:
> On Sat, 24 Dec 2016 04:38:45 -0000
> Tim <email address hidden> wrote:
>
>> you need to push a new branch after rebasing!
> You mean the feature branch I created for enabling long options and
> removing distributions? Where could I push that one or do you mean I
> merge it to my local master and then push?
>

~jarnos/ppa-purge:master updated on 2017-01-04
5f63cfe... by Jarno Suni on 2016-12-31

Improve regular expression matching, do not use [:space:]

Use [:blank:] instead.

abb9aa4... by Jarno Suni on 2016-12-31

Do not autocomplete PPAs as http://*

a14bb53... by Jarno Suni on 2016-12-31

Use temporary directory. Optimize creating REVERTS list for Precise.

Use temporaty directory for easy removing and creating of files.

fef559f... by Jarno Suni on 2017-01-03

Improve completing verbose option.

Besides do not be fooled to think that distribution argument is
given, if only an argument for verbose option is given as a separate
word.

89b15ea... by Jarno Suni on 2017-01-04

Update some debian files.

Jarno Suni (jarnos) wrote :

I have not succeeded in pushing the feature branch where the changes are made anywhere. I am afraid it is hard to merge to the master branch, but I could try.

Jarno Suni (jarnos) wrote :

Could I delete the current master, and make the feature branch new master somehow?

Tim Lunn (darkxst) wrote :

has it been rebased on master?

if so then that is fine.

On 21/02/17 22:55, Jarno Suni wrote:
> Could I delete the current master, and make the feature branch new master somehow?

Jarno Suni (jarnos) wrote :

I used this procedure to make the feature branch the new master: http://stackoverflow.com/a/2763118/4414935
Commits of the old master are shown in log, but they are not used if I understood correctly.

Jarno Suni (jarnos) wrote :

I wonder, if there are any issues, if I remove the commits of the old master?

Jarno Suni (jarnos) wrote :

This version may downgrade ppa-purge itself, but not purge it.

Jarno Suni (jarnos) wrote :

Hello,

How are you? Do you still miss a proper internet connection or what is
keeping you from reviewing the changes?

-Jarno

On Wed, 22 Feb 2017 07:15:44 -0000
Tim <email address hidden> wrote:

> has it been rebased on master?
>
> if so then that is fine.
>
>
>
> On 21/02/17 22:55, Jarno Suni wrote:
> > Could I delete the current master, and make the feature branch new
> > master somehow?
>
>

--
Jarno Ilari Suni - http://www.iki.fi/8/

Tim Lunn (darkxst) wrote :

Yes still without proper internet should have ADSL in a few weeks
so,will take a look then. Sorry about the delay

On Wed, Apr 26, 2017, at 07:06 AM, Jarno Suni wrote:
> Hello,
>
> How are you? Do you still miss a proper internet connection or what is
> keeping you from reviewing the changes?
>
> -Jarno
>
>
> On Wed, 22 Feb 2017 07:15:44 -0000
> Tim <email address hidden> wrote:
>
> > has it been rebased on master?
> >
> > if so then that is fine.
> >
> >
> >
> > On 21/02/17 22:55, Jarno Suni wrote:
> > > Could I delete the current master, and make the feature branch new
> > > master somehow?
> >
> >
>
>
>
> --
> Jarno Ilari Suni - http://www.iki.fi/8/
>
> https://code.launchpad.net/~jarnos/ppa-purge/+git/ppa-purge/+merge/313001
> Your team ppa-purge is requested to review the proposed merge of
> ~jarnos/ppa-purge:master into ppa-purge:master.

--
  Tim Lunn
  <email address hidden>

Jarno Suni (jarnos) wrote :

There seem to be some conflicts. Is it because you have added few commits in master after I made this merge proposal? My changes have parent commit 9dbd19d24294cd87bed43939a1a7366f5f2fcf4a in the target branch. I recently tried to simplify commit history by deleting some branches and force removing last merge commit push. My repository seems to be ok now.

~jarnos/ppa-purge:master updated on 2017-05-01
4b42b42... by Jarno Suni on 2017-05-01

Ubuntu 12.04 is no more supported

Jarno Suni (jarnos) wrote :

I force pushed some small changes.

Jarno Suni (jarnos) wrote :

It may be unnecessary to check for warnings in apt_update(). See https://bugs.launchpad.net/ubuntu/+source/apt/+bug/1693900

~jarnos/ppa-purge:master updated on 2017-08-05
cc0e6e1... by Jarno Suni on 2017-08-05

Give user an option to continue in case update from some irrelevant
source will fail.

Jarno Suni (jarnos) wrote :

My bash completion implementation is maybe too complicated as it shows '--verbose=0', '--verbose=1' and '--verbose=2' directly as completion of '--'. I could simplify that.

Jarno Suni (jarnos) wrote :

Tim, do you have ADSL now after more than 3 months? I do not see why ADSL connection is so critical to you and why it is so hard for you the get internet connection for this reviewing task. (I had ADSL in the past, but the over-head wire was taken away, and I have used 4G ever since.)

Unmerged commits

cc0e6e1... by Jarno Suni on 2017-08-05

Give user an option to continue in case update from some irrelevant
source will fail.

4b42b42... by Jarno Suni on 2017-05-01

Ubuntu 12.04 is no more supported

89b15ea... by Jarno Suni on 2017-01-04

Update some debian files.

fef559f... by Jarno Suni on 2017-01-03

Improve completing verbose option.

Besides do not be fooled to think that distribution argument is
given, if only an argument for verbose option is given as a separate
word.

a14bb53... by Jarno Suni on 2016-12-31

Use temporary directory. Optimize creating REVERTS list for Precise.

Use temporaty directory for easy removing and creating of files.

abb9aa4... by Jarno Suni on 2016-12-31

Do not autocomplete PPAs as http://*

5f63cfe... by Jarno Suni on 2016-12-31

Improve regular expression matching, do not use [:space:]

Use [:blank:] instead.

4744e12... by Jarno Suni on 2016-12-21

Add option --figure-soname-bumps to optionally enable old default.

Disable the explicit figuring by default; let apt-get handle
installing soname bumped packages automatically. If the option
is used, do the figuring, and display the list of packages that are
going to be explicitly installed due to (figured) soname bump.

3e937ff... by Jarno Suni on 2016-12-23

Fine-tune bash completions

Do not always complete options, except when the word begins with -.
As for other words, complete only what could be used to avoid long
lists.

Do not use "command" with sed. If you were paranoid, you would use
it with compgen and complete, too, but it is not usually done.

b51c9e1... by Jarno Suni on 2016-12-22

Instead of matching all components, match only distribution name.

If source distribution name is given, purge repository only, if
the distribution name matches.

The previous approach of matching all components is tricky: The
first component in deb line is actually source distribution name
and it should be treated differently. If there is a deb line
containing many components, specifying one in command line would
purge all of them (in the respective repository), so removing
only that component in the respective deb line should be done
instead of disabling the whold line. Removing components can be
done relatively easy by other tools, so it was dropped here to
keep it simple.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/debian/control b/debian/control
2index 9efef2a..3798563 100644
3--- a/debian/control
4+++ b/debian/control
5@@ -11,8 +11,7 @@ Vcs-Browser: https://git.launchpad.net/ppa-purge
6 Package: ppa-purge
7 Architecture: all
8 Depends: ${misc:Depends}, dpkg (>= 1.16.1)
9-Suggests: aptitude (>= 0.6.6-1ubuntu1.2)
10-Description: disables a PPA and reverts to official packages
11- This program disables a PPA from your Software Sources and reverts your
12- system back to the official Ubuntu packages. You can use this to return your
13- system to normal after testing a new version from a PPA.
14+Description: This program disables a PPA or another APT repository from
15+ Software Sources and reverts system back to the official Ubuntu packages.
16+ You can use this to e.g. return your system to normal after testing a
17+ new version from a PPA or to downgrade packages from e.g. proposed ones.
18diff --git a/debian/copyright b/debian/copyright
19index fc4a6a5..394a34b 100644
20--- a/debian/copyright
21+++ b/debian/copyright
22@@ -7,12 +7,14 @@ Files: *
23 Copyright:
24 2009, Robert Hooker <sarvatt@ubuntu.com>
25 2009, Tormod Volden <debian.tormod@gmail.com>
26+ Jarno Ilari Suni <8@iki.fi>
27 License: GPL-3
28
29 Files: debian/*
30 Copyright:
31 2009, Robert Hooker <sarvatt@ubuntu.com>
32 2010, Lorenzo De Liso <blackz@ubuntu.com>
33+ 2017, Jarno Ilari Suni <8@iki.fi>
34 License: GPL-3
35
36 License: GPL-3
37diff --git a/debian/ppa-purge.1 b/debian/ppa-purge.1
38index cc86fbf..f55008f 100644
39--- a/debian/ppa-purge.1
40+++ b/debian/ppa-purge.1
41@@ -1,33 +1,86 @@
42-.TH ppa-purge 1 2010-08-23 "ppa-purge"
43+.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.4.
44+.TH PPA-PURGE "1" "May 2017" "ppa-purge APT Software Purger" "User Commands"
45 .SH NAME
46-ppa-purge \- disables a PPA and reverts to official packages
47-
48+ppa-purge \- manual page for ppa-purge APT Software Purger
49 .SH SYNOPSIS
50-.B ppa-purge [-h | [-d <distribution>] [-s <host>] [-p <ppaname>] <ppa:<ppaowner[/ppaname>]>]
51-
52+.B ppa-purge
53+[\fI\,options\/\fR] \fI\,ppa:<ppaowner>\/\fR[\fI\,/<ppaname>\/\fR]
54+.br
55+.B ppa-purge
56+[\fI\,options\/\fR] \fI\,<URL> \/\fR[\fI\,<distribution>\/\fR]
57+.br
58+.B ppa-purge
59+[\fI\,options\/\fR] \fI\,<distribution>\/\fR
60+.br
61+.B ppa-purge
62+\fI\,{ --help | --version }\/\fR
63 .SH DESCRIPTION
64-This script provides a bash shell script capable of automatically downgrading all packages in a given PPA back to the ubuntu versions.
65-
66-.PP
67-You have to run it using root privileges because of the package manager.
68-
69+ppa\-purge will disable matching repository/repositories and revert packages to
70+versions available for target release. If a package is not available from any
71+remaining repositories, it will be removed, unless it is a package related to
72+current kernel or it is the package of this command. If <ppaname> is not given,
73+\&'ppa' is used as default. If a distribution (such as xenial\-proposed) is given,
74+repository must match it to be purged. Bash completion is supported.
75+.SS "Exit Status:"
76+.IP
77+0 on success; non\-zero integer on error
78 .SH OPTIONS
79-
80 .TP
81-.B -h
82-Display usage help.
83+\fB\-\-figure\-soname\-bumps\fR
84+Explicitly install packages that are figured as soname
85+bumped version of a package to be removed. Display
86+list of these packages.
87 .TP
88-
89+\fB\-s\fR, \fB\-\-simulate\fR
90+No action; do not downgrade or remove packages.
91 .TP
92-.B -p\fR \fIPPA name\fR
93-Name of the PPA to be reset, the default value is ppa.
94+\fB\-u\fR, \fB\-\-no\-initial\-update\fR
95+Skip initial update of package lists. Use this, if you
96+are sure the package lists are updated already.
97 .TP
98-
99-.B -s\fR \fIPPA host\fR
100-Address of the repository server, the default value is ppa.launchpad.net.
101-
102+\fB\-r\fR, \fB\-\-remove\fR
103+Remove unneeded .list files or repository entries
104+instead of leaving backups or commenting entries out,
105+respectively.
106+.TP
107+\fB\-v\fR <level>, \fB\-v\fR<level>, \fB\-\-verbose\fR <level>, \fB\-\-verbose=\fR<level>
108+Verbosity level of "apt\-get update" output.
109+0: only errors
110+1: output in one line aiming to give indication of
111+progress. (default)
112+2: output in separate lines.
113+.TP
114+\fB\-y\fR, \fB\-\-yes\fR
115+Run non\-interactively; do not prompt for changes.
116+.TP
117+\fB\-h\fR, \fB\-\-help\fR
118+Display this help text and exit.
119+.TP
120+\fB\-V\fR, \fB\-\-version\fR
121+Show version and exit.
122+.SH ENVIRONMENT
123+.TP
124+RELEASE
125+Target release to be downgraded to. If not set, output of
126+"lsb_release \fB\-cs\fR" is used.
127+.SH EXAMPLES
128+.IP
129+sudo ppa\-purge ppa:ubuntu\-x\-swat/x\-updates
130+.IP
131+Purge the same PPA on Linux Mint 18.1 (based on Ubuntu 16.04):
132+.IP
133+sudo RELEASE=16.04 ppa\-purge ppa:ubuntu\-x\-swat/x\-updates
134+.IP
135+Purge Google Chrome repository:
136+.IP
137+sudo ppa\-purge http://dl.google.com/linux/chrome/deb
138+.IP
139+Downgrade packages from xenial\-proposed in Ubuntu 16.04:
140+.IP
141+sudo ppa\-purge xenial\-proposed
142 .SH COPYRIGHT
143-This manual page is Copyright 2010 Lorenzo De Liso <blackz@ubuntu.com>.
144-Permission is granted to copy, distribute and/or modify this document
145-under the terms of the GNU General Public License, Version 3 or any later
146-version published by the Free Software Foundation.
147+Copyright \(co authors.
148+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
149+.br
150+This is free software: you are free to change and redistribute it.
151+There is NO WARRANTY, to the extent permitted by law.
152diff --git a/debian/ppa-purge.bash-completion b/debian/ppa-purge.bash-completion
153index be8edde..96811b7 100644
154--- a/debian/ppa-purge.bash-completion
155+++ b/debian/ppa-purge.bash-completion
156@@ -1,80 +1,94 @@
157 # /usr/share/bash-completion/completions/ppa-purge
158 # Debian ppa-purge(1) completion -*- shell-script -*-
159
160-_update_server(){
161- local i
162- for (( i=1; i < ${#words[@]}-1; i++)) ; do
163- case "${words[i]}" in
164- -s)
165- SERVER=${words[i+1]}
166- ;;
167- *)
168- ;;
169- esac
170- done
171-}
172+while true; do
173
174-_update_owner(){
175- local i
176- for (( i=1; i < ${#words[@]}-1; i++)) ; do
177- case "${words[i]}" in
178- -o)
179- OWNER=${words[i+1]}
180- ;;
181- *)
182- ;;
183- esac
184+# Hack for given strings $2,$3,... possibly being in $1 and $COMP_WORDBREAKS
185+# Only the part after each match is listed as a completion.
186+_ltrim_completions ()
187+{
188+ local cur=$1; shift
189+ while [[ ${1+x} ]]; do
190+ if [[ "$cur" == *$1* && "$COMP_WORDBREAKS" == *$1* ]]; then
191+ local x_word=${cur%"${cur##*$1}"}
192+ local i=${#COMPREPLY[*]}
193+ while [[ $((--i)) -ge 0 ]]; do
194+ COMPREPLY[$i]=${COMPREPLY[$i]#"$x_word"}
195+ done
196+ fi
197+ shift
198 done
199-}
200+} || break
201
202-_ppa_names(){
203- _update_server
204- _update_owner
205- grep -hs "^deb\ .*$SERVER" /etc/apt/sources.list.d/*.list | grep "$OWNER" | command sed "s#.*$SERVER\/.*\/\(.*\)\/.*#\1#"
206-}
207+_ppa_purge_update_args(){
208+ local i word last=$((${#words[@]}-1)) prevword=
209+ for (( i=1; i < last; i++ )) ; do
210+ word=${words[i]}
211+ [[ $word != $cur ]] &&
212+ case "$word" in
213+ http://*) url=$word ;;
214+ ppa:*) ppa=$word ;;
215+ -*) ;;
216+ ?*) [[ $prevword =~ ^-([^-]*v|-verbose)$ ]] || dist=$word
217+ esac
218+ prevword=$word
219+ done
220+} || break
221
222-_ppa_host(){
223- grep -hs "^deb\ .*tp\:\/\/.*\/.*\/.*" /etc/apt/sources.list.d/*.list | command sed "s#^deb.*\:\/\/\(.*\)\/.*\/.*/.*#\1#" | uniq
224-}
225+_repo_dist(){
226+ [[ $url ]] &&
227+ sed -rn \
228+'s#^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+'"$url"'/?[[:blank:]]+([^[:blank:]]+).*#\3#p' \
229+/etc/apt/sources.list.d/*.list /etc/apt/sources.list ||
230+ sed -rn \
231+'s#^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+http://[^[:blank:]]+[[:blank:]]+([^[:blank:]]+).*#\3#p' \
232+/etc/apt/sources.list.d/*.list /etc/apt/sources.list
233+} || break
234
235-_ppa_owner(){
236- _update_server
237- grep -hs "^deb\ .*$SERVER" /etc/apt/sources.list.d/*.list | command sed "s#.*$SERVER\/\(.*\)\/.*\/.*#\1#"
238-}
239+_repo_list(){
240+ [[ $dist ]] &&
241+ sed -rn \
242+'s#^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+(http://[^[:blank:]]+)[[:blank:]]+'"$dist"'[[:blank:]]+.*#\3#p' \
243+/etc/apt/sources.list.d/*.list /etc/apt/sources.list | sed -e '/http:\/\/ppa\.launchpad\.net/d' -e 's#/$##' ||
244+ sed -rn \
245+'s#^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+(http://[^[:blank:]]+).*#\3#p' \
246+/etc/apt/sources.list.d/*.list /etc/apt/sources.list | sed -e '/http:\/\/ppa\.launchpad\.net/d' -e 's#/$##'
247+} || break
248
249 _ppa_list(){
250- _update_server
251- _update_owner
252- grep -hs "^deb\ .*$SERVER" /etc/apt/sources.list.d/*.list | grep "$OWNER" | command sed "s#.*$SERVER\/\(.*\/.*\)\/.*#\1#"
253+ sed -rn \
254+'s#^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+http://ppa\.launchpad\.net/([^/[:blank:]]+/[^/[:blank:]]+).*#\3#p' \
255+/etc/apt/sources.list.d/*.list /etc/apt/sources.list |
256+ sed -e 's#^[^/]*$#&/#' -e 's#.*#ppa:&#'
257+} || break
258
259-}
260 _ppa_purge(){
261- OWNER=""
262- SERVER="ppa.launchpad.net"
263- local cur prev words cword opts
264- _init_completion || return
265-
266- opts="-p -s -o -d -y -i -h"
267+ local cur prev words cword opts url= ppa= dist= wordlist
268+ # Do not treat : and = as word breaks even if they are in $COMP_WORDBREAKS:
269+ _init_completion -n : -n = || return
270
271- case "${prev}" in
272- -p)
273- COMPREPLY=( $( compgen -W "$(_ppa_names)" -- $cur ) )
274- return 0
275- ;;
276- -s)
277- COMPREPLY=( $( compgen -W "$(_ppa_host)" -- $cur ) )
278- return 0
279- ;;
280- -o)
281- COMPREPLY=( $( compgen -W "$(_ppa_owner)" -- $cur ) )
282- return 0
283- ;;
284- *)
285- ;;
286- esac
287-
288- COMPREPLY=( $( compgen -W '${opts} $(_ppa_list)' -- "$cur" ) )
289+ opts=" --help --simulate --no-initial-update --yes --version --remove \
290+--verbose=0 --verbose=1 --verbose=2 --figure-soname-bumps"
291+# short options are redundant and not that informative
292+ opts+=' -h -s -u -y -r -v0 -v1 -v2 -V'
293
294- return 0
295-} &&
296-complete -F _ppa_purge ppa-purge
297+ [[ $prev =~ ^-([^-]*v|-verbose)$ ]] && wordlist='0 1 2' || {
298+ [[ $cur = -* ]] && wordlist=$opts || {
299+ _ppa_purge_update_args
300+ if [[ $ppa ]]; then
301+ wordlist='$opts'
302+ elif [[ $url ]]; then
303+ [[ $dist ]] && wordlist='$opts' || wordlist='$(_repo_dist)'
304+ elif [[ $dist ]]; then
305+ wordlist='$(_repo_list)'
306+ else
307+ wordlist='$(_ppa_list) $(_repo_list) $(_repo_dist)'
308+ fi
309+ }
310+ }
311+ COMPREPLY=( $( compgen -W "$wordlist" -- "$cur" ) )
312+ _ltrim_completions "$cur" : =
313+ return 0
314+} && complete -F _ppa_purge ppa-purge
315+break
316+done
317diff --git a/ppa-purge b/ppa-purge
318index 19ad281..cceb7fc 100755
319--- a/ppa-purge
320+++ b/ppa-purge
321@@ -1,28 +1,100 @@
322-#!/bin/bash
323-# A script to remove all packages in a PPA and revert back to the normal
324-# distribution ones.
325+#!/bin/bash -u
326+# A script to disable a repository and to remove all packages installed in your
327+# system from it and to revert back to the version (if any) available from a
328+# leftover repository.
329 #
330+<<<<<<< ppa-purge
331 # AUTHORS: Robert Hooker (Sarvatt), Tormod Volden, Darkxst, Jarno Suni (jarnos)
332+=======
333+# AUTHORS: Robert Hooker (Sarvatt), Lorenzo De Liso, Tormod Volden,
334+# Lorenzo De Liso, Tim Lunn (Darkxst), Jarno Ilari Suni (jarnos)
335+
336+export LC_ALL=C # Use C locale to get standard sorting and better regex
337+# performance.
338+export TMPDIR=/dev/shm # dir for mktemp to create files in
339+
340+# Constants
341+declare -r APT=apt-get \
342+yes_option='--force-yes' \
343+F_ARCHS=$(dpkg --print-foreign-architectures) \
344+mytmpdir=$(mktemp -d)
345+declare -r PKGS=${mytmpdir}pkgs \
346+REVERTS=${mytmpdir}reverts \
347+EXITCODE=${mytmpdir}exitcode \
348+program_name=ppa-purge \
349+program_full_name='ppa-purge APT Software Purger' \
350+program_pkg_name=ppa-purge \
351+program_version= \
352+copyright='authors' \
353+copyright_year=
354+
355+# Initialize some variables
356+restore=t
357+declare -a lists=()
358+url=
359+no_update=
360+>>>>>>> ppa-purge
361
362 # Defaults
363-F_ARCHS=$(dpkg --print-foreign-architectures)
364-PPA_PKGS=$(mktemp)
365-REVERTS=$(mktemp)
366-trap "rm $PPA_PKGS $REVERTS" 0
367+# Default for RELEASE will be set below, if needed.
368+yes=
369+simulate=
370+skip_initial_update=
371+remove=
372+verbose=1
373+figure_soname=
374
375 # Functions to write output nicely.
376-write_msg() {
377- echo "$*" | fold -s -w "${COLUMNS:-80}"
378-}
379-
380 msg() {
381- write_msg "$*"
382+ echo "[$program_name] $*"
383 }
384
385 warn() {
386- write_msg "Warning: $*" 1>&2
387+ msg "Warning: $*" 1>&2
388+}
389+
390+error() {
391+ msg "Error: $1" 1>&2
392+ exit ${2:-1}
393 }
394
395+apt_update() {
396+ msg "Updating package lists..."
397+ local cols=0
398+ while read -r; do
399+ case $verbose in
400+ 1) cols=$(tput cols)
401+ printf '\r%-*s' $cols "${REPLY:0:$cols}" ;;
402+ 2) printf '%s\n' "$REPLY"
403+ esac
404+ done < <(
405+ exec 3>&1
406+ set -o pipefail
407+ $APT update 2>&1 >&3 | {
408+ # read and echo warning & error messages
409+ w=
410+ while read -r; do
411+ printf '%s\n' "$REPLY" >&2
412+ [[ $REPLY =~ ^W: ]] && w=t # warning detected
413+ done
414+ [[ $w ]] && printf 0 >$EXITCODE || :
415+ } || printf $? >$EXITCODE
416+ set +o pipefail
417+ )
418+ [[ $verbose -eq 1 && $cols -gt 0 ]] && printf '%-*s\r' $cols "" # clear line
419+ # exit with error, if $APT gave warning or error.
420+ [[ -s $EXITCODE ]] && {
421+ no_update=t
422+ local exit_code=$(<$EXITCODE)
423+ [[ $yes || $exit_code -ne 0 ]] || {
424+ read -r -p "$(msg 'Continue even if warning was detected (Y/n)? ')"
425+ [[ ! ( -z $REPLY || $REPLY =~ ^[Yy]$ ) ]]
426+ } && error "Updating package lists failed; error code ${exit_code}." 5
427+ }
428+ return 0
429+}
430+
431+<<<<<<< ppa-purge
432 error() {
433 write_msg "Error: $*" 1>&2
434 }
435@@ -59,11 +131,115 @@ usage() {
436 echo "(For example: you left synaptic open while attempting to run it) simply"
437 echo "uncomment the PPA from your sources, run apt-get update and try again."
438 echo
439+=======
440+finish() {
441+ set +o pipefail
442+ ((${#lists[@]} > 0)) && {
443+
444+ [[ $restore ]] && {
445+ msg 'Restoring .list file(s):'
446+ for file in "${lists[@]}"; do
447+ mv -fv "$file".save "$file"
448+ done
449+ [[ $no_update ]] || apt_update
450+ } || {
451+ [[ $remove ]] && {
452+ msg 'Removing .list file(s):'
453+ for file in "${lists[@]}"; do
454+ grep -Evq '^[[:blank:]]*(#.*)?$' "$file" || {
455+ # everything is commented out
456+ rm -rv "$file" "$file".save* || :
457+ }
458+ done
459+ }
460+ }
461+ }
462+ rm -rf $mytmpdir
463+}
464+
465+trap finish 0
466+
467+usage() {
468+fold -s -w "${COLUMNS:-80}" << EOF
469+Usage: $program_name [options] ppa:<ppaowner>[/<ppaname>]
470+or: $program_name [options] <URL> [<distribution>]
471+or: $program_name [options] <distribution>
472+or: $program_name { --help | --version }
473+
474+$program_name will disable matching repository/repositories and revert \
475+packages to versions available for target release. If a \
476+package is not available from any remaining repositories, it will be removed, \
477+unless it is a package related to current kernel or it is the package of this \
478+command. If <ppaname> is not given, 'ppa' is used as default. If a \
479+distribution (such as xenial-proposed) is given, repository must match it to \
480+be purged. Bash completion is supported.
481+
482+Exit Status:
483+ 0 on success; non-zero integer on error
484+
485+Options:
486+ --figure-soname-bumps Explicitly install packages that are figured as soname
487+ bumped version of a package to be removed. Display
488+ list of these packages.
489+ -s, --simulate No action; do not downgrade or remove packages.
490+ -u, --no-initial-update Skip initial update of package lists. Use this, if you
491+ are sure the package lists are updated already.
492+ -r, --remove Remove unneeded .list files or repository entries
493+ instead of leaving backups or commenting entries out,
494+ respectively.
495+ -v <level>, -v<level>, --verbose <level>, --verbose=<level>
496+ Verbosity level of "$APT update" output.
497+ 0: only errors
498+ 1: output in one line aiming to give indication of
499+ progress. (default)
500+ 2: output in separate lines.
501+ -y, --yes Run non-interactively; do not prompt for changes.
502+ -h, --help Display this help text and exit.
503+ -V, --version Show version and exit.
504+
505+Environment:
506+ RELEASE Target release to be downgraded to. If not set, output of
507+ "lsb_release -cs" is used.
508+
509+Examples:
510+ sudo $program_name ppa:ubuntu-x-swat/x-updates
511+
512+ Purge the same PPA on Linux Mint 18.1 (based on Ubuntu 16.04):
513+
514+ sudo RELEASE=16.04 $program_name ppa:ubuntu-x-swat/x-updates
515+
516+ Purge Google Chrome repository:
517+
518+ sudo $program_name http://dl.google.com/linux/chrome/deb
519+
520+ Downgrade packages from xenial-proposed in Ubuntu 16.04:
521+
522+ sudo $program_name xenial-proposed
523+
524+EOF
525+>>>>>>> ppa-purge
526 exit $1
527 }
528
529+show_version() {
530+printf "$program_full_name $program_version
531+Copyright (C) $copyright_year $copyright.
532+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
533+This is free software: you are free to change and redistribute it.
534+There is NO WARRANTY, to the extent permitted by law.\n"
535+}
536+
537+suggest_usage() {
538+ echo "Run '$program_name -h' to get help."
539+}
540+
541+# escape special characters (http://unix.stackexchange.com/a/209744/111181)
542+escape_regex() {
543+ printf '%s' "$1" | sed 's/[.[\*^$()+?{|]/\\&/g'
544+}
545
546 # Command line options
547+<<<<<<< ppa-purge
548 while getopts ":p:o:s:d:yih" opt; do
549 case "$opt" in
550 p ) PPANAME="$OPTARG" ;;
551@@ -75,8 +251,47 @@ while getopts ":p:o:s:d:yih" opt; do
552 h ) usage 0; ;;
553 \? ) error "Unknown option -$OPTARG'"; usage 1; ;;
554 :) error "Missing arguments -$OPTARG"; usage 1 ;;
555+=======
556+env -u GETOPT_COMPATIBLE getopt --test >/dev/null || [[ $? -ne 4 ]] && {
557+ # This should not happen with util-linux's getopt.
558+ error '`getopt --test` failed in this environment.' 3
559+}
560+
561+# Option name followed by ':' denotes an option that has an argument.
562+# Options are separated by ','.
563+params=$(env -u GETOPT_COMPATIBLE getopt -o suyhrv:V \
564+-l simulate,no-initial-update,yes,help,version,remove,verbose:,\
565+figure-soname-bumps --name "[$program_name] Error" -- "$@") || {
566+ # If $? = 1, command line is invalid; getopt displays an error message
567+ [[ $? -eq 1 ]] && exit 1
568+ >&2 error 'getopt failed.' 3
569+}
570+# $params contains at least --
571+
572+eval set -- "$params"
573+unset -v params
574+while :; do
575+ case $1 in
576+ -s|--simulate ) simulate='-s' ;;
577+ -u|--no-initial-update ) skip_initial_update=t ;;
578+ -y|--yes ) yes="$yes_option" ;;
579+ -V|--version ) show_version; exit ;;
580+ -h|--help ) usage 0 ;;
581+ -r|--remove ) remove=t ;;
582+ -v|--verbose )
583+ case $2 in
584+ 0|1|2) verbose="$2" ;;
585+ *) error "Invalid verbose level." 1 ;;
586+ esac
587+ shift 2; continue ;;
588+ --figure-soname-bumps ) figure_soname=t ;;
589+ -- ) # End of all options.
590+ shift; break
591+>>>>>>> ppa-purge
592 esac
593+ shift
594 done
595+<<<<<<< ppa-purge
596 shift $(($OPTIND -1))
597
598 if [[ $1 ]]; then
599@@ -93,31 +308,41 @@ if [[ $1 ]]; then
600 usage 1
601 fi
602 fi
603+=======
604+>>>>>>> ppa-purge
605
606-APTARG=""
607-if [ ! -z "$APTALT" ]; then
608- if [ ! -z "$FORCEINSTALL" ]; then
609- APTARG="-y"
610- fi
611- APT=aptitude; APTALT=apt-get
612-else
613- if [ ! -z "$FORCEINSTALL" ]; then
614- APTARG="-y --force-yes"
615+distro=
616+while [[ ${1-} ]]; do
617+ if [[ $1 =~ ^ppa:([^/[:blank:]]+)(/[^/[:blank:]]+)?$ ]]; then
618+ url=ppa.launchpad.net/${BASH_REMATCH[1]}${BASH_REMATCH[2]:-/ppa}/ubuntu
619+ elif [[ $1 =~ ^http://([^[:blank:]]*[^/[:blank:]])/?$ ]]; then
620+ url=${BASH_REMATCH[1]}
621+ else
622+ distro=$1
623 fi
624- APT=apt-get; APTALT=aptitude
625-fi
626+ shift
627+done
628
629+<<<<<<< ppa-purge
630 if [ -z "$PPAOWNER" ]; then
631 error "Required ppa-name argument was not specified"
632 usage 1
633-fi
634+=======
635+[[ -z $url && -z $distro ]] && {
636+ error "No argument given. $(suggest_usage)"
637+}
638
639-# If not set, using defaults
640-[ -z "$PPAHOST" ] && PPAHOST="ppa.launchpad.net"
641-[ -z "$PPANAME" ] && PPANAME="ppa"
642-[ -z "$DIST" ] && DIST=$(lsb_release -c -s)
643+if [[ ${RELEASE+x} ]]; then
644+ [[ $RELEASE =~ ^[^/[:blank:]]+$ ]] || {
645+ error "Invalid target release name :" \'"$RELEASE"\'
646+ }
647+else
648+ RELEASE=$(lsb_release -c -s)
649+>>>>>>> ppa-purge
650+fi
651
652 if [ "$(id -u)" != "0" ]; then
653+<<<<<<< ppa-purge
654 error "This script would need superuser privileges, use sudo"
655 usage 1
656 fi
657@@ -127,17 +352,32 @@ if ! $APT update > /dev/null; then
658 error "$APT update failed for some reason"
659 exit 1
660 fi
661+=======
662+ error "This script would need superuser privileges, use sudo" 2
663+fi
664
665-msg "PPA to be removed: $PPAOWNER $PPANAME"
666+[[ $skip_initial_update ]] || apt_update
667+no_update=t
668+>>>>>>> ppa-purge
669
670-# Make list of all packages in PPA
671-PPA_LIST=/var/lib/apt/lists/${PPAHOST}_${PPAOWNER}_${PPANAME}_*_Packages
672-for LIST in $PPA_LIST; do
673- if [ -e $LIST ]; then
674- grep "^Package: " $LIST | cut -d " " -f2 | sort >> $PPA_PKGS
675+msg "To be removed: ${url} ${distro}"
676+
677+# Make list of all packages available from the matching archive(s)
678+[[ $url ]] && _url=$(tr / _ <<<"$url") || _url='*'
679+for LIST in /var/lib/apt/lists/${_url}_dists_*_Packages; do
680+ if [ -f $LIST ]; then
681+ nomatch=
682+ if [[ $distro ]]; then
683+ dist=${LIST##*_dists_}
684+ dist=${dist%%_*}
685+ [[ $dist == $distro ]] || nomatch=t
686+ fi
687+ [[ $nomatch ]] ||
688+ grep "^Package: " $LIST | cut -d " " -f2 >> $PKGS
689 fi
690 done
691
692+<<<<<<< ppa-purge
693 if [ ! -s $PPA_PKGS ]; then
694 error "Could not find package list for PPA: $PPAOWNER $PPANAME"
695 exit 1
696@@ -147,70 +387,148 @@ fi
697 if grep -q "ppa-purge" $PPA_PKGS; then
698 sed -i '/ppa-purge/d' $PPA_PKGS
699 msg "Note: Not removing ppa-purge package"
700+=======
701+if [ ! -s $PKGS ]; then
702+ error "Could not find matching packages." 4
703+>>>>>>> ppa-purge
704 fi
705
706 # Get multi-arch package names for revert list
707-cat $PPA_PKGS | sort -u |
708- xargs dpkg-query -W -f='${binary:Package}\t${db:Status-Abbrev}\n' 2>/dev/null |
709- awk '/\tii $/{print $1}' > $REVERTS
710-# Fallback for Precise
711-if [ ! -s $REVERTS ]; then
712- for PACKAGE in $(cat $PPA_PKGS | sort -u); do
713- dpkg-query -W -f='${PackageSpec}\t${Status}\n' $PACKAGE 2>/dev/null |
714- awk '/\tinstall/{print $1}' >> $REVERTS
715- for F_ARCH in $F_ARCHS; do
716- dpkg-query -W -f='${PackageSpec}\t${Status}\n' "$PACKAGE:$F_ARCH" 2>/dev/null |
717- awk '/\tinstall/{print $1}' >> $REVERTS
718- done
719- done
720-fi
721+sort -u $PKGS | xargs dpkg-query -W \
722+ -f='${binary:Package}\t${db:Status-Abbrev}\n' 2>/dev/null |
723+ awk '/\tii $/{print $1}' > $REVERTS
724+>$PKGS
725
726-# Disable PPA from sources.list files
727-for LIST in $(find /etc/apt/ -name "*.list" -exec readlink -f '{}' \;); do
728- if [ -e $LIST ] && grep -q $PPAOWNER/$PPANAME $LIST; then
729- msg "Disabling $PPAOWNER PPA from $LIST"
730- sed -ri "\:^[^#]+/${PPAOWNER}/${PPANAME}/:s/^deb/# deb/" $LIST
731- fi
732+# Disable matching lines from sources.list files
733+[[ $url ]] &&
734+ regex='^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+http://'"$(escape_regex "$url")"'/?[[:blank:]]+([^[:blank:]]+)' ||
735+ regex='^[[:blank:]]*deb(-src)?([[:blank:]]+\[.+\])?[[:blank:]]+http://[^[:blank:]]+ +([^[:blank:]]+)'
736+newlist=
737+for LIST in $(find /etc/apt/ -name "*.list" -exec readlink -e '{}' \;); do
738+ changed=
739+ while read -r; do
740+ nomatch=
741+ [[ "$REPLY" =~ $regex ]] && {
742+ if [[ $distro ]]; then
743+ [[ ${BASH_REMATCH[3]} == $distro ]] || nomatch=t;
744+ fi
745+ } || nomatch=t
746+
747+ [[ $nomatch ]] && newlist+="$REPLY"$'\n' || {
748+ [[ $remove ]] && msg "Remove entry: $REPLY" || {
749+ newlist+="# $REPLY"$'\n'
750+ msg "Disable entry: $REPLY"
751+ }
752+ changed=t
753+ }
754+ done <$LIST
755+
756+ [[ $changed ]] && {
757+ msg "Making backup of .list file:"
758+ mv -fvb "$LIST" "$LIST".save
759+ lists+=("$LIST")
760+ printf %s "$newlist" > "$LIST"
761+ }
762+ newlist=
763 done
764
765-msg "Updating packages lists"
766-$APT update > /dev/null || warn "$APT update failed for some reason"
767+[[ $yes ]] || {
768+ read -p "$(msg 'Continue with these changes (Y/n)? ')" -r
769+ [[ -z $REPLY || $REPLY =~ ^[Yy]$ ]] || exit
770+}
771+
772+no_update=
773+apt_update
774+
775+msg "Generating revert list..."
776
777-# Create apt argument list for reverting packages, most of the foo here is to attempt
778-# to unroll soname bumps
779+# Create apt argument list for reverting packages
780
781-REINSTALL=""
782+# store available packages in a sorted variable for faster access.
783+avail_pkgs=$(apt-cache dumpavail | grep '^Package:' | cut -d' ' -f2 | sort -urV)
784+
785+# Create an associated array for fast checking of available packages.
786+# Creating takes some time though, say 1s, but will save a lot if there are many
787+# reverts.
788+declare -A avail=()
789+for PKG in $avail_pkgs; do avail[$PKG]=; done
790+
791+# tag for current kernel version
792+curkerversion=$(escape_regex $(uname -r | cut -d- -f1,2))
793+# tag for current kernel flavor
794+curkerflavor=$(escape_regex $(uname -r | cut -d- -f3-))
795+REINSTALL=
796+declare -a sonamepkg=()
797 for PACKAGE in $(cat $REVERTS); do
798- PKG=$(echo $PACKAGE | cut -d ':' -f1)
799- [[ $PACKAGE == *:* ]] && D_ARCH=":"$(echo $PACKAGE | cut -d ':' -f2)
800+ PKG=${PACKAGE%:*}
801
802- if [ $(grep-aptavail -XPc -s Package $PKG) -eq 0 ]; then
803- PAT=$(echo $PKG | sed -e s/[0-9][a-z]\$/'..'/ -e s/[0-9]/'.'/g)
804+ # Test if PKG is still available
805+# if ! grep -xFq "$PKG" <<<"$avail_pkgs"; then
806+ if [[ -z ${avail[$PKG]+x} ]]; then
807
808- APTAVAIL=$(grep-aptavail -eP --pattern='^'$PAT'$' -s Package -n | sort -uV | sed -e '$!d')
809+ # Explicitly remove the package that does not exist in archive unless
810+ # it is versioned kernel package matching the current kernel or the
811+ # package of this program.
812+ [[ $PKG =~ ^linux-.+-${curkerversion}(-${curkerflavor})?$ ||
813+ $PKG == $program_pkg_name ]] &&
814+ msg "Note: Not removing $PKG package." ||
815+ {
816+ REINSTALL+=" $PACKAGE-"
817
818- #explicitly remove packages that don't exist in archive
819- if [ "x$APTAVAIL" != "x$PKG" ]; then
820- REINSTALL="$REINSTALL $PACKAGE-"
821- fi
822+ [[ $figure_soname && $PKG != linux-* ]] && {
823+ # Maybe could even restrict to lib* ?
824+ # check if the package is availabe with another version tag
825+ pkg_regex=$(escape_regex "$PKG")
826+ soname_regex=$(sed -r \
827+ -e 's/[[:digit:]][[:lower:]]$/[[:digit:]][[:lower:]]/' \
828+ -e 's/[[:digit:]]+/[[:digit:]]+/g' <<<"$pkg_regex")
829+ [[ $soname_regex != $pkg_regex ]] && {
830
831- #downgrade packages that have a soname bump
832- if [ -n "$APTAVAIL" ]; then
833- REINSTALL="$REINSTALL $APTAVAIL$D_ARCH/$DIST"
834- fi
835+ # get the greatest available version of the package
836+ APTAVAIL=$(grep -m 1 -E "^${soname_regex}$" \
837+ <<<"$avail_pkgs" || :)
838+
839+ # downgrade packages that have a soname bump
840+ [[ $APTAVAIL ]] && {
841+ newpkg=${APTAVAIL}${PACKAGE#$PKG}
842+ sonamepkg+=("$newpkg")
843+ REINSTALL+=" $newpkg/$RELEASE"
844+ }
845+ }
846+ }
847+ }
848 else
849- REINSTALL="$REINSTALL $PACKAGE/$DIST"
850+ REINSTALL+=" $PACKAGE/$RELEASE"
851 fi
852 done
853+unset -v avail avail_pkgs
854+>$REVERTS
855+
856+[[ ${#sonamepkg[*]} -gt 0 ]] && {
857+ msg "Going to install these packages due to soname bump figuring:
858+$(printf '%s\n' "${sonamepkg[@]}")"
859+ msg "These of them are installed already (but maybe different version):
860+$(dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' "${sonamepkg[@]}" \
861+2>/dev/null | awk '/^.i /{print $2}')"
862
863-msg "Package revert list generated:"
864-msg "$REINSTALL"
865-echo
866+ [[ $yes ]] || {
867+ read -p "$(msg 'Continue (Y/n)? ')" -r
868+ [[ -z $REPLY || $REPLY =~ ^[Yy]$ ]] || exit
869+ }
870+}
871
872-# FIXME:
873-# Workaround for now in case APT fails. APTALT is a little more foregiving if the
874-# revert list isn't 100% correct.
875+msg "Reverting..."
876+$APT $simulate $yes -V install $REINSTALL || {
877+ exit_status=$?
878+ [[ $exit_status -eq 1 ]] &&
879+ # User aborted apt-get; no packages were downgraded or removed.
880+ exit 5 ||
881+ error "Something went wrong with $APT; error code $exit_status. \
882+Packages may not have been reverted." 5
883+}
884+msg "Reverting packages finished successfully."
885
886+<<<<<<< ppa-purge
887 if $APT $APTARG install $REINSTALL; then
888 msg "PPA purged successfully"
889 elif $APTALT $APTARG install $REINSTALL; then
890@@ -219,4 +537,10 @@ else
891 error "Something went wrong, packages may not have been reverted"
892 exit 1
893 fi
894+=======
895+[[ $simulate ]] &&
896+ msg "Restoring repository entries, because this was just simulation:" ||
897+ restore=
898+# successful operation; no need to restore, unless in simulation mode.
899+>>>>>>> ppa-purge
900 exit 0

Subscribers

People subscribed via source and target branches

to all changes: