Exemplo n.º 1
0
class Nightly(object):

    name = None # abstract base class
    _monthlinks = {}
    lastdest = None
    tempdir = None

    @staticmethod
    def _getBuildRegex(bits):
        if mozinfo.os == "win":
            if bits == 64:
                # XXX this should actually throw an error to be consumed by the caller
                print "No builds available for 64 bit Windows (try specifying --bits=32)"
                sys.exit()
            return ".*win32.zip"
        elif mozinfo.os == "linux":
            if bits == 64:
                return ".*linux-x86_64.tar.bz2"
            else:
                return ".*linux-i686.tar.bz2"
        elif mozinfo.os == "mac":
            return ".*mac.*\.dmg"

    def __init__(self, repo_name=None, bits=mozinfo.bits, persist=None):
        self.buildRegex = self._getBuildRegex(bits)
        self.persist = persist
        self.repo_name = repo_name

    ### cleanup functions

    def remove_tempdir(self):
        if self.tempdir:
            rmtree(self.tempdir)
            self.tempdir = None

    def remove_lastdest(self):
        if self.lastdest:
            os.remove(self.lastdest)
            self.lastdest = None

    def cleanup(self):
        self.remove_tempdir()
        if not self.persist:
            self.remove_lastdest()

    __del__ = cleanup

    ### installation functions

    def get_destination(self, url, date):
        repo_name = self.repo_name or self.getRepoName(date)
        dest = os.path.basename(url)
        if self.persist is not None:
            date_str = date.strftime("%Y-%m-%d")
            dest = os.path.join(self.persist, "%s--%s--%s"%(date_str, repo_name, dest))
        return dest

    def download(self, date=datetime.date.today(), dest=None):
        url = self.getBuildUrl(date)
        if url:
            if not dest:
                dest = self.get_destination(url, date)
            if not self.persist:
                self.remove_lastdest()

            self.dest = self.lastdest = dest
            download_url(url, dest)
            return True
        else:
            return False

    def install(self):
        if not self.name:
            raise NotImplementedError("Can't invoke abstract base class")
        self.remove_tempdir()
        self.tempdir = tempfile.mkdtemp()
        self.binary = mozinstall.get_binary(mozinstall.install(src=self.dest, dest=self.tempdir), self.name)
        return True

    def getBuildUrl(self, datestamp):
        if self.appName == 'fennec':
            repo = 'mobile'
        else:
            repo = 'firefox'
        url = "http://ftp.mozilla.org/pub/mozilla.org/" + repo + "/nightly/"
        year = str(datestamp.year)
        month = "%02d" % datestamp.month
        day = "%02d" % datestamp.day
        repo_name = self.repo_name or self.getRepoName(datestamp)
        url += year + "/" + month + "/"

        linkRegex = '^' + year + '-' + month + '-' + day + '-' + '[\d-]+' + repo_name + '/$'
        cachekey = year + '-' + month
        if cachekey in self._monthlinks:
            monthlinks = self._monthlinks[cachekey]
        else:
            monthlinks = urlLinks(url)
            self._monthlinks[cachekey] = monthlinks

        # first parse monthly list to get correct directory
        for dirlink in monthlinks:
            dirhref = dirlink.get("href")
            if re.match(linkRegex, dirhref):
                # now parse the page for the correct build url
                for link in urlLinks(url + dirhref):
                    href = link.get("href")
                    if re.match(self.buildRegex, href):
                        return url + dirhref + href

    ### functions for invoking nightly

    def getAppInfo(self):
        parser = ConfigParser()
        ini_file = os.path.join(os.path.dirname(self.binary), "application.ini")
        parser.read(ini_file)
        try:
            changeset = parser.get('App', 'SourceStamp')
            repo = parser.get('App', 'SourceRepository')
            return (repo, changeset)
        except:
            return None

    def start(self, profile, addons, cmdargs):
        if profile:
            profile = self.profileClass(profile=profile, addons=addons)
        elif len(addons):
            profile = self.profileClass(addons=addons)
        else:
            profile = self.profileClass()

        self.runner = Runner(binary=self.binary, cmdargs=cmdargs, profile=profile)
        self.runner.start()
        return True

    def stop(self):
        self.runner.stop()

    def wait(self):
        self.runner.wait()
