Skip to content

Commit

Permalink
Change git and source updater
Browse files Browse the repository at this point in the history
Switch to real git commands. Using lad1337/XDM as example.
+ Change source updater. Get commits behind directly using github api compare

Add downloaded update file corruption check
Add extra log lines
Add stdin to subprocess.Popen to prevent WindowsError: [Error 6] The handle is invalid on pythonw
  • Loading branch information
Patrick Vos committed Mar 18, 2014
1 parent 28e72ce commit a904139
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 37 deletions.
17 changes: 16 additions & 1 deletion sickbeard/gh_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,20 @@ def commits(self):
Returns a deserialized json object containing the commit info. See http://developer.github.com/v3/repos/commits/
"""
access_API = self._access_API(['repos', self.github_repo_user, self.github_repo, 'commits'], {'per_page': 100, 'sha': self.branch})
access_API = self._access_API(['repos', self.github_repo_user, self.github_repo, 'commits'], params={'per_page': 100, 'sha': self.branch})
return access_API

def compare(self, base, head, per_page=1):
"""
Uses the API to get a list of compares between base and head.
user: The github username of the person whose repo you're querying
repo: The repo name to query
base: Start compare from branch
head: Current commit sha or branch name to compare
per_page: number of items per page
Returns a deserialized json object containing the compare info. See http://developer.github.com/v3/repos/commits/
"""
access_API = self._access_API(['repos', self.github_repo_user, self.github_repo, 'compare', base + '...' + head], params={'per_page': per_page})
return access_API
117 changes: 81 additions & 36 deletions sickbeard/versionChecker.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ def need_update(self):
if self._newest_version and self._newest_version > self._cur_version:
return True

return False

def set_newest_text(self):

sickbeard.NEWEST_VERSION_STRING = None
Expand Down Expand Up @@ -225,6 +227,10 @@ def update(self):
logger.log(u"Unable to retrieve new version from " + zip_download_url + ", can't update", logger.ERROR)
return False

if not ek.ek(zipfile.is_zipfile, zip_download_path):
logger.log(u"Retrieved version from " + zip_download_url + " is corrupt, can't update", logger.ERROR)
return False

# extract to sb-update dir
logger.log(u"Unzipping from " + str(zip_download_path) + " to " + sb_update_dir)
update_zip = zipfile.ZipFile(zip_download_path, 'r')
Expand Down Expand Up @@ -266,6 +272,7 @@ def __init__(self):
self._cur_commit_hash = None
self._newest_commit_hash = None
self._num_commits_behind = 0
self._num_commits_ahead = 0

def _git_error(self):
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.'
Expand Down Expand Up @@ -332,7 +339,7 @@ def _run_git(self, git_path, args):

try:
logger.log(u"Executing " + cmd + " with your shell in " + sickbeard.PROG_DIR, logger.DEBUG)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, cwd=sickbeard.PROG_DIR)
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, cwd=sickbeard.PROG_DIR)
output, err = p.communicate()
exit_status = p.returncode

Expand Down Expand Up @@ -393,38 +400,61 @@ def _find_git_branch(self):

def _check_github_for_update(self):
"""
Uses pygithub to ask github if there is a newer version that the provided
commit hash. If there is a newer version it sets Sick Beard's version text.
commit_hash: hash that we're checking against
Uses git commands to check if there is a newer version that the provided
commit hash. If there is a newer version it sets _num_commits_behind.
"""

self._num_commits_behind = 0
self._newest_commit_hash = None
self._num_commits_behind = 0
self._num_commits_ahead = 0

gh = github.GitHub(self.github_repo_user, self.github_repo, self.branch)
# get all new info from github
output, err, exit_status = self._run_git(self._git_path, 'fetch origin') # @UnusedVariable

# find newest commit
for curCommit in gh.commits():
if not self._newest_commit_hash:
self._newest_commit_hash = curCommit['sha']
if not self._cur_commit_hash:
break
if not exit_status == 0:
logger.log(u"Unable to contact github, can't check for update", logger.ERROR)
return

# get latest commit_hash from remote
output, err, exit_status = self._run_git(self._git_path, 'rev-parse --verify --quiet "@{upstream}"') # @UnusedVariable

if exit_status == 0 and output:
cur_commit_hash = output.strip()

if not re.match('^[a-z0-9]+$', cur_commit_hash):
logger.log(u"Output doesn't look like a hash, not using it", logger.DEBUG)
return

if curCommit['sha'] == self._cur_commit_hash:
break
else:
self._newest_commit_hash = cur_commit_hash
else:
logger.log(u"git didn't return newest commit hash", logger.DEBUG)
return

# get number of commits behind and ahead (option --count not supported git < 1.7.2)
output, err, exit_status = self._run_git(self._git_path, 'rev-list --left-right "@{upstream}"...HEAD') # @UnusedVariable

if exit_status == 0 and output:

try:
self._num_commits_behind = int(output.count("<"))
self._num_commits_ahead = int(output.count(">"))

self._num_commits_behind += 1
except:
logger.log(u"git didn't return numbers for behind and ahead, not using it", logger.DEBUG)
return

logger.log(u"newest: " + str(self._newest_commit_hash) + " and current: " + str(self._cur_commit_hash) + " and num_commits: " + str(self._num_commits_behind), logger.DEBUG)
logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash)
+ u", num_commits_behind = " + str(self._num_commits_behind) + u", num_commits_ahead = " + str(self._num_commits_ahead), logger.DEBUG)

def set_newest_text(self):

# if we're up to date then don't set this
sickbeard.NEWEST_VERSION_STRING = None

if self._num_commits_behind == 100:
newest_text = "You are ahead of " + self.branch + ". Update not possible."
if self._num_commits_ahead:
logger.log(u"Local branch is ahead of " + self.branch + ". Automatic update not possible.", logger.ERROR)
newest_text = "Local branch is ahead of " + self.branch + ". Automatic update not possible."

elif self._num_commits_behind > 0:

Expand Down Expand Up @@ -457,8 +487,6 @@ def need_update(self):
logger.log(u"Unable to contact github, can't check for update: " + repr(e), logger.ERROR)
return False

logger.log(u"After checking, cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash) + u", num_commits_behind = " + str(self._num_commits_behind), logger.DEBUG)

if self._num_commits_behind > 0:
return True

Expand Down Expand Up @@ -518,8 +546,6 @@ def need_update(self):
logger.log(u"Unable to contact github, can't check for update: " + repr(e), logger.ERROR)
return False

logger.log(u"After checking, cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash) + u", num_commits_behind = " + str(self._num_commits_behind), logger.DEBUG)

if not self._cur_commit_hash or self._num_commits_behind > 0:
return True

Expand All @@ -538,29 +564,43 @@ def _check_github_for_update(self):

gh = github.GitHub(self.github_repo_user, self.github_repo, self.branch)

# find newest commit
for curCommit in gh.commits():
if not self._newest_commit_hash:
self._newest_commit_hash = curCommit['sha']
if not self._cur_commit_hash:
break
# try to get newest commit hash and commits behind directly by comparing branch and current commit
if self._cur_commit_hash:
branch_compared = gh.compare(base=self.branch, head=self._cur_commit_hash)

if 'base_commit' in branch_compared:
self._newest_commit_hash = branch_compared['base_commit']['sha']

if 'behind_by' in branch_compared:
self._num_commits_behind = int(branch_compared['behind_by'])

if curCommit['sha'] == self._cur_commit_hash:
break
# fall back and iterate over last 100 (items per page in gh_api) commits
if not self._newest_commit_hash:

self._num_commits_behind += 1
for curCommit in gh.commits():
if not self._newest_commit_hash:
self._newest_commit_hash = curCommit['sha']
if not self._cur_commit_hash:
break

if curCommit['sha'] == self._cur_commit_hash:
break

logger.log(u"newest: " + str(self._newest_commit_hash) + " and current: " + str(self._cur_commit_hash) + " and num_commits: " + str(self._num_commits_behind), logger.DEBUG)
# when _cur_commit_hash doesn't match anything _num_commits_behind == 100
self._num_commits_behind += 1

logger.log(u"cur_commit = " + str(self._cur_commit_hash) + u", newest_commit = " + str(self._newest_commit_hash)
+ u", num_commits_behind = " + str(self._num_commits_behind), logger.DEBUG)

def set_newest_text(self):

# if we're up to date then don't set this
sickbeard.NEWEST_VERSION_STRING = None

if not self._cur_commit_hash or self._num_commits_behind == 100:
logger.log(u"Unknown current version, don't know if we should update or not", logger.DEBUG)
if not self._cur_commit_hash:
logger.log(u"Unknown current version number, don't know if we should update or not", logger.DEBUG)

newest_text = "Unknown version: If you've never used the Sick Beard upgrade system then I don't know what version you have."
newest_text = "Unknown current version number: If you've never used the Sick Beard upgrade system before then current version is not set."
newest_text += "&mdash; <a href=\"" + self.get_update_url() + "\">Update Now</a>"

elif self._num_commits_behind > 0:
Expand Down Expand Up @@ -608,6 +648,10 @@ def update(self):
logger.log(u"Unable to retrieve new version from " + tar_download_url + ", can't update", logger.ERROR)
return False

if not ek.ek(tarfile.is_tarfile, tar_download_path):
logger.log(u"Retrieved version from " + tar_download_url + " is corrupt, can't update", logger.ERROR)
return False

# extract to sb-update dir
logger.log(u"Extracting file " + tar_download_path)
tar = tarfile.open(tar_download_path)
Expand All @@ -626,6 +670,7 @@ def update(self):
content_dir = os.path.join(sb_update_dir, update_dir_contents[0])

# walk temp folder and move files to main folder
logger.log(u"Moving files from " + content_dir + " to " + sickbeard.PROG_DIR)
for dirname, dirnames, filenames in os.walk(content_dir): # @UnusedVariable
dirname = dirname[len(content_dir) + 1:]
for curfile in filenames:
Expand Down

0 comments on commit a904139

Please sign in to comment.