Exemple #1
0
def devices():
    p = FDroidPopen([config['adb'], "devices"])
    if p.returncode != 0:
        raise FDroidException("An error occured when finding devices: %s" %
                              p.output)
    lines = p.output.splitlines()
    if lines[0].startswith('* daemon not running'):
        lines = lines[2:]
    if len(lines) < 3:
        return []
    lines = lines[1:-1]
    return [l.split()[0] for l in lines]
def check_http(app):

    try:

        if 'Update Check Data' not in app:
            raise FDroidException('Missing Update Check Data')

        urlcode, codeex, urlver, verex = app['Update Check Data'].split('|')

        vercode = "99999999"
        if len(urlcode) > 0:
            logging.debug("...requesting {0}".format(urlcode))
            req = urllib2.Request(urlcode, None)
            resp = urllib2.urlopen(req, None, 20)
            page = resp.read()

            m = re.search(codeex, page)
            if not m:
                raise FDroidException("No RE match for version code")
            vercode = m.group(1)

        version = "??"
        if len(urlver) > 0:
            if urlver != '.':
                logging.debug("...requesting {0}".format(urlver))
                req = urllib2.Request(urlver, None)
                resp = urllib2.urlopen(req, None, 20)
                page = resp.read()

            m = re.search(verex, page)
            if not m:
                raise FDroidException("No RE match for version")
            version = m.group(1)

        return (version, vercode)

    except FDroidException:
        msg = "Could not complete http check for app {0} due to unknown error: {1}".format(
            app['id'], traceback.format_exc())
        return (None, msg)
Exemple #3
0
def main():

    global options, config

    options, args = parse_commandline()
    if not args and not options.all:
        raise OptionError(
            "If you really want to build all the apps, use --all", "all")

    config = common.read_config(options)

    if config['build_server_always']:
        options.server = True
    if options.resetserver and not options.server:
        raise OptionError(
            "Using --resetserver without --server makes no sense",
            "resetserver")

    log_dir = 'logs'
    if not os.path.isdir(log_dir):
        logging.info("Creating log directory")
        os.makedirs(log_dir)

    tmp_dir = 'tmp'
    if not os.path.isdir(tmp_dir):
        logging.info("Creating temporary directory")
        os.makedirs(tmp_dir)

    if options.test:
        output_dir = tmp_dir
    else:
        output_dir = 'unsigned'
        if not os.path.isdir(output_dir):
            logging.info("Creating output directory")
            os.makedirs(output_dir)

    if config['archive_older'] != 0:
        also_check_dir = 'archive'
    else:
        also_check_dir = None

    repo_dir = 'repo'

    build_dir = 'build'
    if not os.path.isdir(build_dir):
        logging.info("Creating build directory")
        os.makedirs(build_dir)
    srclib_dir = os.path.join(build_dir, 'srclib')
    extlib_dir = os.path.join(build_dir, 'extlib')

    # Read all app and srclib metadata
    allapps = metadata.read_metadata(xref=not options.onserver)

    apps = common.read_app_args(args, allapps, True)
    for appid, app in apps.items():
        if (app['Disabled'] and not options.force
            ) or not app['Repo Type'] or not app['builds']:
            del apps[appid]

    if not apps:
        raise FDroidException("No apps to process.")

    if options.latest:
        for app in apps.itervalues():
            for build in reversed(app['builds']):
                if build['disable'] and not options.force:
                    continue
                app['builds'] = [build]
                break

    if options.wiki:
        import mwclient
        site = mwclient.Site((config['wiki_protocol'], config['wiki_server']),
                             path=config['wiki_path'])
        site.login(config['wiki_user'], config['wiki_password'])

    # Build applications...
    failed_apps = {}
    build_succeeded = []
    for appid, app in apps.iteritems():

        first = True

        for thisbuild in app['builds']:
            wikilog = None
            try:

                # For the first build of a particular app, we need to set up
                # the source repo. We can reuse it on subsequent builds, if
                # there are any.
                if first:
                    if app['Repo Type'] == 'srclib':
                        build_dir = os.path.join('build', 'srclib',
                                                 app['Repo'])
                    else:
                        build_dir = os.path.join('build', appid)

                    # Set up vcs interface and make sure we have the latest code...
                    logging.debug("Getting {0} vcs interface for {1}".format(
                        app['Repo Type'], app['Repo']))
                    vcs = common.getvcs(app['Repo Type'], app['Repo'],
                                        build_dir)

                    first = False

                logging.debug("Checking " + thisbuild['version'])
                if trybuild(app, thisbuild, build_dir, output_dir,
                            also_check_dir, srclib_dir, extlib_dir, tmp_dir,
                            repo_dir, vcs, options.test, options.server,
                            options.force, options.onserver):
                    build_succeeded.append(app)
                    wikilog = "Build succeeded"
            except BuildException as be:
                logfile = open(os.path.join(log_dir, appid + '.log'), 'a+')
                logfile.write(str(be))
                logfile.close()
                print("Could not build app %s due to BuildException: %s" %
                      (appid, be))
                if options.stop:
                    sys.exit(1)
                failed_apps[appid] = be
                wikilog = be.get_wikitext()
            except VCSException as vcse:
                reason = str(vcse).split(
                    '\n', 1)[0] if options.verbose else str(vcse)
                logging.error("VCS error while building app %s: %s" %
                              (appid, reason))
                if options.stop:
                    sys.exit(1)
                failed_apps[appid] = vcse
                wikilog = str(vcse)
            except Exception as e:
                logging.error(
                    "Could not build app %s due to unknown error: %s" %
                    (appid, traceback.format_exc()))
                if options.stop:
                    sys.exit(1)
                failed_apps[appid] = e
                wikilog = str(e)

            if options.wiki and wikilog:
                try:
                    # Write a page with the last build log for this version code
                    lastbuildpage = appid + '/lastbuild_' + thisbuild['vercode']
                    newpage = site.Pages[lastbuildpage]
                    txt = "Build completed at " + time.strftime(
                        "%Y-%m-%d %H:%M:%SZ", time.gmtime()) + "\n\n" + wikilog
                    newpage.save(txt, summary='Build log')
                    # Redirect from /lastbuild to the most recent build log
                    newpage = site.Pages[appid + '/lastbuild']
                    newpage.save('#REDIRECT [[' + lastbuildpage + ']]',
                                 summary='Update redirect')
                except:
                    logging.error(
                        "Error while attempting to publish build log")

    for app in build_succeeded:
        logging.info("success: %s" % (app['id']))

    if not options.verbose:
        for fa in failed_apps:
            logging.info("Build for app %s failed:\n%s" %
                         (fa, failed_apps[fa]))

    logging.info("Finished.")
    if len(build_succeeded) > 0:
        logging.info(str(len(build_succeeded)) + ' builds succeeded')
    if len(failed_apps) > 0:
        logging.info(str(len(failed_apps)) + ' builds failed')

    sys.exit(0)