Exemplo n.º 2
0
class MozRunnerLauncher(Launcher):
    tempdir = None
    runner = None
    app_name = 'undefined'
    binary = None

    def _install(self, dest):
        self.tempdir = tempfile.mkdtemp()
        try:
            self.binary = mozinstall.get_binary(
                mozinstall.install(src=dest, dest=self.tempdir),
                self.app_name
            )
        except:
            rmtree(self.tempdir)
            raise

    def _start(self, profile=None, addons=(), cmdargs=(), preferences=None):
        profile = self._create_profile(profile=profile, addons=addons,
                                       preferences=preferences)

        LOG.info("Launching %s" % self.binary)
        self.runner = Runner(binary=self.binary,
                             cmdargs=cmdargs,
                             profile=profile)

        def _on_exit():
            # if we are stopping the process do not log anything.
            if not self._stopping:
                # mozprocess (behind mozrunner) fire 'onFinish'
                # a bit early - let's ensure the process is finished.
                # we have to call wait() directly on the subprocess
                # instance of the ProcessHandler, else on windows
                # None is returned...
                # TODO: search that bug and fix that in mozprocess or
                # mozrunner. (likely mozproces)
                try:
                    exitcode = self.runner.process_handler.proc.wait()
                except Exception:
                    print
                    LOG.error(
                        "Error while waiting process, consider filing a bug.",
                        exc_info=True
                    )
                    return
                if exitcode != 0:
                    # first print a blank line, to be sure we don't
                    # write on an already printed line without EOL.
                    print
                    LOG.warning('Process exited with code %s' % exitcode)

        self.runner.process_args = {
            'processOutputLine': [get_default_logger("process").info],
            'onFinish': _on_exit,
        }
        self.runner.start()

    def _wait(self):
        return self.runner.wait()

    def _stop(self):
        self.runner.stop()
        # release the runner since it holds a profile reference
        del self.runner

    def cleanup(self):
        try:
            Launcher.cleanup(self)
        finally:
            # always remove tempdir
            if self.tempdir is not None:
                rmtree(self.tempdir)

    def get_app_info(self):
        return mozversion.get_version(binary=self.binary)
Exemplo n.º 3
0
class MozRunnerLauncher(Launcher):
    tempdir = None
    runner = None
    app_name = 'undefined'
    binary = None

    def _install(self, dest):
        self.tempdir = safe_mkdtemp()
        try:
            self.binary = mozinstall.get_binary(
                mozinstall.install(src=dest, dest=self.tempdir), self.app_name)
        except Exception:
            rmtree(self.tempdir)
            raise

    def _disableUpdateByPolicy(self):
        updatePolicy = {'policies': {'DisableAppUpdate': True}}
        installdir = os.path.dirname(self.binary)
        if mozinfo.os == 'mac':
            # macOS has the following filestructure:
            # binary at:
            #     PackageName.app/Contents/MacOS/firefox
            # we need policies.json in:
            #     PackageName.app/Contents/Resources/distribution
            installdir = os.path.normpath(
                os.path.join(installdir, '..', 'Resources'))
        os.mkdir(os.path.join(installdir, 'distribution'))
        policyFile = os.path.join(installdir, 'distribution', 'policies.json')
        with open(policyFile, 'w') as fp:
            json.dump(updatePolicy, fp, indent=2)

    def _start(self,
               profile=None,
               addons=(),
               cmdargs=(),
               preferences=None,
               adb_profile_dir=None):
        profile = self._create_profile(profile=profile,
                                       addons=addons,
                                       preferences=preferences)

        LOG.info("Launching %s" % self.binary)
        self.runner = Runner(binary=self.binary,
                             cmdargs=cmdargs,
                             profile=profile)

        def _on_exit():
            # if we are stopping the process do not log anything.
            if not self._stopping:
                # mozprocess (behind mozrunner) fire 'onFinish'
                # a bit early - let's ensure the process is finished.
                # we have to call wait() directly on the subprocess
                # instance of the ProcessHandler, else on windows
                # None is returned...
                # TODO: search that bug and fix that in mozprocess or
                # mozrunner. (likely mozproces)
                try:
                    exitcode = self.runner.process_handler.proc.wait()
                except Exception:
                    print()
                    LOG.error(
                        "Error while waiting process, consider filing a bug.",
                        exc_info=True)
                    return
                if exitcode != 0:
                    # first print a blank line, to be sure we don't
                    # write on an already printed line without EOL.
                    print()
                    LOG.warning('Process exited with code %s' % exitcode)

        self.runner.process_args = {
            'processOutputLine': [get_default_logger("process").info],
            'onFinish': _on_exit,
        }
        self.runner.start()

    def _wait(self):
        return self.runner.wait()

    def _stop(self):
        if mozinfo.os == "win" and self.app_name == 'firefox':
            # for some reason, stopping the runner may hang on windows. For
            # example restart the browser in safe mode, it will hang for a
            # couple of minutes. As a workaround, we call that in a thread and
            # wait a bit for the completion. If the stop() can't complete we
            # forgot about that thread.
            thread = Thread(target=self.runner.stop)
            thread.daemon = True
            thread.start()
            thread.join(0.7)
        else:
            self.runner.stop()
        # release the runner since it holds a profile reference
        del self.runner

    def cleanup(self):
        try:
            Launcher.cleanup(self)
        finally:
            # always remove tempdir
            if self.tempdir is not None:
                rmtree(self.tempdir)

    def get_app_info(self):
        return safe_get_version(binary=self.binary)
