PageRenderTime 49ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/sickbeard/versionChecker.py

https://github.com/junalmeida/Sick-Beard
Python | 695 lines | 624 code | 33 blank | 38 comment | 22 complexity | 303bb5120fa8d5dbb81d5f7fc182bcf9 MD5 | raw file
  1. # Author: Nic Wolfe <nic@wolfeden.ca>
  2. # URL: http://code.google.com/p/sickbeard/
  3. #
  4. # This file is part of Sick Beard.
  5. #
  6. # Sick Beard is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # Sick Beard is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
  18. from __future__ import with_statement
  19. import sickbeard
  20. from sickbeard import helpers
  21. from sickbeard import version, ui
  22. from sickbeard import logger
  23. from sickbeard import scene_exceptions
  24. from sickbeard.exceptions import ex
  25. from sickbeard import encodingKludge as ek
  26. import os
  27. import platform
  28. import shutil
  29. import subprocess
  30. import re
  31. import urllib
  32. import zipfile
  33. import tarfile
  34. import gh_api as github
  35. class CheckVersion():
  36. """
  37. Version check class meant to run as a thread object with the SB scheduler.
  38. """
  39. def __init__(self):
  40. self.install_type = self.find_install_type()
  41. if self.install_type == 'win':
  42. self.updater = WindowsUpdateManager()
  43. elif self.install_type == 'git':
  44. self.updater = GitUpdateManager()
  45. elif self.install_type == 'source':
  46. self.updater = SourceUpdateManager()
  47. else:
  48. self.updater = None
  49. def run(self):
  50. self.check_for_new_version()
  51. # refresh scene exceptions too
  52. scene_exceptions.retrieve_exceptions()
  53. def find_install_type(self):
  54. """
  55. Determines how this copy of SB was installed.
  56. returns: type of installation. Possible values are:
  57. 'win': any compiled windows build
  58. 'git': running from source using git
  59. 'source': running from source without git
  60. """
  61. # check if we're a windows build
  62. if sickbeard.version.SICKBEARD_VERSION.startswith('build '):
  63. install_type = 'win'
  64. elif os.path.isdir(ek.ek(os.path.join, sickbeard.PROG_DIR, u'.git')):
  65. install_type = 'git'
  66. else:
  67. install_type = 'source'
  68. return install_type
  69. def check_for_new_version(self, force=False):
  70. """
  71. Checks the internet for a newer version.
  72. returns: bool, True for new version or False for no new version.
  73. force: if true the VERSION_NOTIFY setting will be ignored and a check will be forced
  74. """
  75. if not sickbeard.VERSION_NOTIFY and not force:
  76. logger.log(u"Version checking is disabled, not checking for the newest version")
  77. return False
  78. logger.log(u"Checking if " + self.install_type + " needs an update")
  79. if not self.updater.need_update():
  80. sickbeard.NEWEST_VERSION_STRING = None
  81. logger.log(u"No update needed")
  82. if force:
  83. ui.notifications.message('No update needed')
  84. return False
  85. self.updater.set_newest_text()
  86. return True
  87. def update(self):
  88. if self.updater.need_update():
  89. return self.updater.update()
  90. class UpdateManager():
  91. def get_github_repo_user(self):
  92. return 'junalmeida'
  93. def get_github_repo(self):
  94. return 'Sick-Beard'
  95. def get_update_url(self):
  96. return sickbeard.WEB_ROOT + "/home/update/?pid=" + str(sickbeard.PID)
  97. class WindowsUpdateManager(UpdateManager):
  98. def __init__(self):
  99. self.github_repo_user = self.get_github_repo_user()
  100. self.github_repo = self.get_github_repo()
  101. self.branch = 'windows_binaries'
  102. self._cur_version = None
  103. self._cur_commit_hash = None
  104. self._newest_version = None
  105. self.releases_url = "https://github.com/" + self.github_repo_user + "/" + self.github_repo + "/" + "releases" + "/"
  106. self.version_url = "https://raw.github.com/" + self.github_repo_user + "/" + self.github_repo + "/" + self.branch + "/updates.txt"
  107. def _find_installed_version(self):
  108. try:
  109. version = sickbeard.version.SICKBEARD_VERSION
  110. return int(version[6:])
  111. except ValueError:
  112. logger.log(u"Unknown SickBeard Windows binary release: " + version, logger.ERROR)
  113. return None
  114. def _find_newest_version(self, whole_link=False):
  115. """
  116. Checks git for the newest Windows binary build. Returns either the
  117. build number or the entire build URL depending on whole_link's value.
  118. whole_link: If True, returns the entire URL to the release. If False, it returns
  119. only the build number. default: False
  120. """
  121. regex = ".*SickBeard\-win32\-alpha\-build(\d+)(?:\.\d+)?\.zip"
  122. version_url_data = helpers.getURL(self.version_url)
  123. if version_url_data is None:
  124. return None
  125. else:
  126. for curLine in version_url_data.splitlines():
  127. logger.log(u"checking line " + curLine, logger.DEBUG)
  128. match = re.match(regex, curLine)
  129. if match:
  130. logger.log(u"found a match", logger.DEBUG)
  131. if whole_link:
  132. return curLine.strip()
  133. else:
  134. return int(match.group(1))
  135. return None
  136. def need_update(self):
  137. self._cur_version = self._find_installed_version()
  138. self._newest_version = self._find_newest_version()
  139. logger.log(u"newest version: " + repr(self._newest_version), logger.DEBUG)
  140. if self._newest_version and self._newest_version > self._cur_version:
  141. return True
  142. return False
  143. def set_newest_text(self):
  144. sickbeard.NEWEST_VERSION_STRING = None
  145. if not self._cur_version:
  146. newest_text = "Unknown SickBeard Windows binary version. Not updating with original version."
  147. else:
  148. newest_text = 'There is a <a href="' + self.releases_url + '" onclick="window.open(this.href); return false;">newer version available</a> (build ' + str(self._newest_version) + ')'
  149. newest_text += "&mdash; <a href=\"" + self.get_update_url() + "\">Update Now</a>"
  150. sickbeard.NEWEST_VERSION_STRING = newest_text
  151. def update(self):
  152. zip_download_url = self._find_newest_version(True)
  153. logger.log(u"new_link: " + repr(zip_download_url), logger.DEBUG)
  154. if not zip_download_url:
  155. logger.log(u"Unable to find a new version link, not updating")
  156. return False
  157. try:
  158. # prepare the update dir
  159. sb_update_dir = ek.ek(os.path.join, sickbeard.PROG_DIR, u'sb-update')
  160. if os.path.isdir(sb_update_dir):
  161. logger.log(u"Clearing out update folder " + sb_update_dir + " before extracting")
  162. shutil.rmtree(sb_update_dir)
  163. logger.log(u"Creating update folder " + sb_update_dir + " before extracting")
  164. os.makedirs(sb_update_dir)
  165. # retrieve file
  166. logger.log(u"Downloading update from " + zip_download_url)
  167. zip_download_path = os.path.join(sb_update_dir, u'sb-update.zip')
  168. urllib.urlretrieve(zip_download_url, zip_download_path)
  169. if not ek.ek(os.path.isfile, zip_download_path):
  170. logger.log(u"Unable to retrieve new version from " + zip_download_url + ", can't update", logger.ERROR)
  171. return False
  172. if not ek.ek(zipfile.is_zipfile, zip_download_path):
  173. logger.log(u"Retrieved version from " + zip_download_url + " is corrupt, can't update", logger.ERROR)
  174. return False
  175. # extract to sb-update dir
  176. logger.log(u"Unzipping from " + str(zip_download_path) + " to " + sb_update_dir)
  177. update_zip = zipfile.ZipFile(zip_download_path, 'r')
  178. update_zip.extractall(sb_update_dir)
  179. update_zip.close()
  180. # delete the zip
  181. logger.log(u"Deleting zip file from " + str(zip_download_path))
  182. os.remove(zip_download_path)
  183. # find update dir name
  184. update_dir_contents = [x for x in os.listdir(sb_update_dir) if os.path.isdir(os.path.join(sb_update_dir, x))]
  185. if len(update_dir_contents) != 1:
  186. logger.log(u"Invalid update data, update failed. Maybe try deleting your sb-update folder?", logger.ERROR)
  187. return False
  188. content_dir = os.path.join(sb_update_dir, update_dir_contents[0])
  189. old_update_path = os.path.join(content_dir, u'updater.exe')
  190. new_update_path = os.path.join(sickbeard.PROG_DIR, u'updater.exe')
  191. logger.log(u"Copying new update.exe file from " + old_update_path + " to " + new_update_path)
  192. shutil.move(old_update_path, new_update_path)
  193. except Exception, e:
  194. logger.log(u"Error while trying to update: " + ex(e), logger.ERROR)
  195. return False
  196. return True
  197. class GitUpdateManager(UpdateManager):
  198. def __init__(self):
  199. self._git_path = self._find_working_git()
  200. self.github_repo_user = self.get_github_repo_user()
  201. self.github_repo = self.get_github_repo()
  202. self.branch = self._find_git_branch()
  203. self._cur_commit_hash = None
  204. self._newest_commit_hash = None
  205. self._num_commits_behind = 0
  206. self._num_commits_ahead = 0
  207. def _git_error(self):
  208. error_message = 'Unable to find your git executable - Shutdown SickBeard and EITHER <a href="http://code.google.com/p/sickbeard/wiki/AdvancedSettings" onclick="window.open(this.href); return false;">set git_path in your config.ini</a> OR delete your .git folder and run from source to enable updates.'
  209. sickbeard.NEWEST_VERSION_STRING = error_message
  210. def _find_working_git(self):
  211. test_cmd = 'version'
  212. if sickbeard.GIT_PATH:
  213. main_git = '"' + sickbeard.GIT_PATH + '"'
  214. else:
  215. main_git = 'git'
  216. logger.log(u"Checking if we can use git commands: " + main_git + ' ' + test_cmd, logger.DEBUG)
  217. output, err, exit_status = self._run_git(main_git, test_cmd) # @UnusedVariable
  218. if exit_status == 0:
  219. logger.log(u"Using: " + main_git, logger.DEBUG)
  220. return main_git
  221. else:
  222. logger.log(u"Not using: " + main_git, logger.DEBUG)
  223. # trying alternatives
  224. alternative_git = []
  225. # osx people who start SB from launchd have a broken path, so try a hail-mary attempt for them
  226. if platform.system().lower() == 'darwin':
  227. alternative_git.append('/usr/local/git/bin/git')
  228. if platform.system().lower() == 'windows':
  229. if main_git != main_git.lower():
  230. alternative_git.append(main_git.lower())
  231. if alternative_git:
  232. logger.log(u"Trying known alternative git locations", logger.DEBUG)
  233. for cur_git in alternative_git:
  234. logger.log(u"Checking if we can use git commands: " + cur_git + ' ' + test_cmd, logger.DEBUG)
  235. output, err, exit_status = self._run_git(cur_git, test_cmd) # @UnusedVariable
  236. if exit_status == 0:
  237. logger.log(u"Using: " + cur_git, logger.DEBUG)
  238. return cur_git
  239. else:
  240. logger.log(u"Not using: " + cur_git, logger.DEBUG)
  241. # Still haven't found a working git
  242. error_message = 'Unable to find your git executable - Shutdown SickBeard and EITHER <a href="http://code.google.com/p/sickbeard/wiki/AdvancedSettings" onclick="window.open(this.href); return false;">set git_path in your config.ini</a> OR delete your .git folder and run from source to enable updates.'
  243. sickbeard.NEWEST_VERSION_STRING = error_message
  244. return None
  245. def _run_git(self, git_path, args):
  246. output = err = exit_status = None
  247. if not git_path:
  248. logger.log(u"No git specified, can't use git commands", logger.ERROR)
  249. exit_status = 1
  250. return (output, err, exit_status)
  251. cmd = git_path + ' ' + args
  252. try:
  253. logger.log(u"Executing " + cmd + " with your shell in " + sickbeard.PROG_DIR, logger.DEBUG)
  254. p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, cwd=sickbeard.PROG_DIR)
  255. output, err = p.communicate()
  256. exit_status = p.returncode
  257. if output:
  258. output = output.strip()
  259. logger.log(u"git output: " + output, logger.DEBUG)
  260. except OSError:
  261. logger.log(u"Command " + cmd + " didn't work")
  262. exit_status = 1
  263. if exit_status == 0:
  264. logger.log(cmd + u" : returned successful", logger.DEBUG)
  265. exit_status = 0
  266. elif exit_status == 1:
  267. logger.log(cmd + u" returned : " + output, logger.ERROR)
  268. exit_status = 1
  269. elif exit_status == 128 or 'fatal:' in output or err:
  270. logger.log(cmd + u" returned : " + output, logger.ERROR)
  271. exit_status = 128
  272. else:
  273. logger.log(cmd + u" returned : " + output + u", treat as error for now", logger.ERROR)
  274. exit_status = 1
  275. return (output, err, exit_status)
  276. def _find_installed_version(self):
  277. """
  278. Attempts to find the currently installed version of Sick Beard.
  279. Uses git show to get commit version.
  280. Returns: True for success or False for failure
  281. """
  282. output, err, exit_status = self._run_git(self._git_path, 'rev-parse HEAD') #@UnusedVariable
  283. if exit_status == 0 and output:
  284. cur_commit_hash = output.strip()
  285. if not re.match('^[a-z0-9]+$', cur_commit_hash):
  286. logger.log(u"Output doesn't look like a hash, not using it", logger.ERROR)
  287. return False
  288. self._cur_commit_hash = cur_commit_hash
  289. return True
  290. else:
  291. return False
  292. def _find_git_branch(self):
  293. branch_info, err, exit_status = self._run_git(self._git_path, 'symbolic-ref -q HEAD') # @UnusedVariable
  294. if exit_status == 0 and branch_info:
  295. branch = branch_info.strip().replace('refs/heads/', '', 1)
  296. if branch:
  297. sickbeard.version.SICKBEARD_VERSION = branch
  298. return sickbeard.version.SICKBEARD_VERSION
  299. def _check_github_for_update(self):
  300. """
  301. Uses git commands to check if there is a newer version that the provided
  302. commit hash. If there is a newer version it sets _num_commits_behind.
  303. """
  304. self._newest_commit_hash = None
  305. self._num_commits_behind = 0
  306. self._num_commits_ahead = 0
  307. # get all new info from github
  308. output, err, exit_status = self._run_git(self._git_path, 'fetch origin') # @UnusedVariable
  309. if not exit_status == 0:
  310. logger.log(u"Unable to contact github, can't check for update", logger.ERROR)
  311. return
  312. # get latest commit_hash from remote
  313. output, err, exit_status = self._run_git(self._git_path, 'rev-parse --verify --quiet "@{upstream}"') # @UnusedVariable
  314. if exit_status == 0 and output:
  315. cur_commit_hash = output.strip()
  316. if not re.match('^[a-z0-9]+$', cur_commit_hash):
  317. logger.log(u"Output doesn't look like a hash, not using it", logger.DEBUG)
  318. return
  319. else:
  320. self._newest_commit_hash = cur_commit_hash
  321. else:
  322. logger.log(u"git didn't return newest commit hash", logger.DEBUG)
  323. return
  324. # get number of commits behind and ahead (option --count not supported git < 1.7.2)
  325. output, err, exit_status = self._run_git(self._git_path, 'rev-list --left-right "@{upstream}"...HEAD') # @UnusedVariable
  326. if exit_status == 0 and output:
  327. try:
  328. self._num_commits_behind = int(output.count("<"))
  329. self._num_commits_ahead = int(output.count(">"))
  330. except:
  331. logger.log(u"git didn't return numbers for behind and ahead, not using it", logger.DEBUG)
  332. return
  333. logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash)
  334. + u", num_commits_behind = " + str(self._num_commits_behind) + u", num_commits_ahead = " + str(self._num_commits_ahead), logger.DEBUG)
  335. def set_newest_text(self):
  336. # if we're up to date then don't set this
  337. sickbeard.NEWEST_VERSION_STRING = None
  338. if self._num_commits_ahead:
  339. logger.log(u"Local branch is ahead of " + self.branch + ". Automatic update not possible.", logger.ERROR)
  340. newest_text = "Local branch is ahead of " + self.branch + ". Automatic update not possible."
  341. elif self._num_commits_behind > 0:
  342. base_url = 'http://github.com/' + self.github_repo_user + '/' + self.github_repo
  343. if self._newest_commit_hash:
  344. url = base_url + '/compare/' + self._cur_commit_hash + '...' + self._newest_commit_hash
  345. else:
  346. url = base_url + '/commits/'
  347. newest_text = 'There is a <a href="' + url + '" onclick="window.open(this.href); return false;">newer version available</a> '
  348. newest_text += " (you're " + str(self._num_commits_behind) + " commit"
  349. if self._num_commits_behind > 1:
  350. newest_text += 's'
  351. newest_text += ' behind)' + "&mdash; <a href=\"" + self.get_update_url() + "\">Update Now</a>"
  352. else:
  353. return
  354. sickbeard.NEWEST_VERSION_STRING = newest_text
  355. def need_update(self):
  356. self._find_installed_version()
  357. if not self._cur_commit_hash:
  358. return True
  359. else:
  360. try:
  361. self._check_github_for_update()
  362. except Exception, e:
  363. logger.log(u"Unable to contact github, can't check for update: " + repr(e), logger.ERROR)
  364. return False
  365. if self._num_commits_behind > 0:
  366. return True
  367. return False
  368. def update(self):
  369. """
  370. Calls git pull origin <branch> in order to update Sick Beard. Returns a bool depending
  371. on the call's success.
  372. """
  373. output, err, exit_status = self._run_git(self._git_path, 'pull origin ' + self.branch) #@UnusedVariable
  374. if exit_status == 0:
  375. return True
  376. else:
  377. return False
  378. return False
  379. class SourceUpdateManager(UpdateManager):
  380. def __init__(self):
  381. self.github_repo_user = self.get_github_repo_user()
  382. self.github_repo = self.get_github_repo()
  383. self.branch = sickbeard.version.SICKBEARD_VERSION
  384. self._cur_commit_hash = None
  385. self._newest_commit_hash = None
  386. self._num_commits_behind = 0
  387. def _find_installed_version(self):
  388. version_file = ek.ek(os.path.join, sickbeard.PROG_DIR, u'version.txt')
  389. if not os.path.isfile(version_file):
  390. self._cur_commit_hash = None
  391. return
  392. try:
  393. with open(version_file, 'r') as fp:
  394. self._cur_commit_hash = fp.read().strip(' \n\r')
  395. except EnvironmentError, e:
  396. logger.log(u"Unable to open 'version.txt': " + ex(e), logger.DEBUG)
  397. if not self._cur_commit_hash:
  398. self._cur_commit_hash = None
  399. def need_update(self):
  400. self._find_installed_version()
  401. try:
  402. self._check_github_for_update()
  403. except Exception, e:
  404. logger.log(u"Unable to contact github, can't check for update: " + repr(e), logger.ERROR)
  405. return False
  406. if not self._cur_commit_hash or self._num_commits_behind > 0:
  407. return True
  408. return False
  409. def _check_github_for_update(self):
  410. """
  411. Uses pygithub to ask github if there is a newer version that the provided
  412. commit hash. If there is a newer version it sets Sick Beard's version text.
  413. commit_hash: hash that we're checking against
  414. """
  415. self._num_commits_behind = 0
  416. self._newest_commit_hash = None
  417. gh = github.GitHub(self.github_repo_user, self.github_repo, self.branch)
  418. # try to get newest commit hash and commits behind directly by comparing branch and current commit
  419. if self._cur_commit_hash:
  420. branch_compared = gh.compare(base=self.branch, head=self._cur_commit_hash)
  421. if 'base_commit' in branch_compared:
  422. self._newest_commit_hash = branch_compared['base_commit']['sha']
  423. if 'behind_by' in branch_compared:
  424. self._num_commits_behind = int(branch_compared['behind_by'])
  425. # fall back and iterate over last 100 (items per page in gh_api) commits
  426. if not self._newest_commit_hash:
  427. for curCommit in gh.commits():
  428. if not self._newest_commit_hash:
  429. self._newest_commit_hash = curCommit['sha']
  430. if not self._cur_commit_hash:
  431. break
  432. if curCommit['sha'] == self._cur_commit_hash:
  433. break
  434. # when _cur_commit_hash doesn't match anything _num_commits_behind == 100
  435. self._num_commits_behind += 1
  436. logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash)
  437. + u", num_commits_behind = " + str(self._num_commits_behind), logger.DEBUG)
  438. def set_newest_text(self):
  439. # if we're up to date then don't set this
  440. sickbeard.NEWEST_VERSION_STRING = None
  441. if not self._cur_commit_hash:
  442. logger.log(u"Unknown current version number, don't know if we should update or not", logger.DEBUG)
  443. newest_text = "Unknown current version number: If you've never used the Sick Beard upgrade system before then current version is not set."
  444. newest_text += "&mdash; <a href=\"" + self.get_update_url() + "\">Update Now</a>"
  445. elif self._num_commits_behind > 0:
  446. base_url = 'http://github.com/' + self.github_repo_user + '/' + self.github_repo
  447. if self._newest_commit_hash:
  448. url = base_url + '/compare/' + self._cur_commit_hash + '...' + self._newest_commit_hash
  449. else:
  450. url = base_url + '/commits/'
  451. newest_text = 'There is a <a href="' + url + '" onclick="window.open(this.href); return false;">newer version available</a>'
  452. newest_text += " (you're " + str(self._num_commits_behind) + " commit"
  453. if self._num_commits_behind > 1:
  454. newest_text += "s"
  455. newest_text += " behind)" + "&mdash; <a href=\"" + self.get_update_url() + "\">Update Now</a>"
  456. else:
  457. return
  458. sickbeard.NEWEST_VERSION_STRING = newest_text
  459. def update(self):
  460. """
  461. Downloads the latest source tarball from github and installs it over the existing version.
  462. """
  463. base_url = 'https://github.com/' + self.github_repo_user + '/' + self.github_repo
  464. tar_download_url = base_url + '/tarball/' + self.branch
  465. version_path = ek.ek(os.path.join, sickbeard.PROG_DIR, u'version.txt')
  466. try:
  467. # prepare the update dir
  468. sb_update_dir = ek.ek(os.path.join, sickbeard.PROG_DIR, u'sb-update')
  469. if os.path.isdir(sb_update_dir):
  470. logger.log(u"Clearing out update folder " + sb_update_dir + " before extracting")
  471. shutil.rmtree(sb_update_dir)
  472. logger.log(u"Creating update folder " + sb_update_dir + " before extracting")
  473. os.makedirs(sb_update_dir)
  474. # retrieve file
  475. logger.log(u"Downloading update from " + repr(tar_download_url))
  476. tar_download_path = os.path.join(sb_update_dir, u'sb-update.tar')
  477. urllib.urlretrieve(tar_download_url, tar_download_path)
  478. if not ek.ek(os.path.isfile, tar_download_path):
  479. logger.log(u"Unable to retrieve new version from " + tar_download_url + ", can't update", logger.ERROR)
  480. return False
  481. if not ek.ek(tarfile.is_tarfile, tar_download_path):
  482. logger.log(u"Retrieved version from " + tar_download_url + " is corrupt, can't update", logger.ERROR)
  483. return False
  484. # extract to sb-update dir
  485. logger.log(u"Extracting file " + tar_download_path)
  486. tar = tarfile.open(tar_download_path)
  487. tar.extractall(sb_update_dir)
  488. tar.close()
  489. # delete .tar.gz
  490. logger.log(u"Deleting file " + tar_download_path)
  491. os.remove(tar_download_path)
  492. # find update dir name
  493. update_dir_contents = [x for x in os.listdir(sb_update_dir) if os.path.isdir(os.path.join(sb_update_dir, x))]
  494. if len(update_dir_contents) != 1:
  495. logger.log(u"Invalid update data, update failed: " + str(update_dir_contents), logger.ERROR)
  496. return False
  497. content_dir = os.path.join(sb_update_dir, update_dir_contents[0])
  498. # walk temp folder and move files to main folder
  499. logger.log(u"Moving files from " + content_dir + " to " + sickbeard.PROG_DIR)
  500. for dirname, dirnames, filenames in os.walk(content_dir): # @UnusedVariable
  501. dirname = dirname[len(content_dir) + 1:]
  502. for curfile in filenames:
  503. old_path = os.path.join(content_dir, dirname, curfile)
  504. new_path = os.path.join(sickbeard.PROG_DIR, dirname, curfile)
  505. if os.path.isfile(new_path):
  506. os.remove(new_path)
  507. os.renames(old_path, new_path)
  508. # update version.txt with commit hash
  509. try:
  510. with open(version_path, 'w') as ver_file:
  511. ver_file.write(self._newest_commit_hash)
  512. except EnvironmentError, e:
  513. logger.log(u"Unable to write version file, update not complete: " + ex(e), logger.ERROR)
  514. return False
  515. except Exception, e:
  516. logger.log(u"Error while trying to update: " + ex(e), logger.ERROR)
  517. return False
  518. return True