1
2
3
4 """This module check for PySQL updates and help user to update PySQL online
5 @author: Sébastien Renard (sebastien.renard@digitalfox.org)
6 @license: GNU GPL V3
7 """
8
9
10 import urllib2
11 import re
12 import sys
13 from os.path import dirname, isdir, isfile, islink, join, pardir
14 from os import access, listdir, mkdir, unlink, X_OK
15 from shutil import copy, copytree, rmtree
16 import tarfile
17
18
19 from pysqlexception import PysqlException
20 from pysqlcolor import CYAN, RED, RESET
21
22 PYSQL_DOWNLOAD="http://www.digitalfox.org/projets/download/"
23 UPDATEDIR="update"
24 PYSQLROOTDIR="pysql"
25
27 """Check if the current PySQL is the latest one"""
28 releases=[]
29
30
31 if proxy:
32 proxy_handler=urllib2.ProxyHandler({'http': proxy})
33 proxy_auth_handler=urllib2.HTTPBasicAuthHandler()
34 proxy_auth_handler.add_password("realm", "host", user, password)
35 opener=urllib2.build_opener(proxy_handler, proxy_auth_handler)
36 else:
37 opener=urllib2.build_opener()
38 try:
39 page=opener.open(PYSQL_DOWNLOAD)
40 for line in page.readlines():
41 result=re.match(".*pysql-(.+).tar.gz.*", line)
42 if result:
43 if result.group(1)!="snapshot":
44 releases.append(Version(result.group(1)))
45 releases.sort()
46 last=releases[-1]
47 current=Version(currentVersion())
48
49 print _("Available releases : %s") % ", ".join([str(i) for i in releases])
50 print _("Latest is %s") % last
51 print _("Current is %s") % current
52 if current.isSnapshot:
53 print _("You are in snapshot release - move to last [r]elease or last [s]napshot (r/s) ?")
54 answer=sys.stdin.readline().strip("\n")
55 if answer in ("r", "release"):
56 update(opener, last)
57 else:
58 update(opener, "snapshot")
59 elif last>current:
60 print _("A new release is available (%s). Do you want to update (y/n) ?") % last
61 answer=sys.stdin.readline().strip("\n")
62 if answer in ("y", "yes"):
63 update(opener, last)
64 else:
65 print _("Ok, bye")
66 else:
67 print _("PySQL is up to date. No need to update")
68 except urllib2.URLError, e:
69 print RED + _("Cannot reach PySQL Website (%s)") % e + RESET
70
72 """@return: current pysql version according to 'version' file"""
73 try:
74
75 if join("src", "pysql") in __file__:
76 version=join(dirname(__file__), pardir, pardir, "version")
77 else:
78 version="/usr/share/pysql/version"
79 return file(version).readline().strip("\n")
80 except:
81 raise PysqlException(_("Unable to read 'version' file. Do you remove or change it ?"))
82
84 """Update PySQL
85 @param opener: URL handle to download PySQL tarball
86 @type opener: urllib2 opener object
87 @param version: target version for update
88 @type version: string
89 @return: True if everything is Ok, else False"""
90 print CYAN + _("=>update to version %s<=") % version + RESET
91
92
93 filename="pysql-"+str(version)+".tar.gz"
94 pysqlPath=dirname(sys.argv[0])
95 updatePath=join(pysqlPath, UPDATEDIR)
96 newPath=join(updatePath, PYSQLROOTDIR)
97 if not access(updatePath, X_OK):
98 mkdir(updatePath)
99
100 if access(newPath, X_OK):
101 try:
102 rmtree(newPath)
103 except IOError, e:
104 print RED + _("Cannot remove previous aborted update. Please remove it by hand (%s)") % e + RESET
105 return False
106 try:
107 tmpFile=file(join(updatePath, filename), "w")
108 print _("Downloading from PySQL Website... "),
109 tmpFile.write(opener.open(PYSQL_DOWNLOAD+filename).read())
110 tmpFile.close()
111 print CYAN+_("Done !") + RESET
112 print _("Opening archive and copying files to pysql directory..."),
113 tarball=tarfile.open(join(updatePath, filename), mode="r:gz")
114 for tarinfo in tarball:
115 tarball.extract(tarinfo, "update")
116 tarball.close()
117 except urllib2.URLError, e:
118 print RED+ _("Failed to download file from PySQL WebSite (%s)") % e + RESET
119 return False
120 except IOError, e:
121 print RED+ _("Cannot write archive file to %s (%s)") % (updatePath, e) + RESET
122 return False
123 try:
124 blacklist=("pysqlrc",)
125 for item in listdir(newPath):
126 if item in blacklist:
127 continue
128 if isdir(item):
129 try:
130 rmtree(join(pysqlPath, item))
131 except OSError, e:
132 print RED+_("Cannot remove %s (%s)") % (item, e) + RESET
133 copytree(join(newPath, item), join(pysqlPath, item))
134 elif isfile(item) and not islink(item):
135 try:
136 unlink(join(pysqlPath, item))
137 except OSError, e:
138 print RED+_("Cannot remove %s (%s)") % (item, e) + RESET
139 copy(join(newPath, item), join(pysqlPath, item))
140 print CYAN+_("Done !") + RESET
141
142 print _("Cleanup... "),
143 rmtree(updatePath)
144 print CYAN+_("Done !") + RESET
145 print CYAN+_("Update successul !") + RESET
146 return True
147 except (IOError,OSError) , e:
148 print RED+ _("Error while copying files (%s)") % e + RESET
149 return False
150
152 """Pysql Version handling according to release policy
153 Release model : Major.Minor.Fix
154 Major and minor are mandatory, fix is optionnal
155 Release can be "snapshot" (case unsensitive).
156 If not defined, major/minor/fix are set to empty str ""
157 Standard comparison operator are defined : <, >, <=, <= and =="""
159 """Create version instance from version str"""
160 self.major=0
161 self.minor=0
162 self.fix=0
163 self.isSnapshot=False
164
165 if versionStr.lower()=="snapshot":
166 self.isSnapshot=True
167 elif versionStr.count(".")==1:
168 (self.major, self.minor)=versionStr.split(".")
169 elif versionStr.count(".")==2:
170 (self.major, self.minor, self.fix)=versionStr.split(".")
171 else:
172 raise PysqlException(_("Bad release scheme (%s)") % versionStr)
173
174 try:
175 self.major=int(self.major)
176 self.minor=int(self.minor)
177 self.fix=int(self.fix)
178 except ValueError:
179 raise PysqlException(_("Bad release scheme (%s)") % versionStr)
180
182 if self.isSnapshot or version.isSnapshot:
183 raise PysqlException(_("Cannot compare with snapshot release"))
184 elif self.major<version.major:
185 return True
186 elif self.major>version.major:
187 return False
188 elif self.major==version.major:
189 if self.minor<version.minor:
190 return True
191 elif self.minor>version.minor:
192 return False
193 elif self.minor==version.minor:
194 if self.fix<version.fix:
195 return True
196 else:
197 return False
198
200 return (version<self)
201
203 if self.major==version.major and self.minor==version.minor and self.fix==version.fix:
204 return True
205 else:
206 return False
207
209 return (self==version or self<version)
210
212 return (version<=self)
213
215 if self.isSnapshot:
216 return "snapshot"
217 else:
218 return ("%s.%s.%s" % (self.major, self.minor, self.fix)).rstrip(".0")
219