Exemplo n.º 4
0
class MozRunnerLauncher(Launcher):
    tempdir = None
    runner = None
    app_name = 'undefined'
    binary = None

    def _install(self, dest):
        self.tempdir = tempfile.mkdtemp()
        try:
            self.binary = mozinstall.get_binary(
                mozinstall.install(src=dest, dest=self.tempdir),
                self.app_name
            )
        except Exception:
            rmtree(self.tempdir)
            raise

    def _start(self, profile=None, addons=(), cmdargs=(), preferences=None):
        profile = self._create_profile(profile=profile, addons=addons,
                                       preferences=preferences)

        LOG.info("Launching %s" % self.binary)
        self.runner = Runner(binary=self.binary,
                             cmdargs=cmdargs,
                             profile=profile)

        def _on_exit():
            # if we are stopping the process do not log anything.
            if not self._stopping:
                # mozprocess (behind mozrunner) fire 'onFinish'
                # a bit early - let's ensure the process is finished.
                # we have to call wait() directly on the subprocess
                # instance of the ProcessHandler, else on windows
                # None is returned...
                # TODO: search that bug and fix that in mozprocess or
                # mozrunner. (likely mozproces)
                try:
                    exitcode = self.runner.process_handler.proc.wait()
                except Exception:
                    print
                    LOG.error(
                        "Error while waiting process, consider filing a bug.",
                        exc_info=True
                    )
                    return
                if exitcode != 0:
                    # first print a blank line, to be sure we don't
                    # write on an already printed line without EOL.
                    print
                    LOG.warning('Process exited with code %s' % exitcode)

        self.runner.process_args = {
            'processOutputLine': [get_default_logger("process").info],
            'onFinish': _on_exit,
        }
        self.runner.start()

    def _wait(self):
        return self.runner.wait()

    def _stop(self):
        if mozinfo.os == "win" and self.app_name == 'firefox':
            # for some reason, stopping the runner may hang on windows. For
            # example restart the browser in safe mode, it will hang for a
            # couple of minutes. As a workaround, we call that in a thread and
            # wait a bit for the completion. If the stop() can't complete we
            # forgot about that thread.
            thread = Thread(target=self.runner.stop)
            thread.daemon = True
            thread.start()
            thread.join(0.7)
        else:
            self.runner.stop()
        # release the runner since it holds a profile reference
        del self.runner

    def cleanup(self):
        try:
            Launcher.cleanup(self)
        finally:
            # always remove tempdir
            if self.tempdir is not None:
                rmtree(self.tempdir)

    def get_app_info(self):
        return safe_get_version(binary=self.binary)
Exemplo n.º 5
0
class Nightly(object):
    def __init__(self, repo_name=None):
        platform=get_platform()
        if platform['name'] == "Windows":
            if platform['bits'] == '64':
                print "No nightly builds available for 64 bit Windows"
                sys.exit()
            self.buildRegex = ".*win32.zip"
            self.processName = self.name + ".exe"
            self.binary = "moznightlyapp/" + self.name + "/" + self.name + ".exe"
        elif platform['name'] == "Linux":
            self.processName = self.name + "-bin"
            self.binary = "moznightlyapp/" + self.name + "/" + self.name
            if platform['bits'] == '64':
                self.buildRegex = ".*linux-x86_64.tar.bz2"
            else:
                self.buildRegex = ".*linux-i686.tar.bz2"
        elif platform['name'] == "Mac":
            self.buildRegex = ".*mac.*\.dmg"
            self.processName = self.name + "-bin"
            self.binary = "moznightlyapp/Mozilla.app/Contents/MacOS/" + self.name + "-bin"
        self.repo_name = repo_name
        self._monthlinks = {}
        self.lastdest = None

    def cleanup(self):
        rmtree('moznightlyapp')
        if self.lastdest:
            os.remove(self.lastdest)

    __del__ = cleanup

    def download(self, date=datetime.date.today(), dest=None):
        url = self.getBuildUrl(date)
        if url:
            if not dest:
                dest = os.path.basename(url)
            print "Downloading nightly from %s" % date
            if self.lastdest:
                os.remove(self.lastdest)
            download_url(url, dest)
            self.dest = self.lastdest = dest
            return True
        else:
            return False

    def install(self):
        rmtree("moznightlyapp")
        subprocess._cleanup = lambda : None # mikeal's fix for subprocess threading bug
        MozInstaller(src=self.dest, dest="moznightlyapp", dest_app="Mozilla.app")
        return True

    @staticmethod
    def urlLinks(url):
        res = [] # do not return a generator but an array, so we can store it for later use

        h = httplib2.Http();
        resp, content = h.request(url, "GET")
        if resp.status != 200:
            return res

        soup = BeautifulSoup(content)
        for link in soup.findAll('a'):
            res.append(link)
        return res

    def getBuildUrl(self, date):
        url = "http://ftp.mozilla.org/pub/mozilla.org/" + self.appName + "/nightly/"
        year = str(date.year)
        month = "%02d" % date.month
        day = "%02d" % date.day
        repo_name = self.repo_name or self.getRepoName(date)
        url += year + "/" + month + "/"

        linkRegex = '^' + year + '-' + month + '-' + day + '-' + '[\d-]+' + repo_name + '/$'
        cachekey = year + '-' + month
        if cachekey in self._monthlinks:
            monthlinks = self._monthlinks[cachekey]
        else:
            monthlinks = self.urlLinks(url)
            self._monthlinks[cachekey] = monthlinks

        # first parse monthly list to get correct directory
        for dirlink in monthlinks:
            dirhref = dirlink.get("href")
            if re.match(linkRegex, dirhref):
                # now parse the page for the correct build url
                for link in self.urlLinks(url + dirhref):
                    href = link.get("href")
                    if re.match(self.buildRegex, href):
                        return url + dirhref + href

        return False

    def getAppInfo(self):
        parser = ConfigParser()
        ini_file = os.path.join(os.path.dirname(self.binary), "application.ini")
        parser.read(ini_file)
        try:
            changeset = parser.get('App', 'SourceStamp')
            repo = parser.get('App', 'SourceRepository')
            return (repo, changeset)
        except:
            return ("", "")

    def start(self, profile, addons, cmdargs):
        if profile:
            profile = self.profileClass(profile=profile, addons=addons)
        elif len(addons):
            profile = self.profileClass(addons=addons)
        else:
            profile = self.profileClass()

        self.runner = Runner(binary=self.binary, cmdargs=cmdargs, profile=profile)
        self.runner.names = [self.processName]
        self.runner.start()
        return True

    def stop(self):
        self.runner.stop()

    def wait(self):
        self.runner.wait()
