#!/usr/bin/env ruby $version = '0.5' $aboutText = %Q{ This is rtkmerge version #{$version} usage: rtkmerge world -u rtkmerge ruby Always press the pretend-button to see which packages the current configuration will merge. It might be more then you expect. This program is licensed under GPL, Gnu Public License written by and copyright: Daniel Forchheimer (upiom), 2003 } require 'tk' commandToGetList = "emerge #{$*.join(" ")} -pv --columns" $flagsWhenEmerge = "" # these flags are used when merging the separate packages $flagsWhenPretend = $flagsWhenEmerge + " " + "-pv --columns" nUseFlaggorPerRad = 6; $useProgressBar = true class Paket def initialize(fullStr) fullStr=fullStr[15..fullStr.length]; @paketArray = fullStr.split(' ') @toEmerge = "yes" @pTkWidgets = [] end def tkWidgets @pTkWidgets end def toEmerge=(b) @toEmerge = b; end def toEmerge @toEmerge end def namn @paketArray[0] end def kortNamn namn.split("/",2)[1] end def nyVersion @paketArray[1][1..@paketArray[1].length-2] end def instaleradVersion if @paketArray[2]!=nil then if @paketArray[2][0]==?[ then @paketArray[2][1..@paketArray[2].length-2] else "" end else "" end end def useArray if instaleradVersion == "" then start=2 else start=3 end @paketArray[start..@paketArray.length] || [] end def toggleUse(useString) ind = useArray.index(useString); if(useArray[ind][0]==43) useArray[ind][0]=45 else useArray[ind][0]=43 end useArray[ind] end def setBackground(color) @pTkWidgets.each { |w| w.configure('background'=>color) } end def disableWidgets @pTkWidgets.each { |w| if (w.class == TkButton)||(w.class==TkCheckbutton) then w.configure('state'=>'disabled') end } end def splat sec = hour = min = 0 time = 0.0 str = `splat -s #{kortNamn}` str.each_line do |l| l.strip! if l[11]==?e then while l.index(/[0-9]/) do l = l[l.index(/[0-9]/)..l.length] num = l[0..l.index(' ')].to_i unit= l[l.index(' ')+1] l = l[l.index(' ')..l.length] case unit when ?s time+= num when ?m time+= num*60 when ?h time+= num*60*60 end end end end time end def compileTime # general class to calculate compiletime # various method may be used, for now only # splat is implemented (compile time is aproximated # to the avarage compile time) # # returns compile time in seconds or 0 if failed system("which splat") if $? == 0 then splat else 0 end end def emerge(argString) cmd = "USE=\"" useArray.each do |s| cmd<<" "<'x') orient 'horizontal' from 0 to 100 } end def abortPackage if(@tThread.alive?) then @tThread.kill end end def newPackage(package) totalTime = package.compileTime waitTime = totalTime/100.0 puts "waitTime är: " + waitTime.to_s if waitTime != 0.0 then @tThread = Thread.new { 101.times { |i| @scale.set i sleep waitTime } } else # we have to initialize tThread or abortPackage will be mad @tThread = Thread.new {} @scale.set 50 end end end def aboutWindow aroot = TkToplevel.new(root) {title 'About'} atop = TkFrame.new(aroot) atop.pack TkLabel.new(atop) { pack('side'=>'top') text $aboutText } TkButton.new(atop) { pack('side'=>'top') text 'close' command proc { aroot.destroy } } end def pretendEmerge(mina_paket) pwin = TkToplevel.new(root) { title 'pretend' } bar =TkScrollbar.new(pwin) { pack('side'=>'right','fill'=>'y') } text = TkText.new(pwin) { pack('expand'=>'yes','fill'=>'both','side'=>'left') yscrollbar(bar) wrap 'word' } puts "Calculating dependencies" allToPretend = "These are the packages that I would merge, in order:\n" mina_paket.each { |pk| if pk.toEmerge == 'yes' then pk.emergeCapture($flagsWhenPretend).each_line {|l| if(l["[ebuild"]) then if !(allToPretend[l[16..l.length].split[0]]) then allToPretend << l end end } end } nameColor = TkTextTag.new(text,'foreground'=>'dark green') oldVersionColor= TkTextTag.new(text,'foreground'=>'blue') posColor = TkTextTag.new(text,'foreground'=>'dark red') negColor = TkTextTag.new(text,'foreground'=>'dark blue') uColor = TkTextTag.new(text,'foreground'=>'turquoise') nColor = TkTextTag.new(text,'foreground'=>'green') fColor = TkTextTag.new(text,'foreground'=>'red') rColor = TkTextTag.new(text,'foreground'=>'yellow') dColor = oldVersionColor allToPretend.each_line { |s| if(s.index("[ebuild")) then pk = Paket.new(s) text.insert('end',s[0..6]) s[7..15].each_byte { |apa| case apa when ?U text.insert('end',apa.chr,uColor) when ?N text.insert('end',apa.chr,nColor) when ?F text.insert('end',apa.chr,fColor) when ?R text.insert('end',apa.chr,rColor) when ?D text.insert('end',apa.chr,dColor) else text.insert('end',apa.chr) end } text.insert('end',pk.namn+"-"+pk.nyVersion,nameColor) text.insert('end'," ["+pk.instaleradVersion+"]",oldVersionColor) pk.useArray.each do |uf| if uf[0]==?+ then text.insert('end'," "+uf,posColor) else text.insert('end'," "+uf,negColor) end end text.insert('end',"\n") else text.insert('end',s) end } text.state('disabled') end def setButtonColor(u) if(u[0]==?+) background 'red' activebackground 'red4' else background 'blue' activebackground 'blue4' end end mina_paket = Array.new puts "Calculating #{$*[0]} dependencies" cmd = open("|"+commandToGetList) while (string=cmd.gets) if(string["[ebuild"]) mina_paket << Paket.new(string); end end cmd.close puts " ...done!" puts mina_paket.nitems.to_s+" packages to update." root = TkRoot.new { title "Ruby-Tk-Merge: #{$*[0]}" } top = TkFrame.new(root) top.pack('padx'=>5,'pady'=>5) if $useProgressBar then pb = ProgressBar.new(top) end lineFrame = TkFrame.new(top) { pack('side'=>'top','fill'=>'both','pady'=>5) # background 'pink' border 1 relief 'solid' } spareWidgetsToDisable = [] TkButton.new(lineFrame) { pack('side'=>'left','anchor'=>'w') text "Emerge!" command proc { mina_paket.each { |p| p.disableWidgets } spareWidgetsToDisable.each { |w| w.configure('state'=>'disabled') } state 'disabled' mergeThread =Thread.new { mina_paket.each { |p| #print p.toEmerge.class #puts " " + p.toEmerge if p.toEmerge=='yes' then p.setBackground('yellow') if $useProgressBar then p.emerge("--fetchonly") pb.newPackage(p) end if (p == mina_paket.last) then # the last package could be a new package p.emerge($flagsWhenEmerge) else # some of these might be dep's and should not be added to world # the rest are allready in world p.emerge($flagsWhenEmerge+" --oneshot") end if $? == 0 then p.setBackground('green') else p.setBackground('red') end if $useProgressBar then pb.abortPackage end end } } } } spareWidgetsToDisable << TkButton.new(lineFrame) { pack('side'=>'left','anchor'=>'w') text "pretend" command proc {pretendEmerge(mina_paket) } } TkButton.new(lineFrame) { pack('side'=>'right','anchor'=>'e') text "quit" command proc { root.destroy} } TkButton.new(lineFrame) { pack('side'=>'right','anchor'=>'e') text "about" command proc {aboutWindow } } lineFrame = TkFrame.new(top) { pack('side'=>'top','fill'=>'both','anchor'=>'w') } checkButtons = [] spareWidgetsToDisable << TkButton.new(lineFrame) { pack('side'=>'left','anchor'=>'w') text 'all' command proc { checkButtons.each { |cb| cb.select } mina_paket.each { |pk| pk.toEmerge="yes" } } } spareWidgetsToDisable << TkButton.new(lineFrame) { pack('side'=>'left','anchor'=>'w') text 'none' command proc { checkButtons.each { |cb| cb.deselect } mina_paket.each { |p| p.toEmerge="no" } } } #TkScrollbar.new(top) { # pack('side'=>'right','anchor'=>'e','fill'=>'y'); # command proc { |*args| top.yview *args} #} # create lines for all the packages mina_paket.each { |p| lineFrame = TkFrame.new(top) { pack('side' => 'top','anchor'=>'w','fill'=>'x') } p.tkWidgets << lineFrame check = TkVariable.new p.tkWidgets << TkCheckbutton.new(lineFrame) { variable check check.value='yes' text p.namn+"-"+p.nyVersion onvalue 'yes' offvalue 'no' pack('side'=>'left','fill'=>'x','anchor'=>'nw') command proc { p.toEmerge=check.value; } } checkButtons << p.tkWidgets.last if p.instaleradVersion!="" then p.tkWidgets << TkLabel.new(lineFrame) { text "["+p.instaleradVersion+"]" foreground 'blue' pack('side'=>'left','fill'=>'x','anchor'=>'nw') } end 0.step(p.useArray.length,nUseFlaggorPerRad) { |i| useLineFrame = TkFrame.new(lineFrame) { pack('side'=>'top','anchor'=>'w') } p.useArray[i..i+nUseFlaggorPerRad-1].each { |u| p.tkWidgets << TkButton.new(useLineFrame) { text u # relief 'solid' setButtonColor(u) command proc { newU = p.toggleUse(u); text newU setButtonColor(newU); } pack('fill' => 'x','side'=>'left','anchor'=>'w') } } } } if $useProgressBar then pb.pack('side'=>'top','fill'=>'x') end Tk.mainloop END { trap("SIGINT") {} Process.kill("SIGINT",0) }