Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/tools/dist/release.py  view on Meta::CPAN

        if not dep.have_usable():
           raise RuntimeError('Cannot find usable %s' % dep.label)

    if branch != 'trunk':
        # Make sure CHANGES is sync'd.
        compare_changes(repos, branch, args.revnum)

    # Ensure the output directory doesn't already exist
    if os.path.exists(get_deploydir(args.base_dir)):
        raise RuntimeError('output directory \'%s\' already exists'
                                            % get_deploydir(args.base_dir))

    os.mkdir(get_deploydir(args.base_dir))

    # For now, just delegate to dist.sh to create the actual artifacts
    extra_args = ''
    if args.version.is_prerelease():
        if args.version.pre == 'nightly':
            extra_args = '-nightly'
        else:
            extra_args = '-%s %d' % (args.version.pre, args.version.pre_num)
    # Build Unix last to leave Unix-style svn_version.h for tagging
    logging.info('Buildling Windows tarballs')
    run_script(args.verbose, '%s/dist.sh -v %s -pr %s -r %d -zip %s'
                     % (sys.path[0], args.version.base, branch, args.revnum,
                        extra_args) )
    logging.info('Building UNIX tarballs')
    run_script(args.verbose, '%s/dist.sh -v %s -pr %s -r %d %s'
                     % (sys.path[0], args.version.base, branch, args.revnum,
                        extra_args) )

    # Move the results to the deploy directory
    logging.info('Moving artifacts and calculating checksums')
    for e in extns:
        if args.version.pre == 'nightly':
            filename = 'subversion-nightly.%s' % e
        else:
            filename = 'subversion-%s.%s' % (args.version, e)

        shutil.move(filename, get_deploydir(args.base_dir))
        filename = os.path.join(get_deploydir(args.base_dir), filename)
        m = hashlib.sha1()
        m.update(open(filename, 'r').read())
        open(filename + '.sha1', 'w').write(m.hexdigest())

    shutil.move('svn_version.h.dist',
                get_deploydir(args.base_dir) + '/' + 'svn_version.h.dist'
                + '-' + str(args.version))

    # And we're done!

#----------------------------------------------------------------------
# Sign the candidate release artifacts

def sign_candidates(args):
    'Sign candidate artifacts in the dist development directory.'

    def sign_file(filename):
        asc_file = open(filename + '.asc', 'a')
        logging.info("Signing %s" % filename)
        proc = subprocess.Popen(['gpg', '-ba', '-o', '-', filename],
                              stdout=asc_file)
        proc.wait()
        asc_file.close()

    if args.target:
        target = args.target
    else:
        target = get_deploydir(args.base_dir)

    for e in extns:
        filename = os.path.join(target, 'subversion-%s.%s' % (args.version, e))
        sign_file(filename)
        if args.version.major >= 1 and args.version.minor <= 6:
            filename = os.path.join(target,
                                   'subversion-deps-%s.%s' % (args.version, e))
            sign_file(filename)


#----------------------------------------------------------------------
# Post the candidate release artifacts

def post_candidates(args):
    'Post candidate artifacts to the dist development directory.'

    logging.info('Importing tarballs to %s' % dist_dev_url)
    svn_cmd = ['svn', 'import', '-m',
               'Add %s candidate release artifacts' % args.version.base,
               '--auto-props', '--config-option',
               'config:auto-props:*.asc=svn:eol-style=native;svn:mime-type=text/plain',
               get_deploydir(args.base_dir), dist_dev_url]
    if (args.username):
        svn_cmd += ['--username', args.username]
    proc = subprocess.Popen(svn_cmd)
    (stdout, stderr) = proc.communicate()
    proc.wait()

#----------------------------------------------------------------------
# Create tag

def create_tag(args):
    'Create tag in the repository'

    logging.info('Creating tag for %s' % str(args.version))

    if args.branch:
        branch = secure_repos + '/' + args.branch
    else:
        branch = secure_repos + '/branches/%d.%d.x' % (args.version.major,
                                                       args.version.minor)

    tag = secure_repos + '/tags/' + str(args.version)

    svnmucc_cmd = ['svnmucc', '-m',
                   'Tagging release ' + str(args.version)]
    if (args.username):
        svnmucc_cmd += ['--username', args.username]
    svnmucc_cmd += ['cp', str(args.revnum), branch, tag]
    svnmucc_cmd += ['put', os.path.join(get_deploydir(args.base_dir),
                                        'svn_version.h.dist'),
                    tag + '/subversion/include/svn_version.h']

src/subversion/tools/dist/release.py  view on Meta::CPAN

        if replace:
            # replace the version number with the [version] reference
            i.filename = Version.regex.sub('[version]', fname)
        else:
            i.filename = fname
        i.sha1 = open(s, 'r').read()
        sha1info.append(i)

    return sha1info