Exemplo n.º 6
0
class Nightly(object):

    name = None # abstract base class

    def __init__(self, repo_name=None, bits=mozinfo.bits, persist=None):
        if mozinfo.os == "win":
            if bits == 64:
                # XXX this should actually throw an error to be consumed by the caller
                print "No nightly builds available for 64 bit Windows"
                sys.exit()
            self.buildRegex = ".*win32.zip"
        elif mozinfo.os == "linux":
            if bits == 64:
                self.buildRegex = ".*linux-x86_64.tar.bz2"
            else:
                self.buildRegex = ".*linux-i686.tar.bz2"
        elif mozinfo.os == "mac":
            self.buildRegex = ".*mac.*\.dmg"
        self.persist = persist
        self.repo_name = repo_name
        self._monthlinks = {}
        self.lastdest = None
        self.tempdir = None

    ### cleanup functions

    def remove_tempdir(self):
        if self.tempdir:
            rmtree(self.tempdir)
            self.tempdir = None

    def remove_lastdest(self):
        if self.lastdest:
            os.remove(self.lastdest)
            self.lastdest = None

    def cleanup(self):
        self.remove_tempdir()
        if not self.persist:
            self.remove_lastdest()

    __del__ = cleanup

    ### installation functions

    def get_destination(self, url, date):
        repo_name = self.repo_name or self.getRepoName(date)
        dest = os.path.basename(url)
        if self.persist is not None:
            date_str = date.strftime("%Y-%m-%d")
            dest = os.path.join(self.persist, "%s--%s--%s"%(date_str, repo_name, dest))
        return dest

    def download(self, date=datetime.date.today(), dest=None):
        url = self.getBuildUrl(date)
        if url:
            if not dest:
                dest = self.get_destination(url, date)
            if not self.persist:
                self.remove_lastdest()

            self.dest = self.lastdest = dest
            download_url(url, dest)
            return True
        else:
            return False

    def install(self):
        if not self.name:
            raise NotImplementedError("Can't invoke abstract base class")
        self.remove_tempdir()
        self.tempdir = tempfile.mkdtemp()
        self.binary = mozinstall.get_binary(mozinstall.install(src=self.dest, dest=self.tempdir), self.name)
        return True

    def getBuildUrl(self, date):
        url = "http://ftp.mozilla.org/pub/mozilla.org/" + self.appName + "/nightly/"
        year = str(date.year)
        month = "%02d" % date.month
        day = "%02d" % date.day
        repo_name = self.repo_name or self.getRepoName(date)
        url += year + "/" + month + "/"

        linkRegex = '^' + year + '-' + month + '-' + day + '-' + '[\d-]+' + repo_name + '/$'
        cachekey = year + '-' + month
        if cachekey in self._monthlinks:
            monthlinks = self._monthlinks[cachekey]
        else:
            monthlinks = urlLinks(url)
            self._monthlinks[cachekey] = monthlinks

        # first parse monthly list to get correct directory
        for dirlink in monthlinks:
            dirhref = dirlink.get("href")
            if re.match(linkRegex, dirhref):
                # now parse the page for the correct build url
                for link in urlLinks(url + dirhref):
                    href = link.get("href")
                    if re.match(self.buildRegex, href):
                        return url + dirhref + href

        return False


    ### functions for invoking nightly

    def getAppInfo(self):
        parser = ConfigParser()
        ini_file = os.path.join(os.path.dirname(self.binary), "application.ini")
        parser.read(ini_file)
        try:
            changeset = parser.get('App', 'SourceStamp')
            repo = parser.get('App', 'SourceRepository')
            return (repo, changeset)
        except:
            return ("", "")

    def start(self, profile, addons, cmdargs):
        if profile:
            profile = self.profileClass(profile=profile, addons=addons)
        elif len(addons):
            profile = self.profileClass(addons=addons)
        else:
            profile = self.profileClass()

        self.runner = Runner(binary=self.binary, cmdargs=cmdargs, profile=profile)
        self.runner.start()
        return True

    def stop(self):
        self.runner.stop()

    def wait(self):
        self.runner.wait()
Exemplo n.º 7
0
class Nightly(object):
    def __init__(self, repo_name=None):
        platform = get_platform()
        if platform['name'] == "Windows":
            if platform['bits'] == '64':
                print "No nightly builds available for 64 bit Windows"
                sys.exit()
            self.buildRegex = ".*win32.zip"
            self.processName = self.name + ".exe"
            self.binary = "moznightlyapp/" + self.name + "/" + self.name + ".exe"
        elif platform['name'] == "Linux":
            self.processName = self.name + "-bin"
            self.binary = "moznightlyapp/" + self.name + "/" + self.name
            if platform['bits'] == '64':
                self.buildRegex = ".*linux-x86_64.tar.bz2"
            else:
                self.buildRegex = ".*linux-i686.tar.bz2"
        elif platform['name'] == "Mac":
            self.buildRegex = ".*mac.*\.dmg"
            self.processName = self.name + "-bin"
            self.binary = "moznightlyapp/Mozilla.app/Contents/MacOS/" + self.name + "-bin"
        self.repo_name = repo_name
        self._monthlinks = {}
        self.lastdest = None

    def cleanup(self):
        rmtree('moznightlyapp')
        if self.lastdest:
            os.remove(self.lastdest)

    __del__ = cleanup

    def download(self, date=datetime.date.today(), dest=None):
        url = self.getBuildUrl(date)
        if url:
            if not dest:
                dest = os.path.basename(url)
            print "Downloading nightly from %s" % date
            if self.lastdest:
                os.remove(self.lastdest)
            download_url(url, dest)
            self.dest = self.lastdest = dest
            return True
        else:
            return False

    def install(self):
        rmtree("moznightlyapp")
        subprocess._cleanup = lambda: None  # mikeal's fix for subprocess threading bug
        MozInstaller(src=self.dest,
                     dest="moznightlyapp",
                     dest_app="Mozilla.app")
        return True

    @staticmethod
    def urlLinks(url):
        res = [
        ]  # do not return a generator but an array, so we can store it for later use

        h = httplib2.Http()
        resp, content = h.request(url, "GET")
        if resp.status != 200:
            return res

        soup = BeautifulSoup(content)
        for link in soup.findAll('a'):
            res.append(link)
        return res

    def getBuildUrl(self, date):
        url = "http://ftp.mozilla.org/pub/mozilla.org/" + self.appName + "/nightly/"
        year = str(date.year)
        month = "%02d" % date.month
        day = "%02d" % date.day
        repo_name = self.repo_name or self.getRepoName(date)
        url += year + "/" + month + "/"

        linkRegex = '^' + year + '-' + month + '-' + day + '-' + '[\d-]+' + repo_name + '/$'
        cachekey = year + '-' + month
        if cachekey in self._monthlinks:
            monthlinks = self._monthlinks[cachekey]
        else:
            monthlinks = self.urlLinks(url)
            self._monthlinks[cachekey] = monthlinks

        # first parse monthly list to get correct directory
        for dirlink in monthlinks:
            dirhref = dirlink.get("href")
            if re.match(linkRegex, dirhref):
                # now parse the page for the correct build url
                for link in self.urlLinks(url + dirhref):
                    href = link.get("href")
                    if re.match(self.buildRegex, href):
                        return url + dirhref + href

        return False

    def getAppInfo(self):
        parser = ConfigParser()
        ini_file = os.path.join(os.path.dirname(self.binary),
                                "application.ini")
        parser.read(ini_file)
        try:
            changeset = parser.get('App', 'SourceStamp')
            repo = parser.get('App', 'SourceRepository')
            return (repo, changeset)
        except:
            return ("", "")

    def start(self, profile, addons, cmdargs):
        if profile:
            profile = self.profileClass(profile=profile, addons=addons)
        elif len(addons):
            profile = self.profileClass(addons=addons)
        else:
            profile = self.profileClass()

        self.runner = Runner(binary=self.binary,
                             cmdargs=cmdargs,
                             profile=profile)
        self.runner.names = [self.processName]
        self.runner.start()
        return True

    def stop(self):
        self.runner.stop()

    def wait(self):
        self.runner.wait()
Exemplo n.º 8
0
class MozRunnerLauncher(Launcher):
    tempdir = None
    runner = None
    app_name = 'undefined'
    binary = None

    def _install(self, dest):
        self.tempdir = safe_mkdtemp()
        try:
            self.binary = mozinstall.get_binary(
                mozinstall.install(src=dest, dest=self.tempdir),
                self.app_name
            )
        except Exception:
            rmtree(self.tempdir)
            raise

    def _disableUpdateByPolicy(self):
        updatePolicy = {
            'policies': {
                'DisableAppUpdate': True
            }
        }
        installdir = os.path.dirname(self.binary)
        if mozinfo.os == 'mac':
            # macOS has the following filestructure:
            # binary at:
            #     PackageName.app/Contents/MacOS/firefox
            # we need policies.json in:
            #     PackageName.app/Contents/Resources/distribution
            installdir = os.path.normpath(
                os.path.join(installdir, '..', 'Resources')
            )
        os.mkdir(os.path.join(installdir, 'distribution'))
        policyFile = os.path.join(
            installdir, 'distribution', 'policies.json'
        )
        with open(policyFile, 'w') as fp:
            json.dump(updatePolicy, fp, indent=2)

    def _start(self, profile=None, addons=(), cmdargs=(), preferences=None,
               adb_profile_dir=None):
        profile = self._create_profile(profile=profile, addons=addons,
                                       preferences=preferences)

        LOG.info("Launching %s" % self.binary)
        self.runner = Runner(binary=self.binary,
                             cmdargs=cmdargs,
                             profile=profile)

        def _on_exit():
            # if we are stopping the process do not log anything.
            if not self._stopping:
                # mozprocess (behind mozrunner) fire 'onFinish'
                # a bit early - let's ensure the process is finished.
                # we have to call wait() directly on the subprocess
                # instance of the ProcessHandler, else on windows
                # None is returned...
                # TODO: search that bug and fix that in mozprocess or
                # mozrunner. (likely mozproces)
                try:
                    exitcode = self.runner.process_handler.proc.wait()
                except Exception:
                    print
                    LOG.error(
                        "Error while waiting process, consider filing a bug.",
                        exc_info=True
                    )
                    return
                if exitcode != 0:
                    # first print a blank line, to be sure we don't
                    # write on an already printed line without EOL.
                    print
                    LOG.warning('Process exited with code %s' % exitcode)

        self.runner.process_args = {
            'processOutputLine': [get_default_logger("process").info],
            'onFinish': _on_exit,
        }
        self.runner.start()

    def _wait(self):
        return self.runner.wait()

    def _stop(self):
        if mozinfo.os == "win" and self.app_name == 'firefox':
            # for some reason, stopping the runner may hang on windows. For
            # example restart the browser in safe mode, it will hang for a
            # couple of minutes. As a workaround, we call that in a thread and
            # wait a bit for the completion. If the stop() can't complete we
            # forgot about that thread.
            thread = Thread(target=self.runner.stop)
            thread.daemon = True
            thread.start()
            thread.join(0.7)
        else:
            self.runner.stop()
        # release the runner since it holds a profile reference
        del self.runner

    def cleanup(self):
        try:
            Launcher.cleanup(self)
        finally:
            # always remove tempdir
            if self.tempdir is not None:
                rmtree(self.tempdir)

    def get_app_info(self):
        return safe_get_version(binary=self.binary)
