summaryrefslogtreecommitdiffstats
path: root/yum-presto/shared/prestoTransaction.py
blob: 4f08391bfa2142a0d05913f44ba2106fadf4d63e (plain)
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
# author: Jonathan Dieter <jdieter@gmail.com>
# 
# format_number taken almost completely from progress_meter.py in yum
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Copyright 2005 Duke University
# Copyright 2007 Jonathan Dieter

import os
import deltarpm

def format_number(number, SI=False, space=''):
    """Turn numbers into human-readable metric-like numbers"""
    symbols = ['',  # (none)
                'K', # kilo
                'M', # mega
                'G', # giga
                'T', # tera
                'P', # peta
                'E', # exa
                'Z', # zetta
                'Y'] # yotta

    if SI: step = 1000.0
    else: step = 1024.0

    thresh = 999
    depth = 0

    # we want numbers between 
    while number > thresh:
        depth  = depth + 1
        number = number / step

    # just in case someone needs more than 1000 yottabytes!
    diff = depth - len(symbols) + 1
    if diff > 0:
        depth = depth - diff
        number = number * thresh**depth

    if type(number) == type(1) or type(number) == type(1L):
        format = '%i%s%s'
    elif number < 9.95:
        # must use 9.95 for proper sizing.  For example, 9.99 will be
        # rounded to 10.0 with the .1f format string (which is too long)
        format = '%.1f%s%s'
    else:
        format = '%.0f%s%s'

    return(format % (number, space, symbols[depth]))


def find_available_drpms(conduit, newpkg):
    """Find any applicable drpms for newpkg
       newpkg is a TransactionMember"""
    
    rpmdb = conduit.getRpmDB()
    
    is_local = False
    
    # Set p_repo to be packages delta repository or set to False if
    # there is no delta repository
    try:
        p_repo = newpkg.po.repo.p_repo
        drpm_enabled = p_repo.enabled

        po = newpkg.po
        if hasattr(po, 'pkgtype') and po.pkgtype == 'local':
            is_local = True
        else:
            local = po.localPkg()
            if os.path.exists(local):
                cursize = os.stat(local)[6]
                totsize = long(po.size)
                if not po.verifyLocalPkg():
                    if cursize >= totsize: # otherwise keep it around for regetting
                        os.unlink(local)
                else:
                    conduit.info(5, "using local copy of %s" % po)
                    is_local = True

    except:
        conduit.info(5, "No Presto repository information for %s.%s %i:%s-%s" % (newpkg.name, newpkg.arch, int(newpkg.epoch), newpkg.version, newpkg.release))
        drpm_enabled = False
        is_local = False
        
    chosen_drpm = None
    
    # First part of key when matching drpms
    key1 = "%s*%s*%i*%s*%s" % (newpkg.name, newpkg.arch, int(newpkg.epoch), newpkg.version, newpkg.release)
    
    # Find any installed packages that match the ones we want to download
    installed = rpmdb.searchNevra(newpkg.name, None, None, None, newpkg.arch)

    if installed == []:
        is_installed = False
    else:
        is_installed = True
        
    
    if is_installed and drpm_enabled and not is_local:
        for oldpkg in installed:
            # Generate second part of key for matching drpms, then full key
            key2 = "%s*%s*%i*%s*%s" % (oldpkg.name, oldpkg.arch, int(oldpkg.epoch), oldpkg.version, oldpkg.release)
            key = "%s!!%s" % (key1, key2)
            
            # Check whether we have a matching drpm
            if p_repo.deltalist.has_key(key):
                # Check whether or not we already have a matching drpm, then choose smallest of the two if we do
                if chosen_drpm == None or p_repo.deltalist[key]['size'] < chosen_drpm['size']:
                
                    # Get sequence code for drpm
                    sequence = p_repo.deltalist[key]['sequence']
#                    if int(oldpkg.epoch) == 0:  # Don't try to save space on sequence anymore.  It just won't work.
#                        seq = "%s-%s-%s-%s" % (oldpkg.name, oldpkg.version, oldpkg.release, sequence)
#                    else:
#                        seq = "%s-%i:%s-%s-%s" % (oldpkg.name, int(oldpkg.epoch), oldpkg.version, oldpkg.release, sequence)
                    drpm = deltarpm.DeltaRpmWrapper(conduit)
                    
                    # Attempt to apply sequence code for drpm. If this fails, drpm will not apply cleanly, so
                    # don't even try to download it.
                    try:
                        drpm.verifySequence(sequence)
                    except:
                        conduit.info(5, "Verification of %s failed" % seq)
                    else:
                        chosen_drpm = p_repo.deltalist[key]
                        chosen_drpm['baseurl'] = p_repo.baseurl[0]
                        newpkg.po.oldpkg_string = "%s.%s %s:%s-%s" % (oldpkg.name, oldpkg.arch, oldpkg.epoch, oldpkg.version, oldpkg.release)
                        newpkg.po.newpkg_string = "%s.%s %s:%s-%s" % (newpkg.name, newpkg.arch, newpkg.epoch, newpkg.version, newpkg.release)
        
    return (chosen_drpm, installed, is_local, drpm_enabled)