def write_announcement(args):
    'Write the release announcement.'
    sha1info = get_sha1info(args)
    siginfo = "\n".join(get_siginfo(args, True)) + "\n"

    data = { 'version'              : str(args.version),
             'sha1info'             : sha1info,
             'siginfo'              : siginfo,
             'major-minor'          : '%d.%d' % (args.version.major,
                                                 args.version.minor),
             'major-minor-patch'    : args.version.base,
           }

    if args.version.is_prerelease():
        template_filename = 'rc-release-ann.ezt'
    else:
        template_filename = 'stable-release-ann.ezt'

    template = ezt.Template(compress_whitespace = False)
    template.parse(get_tmplfile(template_filename).read())
    template.generate(sys.stdout, data)


def write_downloads(args):
    'Output the download section of the website.'
    sha1info = get_sha1info(args, replace=True)

    data = { 'version'              : str(args.version),
             'fileinfo'             : sha1info,
           }

    template = ezt.Template(compress_whitespace = False)
    template.parse(get_tmplfile('download.ezt').read())
    template.generate(sys.stdout, data)


#----------------------------------------------------------------------
# Validate the signatures for a release

key_start = '-----BEGIN PGP SIGNATURE-----'
fp_pattern = re.compile(r'^pub\s+(\w+\/\w+)[^\n]*\n\s+Key\sfingerprint\s=((\s+[0-9A-F]{4}){10})\nuid\s+([^<\(]+)\s')

