def _find_sha_branch(self): git = Git(self.path) sha_branches = git.branch(contains=self.sha, all=True).split('\n') sha_branch = [b for b in sha_branches if ' -> ' not in b][0] sha_branch = sha_branch.strip('* \n').replace('remotes/', '') for remote in git.remote().split('\n'): sha_branch = sha_branch.replace(remote + '/', '') return sha_branch
def get_shas(self): git = Git(self.path) with git_to_msm_exceptions(): shas = git.ls_tree('origin/' + self.branch) for line in shas.split('\n'): size, typ, sha, folder = line.split() if typ != 'commit': continue yield folder, sha
def __prepare_repo(self): if not exists(dirname(self.path)): makedirs(dirname(self.path)) if not isdir(self.path): Repo.clone_from(self.url, self.path) git = Git(self.path) git.config('remote.origin.url', self.url) git.fetch() try: git.checkout(self.branch) git.reset('origin/' + self.branch, hard=True) except GitCommandError: raise MsmException('Invalid branch: ' + self.branch)
def install(self, constraints=None): if self.is_local: raise AlreadyInstalled(self.name) LOG.info("Downloading skill: " + self.url) try: tmp_location = mktemp() Repo.clone_from(self.url, tmp_location) self.is_local = True Git(tmp_location).reset(self.sha or 'HEAD', hard=True) except GitCommandError as e: raise CloneException(e.stderr) if isfile(join(tmp_location, '__init__.py')): move(join(tmp_location, '__init__.py'), join(tmp_location, '__init__')) try: move(tmp_location, self.path) if self.msm: self.run_skill_requirements() self.install_system_deps() self.run_pip(constraints) finally: if isfile(join(self.path, '__init__')): move(join(self.path, '__init__'), join(self.path, '__init__.py')) LOG.info('Successfully installed ' + self.name)
def find_git_url(path): """Get the git url from a folder""" try: LOG.debug( 'Attempting to retrieve the remote origin URL config for ' 'skill in path ' + path) return Git(path).config('remote.origin.url') except GitError: return ''
def is_dirty(self): """True if different from the version in the mycroft-skills repo. Considers a skill dirty if - the checkout sha doesn't match the mycroft-skills repo - the skill doesn't exist in the mycroft-skills repo - the skill is not a git repo - has local modifications """ if not exists(self.path): return False try: checkout = Git(self.path) mod = checkout.status(porcelain=True, untracked_files='no') != '' current_sha = checkout.rev_parse('HEAD') except GitCommandError: # Not a git checkout return True skill_shas = {d[0]: d[3] for d in self.msm.repo.get_skill_data()} return (self.name not in skill_shas or current_sha != skill_shas[self.name] or mod)
def update(self): if not self.is_local: raise NotInstalled('{} is not installed'.format(self.name)) git = Git(self.path) with git_to_msm_exceptions(): sha_before = git.rev_parse('HEAD') modified_files = git.status(porcelain=True, untracked='no') if modified_files != '': raise SkillModified('Uncommitted changes:\n' + modified_files) git.fetch() current_branch = git.rev_parse('--abbrev-ref', 'HEAD').strip() if self.sha and current_branch in SWITCHABLE_BRANCHES: # Check out correct branch git.checkout(self._find_sha_branch()) git.merge(self.sha or 'origin/HEAD', ff_only=True) sha_after = git.rev_parse('HEAD') if sha_before != sha_after: self.update_deps() LOG.info('Updated ' + self.name) # Trigger reload by modifying the timestamp os.utime(join(self.path, '__init__.py')) return True else: LOG.info('Nothing new for ' + self.name) return False
def find_git_url(path): """Get the git url from a folder""" try: return Git(path).config('remote.origin.url') except GitError: return ''