migration.py 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429
  1. #!/usr/bin/python
  2. # ***** BEGIN LICENSE BLOCK *****
  3. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. #
  5. # The contents of this file are subject to the Mozilla Public License Version
  6. # 1.1 (the "License"); you may not use this file except in compliance with
  7. # the License. You may obtain a copy of the License at
  8. # http://www.mozilla.org/MPL/
  9. #
  10. # Software distributed under the License is distributed on an "AS IS" basis,
  11. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. # for the specific language governing rights and limitations under the
  13. # License.
  14. #
  15. # The Original Code is addons.mozilla.org site.
  16. #
  17. # The Initial Developer of the Original Code is
  18. # The Mozilla Foundation.
  19. # Portions created by the Initial Developer are Copyright (C) 2006
  20. # the Initial Developer. All Rights Reserved.
  21. #
  22. # Contributor(s):
  23. # Lars Lohn <lars@mozilla.com> (Original Author)
  24. #
  25. # Alternatively, the contents of this file may be used under the terms of
  26. # either the GNU General Public License Version 2 or later (the "GPL"), or
  27. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. # in which case the provisions of the GPL or the LGPL are applicable instead
  29. # of those above. If you wish to allow use of your version of this file only
  30. # under the terms of either the GPL or the LGPL, and not to allow others to
  31. # use your version of this file under the terms of the MPL, indicate your
  32. # decision by deleting the provisions above and replace them with the notice
  33. # and other provisions required by the GPL or the LGPL. If you do not delete
  34. # the provisions above, a recipient may use your version of this file under
  35. # the terms of any one of the MPL, the GPL or the LGPL.
  36. #
  37. # ***** END LICENSE BLOCK *****
  38. import cse.Database
  39. import cse.MySQLDatabase
  40. import cse.TabularData
  41. from Crypto.Hash import *
  42. import mx.DateTime
  43. import os.path
  44. import urllib2
  45. import urllib
  46. import Image
  47. import sys
  48. import os
  49. import traceback
  50. version = "0.7"
  51. standardError = sys.stderr
  52. #standardError = sys.stdout
  53. #sys.stderr = sys.stdout
  54. class MigrationException(Exception):
  55. pass
  56. #-----------------------------------------------------------------------------------------------------------
  57. # imageAndThumbFromURL
  58. #-----------------------------------------------------------------------------------------------------------
  59. def imageAndThumbFromURL (aURL, xThumbSize=200, yThumbSize=150, scratchDirectory=".", transparentPngPathName="./blank.png"):
  60. urlReader = urllib2.urlopen(aURL)
  61. contentType = urlReader.info()['Content-Type']
  62. content = urlReader.read()
  63. temporaryFileName = ("%s/i.%s" % (scratchDirectory, aURL[-3:])).replace("//", "/")
  64. temporaryThumbFileName = ("%s/t.png" % (scratchDirectory, )).replace("//", "/")
  65. f = open(temporaryFileName, "w")
  66. try:
  67. f.write(content)
  68. f.close()
  69. im = Image.open(temporaryFileName)
  70. try:
  71. im.thumbnail((xThumbSize, yThumbSize), Image.ANTIALIAS)
  72. targetImage = Image.open(transparentPngPathName)
  73. targetImage.paste(im, ((xThumbSize - im.size[0]) / 2, (yThumbSize - im.size[1]) / 2))
  74. targetImage.save(temporaryThumbFileName)
  75. f = open(temporaryThumbFileName)
  76. thumbContent = f.read()
  77. f.close()
  78. finally:
  79. os.unlink(temporaryThumbFileName)
  80. finally:
  81. os.unlink(temporaryFileName)
  82. return (content, contentType, thumbContent, "image/png")
  83. #-----------------------------------------------------------------------------------------------------------
  84. # sha1Hash
  85. #-----------------------------------------------------------------------------------------------------------
  86. def sha1Hash (aURL, addonID, cachePath):
  87. basename = os.path.basename(aURL)
  88. try:
  89. f = open ("%s/%d/%s" % (cachePath, addonID, basename))
  90. #print "getting from cache"
  91. block = f.read()
  92. f.close()
  93. fromCache = True
  94. except:
  95. #print "getting from web"
  96. fromCache = False
  97. aURL = urllib.quote(aURL, "/:")
  98. urlReader = urllib2.urlopen(aURL)
  99. block = urlReader.read()
  100. shaCalculator = SHA.new()
  101. shaCalculator.update(block)
  102. if not fromCache and cachePath:
  103. try:
  104. f = open("%s/%d/%s" % (cachePath, addonID, basename), "w")
  105. except:
  106. #print "missing directory %s/%d" % (cachePath, addonID)
  107. os.mkdir("%s/%d" % (cachePath, addonID))
  108. f = open("%s/%d/%s" % (cachePath, addonID, basename), "w")
  109. #print "putting to cache"
  110. f.write(block)
  111. f.close()
  112. return "sha1:%s" % shaCalculator.hexdigest()
  113. #-----------------------------------------------------------------------------------------------------------
  114. # firstWords
  115. #-----------------------------------------------------------------------------------------------------------
  116. def firstWords (originalString, maxCharacters = 250, maxSearchBack = 20):
  117. """This function returns the first maxCharacters of originalString making sure that the end of the
  118. string was cut on a word break and elipsis (...) was appended.
  119. input:
  120. originalString - the string
  121. maxCharacters - the maximum number of characters to return
  122. maxSearchBack - if no word break was found after searching back this many characters, give up and
  123. return the maximum number of characters
  124. """
  125. try:
  126. originalString = originalString.lstrip()
  127. if len(originalString) <= maxCharacters:
  128. maxCharacters = len(originalString)
  129. breakIndex = maxCharacters - 3
  130. maximumSearchBackIndex = breakIndex - maxSearchBack
  131. if maximumSearchBackIndex < 0:
  132. maximumSearchBackIndex = 0
  133. firstLineBreak = min(originalString.find('\n'), originalString.find('\r'))
  134. if -1 < firstLineBreak < breakIndex:
  135. breakIndex = firstLineBreak
  136. while breakIndex > maximumSearchBackIndex and not (originalString[breakIndex] == " " and originalString[breakIndex-1] != " "):
  137. breakIndex -= 1
  138. if breakIndex == maximumSearchBackIndex:
  139. breakIndex = maxCharacters - 3
  140. try:
  141. if originalString[breakIndex - 1] in ".,:\"'!":
  142. breakIndex -= 1
  143. returnPhrase = "%s..." % originalString[:breakIndex]
  144. except IndexError:
  145. returnPhrase = ""
  146. assert(len(returnPhrase) <= maxCharacters)
  147. return returnPhrase
  148. except AssertionError:
  149. print "%d [[[%s]]]" % (len(originalString), originalString)
  150. print "%d <<<%s>>>" % (len(returnPhrase), returnPhrase)
  151. except TypeError, x:
  152. print >>standardError, x
  153. print >>standardError, " %s passed in as a string" % originalString
  154. except Exception, x:
  155. print >>standardError, x
  156. traceback.print_exc(file=standardError)
  157. #-----------------------------------------------------------------------------------------------------------
  158. # yesNoEnumToTinyIntMappings
  159. #-----------------------------------------------------------------------------------------------------------
  160. yesNoEnumToTinyIntMappingForApproval = { "YES": 4, "NO": 1, "?":2, "DISABLED":5 }
  161. yesNoEnumToTinyIntMappingForHighlight = { "YES": 1, "NO": 0 }
  162. #-----------------------------------------------------------------------------------------------------------
  163. # nullToEmptyString
  164. #-----------------------------------------------------------------------------------------------------------
  165. def nullToEmptyString (aString):
  166. if aString is None:
  167. return ""
  168. return aString
  169. #-----------------------------------------------------------------------------------------------------------
  170. # nullToEmptyDate
  171. #-----------------------------------------------------------------------------------------------------------
  172. def nullToEmptyDate (aDate):
  173. if aDate is None:
  174. return "0000-00-00 00:00:00"
  175. return aDate
  176. #-----------------------------------------------------------------------------------------------------------
  177. # addTranslation
  178. #-----------------------------------------------------------------------------------------------------------
  179. def addTranslation (newDB, aTransalationString, aLocaleString):
  180. """adds a new translation to the translations table and returns the index"""
  181. newDB.executeSql("UPDATE translations_seq SET id=LAST_INSERT_ID(id+1)")
  182. newID = newDB.singleValueSql("SELECT LAST_INSERT_ID()")
  183. newDB.commit()
  184. newDB.executeManySql("insert into translations (id, locale, localized_string, created) values (%s, %s, %s, %s)", [(newID, aLocaleString, aTransalationString, mx.DateTime.now())] )
  185. newDB.commit()
  186. return newID
  187. #-----------------------------------------------------------------------------------------------------------
  188. # cleanMetaDataTables
  189. #-----------------------------------------------------------------------------------------------------------
  190. def cleanMetaDataTables (newDB, workingEnvironment):
  191. if "verbose" in workingEnvironment: print >>standardError, "%s\tclearing metadata tables..." % mx.DateTime.now()
  192. listOfTranslationsToDelete = newDB.executeSql("""
  193. select name from applications
  194. union
  195. select shortname from applications
  196. union
  197. select name from platforms
  198. union
  199. select shortname from platforms
  200. union
  201. select name from tags
  202. union
  203. select description from tags""").contents[1]
  204. newDB.executeSql("delete from tags")
  205. newDB.executeSql("delete from appversions")
  206. newDB.executeSql("delete from applications")
  207. newDB.executeSql("delete from platforms")
  208. newDB.executeSql("delete from addons_users")
  209. newDB.executeSql("delete from users")
  210. newDB.executeManySql("delete from translations where id = %s", listOfTranslationsToDelete)
  211. newDB.commit()
  212. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  213. #-----------------------------------------------------------------------------------------------------------
  214. # applicationsToApplications
  215. #-----------------------------------------------------------------------------------------------------------
  216. appversionCorrection = { "Firefox": { "0.9.x":"0.9.3",
  217. "1.0PR":"0.10",
  218. "1.5.0.4":"1.5.0.*",
  219. "1.6a1":"1.5.0.*",
  220. "Deer Park":"1.0+"
  221. },
  222. "Thunderbird": { "1.5.0.5": "1.5.0.*",
  223. "1.5beta": "1.5b",
  224. "1.6a1": "1.5.0.*"
  225. }
  226. }
  227. appversionCorrectionForMin = { "Firefox": { ".9":"0.9",
  228. "0.1":"0.10",
  229. "0.80":"0.8",
  230. "0.9.6":"0.10",
  231. "0.9.x":"0.10",
  232. "00.8":"0.8",
  233. "1.0PR":"0.10",
  234. "1.4.0":"1.4",
  235. "1.5*":"1.5",
  236. "1.5.0.*":"1.5",
  237. "1.5.0.4":"1.5",
  238. "1.6":"2.0a1",
  239. "2.0b1":"2.0b2",
  240. "Deer Park":"1.5"
  241. },
  242. "Flock": { "0.1":"0.1",
  243. "0.4.0":"0.4"
  244. },
  245. "Mozilla": { "-": "1.0",
  246. "1":"1.0",
  247. "1.8+":"1.8"
  248. },
  249. "Netscape": { "8":"8.0"
  250. },
  251. "Nvu": { "1.0":"1.1"
  252. },
  253. "SeaMonkey": { "1.0":"1.1"
  254. },
  255. "Sunbird": { "0.3.1":"0.3a1"
  256. },
  257. "Thunderbird": { "1.4":"1.5",
  258. "1.4.1":"1.5",
  259. "1.5.0.*":"1.5",
  260. "1.5.0.2":"1.5",
  261. "1.5.0.4":"1.5",
  262. "1.5.0.5":"1.5",
  263. "1.6":"2.0"
  264. }
  265. }
  266. appversionCorrectionForMax = { "Firefox": { "0.10.1":"0.10",
  267. "0.10.1+":"0.10.1",
  268. "0.11":"0.10",
  269. "01.6":"1.5.0.*",
  270. "1.1":"1.0.8",
  271. "1.5":"1.5.0.*",
  272. "1.5.0.*":"1.5.0.*",
  273. "1.5.0.4":"1.5.0.*",
  274. "1.6":"1.5.0.*",
  275. "1.6a1":"1.5.0.*",
  276. "2.0":"2.0.0.*",
  277. "2.0.0.*":"2.0.0.*",
  278. "2.0.0.a3":"2.0a3",
  279. "2.0.0.b1":"2.0b1",
  280. "3.0":"3.0a1",
  281. "3.0.0.a1":"3.0a1",
  282. "Deer Park":"1.0+"
  283. },
  284. "Flock": { "0.*":"0.5.*",
  285. "0.8.x":"0.8.*",
  286. "10.0":"1.0",
  287. "6.02":"6.0",
  288. "9999.0+":"1.0+"
  289. },
  290. "Mozilla": { "-":"1.0",
  291. "1":"1.0",
  292. "1.5.0.*":"1.5",
  293. },
  294. "SeaMonkey": { "1.5.0.a":"1.5a"
  295. },
  296. "Sunbird": { "0.3.1":"0.3a1"
  297. },
  298. "Thunderbird": { "0.10":"0.9",
  299. "0.9.0+":"0.9+",
  300. "1.2":"1.1a1",
  301. "1.4":"1.5b1",
  302. "1.4.1":"1.5b2",
  303. "1.5":"1.5.0.*",
  304. "1.5.0.2":"1.5.0.*",
  305. "1.5.0.4":"1.5.0.*",
  306. "1.6":"1.5.0.*",
  307. "1.6a1":"1.5.0.*",
  308. "2.0":"2.0.0.*",
  309. "3.0":"3.0a1",
  310. "3.0a1":"3.0a1"
  311. }
  312. }
  313. #-----------------------------------------------------------------------------------------------------------
  314. # correctAppversion
  315. #-----------------------------------------------------------------------------------------------------------
  316. def correctAppversion (appName, versionName, correctionDictionary):
  317. try:
  318. return correctionDictionary[appName][versionName]
  319. except KeyError:
  320. return versionName
  321. #-----------------------------------------------------------------------------------------------------------
  322. # applicationsToApplications
  323. #-----------------------------------------------------------------------------------------------------------
  324. applicationsInsertSql = """
  325. insert into applications (id, guid, name, shortname, supported, created)
  326. values (%s, %s, %s, %s, %s, %s)"""
  327. appversionsInsertSql = """
  328. insert into appversions (id, application_id, version, created)
  329. values (%s, %s, %s, %s)"""
  330. def applicationsToApplications (oldDB, newDB, workingEnvironment):
  331. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning applicationsToApplications..." % mx.DateTime.now()
  332. applicationsAlreadyInserted = {}
  333. appversionsAlreadyInserted = {}
  334. for a in oldDB.executeSqlNoCache("select * from applications"):
  335. if a.AppName not in applicationsAlreadyInserted:
  336. newDB.executeManySql(applicationsInsertSql, [
  337. (a.AppID, #id
  338. a.GUID, #guid
  339. addTranslation(newDB, a.AppName, "en-US"), #name
  340. addTranslation(newDB, a.AppName, "en-US"), #shortname
  341. a.supported, #supported
  342. mx.DateTime.now()) #created
  343. ] )
  344. applicationsAlreadyInserted[a.AppName] = a.AppID
  345. appversionsAlreadyInserted[a.AppName] = {}
  346. correctedAppversion = correctAppversion(a.AppName, a.Version, appversionCorrection)
  347. if correctedAppversion not in appversionsAlreadyInserted[a.AppName]:
  348. newDB.executeManySql(appversionsInsertSql, [
  349. (a.AppID, #id
  350. applicationsAlreadyInserted[a.AppName], #application_id
  351. correctedAppversion, #version
  352. mx.DateTime.now()) #created
  353. ] )
  354. appversionsAlreadyInserted[a.AppName][correctedAppversion] = True
  355. newDB.commit()
  356. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  357. #-----------------------------------------------------------------------------------------------------------
  358. # categoriesToTags
  359. #-----------------------------------------------------------------------------------------------------------
  360. tagsInsertSql = """
  361. insert into tags (id, name, description, addontype_id, application_id, created)
  362. values (%s, %s, %s, %s, %s, %s)"""
  363. typeEnumToTypeNameMapping = {'E': 'Extension',
  364. 'T': 'Theme',
  365. 'P': 'Plugin' }
  366. def categoriesToTags (oldDB, newDB, workingEnvironment):
  367. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning categoriesToTags..." % mx.DateTime.now()
  368. for c in oldDB.executeSqlNoCache("select * from categories"):
  369. newDB.executeManySql(tagsInsertSql, [ (c.CategoryID, #id
  370. addTranslation(newDB, c.CatName, workingEnvironment["locale"]), #name
  371. addTranslation(newDB, c.CatDesc, workingEnvironment["locale"]), #description
  372. newDB.singleValueSql("select a.id from addontypes a join translations t on a.name = t.id and t.locale = 'en-US' and localized_string = '%s'"
  373. % typeEnumToTypeNameMapping[c.CatType]), #addontype_id
  374. newDB.singleValueSql("select a.id from applications a join translations t on a.name = t.id and t.locale = 'en-US' and localized_string = '%s'" % c.CatApp), #application_id
  375. mx.DateTime.now()) #created
  376. ] )
  377. newDB.commit()
  378. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  379. #-----------------------------------------------------------------------------------------------------------
  380. # osToPlatforms
  381. #-----------------------------------------------------------------------------------------------------------
  382. plaformsInsertSql = """
  383. insert into platforms (id, name, shortname, created)
  384. values (%s, %s, %s, %s)"""
  385. def osToPlatforms (oldDB, newDB, workingEnvironment):
  386. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning osToPlatforms..." % mx.DateTime.now()
  387. for o in oldDB.executeSqlNoCache("select * from os"):
  388. newDB.executeManySql(plaformsInsertSql, [
  389. (o.OSID, #id
  390. addTranslation(newDB, o.OSName, "en-US"), #name
  391. addTranslation(newDB, o.OSName, "en-US"), #shortname
  392. mx.DateTime.now()) #created
  393. ] )
  394. newDB.commit()
  395. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  396. #-----------------------------------------------------------------------------------------------------------
  397. # userprofilesToUsers
  398. #-----------------------------------------------------------------------------------------------------------
  399. usersInsertSql = """
  400. insert into users (id, firstname, lastname, nickname, email, homepage, password, emailhidden, confirmationcode, created, notes)
  401. values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""
  402. def userprofilesToUsers (oldDB, newDB, workingEnvironment):
  403. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning userprofilesToUsers..." % mx.DateTime.now()
  404. for u in oldDB.executeSqlNoCache("select * from userprofiles"):
  405. splitName = u.UserName.split()
  406. try:
  407. lastName = splitName[-1]
  408. except:
  409. lastName = "?"
  410. try:
  411. firstName = ' '.join(splitName[:-1])
  412. except:
  413. firstname = "?"
  414. newDB.executeManySql(usersInsertSql, [
  415. (u.UserID, #id
  416. firstName, #firstname
  417. lastName, #lastname
  418. '', #nickname
  419. u.UserEmail, #email
  420. u.UserWebsite, #homepage
  421. u.UserPass, #password
  422. u.UserEmailHide, #emailhidden
  423. u.ConfirmationCode, #confirmationcode
  424. mx.DateTime.now(), #created
  425. None) #notes
  426. ] )
  427. newDB.commit()
  428. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  429. #-----------------------------------------------------------------------------------------------------------
  430. # cleanAddonsTables
  431. #-----------------------------------------------------------------------------------------------------------
  432. def cleanAddonsTables (newDB, workingEnvironment):
  433. if "verbose" in workingEnvironment: print >>standardError, "%s\tclearing addons tables..." % mx.DateTime.now()
  434. if "all" in workingEnvironment["addons"]:
  435. listOfTranslationsToDelete = newDB.executeSql("""
  436. select caption from previews
  437. union
  438. select releasenotes from versions
  439. union
  440. select name from addons
  441. union
  442. select homepage from addons
  443. union
  444. select description from addons
  445. union
  446. select summary from addons
  447. union
  448. select developercomments from addons
  449. union
  450. select eula from addons
  451. union
  452. select privacypolicy from addons
  453. """).contents[1]
  454. newDB.executeSql("delete from previews")
  455. newDB.executeSql("delete from addons_tags")
  456. newDB.executeSql("delete from applications_versions")
  457. newDB.executeSql("delete from files")
  458. newDB.executeSql("delete from versions")
  459. newDB.executeSql("delete from addons_users")
  460. newDB.executeSql("delete from addons")
  461. else:
  462. listOfTranslationsToDelete = newDB.executeSql("""
  463. select caption from previews where addon_id in (select id from addonSelections)
  464. union
  465. select releasenotes from versions where addon_id in (select id from addonSelections)
  466. union
  467. select name from addons where id in (select id from addonSelections)
  468. union
  469. select homepage from addons where id in (select id from addonSelections)
  470. union
  471. select description from addons where id in (select id from addonSelections)
  472. union
  473. select summary from addons where id in (select id from addonSelections)
  474. union
  475. select developercomments from addons where id in (select id from addonSelections)
  476. union
  477. select eula from addons where id in (select id from addonSelections)
  478. union
  479. select privacypolicy from addons where id in (select id from addonSelections)
  480. """).contents[1]
  481. newDB.executeSql("delete from previews where addon_id in (select id from addonSelections)")
  482. newDB.executeSql("delete from addons_tags where addon_id in (select id from addonSelections)")
  483. newDB.executeSql("delete from applications_versions where version_id in (select v.id from versions v where addon_id in (select id from addonSelections))")
  484. newDB.executeSql("delete from files where version_id in (select v.id from versions v where addon_id in (select id from addonSelections))")
  485. newDB.executeSql("delete from versions where addon_id in (select id from addonSelections)")
  486. newDB.executeSql("delete from addons_users where addon_id in (select id from addonSelections)")
  487. newDB.executeSql("delete from addons where id in (select id from addonSelections)")
  488. newDB.executeManySql("delete from translations where id = %s", listOfTranslationsToDelete)
  489. newDB.commit()
  490. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  491. #-----------------------------------------------------------------------------------------------------------
  492. # mainToAddOns
  493. #-----------------------------------------------------------------------------------------------------------
  494. addonsInsertSql = """
  495. insert into addons (id, guid, name, addontype_id, created, homepage, description, averagerating,
  496. weeklydownloads, totaldownloads, developercomments, summary,
  497. eula, privacypolicy)
  498. values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""
  499. def mainToAddOns (oldDB, newDB, workingEnvironment):
  500. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning mainToAddOns..." % mx.DateTime.now()
  501. if "all" in workingEnvironment["addons"]:
  502. sql = "select m.* from main m"
  503. else:
  504. sql = "select m.* from main m where m.ID in (select id from addonSelections)"
  505. currentLocale = workingEnvironment["locale"]
  506. for a in oldDB.executeSqlNoCache(sql):
  507. #print a.ID, sql
  508. x = (a.ID, #id
  509. a.GUID, #guid
  510. addTranslation(newDB, a.Name, currentLocale), #name
  511. newDB.singleValueSql("select a.id from addontypes a join translations t on a.name = t.id and t.locale = 'en-US' and localized_string = '%s'"
  512. % typeEnumToTypeNameMapping[a.Type]), #addontype_id
  513. mx.DateTime.now(), #created
  514. addTranslation(newDB, a.Homepage, currentLocale), #homepage
  515. addTranslation(newDB, a.Description, currentLocale), #description
  516. a.Rating, #averagerating
  517. a.downloadcount, #weeklydownloads
  518. a.TotalDownloads, #totaldownloads
  519. addTranslation(newDB, a.devcomments, currentLocale), #developercomments
  520. addTranslation(newDB, firstWords(a.Description, 250), currentLocale), #summary
  521. None, #eula
  522. None) #privacypolicy
  523. newDB.executeManySql(addonsInsertSql, [ x ] )
  524. newDB.commit()
  525. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  526. #-----------------------------------------------------------------------------------------------------------
  527. # authorxrefToAddons_users
  528. #-----------------------------------------------------------------------------------------------------------
  529. addons_usersInsertSql = """
  530. insert into addons_users (addon_id, user_id)
  531. values (%s, %s)"""
  532. def authorxrefToAddons_users (oldDB, newDB, workingEnvironment):
  533. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning authorxrefToAddons_users..." % mx.DateTime.now()
  534. if "all" in workingEnvironment["addons"]:
  535. sql = "select * from authorxref"
  536. else:
  537. sql = "select * from authorxref where id in (select id from addonSelections)"
  538. for u in oldDB.executeSqlNoCache(sql):
  539. newDB.executeManySql(addons_usersInsertSql, [ (u.ID, u.UserID) ] )
  540. newDB.commit()
  541. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  542. #-----------------------------------------------------------------------------------------------------------
  543. # versionToVerions
  544. #-----------------------------------------------------------------------------------------------------------
  545. versionsInsertSql = """
  546. insert into versions (id, addon_id, version, releasenotes, approvalnotes, created, modified)
  547. values (%s, %s, %s, %s, %s, %s, %s)"""
  548. applications_versionsInsertSql = """
  549. insert into applications_versions (application_id, version_id, min, max)
  550. values (%s, %s, %s, %s)"""
  551. applications_versionsUpdateSql = """
  552. update applications_versions set min = %s, max = %s where application_id =%s and version_id = %s"""
  553. filesInsertSql = """
  554. insert into files (version_id, platform_id, filename, size, hash, status, datestatuschanged, created)
  555. values (%s, %s, %s, %s, %s, %s, %s, %s)"""
  556. filesUpdateSql = """
  557. update files set size = %s, hash = %s, status = %s, datestatuschanged = %s, created = %s
  558. where version_id = %s and platform_id = %s and filename = %s"""
  559. findAppVersionSql = """select id from appversions where application_id = %d and version = '%s'"""
  560. findAppNameSql = """select appname from applications where AppID = %d"""
  561. findNewAppIDSql = "select a.id from applications a join translations t on a.name = t.id and t.locale = 'en-US' and localized_string = '%s'"
  562. appversionsInsertWithNewIDSql = """
  563. insert into appversions (application_id, version, created)
  564. values (%s, %s, %s)"""
  565. addonUpdateForStatus = """update addons set status = %s where id = %s"""
  566. def versionToVerions (oldDB, newDB, workingEnvironment):
  567. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning versionToVerions..." % mx.DateTime.now()
  568. if "all" in workingEnvironment["addons"]:
  569. if "verbose" in workingEnvironment: print >>standardError, "\t\t\t(this may take over ten minutes)"
  570. # for duplicates of the same Addon, Version, OS and Application, take only the latest
  571. #sql = "select * from version where vID in (select max(vID) from version group by ID, Version, OSID, AppID) order by ID, vID"
  572. sql = "select * from version order by ID, vID"
  573. else:
  574. #sql = "select * from version where id in (select id from addonSelections) and vID in (select max(vID) from version group by ID, Version, OSID, AppID) order by ID, vID"
  575. sql = "select * from version where id in (select id from addonSelections) order by ID, vID"
  576. versionsAlreadyInserted = {}
  577. applications_versionsAlreadyInserted = {}
  578. filesAlreadyInserted = {}
  579. fileStatusKeyedByAddon = {}
  580. for v in filterVersionsAndFilesGenerator(sql, oldDB, newDB):
  581. #print v
  582. try:
  583. if v.ID in fileStatusKeyedByAddon:
  584. fileStatusKeyedByAddon[v.ID].append(yesNoEnumToTinyIntMappingForApproval[v.approved])
  585. else:
  586. fileStatusKeyedByAddon[v.ID] = [yesNoEnumToTinyIntMappingForApproval[v.approved]]
  587. if v.AppID == 79: v.AppID = 1 #hack hack hack
  588. if (v.ID, v.Version) not in versionsAlreadyInserted:
  589. newDB.executeManySql(versionsInsertSql, [
  590. (v.vID, #id
  591. v.ID, #addon_id
  592. v.Version, #version
  593. addTranslation(newDB, v.Notes, workingEnvironment["locale"]), #releasenotes
  594. "", #approvalnotes
  595. v.DateAdded, #created
  596. nullToEmptyDate(v.DateUpdated)) #modified
  597. ] )
  598. versionId = versionsAlreadyInserted[(v.ID, v.Version)] = v.vID
  599. else:
  600. versionId = versionsAlreadyInserted[(v.ID, v.Version)]
  601. applicationName = oldDB.singleValueSql(findAppNameSql % v.AppID)
  602. #newAppId = newDB.singleValueSql(findNewAppIDSql % applicationName)
  603. newAppId = v.newAppId
  604. appversionIdForMin = newDB.singleValueSql(findAppVersionSql % (newAppId, v.MinAppVer))
  605. if not appversionIdForMin:
  606. translatedVersion = correctAppversion(applicationName, v.MinAppVer, appversionCorrectionForMin)
  607. appversionIdForMin = newDB.singleValueSql(findAppVersionSql % (newAppId, translatedVersion))
  608. if not appversionIdForMin:
  609. newDB.executeManySql(appversionsInsertWithNewIDSql, [ (newAppId, translatedVersion , mx.DateTime.now()) ] )
  610. appversionIdForMin = newDB.singleValueSql(findAppVersionSql % (newAppId, translatedVersion))
  611. appversionIdForMax = newDB.singleValueSql(findAppVersionSql % (newAppId, v.MaxAppVer))
  612. if not appversionIdForMax:
  613. translatedVersion = correctAppversion(applicationName, v.MaxAppVer, appversionCorrectionForMax)
  614. appversionIdForMax = newDB.singleValueSql(findAppVersionSql % (newAppId, translatedVersion))
  615. if not appversionIdForMax:
  616. newDB.executeManySql(appversionsInsertWithNewIDSql, [ (newAppId, translatedVersion, mx.DateTime.now()) ] )
  617. appversionIdForMax = newDB.singleValueSql(findAppVersionSql % (newAppId, translatedVersion))
  618. if (v.AppID, versionId) not in applications_versionsAlreadyInserted:
  619. newDB.executeManySql(applications_versionsInsertSql, [ (v.AppID, versionId, appversionIdForMin, appversionIdForMax) ] )
  620. applications_versionsAlreadyInserted[(v.AppID, versionId)] = (appversionIdForMin, appversionIdForMax)
  621. elif applications_versionsAlreadyInserted[(v.AppID, versionId)] != (appversionIdForMin, appversionIdForMax):
  622. print >>standardError, "%s\tWARNING -- version ID %d of addon %s for application %d has a min/max appversion conflict" % (mx.DateTime.now(), v.vID, v.ID, v.AppID)
  623. print >>standardError, " old values: %s are superceded by new values: %s," % (applications_versionsAlreadyInserted[(v.AppID, versionId)], (appversionIdForMin, appversionIdForMax))
  624. newDB.executeManySql(applications_versionsUpdateSql, [ (appversionIdForMin, appversionIdForMax, v.AppID, versionId) ] )
  625. applications_versionsAlreadyInserted[(v.AppID, versionId)] = (appversionIdForMin, appversionIdForMax)
  626. baseFileName = os.path.basename(v.URI)
  627. #print "considering:", (versionId, v.OSID, baseFileName, v.AppID), v.URI
  628. #if (versionId, v.OSID, baseFileName, v.AppID) not in filesAlreadyInserted:
  629. if 'ignoreHash' not in workingEnvironment and ("recalculateHash" in workingEnvironment or v.hash == "" or v.hash is None):
  630. try:
  631. newHash = sha1Hash(v.URI, v.ID, workingEnvironment["fileCachePath"])
  632. except Exception, x:
  633. print >>standardError, "%s\tWARNING -- version ID %d of addon %s for application %d has a URL problem - %s: %s -- No hash value has been computed" % (mx.DateTime.now(), v.vID, v.ID, v.AppID, x, v.URI)
  634. newHash = ""
  635. else:
  636. newHash = v.hash
  637. if (versionId, v.OSID, baseFileName) not in filesAlreadyInserted:
  638. newDB.executeManySql(filesInsertSql, [
  639. (versionId, #version_id
  640. v.OSID, #platform_id
  641. baseFileName, #filename
  642. v.Size, #size
  643. newHash, #hash
  644. yesNoEnumToTinyIntMappingForApproval[v.approved], #status
  645. nullToEmptyDate(v.DateApproved), #datestatuschanged
  646. mx.DateTime.now()) #created
  647. ] )
  648. #filesAlreadyInserted[(versionId, v.OSID, baseFileName, v.AppID)] = None
  649. filesAlreadyInserted[(versionId, v.OSID, baseFileName)] = None
  650. else:
  651. #print >>standardError, "%s\tWARNING -- version ID %d of addon %s for application %d has a duplicate file - the later one supercedes the older one" % (mx.DateTime.now(), versionId, v.ID, v.AppID)
  652. newDB.executeManySql(filesUpdateSql, [
  653. (v.Size, #size
  654. newHash, #hash
  655. yesNoEnumToTinyIntMappingForApproval[v.approved], #status
  656. nullToEmptyDate(v.DateApproved), #datestatuschanged
  657. mx.DateTime.now(), #created
  658. versionId, #version_id
  659. v.OSID, #platform_id
  660. baseFileName ) #filename
  661. ] )
  662. newDB.commit()
  663. except KeyboardInterrupt, x:
  664. raise x
  665. except Exception, x:
  666. print >>standardError, "%s\tWARNING -- version ID %d of addon %s for application %d fails to migrate.\n\t\t\t%s" % (mx.DateTime.now(), v.vID, v.ID, v.AppID, x)
  667. traceback.print_exc(file=standardError)
  668. newDB.rollback()
  669. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tupdating addon status..."
  670. try:
  671. for addonId, listOfFileApprovals in fileStatusKeyedByAddon.iteritems():
  672. #print addonId, listOfFileApprovals,
  673. if 4 in listOfFileApprovals: #if any files approved
  674. newAddonStatus = workingEnvironment["addonStatusWhenSomeFilesApproved"]
  675. #print "any", newAddonStatus
  676. else:
  677. newAddonStatus = workingEnvironment["addonStatusWhenNoFilesApproved"]
  678. #print "all", newAddonStatus
  679. newDB.executeManySql (addonUpdateForStatus, [(newAddonStatus, addonId)])
  680. except Exception, x:
  681. newDB.rollback()
  682. raise x
  683. newDB.commit()
  684. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  685. def onlyFirefoxUnlessThereIsNoFirefox (versionFileListForOneVersion):
  686. differentFilesFound = False
  687. try:
  688. initialURI = versionFileListForOneVersion[0].URI
  689. except IndexError:
  690. return
  691. for x in versionFileListForOneVersion:
  692. differentFilesFound = initialURI != x.URI
  693. if differentFilesFound: break
  694. if differentFilesFound:
  695. firefoxFound = False
  696. for aVersionFile in versionFileListForOneVersion:
  697. if aVersionFile.AppID == 1: #Firefox
  698. #print "FF only", aVersionFile
  699. #if len(versionFileListForOneVersion) > 1:
  700. # print aVersionFile.ID, aVersionFile.Version
  701. yield aVersionFile
  702. firefoxFound = True
  703. if not firefoxFound:
  704. for aVersionFile in versionFileListForOneVersion:
  705. #print "NO FF", aVersionFile
  706. yield aVersionFile
  707. else:
  708. for aVersionFile in versionFileListForOneVersion:
  709. #print "NO FF", aVersionFile
  710. yield aVersionFile
  711. def filterVersionsAndFilesGenerator (sqlToFetchVersionFiles, oldDB, newDB):
  712. previousVersion = None
  713. currentVersion = None
  714. versionFileList = []
  715. for aVersionFileRow in oldDB.executeSqlNoCache(sqlToFetchVersionFiles):
  716. applicationName = oldDB.singleValueSql(findAppNameSql % aVersionFileRow.AppID)
  717. newAppId = newDB.singleValueSql(findNewAppIDSql % applicationName)
  718. aVersionFileRow.__dict__["newAppId"] = newAppId
  719. currentVersion = (aVersionFileRow.ID, aVersionFileRow.Version, aVersionFileRow.OSID)
  720. if previousVersion != currentVersion:
  721. for x in onlyFirefoxUnlessThereIsNoFirefox(versionFileList):
  722. yield x
  723. previousVersion = currentVersion
  724. versionFileList = []
  725. versionFileList.append(aVersionFileRow)
  726. for x in onlyFirefoxUnlessThereIsNoFirefox(versionFileList):
  727. yield x
  728. #-----------------------------------------------------------------------------------------------------------
  729. # categoryxrefToAddons_tags
  730. #-----------------------------------------------------------------------------------------------------------
  731. addons_tagsInsertSql = """
  732. insert into addons_tags (addon_id, tag_id)
  733. values (%s, %s)"""
  734. def categoryxrefToAddons_tags (oldDB, newDB, workingEnvironment):
  735. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning categoryxrefToAddons_tags..." % mx.DateTime.now()
  736. if "all" in workingEnvironment["addons"]:
  737. sql = "select * from categoryxref"
  738. else:
  739. sql = "select * from categoryxref where id in (select id from addonSelections)"
  740. for c in oldDB.executeSqlNoCache(sql):
  741. #print c.ID, c.CategoryID
  742. try:
  743. newDB.executeManySql(addons_tagsInsertSql, [ (c.ID, c.CategoryID) ] )
  744. except:
  745. pass
  746. newDB.commit()
  747. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  748. #-----------------------------------------------------------------------------------------------------------
  749. # previewsToPreviews
  750. #-----------------------------------------------------------------------------------------------------------
  751. previewsInsertSql = """
  752. insert into previews (id, addon_id, filedata, filetype, thumbdata, thumbtype, caption, highlight, created)
  753. values (%s, %s, %s, %s, %s, %s, %s, %s, %s)"""
  754. def previewsToPreviews (oldDB, newDB, workingEnvironment):
  755. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning previewsToPreviews..." % mx.DateTime.now()
  756. if "all" in workingEnvironment["addons"]:
  757. sql = "select * from previews"
  758. else:
  759. sql = "select * from previews where id in (select id from addonSelections)"
  760. for p in oldDB.executeSqlNoCache(sql):
  761. contentType = thumbType = ""
  762. content = thumbContent = None
  763. if 'noPreviewImageProcessing' not in workingEnvironment:
  764. try:
  765. content, contentType, thumbContent, thumbType = imageAndThumbFromURL("%s%s" % (workingEnvironment["previewURIPrefix"], p.PreviewURI))
  766. except Exception, x:
  767. print >>standardError, "%s\tWARNING -- Error downloading %s%s for addon_id %d, preview.id %s - %s" % (mx.DateTime.now(), workingEnvironment["previewURIPrefix"], p.PreviewURI, p.ID, p.PreviewID, x)
  768. newDB.executeManySql(previewsInsertSql, [
  769. (p.PreviewID, #id
  770. p.ID, #addon_id
  771. content, #filedata
  772. contentType, #filetype
  773. thumbContent, #thumbdata
  774. thumbType, #thumbtype
  775. addTranslation(newDB, p.caption, workingEnvironment["locale"]), #caption
  776. yesNoEnumToTinyIntMappingForHighlight[p.preview], #caption
  777. mx.DateTime.now()) #created
  778. ] )
  779. newDB.commit()
  780. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  781. #-----------------------------------------------------------------------------------------------------------
  782. # setupAddonSelectionTable
  783. #-----------------------------------------------------------------------------------------------------------
  784. def setupAddonSelectionTable(oldDB, newDB, workingEnvironment):
  785. if "all" in workingEnvironment["addons"]: return
  786. if "verbose" in workingEnvironment: print >>standardError, "%s\tbeginning setupAddonSelectionTable..." % mx.DateTime.now()
  787. cleanupAddonSelectionTable(oldDB, newDB, workingEnvironment)
  788. oldDB.executeSql("create table addonSelections (id int, primary key (id))")
  789. newDB.executeSql("create table addonSelections (id int, primary key (id))")
  790. try:
  791. listOfAddons = [x.strip() for x in workingEnvironment["addons"].split(",")]
  792. if "not" in workingEnvironment:
  793. for anAddon in oldDB.executeSqlNoCache("select ID from main"):
  794. if str(anAddon.ID) not in listOfAddons:
  795. oldDB.executeSql("insert into addonSelections (id) values (%d)" % anAddon.ID)
  796. newDB.executeSql("insert into addonSelections (id) values (%d)" % anAddon.ID)
  797. else:
  798. oldDB.executeManySql("insert into addonSelections (id) values (%s)", listOfAddons)
  799. newDB.executeManySql("insert into addonSelections (id) values (%s)", listOfAddons)
  800. except Exception, x:
  801. cleanupAddonSelectionTable(oldDB, newDB, workingEnvironment)
  802. raise x
  803. if "verbose" in workingEnvironment: print >>standardError, "\t\t\tdone."
  804. #-----------------------------------------------------------------------------------------------------------
  805. # cleanupAddonSelectionTable
  806. #-----------------------------------------------------------------------------------------------------------
  807. def cleanupAddonSelectionTable (oldDB, newDB, workingEnvironment):
  808. if "all" in workingEnvironment["addons"]: return
  809. oldDB.executeSql("drop table if exists addonSelections")
  810. newDB.executeSql("drop table if exists addonSelections")
  811. #-----------------------------------------------------------------------------------------------------------
  812. # cleanMetaDataTables_test
  813. #-----------------------------------------------------------------------------------------------------------
  814. def cleanMetaDataTables_test(newDB, workingEnvironment):
  815. print >>standardError, "cleanMetaDataTables_test"
  816. errorCount = 0
  817. try:
  818. cleanAddonsTables(newDB, workingEnvironment)
  819. cleanMetaDataTables(newDB, workingEnvironment)
  820. except Exception, x:
  821. print >>standardError, " ***Failure*** cleanMetaDataTables: %s" % x
  822. errorCount += 1
  823. try:
  824. if newDB.singleValueSql("select count(*) from tags") != 0:
  825. print >>standardError, " ***Failure*** cleanMetaDataTables: tags table not cleared"
  826. errorCount += 1
  827. if newDB.singleValueSql("select count(*) from appversions") != 0:
  828. print >>standardError, " ***Failure*** cleanMetaDataTables: appversions table not cleared"
  829. errorCount += 1
  830. if newDB.singleValueSql("select count(*) from applications") != 0:
  831. print >>standardError, " ***Failure*** cleanMetaDataTables: applications table not cleared"
  832. errorCount += 1
  833. if newDB.singleValueSql("select count(*) from platforms") != 0:
  834. print >>standardError, " ***Failure*** cleanMetaDataTables: platforms table not cleared"
  835. errorCount += 1
  836. if newDB.singleValueSql("select count(*) from addons_users") != 0:
  837. print >>standardError, " ***Failure*** cleanMetaDataTables: addons_users table not cleared"
  838. errorCount += 1
  839. if newDB.singleValueSql("select count(*) from users") != 0:
  840. print >>standardError, " ***Failure*** cleanMetaDataTables: users table not cleared"
  841. errorCount += 1
  842. #if newDB.singleValueSql("select count(*) from addontypes") != 2:
  843. # print >>standardError, " ***Failure*** cleanMetaDataTables: addontypes not initialized properly"
  844. # errorCount += 1
  845. except Exception, x:
  846. print >>standardError, " ***Failure*** cleanMetaDataTables: Testing system failure: %s" % x
  847. print >>standardError, " %d errors" % errorCount
  848. #-----------------------------------------------------------------------------------------------------------
  849. # applicationsToApplications_test
  850. #-----------------------------------------------------------------------------------------------------------
  851. def applicationsToApplications_test(oldDB, newDB, workingEnvironment):
  852. print >>standardError, "applicationsToApplications_test"
  853. errorCount = 0
  854. try:
  855. cleanMetaDataTables(newDB, workingEnvironment)
  856. applicationsToApplications(oldDB, newDB, workingEnvironment)
  857. except Exception, x:
  858. print >>standardError, " ***Failure*** applicationsToApplications: %s" % x
  859. errorCount += 1
  860. try:
  861. for anApplication in oldDB.executeSqlNoCache("select distinct AppName from applications"):
  862. if newDB.singleValueSql("select count(*) from applications a join translations t on a.name = t.id and t.locale = 'en-US' where t.localized_string = '%s'" % anApplication.AppName) != 1:
  863. print >>standardError, " ***Failure*** applicationsToApplications: %s not in new database" % anApplication.AppName
  864. errorCount += 1
  865. for anApplication in oldDB.executeSqlNoCache("select * from applications"):
  866. sql = """
  867. select
  868. count(*)
  869. from
  870. applications a join appversions av on a.id = av.application_id
  871. where av.id = %d""" % anApplication.AppID
  872. result = newDB.executeSql(sql)
  873. if len(result.content) == 0:
  874. print >>standardError, " ***Failure*** applicationsToApplications: %s - %s %s not in new database" % (anApplication.AppID, anApplication.AppName, anApplication.Version)
  875. errorCount += 1
  876. if len(result.content) > 1:
  877. print >>standardError, " ***Failure*** applicationsToApplications: %s - %s %s duplicated in new database" % (anApplication.AppID, anApplication.AppName, anApplication.Version)
  878. errorCount += 1
  879. except Exception, x:
  880. print >>standardError, " ***Failure*** applicationsToApplications: Testing system failure: %s" % x
  881. print >>standardError, " %d errors" % errorCount
  882. #-----------------------------------------------------------------------------------------------------------
  883. # categoriesToTags_test
  884. #-----------------------------------------------------------------------------------------------------------
  885. def categoriesToTags_test(oldDB, newDB, workingEnvironment):
  886. print >>standardError, "categoriesToTags_test"
  887. errorCount = 0
  888. try:
  889. cleanMetaDataTables(newDB, workingEnvironment)
  890. applicationsToApplications(oldDB, newDB, workingEnvironment)
  891. categoriesToTags(oldDB, newDB, workingEnvironment)
  892. except Exception, x:
  893. print >>standardError, " ***Failure*** categoriesToTags: %s" % x
  894. errorCount += 1
  895. try:
  896. for x in zip(oldDB.executeSql("select * from categories order by CategoryID"),
  897. newDB.executeSql("select * from tags order by id")):
  898. if (x[0].CategoryID != x[1].id):
  899. print >>standardError, " ***Failure*** categoriesToTags: %s - %s missing in new database" % (x[0].CategoryID, x[0].CatName)
  900. errorCount += 1
  901. break
  902. except Exception, x:
  903. print >>standardError, " ***Failure*** categoriesToTags: Testing system failure: %s" % x
  904. print >>standardError, " %d errors" % errorCount
  905. #-----------------------------------------------------------------------------------------------------------
  906. # osToPlatforms_test
  907. #-----------------------------------------------------------------------------------------------------------
  908. def osToPlatforms_test(oldDB, newDB, workingEnvironment):
  909. print >>standardError, "osToPlatforms_test"
  910. errorCount = 0
  911. try:
  912. cleanMetaDataTables(newDB, workingEnvironment)
  913. osToPlatforms(oldDB, newDB, workingEnvironment)
  914. except Exception, x:
  915. print >>standardError, " ***Failure*** osToPlatforms: %s" % x
  916. errorCount += 1
  917. try:
  918. for x in zip(oldDB.executeSql("select * from os order by OSID"),
  919. newDB.executeSql("select * from platforms order by id")):
  920. if (x[0].OSID != x[1].id):
  921. print >>standardError, " ***Failure*** osToPlatforms: %s - %s missing in new database" % (x[0].OSID, x[0].OSName)
  922. errorCount += 1
  923. break
  924. except Exception, x:
  925. print >>standardError, " ***Failure*** osToPlatforms: Testing system failure: %s" % x
  926. print >>standardError, " %d errors" % errorCount
  927. #-----------------------------------------------------------------------------------------------------------
  928. # userprofilesToUsers_test
  929. #-----------------------------------------------------------------------------------------------------------
  930. def userprofilesToUsers_test(oldDB, newDB, workingEnvironment):
  931. print >>standardError, "userprofilesToUsers_test"
  932. errorCount = 0
  933. try:
  934. cleanMetaDataTables(newDB, workingEnvironment)
  935. userprofilesToUsers(oldDB, newDB, workingEnvironment)
  936. except Exception, x:
  937. print >>standardError, " ***Failure*** userprofilesToUsers: %s" % x
  938. errorCount += 1
  939. try:
  940. for x in zip(oldDB.executeSql("select * from userprofiles order by UserID"),
  941. newDB.executeSql("select * from users order by id")):
  942. if (x[0].UserID != x[1].id):
  943. print >>standardError, " ***Failure*** userprofilesToUsers: %s - %s missing in new database" % (x[0].UserID, x[0].UserName)
  944. errorCount += 1
  945. break
  946. except Exception, x:
  947. print >>standardError, " ***Failure*** userprofilesToUsers: Testing system failure: %s" % x
  948. print >>standardError, " %d errors" % errorCount
  949. #-----------------------------------------------------------------------------------------------------------
  950. # cleanAddonsTables_test
  951. #-----------------------------------------------------------------------------------------------------------
  952. def cleanAddonsTables_test(newDB, workingEnvironment):
  953. print >>standardError, 'cleanAddonsTables_test ("all" phase)'
  954. errorCount = 0
  955. theTables = [ "previews", "addons_tags", "applications_versions", "files", "versions", "addons_users", "addons" ]
  956. try:
  957. workingEnvironment["addons"] = "all"
  958. cleanAddonsTables(newDB, workingEnvironment)
  959. except Exception, x:
  960. print >>standardError, " ***Failure*** cleanAddonsTables: %s" % x
  961. errorCount += 1
  962. try:
  963. for aTableName in theTables:
  964. if newDB.singleValueSql("select count(*) from %s" % aTableName) != 0:
  965. print >>standardError, " ***Failure*** cleanAddonsTables: %s table not cleared" % aTableName
  966. errorCount += 1
  967. except Exception, x:
  968. print >>standardError, ' ***Failure*** cleanAddonsTables: Testing system failure during "all" phase: %s' % x
  969. print >>standardError, " %d errors" % errorCount
  970. print >>standardError, 'cleanAddonsTables_test ("subset" phase)'
  971. errorCount = 0
  972. try:
  973. workingEnvironment["addons"] = "all"
  974. cleanAddonsTables(newDB, workingEnvironment)
  975. cleanMetaDataTables(newDB, workingEnvironment)
  976. applicationsToApplications (oldDatabase, newDatabase, workingEnvironment)
  977. categoriesToTags (oldDatabase, newDatabase, workingEnvironment)
  978. osToPlatforms (oldDatabase, newDatabase, workingEnvironment)
  979. userprofilesToUsers (oldDatabase, newDatabase, workingEnvironment)
  980. mainToAddOns (oldDatabase, newDatabase, workingEnvironment)
  981. authorxrefToAddons_users (oldDatabase, newDatabase, workingEnvironment)
  982. versionToVerions (oldDatabase, newDatabase, workingEnvironment)
  983. categoryxrefToAddons_tags (oldDatabase, newDatabase, workingEnvironment)
  984. previewsToPreviews (oldDatabase, newDatabase, workingEnvironment)
  985. delimitedListOfAddons = workingEnvironment["addons"] = "3110,3112,3115"
  986. delimitedListOfVersionIdsThatShouldBeDeleted = ",".join((str(x.id) for x in newDB.executeSql("select v.id from versions v where addon_id in (%s)" % delimitedListOfAddons)))
  987. setupAddonSelectionTable(oldDatabase, newDatabase, workingEnvironment)
  988. try:
  989. cleanAddonsTables(newDB, workingEnvironment)
  990. finally:
  991. cleanupAddonSelectionTable (oldDatabase, newDatabase, workingEnvironment)
  992. except Exception, x:
  993. print >>standardError, " ***Failure*** cleanAddonsTables: %s" % x
  994. errorCount += 1
  995. try:
  996. if newDB.singleValueSql("select count(*) from addons where id in (%s)" % delimitedListOfAddons) != 0:
  997. print >>standardError, " ***Failure*** cleanAddonsTables: one or more of deleted addon_id values %s found in addons table" % delimitedListOfAddons
  998. errorCount += 1
  999. if newDB.singleValueSql("select count(*) from versions where addon_id in (%s)" % delimitedListOfAddons) != 0:
  1000. print >>standardError, " ***Failure*** cleanAddonsTables: one or more of deleted addon_id values %s found in versions table" % delimitedListOfAddons
  1001. errorCount += 1
  1002. if newDB.singleValueSql("select count(*) from applications_versions where version_id in (%s)" % delimitedListOfVersionIdsThatShouldBeDeleted) != 0:
  1003. print >>standardError, " ***Failure*** cleanAddonsTables: one or more of deleted version values %s found in applications_versions table" % delimitedListOfVersionIdsThatShouldBeDeleted
  1004. errorCount += 1
  1005. if newDB.singleValueSql("select count(*) from files where version_id in (%s)" % delimitedListOfVersionIdsThatShouldBeDeleted) != 0:
  1006. print >>standardError, " ***Failure*** cleanAddonsTables: one or more of deleted version values %s found in files table" % delimitedListOfVersionIdsThatShouldBeDeleted
  1007. errorCount += 1
  1008. if newDB.singleValueSql("select count(*) from addons_tags where addon_id in (%s)" % delimitedListOfAddons) != 0:
  1009. print >>standardError, " ***Failure*** cleanAddonsTables: one or more of deleted addon_id values %s found in addons_tags table" % delimitedListOfAddons
  1010. errorCount += 1
  1011. if newDB.singleValueSql("select count(*) from previews where addon_id in (%s)" % delimitedListOfAddons) != 0:
  1012. print >>standardError, " ***Failure*** cleanAddonsTables: one or more of deleted addon_id values %s found in previews table" % delimitedListOfAddons
  1013. errorCount += 1
  1014. except Exception, x:
  1015. print >>standardError, ' ***Failure*** cleanAddonsTables: Testing system failure during "subset" phase: %s' % x
  1016. traceback.print_exc(file=standardError)
  1017. print >>standardError, " %d errors" % errorCount
  1018. #-----------------------------------------------------------------------------------------------------------
  1019. # mainToAddOnsTables_test
  1020. #-----------------------------------------------------------------------------------------------------------
  1021. def mainToAddOnsTables_test (oldDB, newDB, workingEnvironment):
  1022. print >>standardError, 'mainToAddOns_test ("all" phase)'
  1023. errorCount = 0
  1024. theTables = [ "previews", "addons_tags", "applications_versions", "files", "versions", "addons_users", "addons" ]
  1025. try:
  1026. workingEnvironment["addons"] = "all"
  1027. cleanAddonsTables(newDB, workingEnvironment)
  1028. cleanMetaDataTables(newDB, workingEnvironment)
  1029. applicationsToApplications (oldDatabase, newDatabase, workingEnvironment)
  1030. categoriesToTags (oldDatabase, newDatabase, workingEnvironment)
  1031. osToPlatforms (oldDatabase, newDatabase, workingEnvironment)
  1032. userprofilesToUsers (oldDatabase, newDatabase, workingEnvironment)
  1033. mainToAddOns (oldDatabase, newDatabase, workingEnvironment)
  1034. authorxrefToAddons_users (oldDatabase, newDatabase, workingEnvironment)
  1035. versionToVerions (oldDatabase, newDatabase, workingEnvironment)
  1036. categoryxrefToAddons_tags (oldDatabase, newDatabase, workingEnvironment)
  1037. previewsToPreviews (oldDatabase, newDatabase, workingEnvironment)
  1038. except Exception, x:
  1039. print >>standardError, " ***Failure*** mainToAddOns: %s" % x
  1040. errorCount += 1
  1041. try:
  1042. # check addons Table
  1043. for anAddonFromOldDB in oldDB.executeSql("select * from main"):
  1044. try:
  1045. newDB.executeSql("select * from addons where id = %d" % anAddonFromOldDB.ID).__iter__().next()
  1046. except StopIteration:
  1047. print >>standardError, ' ***Failure*** mainToAddOns: addon %d missing from new database "all" phase' % anAddonFromOldDB.ID
  1048. errorCount += 1
  1049. # check addons_users Table
  1050. for anAuthorxrefFromOldDB in oldDB.executeSql("select * from authorxref"):
  1051. try:
  1052. newDB.executeSql("select * from addons_users where addon_id = %d and user_id = %d" % (anAuthorxrefFromOldDB.ID, anAuthorxrefFromOldDB.UserID)).__iter__().next()
  1053. except StopIteration:
  1054. print >>standardError, ' ***Failure*** mainToAddOns: addons_users %d, %d missing from new database "all" phase' % (anAuthorxrefFromOldDB.ID, anAuthorxrefFromOldDB.UserID)
  1055. errorCount += 1
  1056. # check versions, files, applications_versions tables
  1057. ##TESTED ONLY IN SUBSET PHASE##
  1058. #for aVersionFromOldDB in oldDB.executeSql("select * from version"):
  1059. # try:
  1060. # aVersionFromNewDB = newDB.executeSql("select * from versions where id = %d" % aVersionFromOldDB.vID).__iter__().next()
  1061. # except StopIteration:
  1062. # print >>standardError, ' ***Failure*** mainToAddOns: versions %d missing from new database "all" phase' % aVersionFromOldDB.vID
  1063. # errorCount += 1
  1064. # try:
  1065. # newDB.executeSql("select * from applications_versions where application_id = %d and version_id = %d" % (aVersionFromOldDB.AppID, aVersionFromOldDB.vID)).__iter__().next()
  1066. # except StopIteration:
  1067. # print >>standardError, ' ***Failure*** mainToAddOns: applications_versions %d, %d missing from new database "all" phase' % (aVersionFromOldDB.AppID, aVersionFromOldDB.vID)
  1068. # errorCount += 1
  1069. # try:
  1070. # newDB.executeSql("select * from files where version_id = %d" % aVersionFromOldDB.vID).__iter__().next()
  1071. # except StopIteration:
  1072. # print >>standardError, ' ***Failure*** mainToAddOns: files entry for version %d missing from new database "all" phase' % aVersionFromOldDB.vID
  1073. # errorCount += 1
  1074. # check categoryxref Table
  1075. for aCategoryxrefFromOldDB in oldDB.executeSql("select * from categoryxref"):
  1076. try:
  1077. newDB.executeSql("select * from addons_tags where addon_id = %d and tag_id = %d" % (aCategoryxrefFromOldDB.ID, aCategoryxrefFromOldDB.CategoryID)).__iter__().next()
  1078. except StopIteration:
  1079. print >>standardError, ' ***Failure*** mainToAddOns: addons_tags %d, %d missing from new database "all" phase' % (aCategoryxrefFromOldDB.ID, aCategoryxrefFromOldDB.CategoryID)
  1080. errorCount += 1
  1081. # check previews Table
  1082. for aPreviewsFromOldDB in oldDB.executeSql("select * from previews"):
  1083. try:
  1084. newDB.executeSql("select * from previews where id = %d " % aPreviewsFromOldDB.PreviewID).__iter__().next()
  1085. except StopIteration:
  1086. print >>standardError, ' ***Failure*** mainToAddOns: previews %d missing from new database "all" phase' % aPreviewsFromOldDB.PreviewID
  1087. errorCount += 1
  1088. except Exception, x:
  1089. print >>standardError, ' ***Failure*** mainToAddOns: Testing system failure during "all" phase: %s' % x
  1090. print >>standardError, " %d errors" % errorCount
  1091. print >>standardError, 'mainToAddOns_test ("subset" phase)'
  1092. errorCount = 0
  1093. try:
  1094. workingEnvironment["addons"] = "all"
  1095. cleanAddonsTables(newDB, workingEnvironment)
  1096. cleanMetaDataTables(newDB, workingEnvironment)
  1097. applicationsToApplications (oldDatabase, newDatabase, workingEnvironment)
  1098. categoriesToTags (oldDatabase, newDatabase, workingEnvironment)
  1099. osToPlatforms (oldDatabase, newDatabase, workingEnvironment)
  1100. userprofilesToUsers (oldDatabase, newDatabase, workingEnvironment)
  1101. delimitedListOfAddons = workingEnvironment["addons"] = "3110,3112,3115"
  1102. delimitedListOfVersionIdsThatShouldBeDeleted = ",".join((str(x.id) for x in newDB.executeSql("select v.id from versions v where addon_id in (%s)" % delimitedListOfAddons)))
  1103. setupAddonSelectionTable(oldDatabase, newDatabase, workingEnvironment)
  1104. try:
  1105. mainToAddOns (oldDatabase, newDatabase, workingEnvironment)
  1106. authorxrefToAddons_users (oldDatabase, newDatabase, workingEnvironment)
  1107. versionToVerions (oldDatabase, newDatabase, workingEnvironment)
  1108. categoryxrefToAddons_tags (oldDatabase, newDatabase, workingEnvironment)
  1109. previewsToPreviews (oldDatabase, newDatabase, workingEnvironment)
  1110. finally:
  1111. cleanupAddonSelectionTable (oldDatabase, newDatabase, workingEnvironment)
  1112. except Exception, x:
  1113. print >>standardError, " ***Failure*** mainToAddOns: %s" % x
  1114. errorCount += 1
  1115. try:
  1116. # check addons Table
  1117. for anAddonFromOldDB in oldDB.executeSql("select * from main where id in (%s)" % delimitedListOfAddons):
  1118. try:
  1119. newDB.executeSql("select * from addons where id = %d" % anAddonFromOldDB.ID).__iter__().next()
  1120. except StopIteration:
  1121. print >>standardError, ' ***Failure*** mainToAddOns: addon %d missing from new database "subset" phase' % anAddonFromOldDB.ID
  1122. errorCount += 1
  1123. # check addons_users Table
  1124. for anAuthorxrefFromOldDB in oldDB.executeSql("select * from authorxref where id in (%s)" % delimitedListOfAddons):
  1125. try:
  1126. newDB.executeSql("select * from addons_users where addon_id = %d and user_id = %d" % (anAuthorxrefFromOldDB.ID, anAuthorxrefFromOldDB.UserID)).__iter__().next()
  1127. except StopIteration:
  1128. print >>standardError, ' ***Failure*** mainToAddOns: addons_users %d, %d missing from new database "subset" phase' % (anAuthorxrefFromOldDB.ID, anAuthorxrefFromOldDB.UserID)
  1129. errorCount += 1
  1130. # check versions, files, applications_versions tables
  1131. for aVersionFromOldDB in oldDB.executeSql("select * from version where id in (%s)" % delimitedListOfAddons):
  1132. try:
  1133. aVersionFromNewDB = newDB.executeSql("select * from versions where id = %d" % aVersionFromOldDB.vID).__iter__().next()
  1134. except StopIteration:
  1135. print >>standardError, ' ***Failure*** mainToAddOns: versions %d missing from new database "subset" phase' % aVersionFromOldDB.vID
  1136. errorCount += 1
  1137. try:
  1138. newDB.executeSql("select * from applications_versions where application_id = %d and version_id = %d" % (aVersionFromOldDB.AppID, aVersionFromOldDB.vID)).__iter__().next()
  1139. except StopIteration:
  1140. print >>standardError, ' ***Failure*** mainToAddOns: applications_versions %d, %d missing from new database "subset" phase' % (aVersionFromOldDB.AppID, aVersionFromOldDB.vID)
  1141. errorCount += 1
  1142. try:
  1143. newDB.executeSql("select * from files where version_id = %d" % aVersionFromOldDB.vID).__iter__().next()
  1144. except StopIteration:
  1145. print >>standardError, ' ***Failure*** mainToAddOns: files entry for version %d missing from new database "subset" phase' % aVersionFromOldDB.vID
  1146. errorCount += 1
  1147. # check categoryxref Table
  1148. for aCategoryxrefFromOldDB in oldDB.executeSql("select * from categoryxref where id in (%s)" % delimitedListOfAddons):
  1149. try:
  1150. newDB.executeSql("select * from addons_tags where addon_id = %d and tag_id = %d" % (aCategoryxrefFromOldDB.ID, aCategoryxrefFromOldDB.CategoryID)).__iter__().next()
  1151. except StopIteration:
  1152. print >>standardError, ' ***Failure*** mainToAddOns: addons_tags %d, %d missing from new database "all" phase' % (aCategoryxrefFromOldDB.ID, aCategoryxrefFromOldDB.CategoryID)
  1153. errorCount += 1
  1154. # check previews Table
  1155. for aPreviewsFromOldDB in oldDB.executeSql("select * from previews where id in (%s)" % delimitedListOfAddons):
  1156. try:
  1157. newDB.executeSql("select * from previews where id = %d " % aPreviewsFromOldDB.PreviewID).__iter__().next()
  1158. except StopIteration:
  1159. print >>standardError, ' ***Failure*** mainToAddOns: previews %d missing from new database "all" phase' % aPreviewsFromOldDB.PreviewID
  1160. errorCount += 1
  1161. except Exception, x:
  1162. print >>standardError, ' ***Failure*** mainToAddOns: Testing system failure during "subset" phase: %s' % x
  1163. traceback.print_exc(file=standardError)
  1164. print >>standardError, " %d errors" % errorCount
  1165. #-----------------------------------------------------------------------------------------------------------
  1166. # runTests
  1167. #-----------------------------------------------------------------------------------------------------------
  1168. def runTests (oldDB, newDB, workingEnvironment):
  1169. cleanMetaDataTables_test(newDB, workingEnvironment)
  1170. applicationsToApplications_test(oldDB, newDB, workingEnvironment)
  1171. categoriesToTags_test(oldDB, newDB, workingEnvironment)
  1172. osToPlatforms_test(oldDB, newDB, workingEnvironment)
  1173. userprofilesToUsers_test(oldDB, newDB, workingEnvironment)
  1174. cleanAddonsTables_test(newDB, workingEnvironment)
  1175. mainToAddOnsTables_test(oldDB, newDB, workingEnvironment)
  1176. #-----------------------------------------------------------------------------------------------------------
  1177. # addBogusTranslations
  1178. #-----------------------------------------------------------------------------------------------------------
  1179. def addBogusTranslations (newDB):
  1180. counter = 1
  1181. for aTranslationIDRow in newDB.executeSqlNoCache("select distinct id from translations"):
  1182. for aLocale in ['de', 'ru', 'nl']:
  1183. newDB.executeManySql("insert into translations (id, locale, localized_string) values (%s, %s, %s)", [(aTranslationIDRow.id, aLocale, "bogus translation #%06d" % counter)])
  1184. newDB.commit()
  1185. counter += 1
  1186. #-----------------------------------------------------------------------------------------------------------
  1187. # removeBogusTranslations
  1188. #-----------------------------------------------------------------------------------------------------------
  1189. def removeBogusTranslations (newDB):
  1190. newDB.executeSql ("delete from translations where localized_string like 'bogus translation #%'")
  1191. newDB.commit()
  1192. #===========================================================================================================
  1193. # main
  1194. #===========================================================================================================
  1195. if __name__ == "__main__":
  1196. import cse.ConfigurationManager
  1197. try:
  1198. options = [ ('?', 'help', False, None, 'print this message'),
  1199. ('c', 'config', True, './migration.conf', 'specify the location and name of the config file'),
  1200. (None, 'oldDatabaseName', True, "", 'the name of the old database within the server'),
  1201. (None, 'oldServerName', True, "", 'the name of the old database server'),
  1202. (None, 'oldUserName', True, "", 'the name of the user in the old database'),
  1203. (None, 'oldPassword', True, "", 'the password for the user in the old database'),
  1204. (None, 'newDatabaseName', True, "", 'the name of the new database within the server'),
  1205. (None, 'newServerName', True, "", 'the name of the new database server'),
  1206. (None, 'newUserName', True, "", 'the name of the user in the new database'),
  1207. (None, 'newPassword', True, "", 'the password for the user in the new database'),
  1208. ('a', 'addons', True, "all", 'a quoted comma delimited list of the ids of addons OR the word "all"'),
  1209. ('n', 'not', False, None, """reverses the meaning of the "addon" option. If the "addon" option has a list, then specify everything except what's on the list"""),
  1210. ('M', 'migrateMetaData', False, None, 'if present, this switch causes the metadata tables to be migrated'),
  1211. ('A', 'migrateAddons', False, None, 'if present, this switch causes the addons in the "addons" option list to be migrated'),
  1212. ('v', 'verbose', False, None, 'print status information as it runs to stderr'),
  1213. ('l', 'locale', True, "en-US", 'set the locale for addons being migrated'),
  1214. (None, 'clear', False, None, 'clear all exisiting information from the new database'),
  1215. (None, 'clearAddons', False, None, 'clear all exisiting addons in the "addons" option list information from the new database'),
  1216. (None, 'test', False, None, 'run the test cases'),
  1217. (None, 'show', False, None, 'echo the configuration to stdout and then quit'),
  1218. (None, 'bogusTranslationsInsert', False, None, 'fill out the translations table with a full set of locales for all entries for load testing'),
  1219. (None, 'bogusTranslationsRemove', False, None, 'remove any bogus translations from the translations table'),
  1220. (None, 'logPathName', True, "./migration.log", 'a progressive log of all runs of the migration script'),
  1221. (None, 'addonStatusWhenNoFilesApproved', True, "sandbox", 'the status to set an addon if no files approved (null, sandbox, pending, nominated, public, disabled)'),
  1222. (None, 'addonStatusWhenSomeFilesApproved', True, "public", 'the status to set an addon if some files approved (null, sandbox, pending, nominated, public, disabled)'),
  1223. (None, 'noPreviewImageProcessing', False, "", 'do not process preview images'),
  1224. (None, 'previewURIPrefix', True, "https://addons.mozilla.org", 'a prefix to add to the URI in the preview table to enable downloading'),
  1225. (None, 'fileCachePath', True, "", 'a path for the caching of files (blank for no cache)'),
  1226. (None, 'recalculateHash', False, "", 'force the recaclulation of the hash for the xpi files'),
  1227. (None, 'ignoreHash', False, "", 'no not allow the migration to touch the hash'),
  1228. ]
  1229. workingEnvironment = cse.ConfigurationManager.ConfigurationManager(options)
  1230. #workingEnvironment["version"] = version
  1231. if 'help' in workingEnvironment:
  1232. print >>standardError, "migration %s\nThis routine migrates data from the old AMO database schema to the new one." % version
  1233. workingEnvironment.outputCommandSummary(standardError, 1)
  1234. sys.exit()
  1235. if 'show' in workingEnvironment:
  1236. workingEnvironment.output(sys.stdout)
  1237. sys.exit()
  1238. except cse.ConfigurationManager.ConfigurationManagerNotAnOption, x:
  1239. print >>standardError, "m1 %s\n%s\nFor usage, try --help" % (version, x)
  1240. sys.exit()
  1241. try:
  1242. useLogFile = open(workingEnvironment["logPathName"], "a")
  1243. print >>useLogFile, mx.DateTime.now()
  1244. workingEnvironment.output(useLogFile)
  1245. useLogFile.close()
  1246. if "verbose" in workingEnvironment:
  1247. print >>standardError, "%s beginning migration version %s with options:" % (mx.DateTime.now(), version)
  1248. workingEnvironment.output(standardError)
  1249. validStatusStates = {"null": 0, "sandbox": 1, "pending": 2, "nominated": 3, "public": 4, "disabled": 5}
  1250. try:
  1251. workingEnvironment["addonStatusWhenNoFilesApproved"] = validStatusStates[workingEnvironment["addonStatusWhenNoFilesApproved"]]
  1252. except KeyError:
  1253. print >>standardError, "%s is not a valid value for addonStatusWhenNoFilesApproved. See --help" % workingEnvironment["addonStatusWhenNoFilesApproved"]
  1254. sys.exit()
  1255. try:
  1256. workingEnvironment["addonStatusWhenSomeFilesApproved"] = validStatusStates[workingEnvironment["addonStatusWhenSomeFilesApproved"]]
  1257. except KeyError:
  1258. print >>standardError, "%s is not a valid value for addonStatusWhenSomeFilesApproved. See --help" % workingEnvironment["addonStatusWhenSomeFilesApproved"]
  1259. sys.exit()
  1260. oldDatabase = cse.MySQLDatabase.MySQLDatabase(workingEnvironment["oldDatabaseName"], workingEnvironment["oldServerName"],
  1261. workingEnvironment["oldUserName"], workingEnvironment["oldPassword"])
  1262. newDatabase = cse.MySQLDatabase.MySQLDatabase(workingEnvironment["newDatabaseName"], workingEnvironment["newServerName"],
  1263. workingEnvironment["newUserName"], workingEnvironment["newPassword"])
  1264. if "test" in workingEnvironment:
  1265. runTests(oldDatabase, newDatabase, workingEnvironment)
  1266. else:
  1267. setupAddonSelectionTable(oldDatabase, newDatabase, workingEnvironment)
  1268. try:
  1269. if "clear" in workingEnvironment:
  1270. originalAddonsOption = workingEnvironment["addons"]
  1271. workingEnvironment["addons"] = "all"
  1272. cleanAddonsTables(newDatabase, workingEnvironment)
  1273. cleanMetaDataTables(newDatabase, workingEnvironment)
  1274. workingEnvironment["addons"] = originalAddonsOption
  1275. elif "clearAddons" in workingEnvironment:
  1276. cleanAddonsTables(newDatabase, workingEnvironment)
  1277. if "migrateMetaData" in workingEnvironment:
  1278. if "verbose" in workingEnvironment: print >>standardError, "%s beginning metadata migration" % mx.DateTime.now()
  1279. try:
  1280. cleanMetaDataTables (newDatabase, workingEnvironment)
  1281. except:
  1282. raise MigrationException("Migrating MetaData implies clearing MetaData tables, but there appears to be Addon data in the database. Clear the Addon data before trying to migrate MetaData.")
  1283. applicationsToApplications (oldDatabase, newDatabase, workingEnvironment)
  1284. categoriesToTags (oldDatabase, newDatabase, workingEnvironment)
  1285. osToPlatforms (oldDatabase, newDatabase, workingEnvironment)
  1286. userprofilesToUsers (oldDatabase, newDatabase, workingEnvironment)
  1287. if "migrateAddons" in workingEnvironment:
  1288. if "verbose" in workingEnvironment: print >>standardError, "%s beginning addons migration" % mx.DateTime.now()
  1289. cleanAddonsTables (newDatabase, workingEnvironment)
  1290. mainToAddOns (oldDatabase, newDatabase, workingEnvironment)
  1291. categoryxrefToAddons_tags (oldDatabase, newDatabase, workingEnvironment)
  1292. authorxrefToAddons_users (oldDatabase, newDatabase, workingEnvironment)
  1293. versionToVerions (oldDatabase, newDatabase, workingEnvironment)
  1294. #categoryxrefToAddons_tags (oldDatabase, newDatabase, workingEnvironment)
  1295. previewsToPreviews (oldDatabase, newDatabase, workingEnvironment)
  1296. if "bogusTranslationsInsert" in workingEnvironment:
  1297. if "verbose" in workingEnvironment: print >>standardError, "%s creating bogus translations" % mx.DateTime.now()
  1298. addBogusTranslations(newDatabase)
  1299. if "bogusTranslationsRemove" in workingEnvironment:
  1300. if "verbose" in workingEnvironment: print >>standardError, "%s removing bogus translations" % mx.DateTime.now()
  1301. removeBogusTranslations(newDatabase)
  1302. finally:
  1303. cleanupAddonSelectionTable (oldDatabase, newDatabase, workingEnvironment)
  1304. except KeyboardInterrupt:
  1305. print >>standardError, "Interrupted..."
  1306. pass
  1307. except MigrationException, x:
  1308. print >>standardError, x
  1309. except Exception, x:
  1310. print >>standardError, x
  1311. traceback.print_exc(file=standardError)
  1312. if "verbose" in workingEnvironment: print >>standardError, "done."