def get_siginfo(args, quiet=False):
    'Returns a list of signatures for the release.'

    try:
        import gnupg
    except ImportError:
        import _gnupg as gnupg
    gpg = gnupg.GPG()

    if args.target:
        target = args.target
    else:
        target = get_deploydir(args.base_dir)

    good_sigs = {}
    fingerprints = {}
    output = []

    glob_pattern = os.path.join(target, 'subversion*-%s*.asc' % args.version)
    for filename in glob.glob(glob_pattern):
        text = open(filename).read()
        keys = text.split(key_start)

        if not quiet:
            logging.info("Checking %d sig(s) in %s" % (len(keys[1:]), filename))
        for key in keys[1:]:
            fd, fn = tempfile.mkstemp()
            os.write(fd, key_start + key)
            os.close(fd)
            verified = gpg.verify_file(open(fn, 'rb'), filename[:-4])
            os.unlink(fn)

            if verified.valid:
                good_sigs[verified.key_id[-8:]] = True
            else:
                sys.stderr.write("BAD SIGNATURE for %s\n" % filename)
                if verified.key_id:
                    sys.stderr.write("  key id: %s\n" % verified.key_id)
                sys.exit(1)

    for id in good_sigs.keys():
        gpg = subprocess.Popen(['gpg', '--fingerprint', id],
                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        rc = gpg.wait()
        gpg_output = gpg.stdout.read()
        if rc:
            print(gpg_output)
            sys.stderr.write("UNABLE TO GET FINGERPRINT FOR %s" % id)
            sys.exit(1)

        gpg_output = "\n".join([ l for l in gpg_output.splitlines()
                                                     if l[0:7] != 'Warning' ])

        fp = fp_pattern.match(gpg_output).groups()
        fingerprints["%s [%s] %s" % (fp[3], fp[0], fp[1])] = fp

    for entry in sorted(fingerprints.keys()):
        fp = fingerprints[entry]
        output.append("   %s [%s] with fingerprint:" % (fp[3], fp[0]))
        output.append("   %s" % fp[1])

    return output

def check_sigs(args):
    'Check the signatures for the release.'

    output = get_siginfo(args)
    for line in output:
        print(line)

def get_keys(args):
    'Import the LDAP-based KEYS file to gpg'
    # We use a tempfile because urlopen() objects don't have a .fileno()
    with tempfile.SpooledTemporaryFile() as fd:
        fd.write(urllib2.urlopen(KEYS).read())
        fd.flush()
        fd.seek(0)
        subprocess.check_call(['gpg', '--import'], stdin=fd)

#----------------------------------------------------------------------
# Main entry point for argument parsing and handling

def main():
    'Parse arguments, and drive the appropriate subcommand.'

    # Setup our main parser
    parser = argparse.ArgumentParser(
                            description='Create an Apache Subversion release.')
    parser.add_argument('--clean', action='store_true', default=False,
                   help='Remove any directories previously created by %(prog)s')
    parser.add_argument('--verbose', action='store_true', default=False,
                   help='Increase output verbosity')
    parser.add_argument('--base-dir', default=os.getcwd(),
                   help='''The directory in which to create needed files and
                           folders.  The default is the current working
                           directory.''')
    subparsers = parser.add_subparsers(title='subcommands')

    # Setup the parser for the build-env subcommand
    subparser = subparsers.add_parser('build-env',
                    help='''Download release prerequisistes, including autoconf,
                            libtool, and swig.''')
    subparser.set_defaults(func=build_env)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')
    subparser.add_argument('--sf-mirror', default='softlayer',
                    help='''The mirror to use for downloading files from
                            SourceForge.  If in the EU, you may want to use
                            'kent' for this value.''')
    subparser.add_argument('--use-existing', action='store_true', default=False,
                    help='''Attempt to use existing build dependencies before
                            downloading and building a private set.''')

    # Setup the parser for the roll subcommand
    subparser = subparsers.add_parser('roll',
                    help='''Create the release artifacts.''')
    subparser.set_defaults(func=roll_tarballs)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')
    subparser.add_argument('revnum', type=int,
                    help='''The revision number to base the release on.''')
    subparser.add_argument('--branch',
                    help='''The branch to base the release on.''')

    # Setup the parser for the sign-candidates subcommand
    subparser = subparsers.add_parser('sign-candidates',
                    help='''Sign the release artifacts.''')
    subparser.set_defaults(func=sign_candidates)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')
    subparser.add_argument('--target',
                    help='''The full path to the directory containing
                            release artifacts.''')

    # Setup the parser for the post-candidates subcommand
    subparser = subparsers.add_parser('post-candidates',
                    help='''Commit candidates to the release development area
                            of the dist.apache.org repository.''')

src/subversion/tools/dist/release.py  view on Meta::CPAN

    subparser = subparsers.add_parser('clean-dist',
                    help='''Clean the distribution directory (and mirrors) of
                            all but the most recent MAJOR.MINOR release.''')
    subparser.set_defaults(func=clean_dist)
    subparser.add_argument('--dist-dir',
                    help='''The directory to clean.''')
    subparser.add_argument('--username',
                    help='''Username for ''' + dist_repos + '''.''')

    # The move-to-dist subcommand
    subparser = subparsers.add_parser('move-to-dist',
                    help='''Move candiates and signatures from the temporary
                            release dev location to the permanent distribution
                            directory.''')
    subparser.set_defaults(func=move_to_dist)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')
    subparser.add_argument('--username',
                    help='''Username for ''' + dist_repos + '''.''')

    # The write-news subcommand
    subparser = subparsers.add_parser('write-news',
                    help='''Output to stdout template text for use in the news
                            section of the Subversion website.''')
    subparser.set_defaults(func=write_news)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')

    # write-announcement
    subparser = subparsers.add_parser('write-announcement',
                    help='''Output to stdout template text for the emailed
                            release announcement.''')
    subparser.set_defaults(func=write_announcement)
    subparser.add_argument('--target',
                    help='''The full path to the directory containing
                            release artifacts.''')
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')

    # write-downloads
    subparser = subparsers.add_parser('write-downloads',
                    help='''Output to stdout template text for the download
                            table for subversion.apache.org''')
    subparser.set_defaults(func=write_downloads)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')

    # check-sigs
    subparser = subparsers.add_parser('check-sigs',
                    help='''Output to stdout the signatures collected for this
                            release''')
    subparser.set_defaults(func=check_sigs)
    subparser.add_argument('version', type=Version,
                    help='''The release label, such as '1.7.0-alpha1'.''')
    subparser.add_argument('--target',
                    help='''The full path to the directory containing
                            release artifacts.''')

    # get-keys
    subparser = subparsers.add_parser('get-keys',
                    help='''Import committers' public keys to ~/.gpg/''')
    subparser.set_defaults(func=get_keys)

    # A meta-target
    subparser = subparsers.add_parser('clean',
                    help='''The same as the '--clean' switch, but as a
                            separate subcommand.''')
    subparser.set_defaults(func=cleanup)

    # Parse the arguments
    args = parser.parse_args()

    # first, process any global operations
    if args.clean:
        cleanup(args)

    # Set up logging
    logger = logging.getLogger()
    if args.verbose:
        logger.setLevel(logging.DEBUG)
    else:
        logger.setLevel(logging.INFO)

    # Fix up our path so we can use our installed versions
    os.environ['PATH'] = os.path.join(get_prefix(args.base_dir), 'bin') + ':' \
                                                            + os.environ['PATH']

    # finally, run the subcommand, and give it the parsed arguments
    args.func(args)


if __name__ == '__main__':
    main()



( run in 0.952 second using v1.01-cache-2.11-cpan-df04353d9ac )