Exemple #4
0
def main():

    global options, config

    # Parse command line...
    parser = OptionParser(
        usage="Usage: %prog [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
    parser.add_option("-v",
                      "--verbose",
                      action="store_true",
                      default=False,
                      help="Spew out even more information than normal")
    parser.add_option("-q",
                      "--quiet",
                      action="store_true",
                      default=False,
                      help="Restrict output to warnings and errors")
    parser.add_option("-a",
                      "--all",
                      action="store_true",
                      default=False,
                      help="Install all signed applications available")
    (options, args) = parser.parse_args()

    if not args and not options.all:
        raise OptionError(
            "If you really want to install all the signed apps, use --all",
            "all")

    config = common.read_config(options)

    output_dir = 'repo'
    if not os.path.isdir(output_dir):
        logging.info("No signed output directory - nothing to do")
        sys.exit(0)

    if args:

        vercodes = common.read_pkg_args(args, True)
        apks = {appid: None for appid in vercodes}

        # Get the signed apk with the highest vercode
        for apkfile in sorted(glob.glob(os.path.join(output_dir, '*.apk'))):

            try:
                appid, vercode = common.apknameinfo(apkfile)
            except FDroidException:
                continue
            if appid not in apks:
                continue
            if vercodes[appid] and vercode not in vercodes[appid]:
                continue
            apks[appid] = apkfile

        for appid, apk in apks.iteritems():
            if not apk:
                raise FDroidException("No signed apk available for %s" % appid)

    else:

        apks = {
            common.apknameinfo(apkfile)[0]: apkfile
            for apkfile in sorted(glob.glob(os.path.join(output_dir, '*.apk')))
        }

    for appid, apk in apks.iteritems():
        # Get device list each time to avoid device not found errors
        devs = devices()
        if not devs:
            raise FDroidException("No attached devices found")
        logging.info("Installing %s..." % apk)
        for dev in devs:
            logging.info("Installing %s on %s..." % (apk, dev))
            p = FDroidPopen([config['adb'], "-s", dev, "install", apk])
            fail = ""
            for line in p.output.splitlines():
                if line.startswith("Failure"):
                    fail = line[9:-1]
            if not fail:
                continue

            if fail == "INSTALL_FAILED_ALREADY_EXISTS":
                logging.warn("%s is already installed on %s." % (apk, dev))
            else:
                raise FDroidException("Failed to install %s on %s: %s" %
                                      (apk, dev, fail))

    logging.info("\nFinished")
def main():

    global options, config

    # Parse command line...
    parser = OptionParser(usage="Usage: %prog [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
    parser.add_option("-v", "--verbose", action="store_true", default=False,
                      help="Spew out even more information than normal")
    parser.add_option("-q", "--quiet", action="store_true", default=False,
                      help="Restrict output to warnings and errors")
    (options, args) = parser.parse_args()

    config = common.read_config(options)

    tmp_dir = 'tmp'
    if not os.path.isdir(tmp_dir):
        logging.info("Creating temporary directory")
        os.makedirs(tmp_dir)

    unsigned_dir = 'unsigned'
    if not os.path.isdir(unsigned_dir):
        logging.error("No unsigned directory - nothing to do")
        sys.exit(0)

    verified = 0
    notverified = 0

    vercodes = common.read_pkg_args(args, True)

    for apkfile in sorted(glob.glob(os.path.join(unsigned_dir, '*.apk'))):

        apkfilename = os.path.basename(apkfile)
        appid, vercode = common.apknameinfo(apkfile)

        if vercodes and appid not in vercodes:
            continue
        if vercodes[appid] and vercode not in vercodes[appid]:
            continue

        try:

            logging.info("Processing " + apkfilename)

            remoteapk = os.path.join(tmp_dir, apkfilename)
            if os.path.exists(remoteapk):
                os.remove(remoteapk)
            url = 'https://f-droid.org/repo/' + apkfilename
            logging.info("...retrieving " + url)
            p = FDroidPopen(['wget', url], cwd=tmp_dir)
            if p.returncode != 0:
                raise FDroidException("Failed to get " + apkfilename)

            thisdir = os.path.join(tmp_dir, 'this_apk')
            thatdir = os.path.join(tmp_dir, 'that_apk')
            for d in [thisdir, thatdir]:
                if os.path.exists(d):
                    shutil.rmtree(d)
                os.mkdir(d)

            if subprocess.call(['jar', 'xf',
                                os.path.join("..", "..", unsigned_dir, apkfilename)],
                               cwd=thisdir) != 0:
                raise FDroidException("Failed to unpack local build of " + apkfilename)
            if subprocess.call(['jar', 'xf',
                                os.path.join("..", "..", remoteapk)],
                               cwd=thatdir) != 0:
                raise FDroidException("Failed to unpack remote build of " + apkfilename)

            p = FDroidPopen(['diff', '-r', 'this_apk', 'that_apk'], cwd=tmp_dir)
            lines = p.output.splitlines()
            if len(lines) != 1 or 'META-INF' not in lines[0]:
                raise FDroidException("Unexpected diff output - " + p.output)

            logging.info("...successfully verified")
            verified += 1

        except FDroidException, e:
            logging.info("...NOT verified - {0}".format(e))
            notverified += 1
Exemple #6
0
def main():

    global options, config

    # Parse command line...
    parser = OptionParser(
        usage="Usage: %prog [options] [APPID[:VERCODE] [APPID[:VERCODE] ...]]")
    parser.add_option("-v",
                      "--verbose",
                      action="store_true",
                      default=False,
                      help="Spew out even more information than normal")
    parser.add_option("-q",
                      "--quiet",
                      action="store_true",
                      default=False,
                      help="Restrict output to warnings and errors")
    (options, args) = parser.parse_args()

    config = common.read_config(options)

    tmp_dir = 'tmp'
    if not os.path.isdir(tmp_dir):
        logging.info("Creating temporary directory")
        os.makedirs(tmp_dir)

    unsigned_dir = 'unsigned'
    if not os.path.isdir(unsigned_dir):
        logging.error("No unsigned directory - nothing to do")
        sys.exit(0)

    verified = 0
    notverified = 0

    vercodes = common.read_pkg_args(args, True)

    for apkfile in sorted(glob.glob(os.path.join(unsigned_dir, '*.apk'))):

        apkfilename = os.path.basename(apkfile)
        appid, vercode = common.apknameinfo(apkfile)

        if vercodes and appid not in vercodes:
            continue
        if vercodes[appid] and vercode not in vercodes[appid]:
            continue

        try:

            logging.info("Processing " + apkfilename)

            remoteapk = os.path.join(tmp_dir, apkfilename)
            if os.path.exists(remoteapk):
                os.remove(remoteapk)
            url = 'https://f-droid.org/repo/' + apkfilename
            logging.info("...retrieving " + url)
            common.download_file(url, dldir=tmp_dir)

            compare_result = common.compare_apks(
                os.path.join(unsigned_dir, apkfilename), remoteapk, tmp_dir)
            if compare_result:
                raise FDroidException(compare_result)

            logging.info("...successfully verified")
            verified += 1

        except FDroidException, e:
            logging.info("...NOT verified - {0}".format(e))
            notverified += 1