Exemplo n.º 9
0
class Nightly(object):

    name = None  # abstract base class
    _monthlinks = {}
    lastdest = None
    tempdir = None
    app_name = None
    profile_class = Profile
    build_base_repo_name = "firefox"

    @staticmethod
    def _get_os_regex_suffix(bits, with_ext=True):
        if mozinfo.os == "win":
            if bits == 64:
                suffix, ext = ".*win64-x86_64", ".zip"
            else:
                suffix, ext = ".*win32", ".zip"
        elif mozinfo.os == "linux":
            if bits == 64:
                suffix, ext = ".*linux-x86_64", ".tar.bz2"
            else:
                suffix, ext = ".*linux-i686", ".tar.bz2"
        elif mozinfo.os == "mac":
            suffix, ext = r".*mac.*", "\.dmg"

        if with_ext:
            return '%s%s' % (suffix, ext)
        else:
            return suffix

    @staticmethod
    def _get_build_regex(name, bits, with_ext=True):
        name_prefix = name if ".*%s" % name is not None else ''
        suffix = Nightly._get_os_regex_suffix(bits, with_ext)
        return "%s%s" % (name_prefix, suffix)

    def __init__(self, inbound_branch=None, bits=mozinfo.bits, persist=None):
        self.inbound_branch = inbound_branch
        self.bits = bits
        self.persist = persist
        self.build_regex = self._get_build_regex(self.name, bits) + "$"
        self.build_info_regex = \
            self._get_build_regex(self.name, bits, with_ext=False) + "\.txt$"

    def get_inbound_branch(self, date):
        raise NotImplementedError

    # cleanup functions

    def remove_tempdir(self):
        if self.tempdir:
            rmtree(self.tempdir)
            self.tempdir = None

    def remove_lastdest(self):
        if self.lastdest:
            os.remove(self.lastdest)
            self.lastdest = None

    def cleanup(self):
        self.remove_tempdir()
        if not self.persist:
            self.remove_lastdest()

    __del__ = cleanup

    # installation functions

    def get_destination(self, url, date):
        inbound_branch = self.get_inbound_branch(date)
        dest = os.path.basename(url)
        if self.persist is not None:
            if hasattr(date, "strftime"):
                date_str = date.strftime("%Y-%m-%d")
            else:
                date_str = date  # Might be just a number with inbound
            dest = os.path.join(self.persist,
                                "%s--%s--%s" % (date_str, inbound_branch, dest))
        return dest

    def download(self, date=datetime.date.today(), dest=None):
        url = self.get_build_url(date)
        if url:
            if not dest:
                dest = self.get_destination(url, date)
            if not self.persist:
                self.remove_lastdest()

            if os.path.exists(dest):
                print "Using local file: %s" % dest
            else:
                download_url(url, dest)
            self.dest = self.lastdest = dest
            return True
        else:
            return False

    def install(self):
        if not self.name:
            raise NotImplementedError("Can't invoke abstract base class")
        self.remove_tempdir()
        self.tempdir = tempfile.mkdtemp()
        self.binary = mozinstall.get_binary(
            mozinstall.install(src=self.dest, dest=self.tempdir),
            self.name)
        return True

    def get_build_info(self, date):
        url = self._get_build_url(date, self.build_info_regex, 'builds info')
        if url is not None:
            print "Getting %s" % url
            response = requests.get(url)
            if response.status_code == 200:
                for line in response.text.splitlines():
                    if '/rev/' in line:
                        # returns [repository, changeset]
                        return line.split('/rev/')

    def get_build_url(self, datestamp):
        return self._get_build_url(datestamp, self.build_regex, 'builds')

    def _get_build_url(self, datestamp, regex, what):
        url = "http://ftp.mozilla.org/pub/mozilla.org/" + \
            self.build_base_repo_name + "/nightly/"
        year = str(datestamp.year)
        month = "%02d" % datestamp.month
        day = "%02d" % datestamp.day
        inbound_branch = self.get_inbound_branch(datestamp)
        url += year + "/" + month + "/"

        link_regex = '^' + year + '-' + month + '-' + day + '-' \
                     + r'[\d-]+' + inbound_branch + '/$'
        cachekey = year + '-' + month
        if cachekey in self._monthlinks:
            monthlinks = self._monthlinks[cachekey]
        else:
            monthlinks = url_links(url)
            self._monthlinks[cachekey] = monthlinks

        # first parse monthly list to get correct directory
        matches = []
        for dirlink in monthlinks:
            if re.match(link_regex, dirlink):
                # now parse the page for the correct build url
                for link in url_links(url + dirlink, regex=regex):
                    matches.append(url + dirlink + link)
        if not matches:
            print "Tried to get %s from %s that match '%s' but didn't find any." % \
                  (what, url, self.build_regex)
            return None
        else:
            return sorted(matches)[-1] # the most recent build url

    # functions for invoking nightly

    def get_app_info(self):
        return mozversion.get_version(binary=self.binary)

    def start(self, profile, addons, cmdargs):
        if profile:
            profile = self.profile_class(profile=profile, addons=addons)
        elif len(addons):
            profile = self.profile_class(addons=addons)
        else:
            profile = self.profile_class()

        self.runner = Runner(binary=self.binary, cmdargs=cmdargs,
                             profile=profile)
        self.runner.start()
        return True

    def stop(self):
        self.runner.stop()

    def wait(self):
        self.runner.wait()
Exemplo n.º 10
0
class Nightly(object):

    name = None  # abstract base class
    _monthlinks = {}
    lastdest = None
    tempdir = None
    app_name = None
    profile_class = Profile
    build_base_repo_name = "firefox"

    @staticmethod
    def _get_os_regex_suffix(bits, with_ext=True):
        if mozinfo.os == "win":
            if bits == 64:
                raise errors.Win64NoAvailableBuildError()
            suffix, ext = ".*win32", ".zip"
        elif mozinfo.os == "linux":
            if bits == 64:
                suffix, ext = ".*linux-x86_64", ".tar.bz2"
            else:
                suffix, ext = ".*linux-i686", ".tar.bz2"
        elif mozinfo.os == "mac":
            suffix, ext = r".*mac.*", "\.dmg"

        if with_ext:
            return '%s%s' % (suffix, ext)
        else:
            return suffix

    @staticmethod
    def _get_build_regex(name, bits, with_ext=True):
        name_prefix = name if ".*%s" % name is not None else ''
        suffix = Nightly._get_os_regex_suffix(bits, with_ext)
        return "%s%s" % (name_prefix, suffix)

    def __init__(self, inbound_branch=None, bits=mozinfo.bits, persist=None):
        self.inbound_branch = inbound_branch
        self.bits = bits
        self.persist = persist
        self.build_regex = self._get_build_regex(self.name, bits) + "$"
        self.build_info_regex = \
            self._get_build_regex(self.name, bits, with_ext=False) + "\.txt$"

    def get_inbound_branch(self, date):
        raise NotImplementedError

    # cleanup functions

    def remove_tempdir(self):
        if self.tempdir:
            rmtree(self.tempdir)
            self.tempdir = None

    def remove_lastdest(self):
        if self.lastdest:
            os.remove(self.lastdest)
            self.lastdest = None

    def cleanup(self):
        self.remove_tempdir()
        if not self.persist:
            self.remove_lastdest()

    __del__ = cleanup

    # installation functions

    def get_destination(self, url, date):
        inbound_branch = self.get_inbound_branch(date)
        dest = os.path.basename(url)
        if self.persist is not None:
            if hasattr(date, "strftime"):
                date_str = date.strftime("%Y-%m-%d")
            else:
                date_str = date  # Might be just a number with inbound
            dest = os.path.join(
                self.persist, "%s--%s--%s" % (date_str, inbound_branch, dest))
        return dest

    def download(self, date=datetime.date.today(), dest=None):
        url = self.get_build_url(date)
        if url:
            if not dest:
                dest = self.get_destination(url, date)
            if not self.persist:
                self.remove_lastdest()

            download_url(url, dest)
            self.dest = self.lastdest = dest
            return True
        else:
            return False

    def install(self):
        if not self.name:
            raise NotImplementedError("Can't invoke abstract base class")
        self.remove_tempdir()
        self.tempdir = tempfile.mkdtemp()
        self.binary = mozinstall.get_binary(
            mozinstall.install(src=self.dest, dest=self.tempdir), self.name)
        return True

    def get_build_info(self, date):
        url = self._get_build_url(date, self.build_info_regex, 'builds info')
        if url is not None:
            print "Getting %s" % url
            response = requests.get(url)
            if response.status_code == 200:
                for line in response.text.splitlines():
                    if '/rev/' in line:
                        # returns [repository, changeset]
                        return line.split('/rev/')

    def get_build_url(self, datestamp):
        return self._get_build_url(datestamp, self.build_regex, 'builds')

    def _get_build_url(self, datestamp, regex, what):
        url = "http://ftp.mozilla.org/pub/mozilla.org/" + \
            self.build_base_repo_name + "/nightly/"
        year = str(datestamp.year)
        month = "%02d" % datestamp.month
        day = "%02d" % datestamp.day
        inbound_branch = self.get_inbound_branch(datestamp)
        url += year + "/" + month + "/"

        link_regex = '^' + year + '-' + month + '-' + day + '-' \
                     + r'[\d-]+' + inbound_branch + '/$'
        cachekey = year + '-' + month
        if cachekey in self._monthlinks:
            monthlinks = self._monthlinks[cachekey]
        else:
            monthlinks = url_links(url)
            self._monthlinks[cachekey] = monthlinks

        # first parse monthly list to get correct directory
        matches = []
        for dirlink in monthlinks:
            if re.match(link_regex, dirlink):
                # now parse the page for the correct build url
                for link in url_links(url + dirlink, regex=regex):
                    matches.append(url + dirlink + link)
        if not matches:
            print "Tried to get %s from %s that match '%s' but didn't find any." % \
                  (what, url, self.build_regex)
            return None
        else:
            return sorted(matches)[-1]  # the most recent build url

    # functions for invoking nightly

    def get_app_info(self):
        return mozversion.get_version(binary=self.binary)

    def start(self, profile, addons, cmdargs):
        if profile:
            profile = self.profile_class(profile=profile, addons=addons)
        elif len(addons):
            profile = self.profile_class(addons=addons)
        else:
            profile = self.profile_class()

        self.runner = Runner(binary=self.binary,
                             cmdargs=cmdargs,
                             profile=profile)
        self.runner.start()
        return True

    def stop(self):
        self.runner.stop()

    def wait(self):
        self.runner.wait()