예제 #1
0
파일: solbot.py 프로젝트: flip40/SolBot
async def on_message(message):
	if client.sleeping:
		if message.content == '!wake':
			client.sleeping = False
			await client.send_message(message.channel, 'SolBot online!')
	else:
		if message.content == '!sleep':
			client.sleeping = True
			await client.send_message(message.channel, 'Going to sleep...')
		elif message.content == '!update':
			g = Git(os.path.dirname(os.path.abspath(__file__)))
			tmp = await client.send_message(message.channel, 'Pulling new code...')
			g.pull()
			await client.edit_message(tmp, 'Code pulled. Restarting...')
			client.logout()
			os.execv(sys.executable, ['python3.5'] + sys.argv)
		elif message.content == '!gitstatus':
			g = Git(os.path.dirname(os.path.abspath(__file__)))
			tmp = await client.send_message(message.channel, 'Checking status...')
			g.fetch()
			p = re.compile('Your branch is.*by (\d+) commits.*')
			m = p.match(g.status())
			if m:
				await client.edit_message(tmp, 'I am behind by {} commits'.format(m.group(1)))
			else:
				await client.edit_message(tmp, 'I am up to date!')
예제 #2
0
def branches():
    g = Git(PROJECT_DIR)
    send('重新获取远程分支中.....')
    g.fetch(REMOTE_NAME)
    send('获取成功')
    branch_names = g.branch('-a').split('\n')
    return jsonify(branch_names)
예제 #3
0
def branches():
    g = Git(PROJECT_DIR)
    send('重新获取远程分支中.....')
    g.fetch(REMOTE_NAME)
    send('获取成功')
    branch_names = g.branch('-a').split('\n')
    return jsonify(branch_names)
예제 #4
0
    def update(self):
        """
        Updates the opsoro software thru git
        """
        if self.git is None:
            return False
        # Create file to let deamon know it has to update before starting the server
        # file = open(self.dir + 'update.var', 'w+')

        backup_dir = '/home/pi/OPSORO/backup/'

        print('Updating...')
        if os.path.exists(backup_dir):
            # remove previous backup
            try:
                shutil.rmtree(backup_dir)
            except Exception as e:
                print_error('Remove backup failed: ' + str(e))
                pass

        try:
            shutil.copytree(self.dir, backup_dir)
        except Exception as e:
            print_error('Backup copy failed: ' + str(e))
            pass

        # Link git & update
        try:
            g = Git(self.dir)
            g.fetch('--all')
            g.reset('--hard', 'origin/' + g.branch().split()[-1])
            # g.pull()
        except Exception as e:
            print_error('Git failed to update: ' + str(e))
            pass

        # Set script executable for deamon
        try:
            st = os.stat(os.path.join(self.dir, 'run'))
            os.chmod(os.path.join(self.dir, 'run'),
                     st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
        except Exception as e:
            print_error('Exec state set failed: ' + str(e))
            pass

        # Clear update var file
        # os.remove(os.path.join(self.dir, 'update.var'))

        # restart service
        command = ['/usr/sbin/service', 'opsoro', 'restart']
        #shell=FALSE for sudo to work.
        subprocess.call(command, shell=False)
예제 #5
0
def fetch_and_checkout(config, repo):
    """Try to fetch the remote ref in the personal gerrit branch for
    the running user."""
    g = Git(repo.working_tree_dir)
    try:
        g.fetch(['origin', config._state_ref])
        g.checkout('FETCH_HEAD')
    except git.exc.GitCommandError as e:
        if "couldn't find remote ref refs/personal" in e.stderr:
            pass
        else:
            print(e)
    del g
def cloneOrCheckout(base_path, repo):
	git = Git()
	repo_path = os.path.join(base_path, repo['name'])
	print (repo_path)
	try:
		os.chdir(repo_path)
	except OSError:
		os.chdir(base_path)
		git.clone(repo['base_url'] + repo['name'])
		os.chdir(repo_path)
		cloned = True
	finally:
		git.fetch()
		git.checkout(repo['branch'])
		os.chdir(base_path)
예제 #7
0
class GitRepo:
    def __init__(self, directory, url, branch, update_freq=1, tag=None):
        self.dir = directory
        self.url = url
        self.branch = branch
        self.update_freq = update_freq  # Hours
        self.tag = tag
        self.git = Git(self.dir)

    def run_inside(self, command):
        cur_path = getcwd()
        if command.startswith('./'):
            command = join(self.dir, command[2:])
        try:
            chdir(self.dir)
            if isinstance(command, str):
                call(command.split(' '))
            else:
                call(command)
        finally:
            chdir(cur_path)

    def _clone(self):
        if self.tag is None:
            Git().clone(self.url, self.dir, branch=self.branch, single_branch=True, depth=1)
        else:
            self.git.init()
            self.git.remote('add', 'origin', self.url)
            self.git.fetch('origin', self.tag, depth=1)
            self.git.reset('FETCH_HEAD', hard=True)

    def try_pull(self):
        if not isdir(self.dir):
            self._clone()
            return True

        git_folder = join(self.dir, '.git')
        stat = os.stat(git_folder)
        if time() - stat.st_mtime > self.update_freq * 60 * 60:
            # Touch folder
            os.utime(git_folder)
            if not self.tag:
                self.git.pull(ff_only=True)
            return True
        return False
	def addSuperModuleCommit(self, id, hash, url, who, branch, project):	
		self.log.debug("branch: " + branch + ", project:" + project)
		
		hasSuperModule = False
		isSuperModuleBr = False
		self.log.debug("Project names: " + str(self.config.projects))
		
		projectNames = self.config.projects.keys()
		for proj in projectNames:
				self.log.debug("project: " + project + " proj: " + proj)
				if project.lower() == proj:
					hasSuperModule = True
					break
	
		for br in self.config.branches:
			if branch == br:
				isSuperModuleBr = True
				break

		self.log.debug("isSuperModuleBr: " + str(isSuperModuleBr) + " hasSuperModule: " + str(hasSuperModule))	
		if isSuperModuleBr and hasSuperModule:
			self.log.debug("Git Profile Path: " + str(self.config.profile))
			git = Git(self.config.profile)
			self.checkoutTrackingBranch(git, branch)
			git.pull()
			git.submodule("update","--init")
			gitSubmoduleProfile = {'git':self.config.superRepoPath + self.config.projects[project.lower()]}
			gitSubmodule = Git(gitSubmoduleProfile)
			self.log.debug("checking out hash: " + hash)
			gitSubmodule.fetch()
	
			if self.isOptOut(gitSubmodule, hash):
				return	
	
			gitSubmodule.checkout(hash, True)
			git.add(".")
			commitMsg = "Auto checkin: " + self.getCommitMessage(gitSubmodule, hash) + "\nuser:"******"\nhash:" + hash + "\nproject: " + project
			self.log.debug("commiting in super module: " +  commitMsg)
			git.commit(commitMsg)
			self.log.debug("pushing super module to branch: " + branch)
			git.push(branch)
		else:
			self.log.debug("No super module commit is required.")
예제 #9
0
def branch(branch_name):
    # branch_name = 'remotes/ssh/' + branch_name
    g = Git(PROJECT_DIR)
    send('重新获取远程分支中.....')
    g.fetch(REMOTE_NAME)
    send('获取成功')
    branch_names = g.branch('-a').split('\n')
    branch_names = [_.strip() for _ in branch_names]
    if branch_name not in branch_names:
        return '你的这个branch啊,鹅母鸡鸭'
    try:
        send('重置分支')
        g.reset('--hard')
        send('切换分支中')
        g.checkout(branch_name)
        send('切换分支完成')
    except Exception as e:
        return str(e)
    return branch_name
예제 #10
0
def branch(branch_name):
    # branch_name = 'remotes/ssh/' + branch_name
    g = Git(PROJECT_DIR)
    send('重新获取远程分支中.....')
    g.fetch(REMOTE_NAME)
    send('获取成功')
    branch_names = g.branch('-a').split('\n')
    branch_names = [_.strip() for _ in branch_names]
    if branch_name not in branch_names:
        return '你的这个branch啊,鹅母鸡鸭'
    try:
        send('重置分支')
        g.reset('--hard')
        send('切换分支中')
        g.checkout(branch_name)
        send('切换分支完成')
    except Exception as e:
        return str(e)
    return branch_name
예제 #11
0
class TempClone:
    """Create a clone in a temp dir used to write and push file changes"""
    def __init__(self, url: str, branch: str=None):
        import posixpath
        self.path = join(gettempdir(), posixpath.basename(url))
        if not isdir(self.path):
            Repo.clone_from(url, self.path)
        self.git = Git(self.path)
        self.git.fetch()
        if branch:
            self.git.checkout(branch)

    def write(self, path: str, content: str):
        with open(join(self.path, path), 'w') as f:
            f.write(content)
        self.git.add(path)
        self.git.commit(message="Automatic update of skill-metadata.json")
        self.git.push()

    def delete(self):
        shutil.rmtree(self.path)
예제 #12
0
def temporary_macro(tag, macro, app, nevents):
    app_map = {'BACCARAT': 'Bacc'}
    macro_extras = Template(dedent("""
        /control/getEnv SEED
        /$app/randomSeed {SEED}
        /$app/beamOn $nevents
        exit
        """))
    lzprod_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
    git_dir = os.path.join(lzprod_root, 'git', 'TDRAnalysis')
    macro = os.path.join(git_dir, macro)
    git = Git(git_dir)
    git.fetch('origin')
    git.checkout(tag)
    if not os.path.isfile(macro):
        raise Exception("Macro file '%s' doesn't exist in tag %s" % (macro, tag))

    with NamedTemporaryFile(prefix=os.path.splitext(os.path.basename(macro))[0] + '_',
                            suffix='.mac') as tmpfile:
        with open(macro, 'rb') as macro_file:
            tmpfile.write(macro_file.read())
        tmpfile.write(macro_extras.safe_substitute(app=app_map.get(app, app), nevents=nevents))
        tmpfile.flush()
        yield tmpfile
예제 #13
0
class GitWrapper:
    """
    A wrapper for repo.git providing better stdout handling + better exeptions.

    It is preferred to repo.git because it doesn't print to stdout
    in real time. In addition, this wrapper provides better error
    handling (it provides stdout messages inside the exception, too).
    """
    def __init__(self, repo):
        if repo:
            #: :type: git.Repo
            self.repo = repo
            #: :type: git.Git
            self.git = self.repo.git
        else:
            #: :type: git.Git
            self.git = Git()

    def __del__(self):
        # Is the following true?

        # GitPython runs persistent git processes in  the working directory.
        # Therefore, when we use 'git up' in something like a test environment,
        # this might cause troubles because of the open file handlers (like
        # trying to remove the directory right after the test has finished).
        # 'clear_cache' kills the processes...

        if platform.system() == 'Windows':  # pragma: no cover
            pass
            # ... or rather "should kill", because but somehow it recently
            # started to not kill cat_file_header out of the blue (I even
            # tried running old code, but the once working code failed).
            # Thus, we kill it  manually here.
            if self.git.cat_file_header is not None:
                subprocess.call(("TASKKILL /F /T /PID {} 2>nul 1>nul".format(
                    str(self.git.cat_file_header.proc.pid))),
                                shell=True)
            if self.git.cat_file_all is not None:
                subprocess.call(("TASKKILL /F /T /PID {} 2>nul 1>nul".format(
                    str(self.git.cat_file_all.proc.pid))),
                                shell=True)

        self.git.clear_cache()

    def _run(self, name, *args, **kwargs):
        """ Run a git command specified by name and args/kwargs. """

        stdout = b''
        cmd = getattr(self.git, name)

        # Ask cmd(...) to return a (status, stdout, stderr) tuple
        kwargs['with_extended_output'] = True

        # Execute command
        try:
            (_, stdout, _) = cmd(*args, **kwargs)
        except GitCommandError as error:
            # Add more meta-information to errors
            message = "'{}' returned exit status {}".format(
                ' '.join(str(c) for c in error.command), error.status)

            raise GitError(message, stderr=error.stderr, stdout=stdout)

        return stdout.strip()

    def __getattr__(self, name):
        return lambda *args, **kwargs: self._run(name, *args, **kwargs)

    ###########################################################################
    # Overwrite some methods and add new ones
    ###########################################################################

    @contextmanager
    def stasher(self):
        """
        A stashing contextmanager.
        """
        # nonlocal for python2
        stashed = [False]
        clean = [False]

        def stash():
            if clean[0] or not self.repo.is_dirty(submodules=False):
                clean[0] = True
                return
            if stashed[0]:
                return

            if self.change_count > 1:
                message = 'stashing {0} changes'
            else:
                message = 'stashing {0} change'
            print(colored(message.format(self.change_count), 'magenta'))
            try:
                self._run('stash')
            except GitError as e:
                raise StashError(stderr=e.stderr, stdout=e.stdout)

            stashed[0] = True

        yield stash

        if stashed[0]:
            print(colored('unstashing', 'magenta'))
            try:
                self._run('stash', 'pop')
            except GitError as e:
                raise UnstashError(stderr=e.stderr, stdout=e.stdout)

    def checkout(self, branch_name):
        """ Checkout a branch by name. """
        try:
            find(self.repo.branches,
                 lambda b: b.name == branch_name).checkout()
        except OrigCheckoutError as e:
            raise CheckoutError(branch_name, details=e)

    def rebase(self, target_branch):
        """ Rebase to target branch. """
        current_branch = self.repo.active_branch

        arguments = (([self.config('git-up.rebase.arguments')] or []) +
                     [target_branch.name])
        try:
            self._run('rebase', *arguments)
        except GitError as e:
            raise RebaseError(current_branch.name, target_branch.name,
                              **e.__dict__)

    def fetch(self, *args, **kwargs):
        """ Fetch remote commits. """

        # Unlike the other git commands, we want to output `git fetch`'s
        # output in real time. Therefore we use a different implementation
        # from `GitWrapper._run` which buffers all output.
        # In theory this may deadlock if `git fetch` prints more than 8 KB
        # to stderr which is here assumed to not happen in day-to-day use.

        stdout = b''

        # Execute command
        cmd = self.git.fetch(as_process=True, *args, **kwargs)

        # Capture output
        while True:
            output = cmd.stdout.read(1)

            sys.stdout.write(output.decode('utf-8'))
            sys.stdout.flush()

            stdout += output

            # Check for EOF
            if output == b"":
                break

        # Wait for the process to quit
        try:
            cmd.wait()
        except GitCommandError as error:
            # Add more meta-information to errors
            message = "'{}' returned exit status {}".format(
                ' '.join(str(c) for c in error.command), error.status)

            raise GitError(message, stderr=error.stderr, stdout=stdout)

        return stdout.strip()

    def push(self, *args, **kwargs):
        ''' Push commits to remote '''
        stdout = b''

        # Execute command
        cmd = self.git.push(as_process=True, *args, **kwargs)

        # Capture output
        while True:
            output = cmd.stdout.read(1)

            sys.stdout.write(output.decode('utf-8'))
            sys.stdout.flush()

            stdout += output

            # Check for EOF
            if output == b"":
                break

        # Wait for the process to quit
        try:
            cmd.wait()
        except GitCommandError as error:
            # Add more meta-information to errors
            message = "'{}' returned exit status {}".format(
                ' '.join(str(c) for c in error.command), error.status)

            raise GitError(message, stderr=error.stderr, stdout=stdout)

        return stdout.strip()

    def config(self, key):
        """ Return `git config key` output or None. """
        try:
            return self.git.config(key)
        except GitCommandError:
            return None

    @property
    def change_count(self):
        """ The number of changes in the working directory. """
        status = self.git.status(porcelain=True, untracked_files='no').strip()
        if not status:
            return 0
        else:
            return len(status.split('\n'))

    @property
    def version(self):
        """
        Return git's version as a list of numbers.

        The original repo.git.version_info has problems with tome types of
        git version strings.
        """
        return re.search(r'\d+(\.\d+)+', self.git.version()).group(0)

    def is_version_min(self, required_version):
        """ Does git's version match the requirements? """
        return self.version.split('.') >= required_version.split('.')
예제 #14
0
class _Updater(object):
    def __init__(self):
        self.dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), '..', '..')) + '/'

        self.git = None
        self.repo = None
        try:
            self.git = Git(self.dir)
            self.repo = Repo(self.dir)
        except Exception as e:
            print_warning('Git repo error' + str(e))
            pass

    def get_current_branch(self):
        """
        Retrieves the current git branch of the repository.

        :return:    current git branch.
        :rtype:     string
        """
        if self.git is None:
            return False
        try:
            return str(self.repo.active_branch).split()[-1]
        except Exception as e:
            print_error(
                "Failed to get current branch, is there a git repo setup?" +
                str(e))
            return ""

    def get_current_revision(self):
        """
        Retrieves the current git revision of the repository.

        :return:    current git revision.
        :rtype:     string
        """
        if self.git is None:
            return False
        try:
            # Request latest commit revision
            return str(self.git.log("--pretty=%h", "-1"))
        except Exception as e:
            print_error(
                "Failed to get current revision, is there a git repo setup?" +
                str(e))
            return ""

    def get_remote_branches(self):
        """
        Retrieve all git branches of the repository.

        :return:    branches of the repository.
        :rtype:     list
        """
        if self.git is None:
            return False
        branches = []

        try:
            # Get all remote branches (not only local)
            returnvalue = self.git.ls_remote('--heads').split()

            # Strip data
            for i in range(len(returnvalue)):
                if i % 2 != 0:
                    # Get only branch name (last value)
                    branches.append(returnvalue[i].split("/")[-1])
        except Exception as e:
            print_warning(
                "Failed to get remote branches, is there a git repo setup and do you have internet?"
                + str(e))
            pass

        return branches

    def is_update_available(self):
        """
        Checks git repository for available changes.

        :return:    True if update is available, False if the command failed or no update available.
        :rtype:     bool
        """
        if self.git is None:
            return False
        try:
            # Update local git data
            self.git.fetch()
        except Exception as e:
            print_error('Failed to fetch: ' + str(e))
            return False
        # Retrieve git remote <-> local difference status
        status = self.git.status()
        # easy check to see if local is behind
        if status.find('behind') > 0:
            return True
        return False

    def update(self):
        """
        Updates the opsoro software thru git
        """
        if self.git is None:
            return False
        # Create file to let deamon know it has to update before starting the server
        # file = open(self.dir + 'update.var', 'w+')

        backup_dir = '/home/pi/OPSORO/backup/'

        print('Updating...')
        if os.path.exists(backup_dir):
            # remove previous backup
            try:
                shutil.rmtree(backup_dir)
            except Exception as e:
                print_error('Remove backup failed: ' + str(e))
                pass

        try:
            shutil.copytree(self.dir, backup_dir)
        except Exception as e:
            print_error('Backup copy failed: ' + str(e))
            pass

        # Link git & update
        try:
            g = Git(self.dir)
            g.fetch('--all')
            g.reset('--hard', 'origin/' + g.branch().split()[-1])
            # g.pull()
        except Exception as e:
            print_error('Git failed to update: ' + str(e))
            pass

        # Set script executable for deamon
        try:
            st = os.stat(os.path.join(self.dir, 'run'))
            os.chmod(os.path.join(self.dir, 'run'),
                     st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
        except Exception as e:
            print_error('Exec state set failed: ' + str(e))
            pass

        # Clear update var file
        # os.remove(os.path.join(self.dir, 'update.var'))

        # restart service
        command = ['/usr/sbin/service', 'opsoro', 'restart']
        #shell=FALSE for sudo to work.
        subprocess.call(command, shell=False)
예제 #15
0
class _Preferences(object):
    def __init__(self):
        """
        Preferences class to store and retrieve settings.
        """
        self.data = {}
        self.load_prefs()
        self.dir = os.path.abspath(
            os.path.join(os.path.dirname(__file__), '..', '..')) + '/'

        self.git = None
        self.repo = None
        try:
            self.git = Git(self.dir)
            self.repo = Repo(self.dir)
        except:
            pass

    def get_current_branch(self):
        """
        Retrieves the current git branch of the repository.

        :return:    current git branch.
        :rtype:     string
        """
        if self.git is None:
            return False
        try:
            return self.git.branch().split()[-1]
        except:
            print_error(
                "Failed to get current branch, is there a git repo setup?")
            return ""

    def get_remote_branches(self):
        """
        Retrieve all git branches of the repository.

        :return:    branches of the repository.
        :rtype:     list
        """
        if self.git is None:
            return False
        branches = []

        try:
            # Get all remote branches (not only local)
            returnvalue = self.git.ls_remote('--heads').split()

            # Strip data
            for i in range(len(returnvalue)):
                if i % 2 != 0:
                    # Get only branch name (last value)
                    branches.append(returnvalue[i].split("/")[-1])
        except:
            print_warning(
                "Failed to get remote branches, is there a git repo setup and do you have internet?"
            )
            pass

        return branches

    def check_if_update(self):
        """
        Checks git repository for available changes.

        :return:    True if update is available, False if the command failed or no update available.
        :rtype:     bool
        """
        if self.git is None:
            return False
        try:
            # Update local git data
            self.git.fetch()
        except:
            print_warning(
                "Failed to fetch, is there a git repo setup and do you have internet?"
            )
            return False
        # Retrieve git remote <-> local difference status
        status = self.git.status()
        # easy check to see if local is behind
        if status.find('behind') > 0:
            return True
        return False

    def update(self):
        """
        Creates a update file flag and restarts the service.
        """
        if self.git is None:
            return False
        # Create file to let deamon know it has to update before starting the server
        file = open(self.dir + 'update.var', 'w+')

        # restart service
        command = ['/usr/sbin/service', 'opsoro', 'restart']
        #shell=FALSE for sudo to work.
        subprocess.call(command, shell=False)

        python = sys.executable
        os.execl(python, python, *sys.argv)

        # # Reboot system used for user development server run
        # os.system('/sbin/shutdown -r now')

    def load_prefs(self):
        """
        Load preferences into data.
        """
        try:
            with open(get_path("config/preferences.yaml")) as f:
                self.data = yaml.load(f, Loader=Loader)
        except IOError:
            self.data = {}
            print_warning("Could not open config/preferences.yaml")

        print_info("Preferences loaded")

    def get(self, section, item, default):
        """
        Retrieve preference value.

        :param string section:  category in which the item is defined.
        :param string item:     item to retrieve.
        :param default:         default value to return if the value is not available.

        :return:    preference value
        """
        return self.data.get(section, {}).get(item, default)

    def set(self, section, item, value):
        """
        Set preference value.

        :param string section:  category in which the item is defined.
        :param string item:     item to set.
        :param value:           value to set.
        """
        if value is None:
            return
        try:
            self.data[section][item] = value
        except KeyError:
            self.data[section] = {item: value}

    def save_prefs(self):
        """
        Saves preferences to yaml file.
        """
        try:
            with open(get_path("config/preferences.yaml"), "w") as f:
                f.write(
                    yaml.dump(self.data,
                              default_flow_style=False,
                              Dumper=Dumper))
        except IOError:
            print_warning("Could not save config/preferences.yaml")

    def apply_prefs(self,
                    update_audio=False,
                    update_wireless=False,
                    restart_wireless=False,
                    update_dns=False):
        """
        Apply preferences to the system.

        :param bool update_audio:       True if audio settings have changed and needs to update.
        :param bool update_wireless:    True if wireless settings have changed and the wireless interface needs to update.
        :param bool restart_wireless:   True if wireless settings have changed and the wireless interface needs to restart.
        :param bool update_dns:         True if DNS settings have changed and needs to update.
        """
        def change_conf_setting(txt, name, val):
            pattern = "^%s([ \t]*)=([ \t]*).*$" % name
            new = "%s=%s" % (name, val)
            txt, subs = re.subn(pattern, new, txt, flags=re.MULTILINE)
            if subs == 0:
                if txt[-1:] != "\n":
                    txt = txt + "\n"
                txt = txt + new
            return txt

        FNULL = open(os.devnull, "w")

        if update_audio:
            vol = self.get("audio", "master_volume", 66)
            vol = constrain(vol, 0, 100)

            subprocess.Popen(["amixer", "sset", "'Master'",
                              "%d%%" % vol],
                             stdout=FNULL,
                             stderr=subprocess.STDOUT)

        if update_wireless:
            with open("/etc/hostapd/hostapd.conf", "r+") as f:
                lines = f.read()

                ssid = self.get("wireless", "ssid", "OPSORO-bot")
                password = self.get("wireless", "password", "opsoro123")
                channel = self.get("wireless", "channel", 6)
                channel = constrain(int(channel), 1, 11)

                lines = change_conf_setting(lines, "ssid", ssid)
                lines = change_conf_setting(lines, "wpa_passphrase", password)
                lines = change_conf_setting(lines, "channel", channel)

                f.seek(0)
                f.write(lines)
                f.truncate()

            if restart_wireless:
                subprocess.Popen(["service", "hostapd", "restart"],
                                 stdout=FNULL,
                                 stderr=subprocess.STDOUT)

        if update_dns:
            with open("/etc/dnsmasq.d/dnsmasq.opsoro.conf", "r+") as f:
                lines = f.read()

                # redirect = self.get("wireless", "ssid", "OPSORO-bot")
                # password = self.get("wireless", "password", "opsoro123")
                # channel = self.get("wireless", "channel", 6)
                # channel = constrain(int(channel), 1, 11)

                address = "/play.opsoro.be/192.168.42.1"
                dhcp = "interface:wlan0,192.168.42.100,192.168.42.200,infinite"

                lines = change_conf_setting(lines, "address", address)
                lines = change_conf_setting(lines, "dhcp-range", dhcp)

                f.seek(0)
                f.write(lines)
                f.truncate()
                subprocess.Popen(["service", "dnsmasq", "restart"],
                                 stdout=FNULL,
                                 stderr=subprocess.STDOUT)
예제 #16
0
class GitWrapper(object):
    """
    A wrapper for repo.git providing better stdout handling + better exeptions.

    It is preferred to repo.git because it doesn't print to stdout
    in real time. In addition, this wrapper provides better error
    handling (it provides stdout messages inside the exception, too).
    """

    def __init__(self, repo):
        if repo:
            #: :type: git.Repo
            self.repo = repo
            #: :type: git.Git
            self.git = self.repo.git
        else:
            #: :type: git.Git
            self.git = Git()

    def __del__(self):
        # Is the following true?

        # GitPython runs persistent git processes in  the working directory.
        # Therefore, when we use 'git up' in something like a test environment,
        # this might cause troubles because of the open file handlers (like
        # trying to remove the directory right after the test has finished).
        # 'clear_cache' kills the processes...

        if platform.system() == 'Windows':  # pragma: no cover
            pass
            # ... or rather "should kill", because but somehow it recently
            # started to not kill cat_file_header out of the blue (I even
            # tried running old code, but the once working code failed).
            # Thus, we kill it  manually here.
            if self.git.cat_file_header is not None:
                subprocess.call(("TASKKILL /F /T /PID {0} 2>nul 1>nul".format(
                    str(self.git.cat_file_header.proc.pid)
                )), shell=True)
            if self.git.cat_file_all is not None:
                subprocess.call(("TASKKILL /F /T /PID {0} 2>nul 1>nul".format(
                    str(self.git.cat_file_all.proc.pid)
                )), shell=True)

        self.git.clear_cache()

    def _run(self, name, *args, **kwargs):

        """ Run a git command specified by name and args/kwargs. """

        stdout = six.b('')
        cmd = getattr(self.git, name)

        # Ask cmd(...) to return a (status, stdout, stderr) tuple
        kwargs['with_extended_output'] = True

        # Execute command
        try:
            (_, stdout, _) = cmd(*args, **kwargs)
        except GitCommandError as error:
            # Add more meta-information to errors
            message = "'{0}' returned exit status {1}".format(
                ' '.join(str(c) for c in error.command),
                error.status
            )

            raise GitError(message, stderr=error.stderr, stdout=stdout)

        return stdout.strip()

    def __getattr__(self, name):
        return lambda *args, **kwargs: self._run(name, *args, **kwargs)

    ###########################################################################
    # Overwrite some methods and add new ones
    ###########################################################################

    @contextmanager
    def stasher(self):
        """
        A stashing contextmanager.
        """
        # nonlocal for python2
        stashed = [False]
        clean = [False]

        def stash():
            if clean[0] or not self.repo.is_dirty(submodules=False):
                clean[0] = True
                return
            if stashed[0]:
                return

            if self.change_count > 1:
                message = 'stashing {0} changes'
            else:
                message = 'stashing {0} change'
            print(colored(
                message.format(self.change_count),
                'magenta'
            ))
            try:
                self._run('stash')
            except GitError as e:
                raise StashError(stderr=e.stderr, stdout=e.stdout)

            stashed[0] = True

        yield stash

        if stashed[0]:
            print(colored('unstashing', 'magenta'))
            try:
                self._run('stash', 'pop')
            except GitError as e:
                raise UnstashError(stderr=e.stderr, stdout=e.stdout)

    def checkout(self, branch_name):
        """ Checkout a branch by name. """
        try:
            find(
                self.repo.branches, lambda b: b.name == branch_name
            ).checkout()
        except OrigCheckoutError as e:
            raise CheckoutError(branch_name, details=e)

    def rebase(self, target_branch):
        """ Rebase to target branch. """
        current_branch = self.repo.active_branch

        arguments = (
                ([self.config('git-up.rebase.arguments')] or []) +
                [target_branch.name]
        )
        try:
            self._run('rebase', *arguments)
        except GitError as e:
            raise RebaseError(current_branch.name, target_branch.name,
                              **e.__dict__)

    def fetch(self, *args, **kwargs):
        """ Fetch remote commits. """

        # Unlike the other git commands, we want to output `git fetch`'s
        # output in real time. Therefore we use a different implementation
        # from `GitWrapper._run` which buffers all output.
        # In theory this may deadlock if `git fetch` prints more than 8 KB
        # to stderr which is here assumed to not happen in day-to-day use.

        stdout = six.b('')

        # Execute command
        cmd = self.git.fetch(as_process=True, *args, **kwargs)

        # Capture output
        while True:
            output = cmd.stdout.read(1)

            sys.stdout.write(output.decode('utf-8'))
            sys.stdout.flush()

            stdout += output

            # Check for EOF
            if output == six.b(""):
                break

        # Wait for the process to quit
        try:
            cmd.wait()
        except GitCommandError as error:
            # Add more meta-information to errors
            message = "'{0}' returned exit status {1}".format(
                ' '.join(str(c) for c in error.command),
                error.status
            )

            raise GitError(message, stderr=error.stderr, stdout=stdout)

        return stdout.strip()

    def push(self, *args, **kwargs):
        ''' Push commits to remote '''
        stdout = six.b('')

        # Execute command
        cmd = self.git.push(as_process=True, *args, **kwargs)

        # Capture output
        while True:
            output = cmd.stdout.read(1)

            sys.stdout.write(output.decode('utf-8'))
            sys.stdout.flush()

            stdout += output

            # Check for EOF
            if output == six.b(""):
                break

        # Wait for the process to quit
        try:
            cmd.wait()
        except GitCommandError as error:
            # Add more meta-information to errors
            message = "'{0}' returned exit status {1}".format(
                ' '.join(str(c) for c in error.command),
                error.status
            )

            raise GitError(message, stderr=error.stderr, stdout=stdout)

        return stdout.strip()

    def config(self, key):
        """ Return `git config key` output or None. """
        try:
            return self.git.config(key)
        except GitCommandError:
            return None

    @property
    def change_count(self):
        """ The number of changes in the working directory. """
        status = self.git.status(porcelain=True, untracked_files='no').strip()
        if not status:
            return 0
        else:
            return len(status.split('\n'))

    @property
    def version(self):
        """
        Return git's version as a list of numbers.

        The original repo.git.version_info has problems with tome types of
        git version strings.
        """
        return re.search(r'\d+(\.\d+)+', self.git.version()).group(0)

    def is_version_min(self, required_version):
        """ Does git's version match the requirements? """
        return self.version.split('.') >= required_version.split('.')