Re: dpkg BUG install order problem & suggestion to add...
debian-dpkg@lists.debian.org
Jonathan Nieder wrote:
John D. Hendrickson and Sara Darnell wrote:
I have a working example of what to do that mostly uses existing
unix tools.
Well, what are you waiting for? :)
The problem seems to be when allot of packages need to be installed (makes unreasonable choices) and
it begins to deteriorate after initial install failures. Soon the "solver" is trying to install
small desktop apps before base components (every time I upgrade).
I looked at the dpkg ant aptitude sources. It seems there's allot of maybe's involved "grading"
(not that I'm complaining it makes good lists in a thin env.) (extended discussion). The "grade"
method is great for finding a wishlist.
I only say the resulting list is likely unordered and this is likely to cause problems during large
install / uninstall "runs".
My thesis, still preliminary, is ONLY TO RE-ORDER the given list dpkg will attempt, only optionally,
nothing else. It should reduce errors and no effect anything, not even triggers, at all.
SEE PROPOSAL BELOW. (it shows the make tsort-out but not utilities I have that go with it)
(the simple lookup utilities to things like show all possible deps and ordre them against the
tsorted list (easy), etc)
Thanks hope you enjoy discussion,
John Hendrickson
# -----------------------------------------------------
# FILE: Makefile
# DESC: generates tsort-out
# USAGE: 'make'
# or make [ show | clean | realclean ]
# -----------------------------------------------------
# below is mostly simple table making & lookup. several
# tables can be a bear to tend but make makes it easy
# due to make syntax sh script needs $$ instead of $
SHELL = /bin/sh
DEPENDENCIES= available pack prov dep ppd prov-flat prov-idx prov-flat \
pP-dup pP-dep num-dep-1 num-dep-2 pP-dep-2 num-dep-done tsort-in
# -----------------------------------------------------
LINES = `wc -l pack | sed -e 's/ .*$$//'`
# -----------------------------------------------------
# main file : depends on other files
# before being able to create it
tsort-out : ${DEPENDENCIES}
@echo 'making tsort-in';
tsort tsort-in 2>>dep-loops | tac > tsort-out
# tsort-out : tsort-in # skips optionals, ie, ppd
# -----------------------------------------------------
.PHONY : show
show : tsort-out
show-all | sort -s -k 3,3 | less -S
.PHONY : install
install :
@echo "preliminary - nothing to install"
.PHONY : clean
clean :
@echo "cleaning intermediate files (can still use scripts)"
rm dep dep-idx dep-loops growth num-dep-1 num-dep-2 \
pP-dep pP-dep-2 pP-dup ppd prov prov-flat \
tsort-in pass.log 2>> /dev/null ; /bin/true
.PHONY : realclean
realclean : clean
@echo "cleaning all tables ('make all' needed to use scripts)"
rm ${DEPENDENCIES} 2>> /dev/null ; /bin/true
.PHONY : all
all : tsort-out
available :
@echo "no ./available, using softlink"
ln -s /var/lib/dpkg/available .
pack prov dep : available
@echo 'making pack prov dep';
@rm pack prov dep 2>>/dev/null ; awk 'BEGIN{OFS=""} /^Pa/{if(ln!=0){print n pdhold dhold >> "dep"
}; ln=0; dhold=""; pdhold=""; ++n; print n " " $$2 >> "pack"} /^Pro/{sub(/Provides: /,"");
gsub(/,/,""); print n " " $$0 >> "prov"} /^Dep/{ln=n; gsub(/Depends: /,""); gsub(/\([^)]*\)/,"");
gsub(/,/,""); gsub(/\|/,""); dhold=" "$$0} /^Pre/{ln=n; gsub(/Pre-Depends: /,"");
gsub(/\([^)]*\)/,""); gsub(/,/,""); gsub(/\|/,""); pdhold=" "$$0} {if(d==1 && pre==0) print n" "hold
>> "dep"; pre=0}' available
ppd : available
@echo 'making ppd';
@awk 'BEGIN{FS="\n"}; /^Pa/{print $$0}; /^Pri/{gsub(/,/,""); print $$0}; /^Sec/{print $$0};
/^Pro/{print $$0}; /^Dep/{gsub(/\([^)]*\)/,""); gsub(/,/,""); gsub(/\|/,""); print $$0};
/^Pre/{gsub(/\([^)]*\)/,""); gsub(/,/,""); gsub(/\|/,""); print $$0}; /^$$/{print "Index: "
++n"\n"}' available > ppd
prov-flat : prov
@echo 'making prov-flat';
@awk '{x=2; while($$x != ""){print $$1 " " $$x; ++x}}' prov > prov-flat
prov-idx : prov-flat
@echo 'making prov-idx';
@cat prov-flat | sed -e 's/^.* //' | sort | uniq | awk -v l=${LINES} '{print NR+l " " $$1}' > prov-idx
pP-dup : prov-idx prov-flat
@echo 'making pP-dup';
@awk 'BEGIN{while(getline <"prov-idx"){x[$$2]=$$1}} ; {print x[$$2] " " $$1}' prov-flat | sort > pP-dup
pP-dep : pP-dup
@echo 'making pP-dep';
@awk 'BEGIN{ORS=""} ; {if(last == $$1){print " " $$2} else {if(NR>1)print "\n"; print $$1" "$$2;}
last=$$1;}' pP-dup > pP-dep
num-dep-1 : pack prov-idx dep
@echo 'making num-dep-1';
@awk 'BEGIN{ORS=""; while(getline <"pack"){x[$$2]=$$1}; while(getline <"prov-idx"){xx[$$2]=$$1}};
{print $$1 ; y=2; while(y <= NF){str=x[$$y]; if(str=="") str=xx[$$y]; print " " str; ++y}; print
"\n"}' dep | sed -e 's/0[[:space:]]*||//g ; s/||[[:space:]]*0//g' > num-dep-1
num-dep-2 : num-dep-1
@echo 'making num-dep-2';
@awk '{if($$1>FNR){while(FNR<$$1){print FNR " " FNR; ++FNR}}; if($$2==""){print $$1 " " $$1; next}
else print $$0}' num-dep-1 > num-dep-2
# NOTE
# fix Provides-Depends loops now, right time to sweep that
# could just do until no provs, but does all
# sweep zo L-R, insert new unique as found at zo at nj (non-recursive)
# don't keep a Provides after once de-referencing
# leave all in order found (inserts zi in zo)
# if(jj<=lines) means is not in dep table so try prov table
# don't try combining tables AWK searches funny: really
pP-dep-2 : num-dep-2 pP-dep
@echo 'making pP-dep-2';
@rm pass.log 2>>/dev/null ; awk -v rn=40000 -v lines=${LINES} 'BEGIN { ORS=""; while(getline
<"num-dep-2") x1[$$1]=$$0; while(getline <"pP-dep") x2[$$1]=$$0 } { if($$1==rn) print "#"; if(NF==2
&& $$1==$$2){print $$1" "$$1"\n"; next} delete zi; delete zo; delete zb; delete zy; zb[$$1]=1;
zy[$$1]=1; zf=0; nf=NF; split($$0,zo); nj=1; while(++nj<=nf) { jj=zo[nj]; if(jj==0 ||
zb[jj]==1){if($$1==rn) print jj"-->"zo[nj]"<--"zb[jj]; zo[nj]=""; continue} zb[jj]=1; zy[jj]=1;
if($$1==rn) print "%"nj; if(jj<=lines){len=split(x1[jj], str)}else{zo[nj]=""; len=split(x2[jj],
str)} if($$1==rn) print " L="len" jj="jj; k=1; while(++k<=len) { if(zy[str[k]]==0){zy[str[k]]=1;
zi[++zf]=str[k]; if($$1==rn) print "+"} if($$1==rn) print "\nrec "$$1"\n nf "nf"\n nj "nj"\n jj
"jj"\n k "k"\n strk "str[k]"\n" } if($$1==rn){print "\nzo "; n=0; while(++n<=nf) print zo[n]" ";
print "\nzi "; n=0; while(++n<=zf) print zi[n]" "} if(zf>0){n=nf+1; while(--n>nj) zo[n+zf]=zo[n]}
n=0; while(++n<=zf) zo[nj+n]=zi[n]; nf+=zf; if($$1==rn){print "\nzo "; n=0; while(++n<=nf) print
zo[n]" "; print "\nzi "; n=0; while(++n<=zf) print zi[n]" "; print "\n"} delete zi; zf=0; nf2=nf;
if(nj>=lines){print "\n"$$0" err: pass#>"lines", see pass.log\n" >>"/dev/stderr"; break} } print
"\n"$$1" pass "nj >>"pass.log"; k=0; n=0; while(++n<=nf) if(zo[n]!=""){print zo[n] " "; ++k}
if(k==1) print $$1; print "\n"; if($$1==rn) exit }' pP-dep > pP-dep-2
num-dep-done : num-dep-2 pP-dep-2
@echo 'making num-dep-done';
@rm pass.log 2>>/dev/null ; awk -v rn=40000 -v lines=${LINES} 'BEGIN { ORS=""; while(getline
<"num-dep-2") x1[$$1]=$$0; while(getline <"pP-dep-2") x2[$$1]=$$0 } { if($$1==rn) print "#";
if(NF==2 && $$1==$$2){print $$1" "$$1"\n"; next} delete zi; delete zo; delete zb; delete zy;
zb[$$1]=1; zy[$$1]=1; zf=0; nf=NF; split($$0,zo); nj=1; while(++nj<=nf) { jj=zo[nj]; if(jj==0 ||
zb[jj]==1){if($$1==rn) print jj"-->"zo[nj]"<--"zb[jj]; zo[nj]=""; continue} zb[jj]=1; zy[jj]=1;
if($$1==rn) print "%"nj; if(jj<=lines){len=split(x1[jj], str)}else{zo[nj]=""; len=split(x2[jj],
str)} if($$1==rn) print " L="len" jj="jj; k=1; while(++k<=len) { if(zy[str[k]]==0){zy[str[k]]=1;
zi[++zf]=str[k]; if($$1==rn) print "+"} if($$1==rn) print "\nrec "$$1"\n nf "nf"\n nj "nj"\n jj
"jj"\n k "k"\n strk "str[k]"\n" } if($$1==rn){print "\nzo "; n=0; while(++n<=nf) print zo[n]" ";
print "\nzi "; n=0; while(++n<=zf) print zi[n]" "} if(zf>0){n=nf+1; while(--n>nj) zo[n+zf]=zo[n]}
n=0; while(++n<=zf) zo[nj+n]=zi[n]; nf+=zf; if($$1==rn){print "\nzo "; n=0; while(++n<=nf) print
zo[n]" "; print "\nzi "; n=0; while(++n<=zf) print zi[n]" "; print "\n"} delete zi; zf=0; nf2=nf;
if(nj>=lines){print "\n"$$0" err: pass#>"lines", see pass.log\n" >>"/dev/stderr"; break} } print
"\n"$$1" pass "nj >>"pass.log"; k=0; n=0; while(++n<=nf) if(zo[n]!=""){print zo[n] " "; ++k}
if(k==1) print $$1; print "\n"; if($$1==rn) exit }' num-dep-2 > num-dep-done
tsort-in : num-dep-done
@echo 'making tsort-in';
awk '{n=1; while(++n<=NF){print $$1 " " $$n}}' num-dep-done > tsort-in
Reply to: