Example #1
0
def bump_version(new_version):
    """Set new base version to base version file and commit"""
    v = utils.get_vcs_info()
    mode = utils.get_build_mode()

    # Check that new base version is valid
    python_version(new_version, v, mode)

    repo = utils.get_repository()
    toplevel = repo.working_dir

    old_version = get_base_version(v)
    sys.stdout.write("Current base version is '%s'\n" % old_version)

    version_file = os.path.join(toplevel, "version")
    sys.stdout.write("Updating version file %s from version '%s' to '%s'\n" % (version_file, old_version, new_version))

    f = open(version_file, "rw+")
    lines = f.readlines()
    for i in range(0, len(lines)):
        if not lines[i].startswith("#"):
            lines[i] = lines[i].replace(old_version, new_version)
    f.seek(0)
    f.truncate(0)
    f.writelines(lines)
    f.close()

    repo.git.add(version_file)
    repo.git.commit(m="Bump version to %s" % new_version)
    sys.stdout.write("Update version file and commited\n")
Example #2
0
def bump_version(new_version):
    """Set new base version to base version file and commit"""
    v = utils.get_vcs_info()

    # Check that new base version is valid
    validate_version(new_version, v)
    _bump_version(new_version, v)
Example #3
0
def update_version():
    """Generate or replace version files

    Helper function for generating/replacing version files containing version
    information.

    """

    v = utils.get_vcs_info()
    toplevel = v.toplevel

    config = utils.get_config()
    if not v:
        # Return early if not in development environment
        raise RuntimeError("Can not compute version outside of a git" " repository.")
    b = get_base_version(v)
    mode = utils.get_build_mode()
    version = python_version(b, v, mode)
    debian_version_ = debian_version_from_python_version(version)
    env = {
        "DEVFLOW_VERSION": version,
        "DEVFLOW_DEBIAN_VERSION": debian_version_,
        "DEVFLOW_BRANCH": v.branch,
        "DEVFLOW_REVISION_ID": v.revid,
        "DEVFLOW_REVISION_NUMBER": v.revno,
        "DEVFLOW_USER_EMAIL": v.email,
        "DEVFLOW_USER_NAME": v.name,
    }

    for _pkg_name, pkg_info in config["packages"].items():
        version_filename = pkg_info.get("version_file")
        if not version_filename:
            continue
        version_template = pkg_info.get("version_template")
        if version_template:
            vtemplate_file = os.path.join(toplevel, version_template)
            try:
                with file(vtemplate_file) as f:
                    content = f.read(-1) % env
            except IOError as e:
                if e.errno == 2:
                    raise RuntimeError(
                        "devflow.conf contains '%s' as a"
                        " version template file, but file does"
                        " not exists!" % vtemplate_file
                    )
                else:
                    raise
        else:
            content = DEFAULT_VERSION_FILE % env
        with file(os.path.join(toplevel, version_filename), "w+") as f:
            log.info("Updating version file '%s'" % version_filename)
            f.write(content)
Example #4
0
def main():
    v = utils.get_vcs_info()
    b = get_base_version(v)
    mode = utils.get_build_mode()

    try:
        arg = sys.argv[1]
        assert arg == "python" or arg == "debian"
    except IndexError:
        raise ValueError("A single argument, 'python' or 'debian is required")

    if arg == "python":
        print python_version(b, v, mode)
    elif arg == "debian":
        print debian_version(b, v, mode)
Example #5
0
    def start_hotfix(self, args):
        repo = self.repo
        upstream = "master"
        debian = "debian"
        repo.git.checkout(upstream)
        #maybe provide major.minor version, find the latest release/hotfix and
        #branch from there ?

        vcs = utils.get_vcs_info()
        version = versioning.get_base_version(vcs)
        if not args.version:
            version = get_hotfix_version(version)
            if not args.defaults:
                version = query_user("Hotfix version", default=version)
        else:
            #validate version?
            pass

        rc_version = "%src1" % version
        new_develop_version = "%snext" % version

        upstream_branch = self.get_branch("hotfix", version)
        debian_branch = self.get_debian_branch("hotfix", version)

        #create hotfix branch
        repo.git.branch(upstream_branch, upstream)
        self.new_branches.append(upstream_branch)
        repo.git.checkout(upstream_branch)
        versioning.bump_version(rc_version)

        #create debian hotfix branch
        repo.git.checkout(debian)
        repo.git.branch(debian_branch, debian)
        self.new_branches.append(debian_branch)

        repo.git.checkout(upstream_branch)
        repo.git.checkout(debian)

        #bump develop version. Ask first or verify we have the same
        #major.minornext?
        #repo.git.checkout(upstream)
        #versioning.bump_version(new_develop_version)

        repo.git.checkout(upstream_branch)
Example #6
0
def check_obsolete_version(version=None):
    """Check if the version is postfixed with 'next' which is deprecated.
    Output a warning"""

    if version is None:
        v = utils.get_vcs_info()
        version = get_base_version(v)

    if not version.endswith('next'):
        return

    new_version = version.rstrip('next').split('.')
    new_version[-1] = str(int(new_version[-1]) + 1)
    new_version = ".".join(new_version)
    sys.stderr.write(
        "Warning: Version %s contains postfix 'next' which is obsolete.\n"
        "Warning: Replace it to the forthcoming release version (e.g. %s).\n"
        "Warning: Support for postfix next will be removed in the future.\n" %
        (version, new_version))
Example #7
0
    def start_release(self, args):
        repo = self.repo
        upstream = "develop"
        debian = "debian-develop"
        repo.git.checkout(upstream)

        vcs = utils.get_vcs_info()
        develop_version = versioning.get_base_version(vcs)
        if not args.version:
            version = get_release_version(develop_version)
            if not args.defaults:
                version = query_user("Release version", default=version)
        else:
            #validate version?
            pass
        rc_version = "%src1" % version
        new_develop_version = "%snext" % version

        upstream_branch = self.get_branch("release", version)
        debian_branch = self.get_debian_branch("release", version)

        #create release branch
        repo.git.branch(upstream_branch, upstream)
        self.new_branches.append(upstream_branch)
        repo.git.checkout(upstream_branch)
        versioning.bump_version(rc_version)

        #create debian release branch
        repo.git.checkout(debian)
        repo.git.branch(debian_branch, debian)
        self.new_branches.append(debian_branch)

        repo.git.checkout(upstream_branch)
        repo.git.checkout(debian)

        #bump develop version
        repo.git.checkout(upstream)
        versioning.bump_version(new_develop_version)

        repo.git.checkout(upstream_branch)
Example #8
0
    def end_release(self, args):
        version = args.version
        repo = self.repo
        master = "master"
        debian_master = "debian"
        upstream = "develop"
        debian = "debian-develop"
        upstream_branch = self.get_branch("release", version)
        debian_branch = self.get_debian_branch("release", version)
        tag = upstream_branch
        debian_tag = "debian/" + tag

        edit_action = partial(self.edit_changelog, upstream_branch, "develop")
        self.check_edit_changelog(edit_action, args, default=True)

        vcs = utils.get_vcs_info()
        release_version = versioning.get_base_version(vcs)
        if re.match('.*'+RC_RE, release_version):
            new_version = re.sub(RC_RE, '', release_version)
            versioning._bump_version(new_version, vcs)

        #merge to master
        self._merge_branches(master, upstream_branch)
        self._merge_branches(debian_master, debian_branch)

        #create tags
        repo.git.checkout(master)
        repo.git.tag("%s" % tag)
        repo.git.checkout(debian)
        repo.git.tag("%s" % debian_tag)

        #merge release changes to upstream
        self.merge_branches(upstream, upstream_branch, args, default=True)
        self.merge_branches(debian, debian_branch, args, default=True)

        repo.git.checkout(upstream)

        branches = [upstream_branch, debian_branch]
        self.cleanup_branches(branches, args, default=True)
Example #9
0
def update_version():
    """Generate or replace version files

    Helper function for generating/replacing version files containing version
    information.

    """

    v = utils.get_vcs_info()
    toplevel = v.toplevel

    config = utils.get_config()
    if not v:
        # Return early if not in development environment
        raise RuntimeError("Can not compute version outside of a git"
                           " repository.")
    b = get_base_version(v)
    check_obsolete_version(b)
    mode = utils.get_build_mode()
    version = python_version(b, v, mode)
    debian_version_ = debian_version_from_python_version(version)
    env = {"DEVFLOW_VERSION": version,
           "DEVFLOW_DEBIAN_VERSION": debian_version_,
           "DEVFLOW_BRANCH": v.branch,
           "DEVFLOW_REVISION_ID": v.revid,
           "DEVFLOW_REVISION_NUMBER": v.revno,
           "DEVFLOW_USER_EMAIL": v.email,
           "DEVFLOW_USER_NAME": v.name}

    for _pkg_name, pkg_info in config['packages'].items():
        if pkg_info.get("version_file"):
            version_filenames = pkg_info.as_list("version_file")
        else:
            continue
        if pkg_info.get('version_template'):
            version_templates = pkg_info.as_list("version_template")
        else:
            version_templates = itertools.repeat(None, len(version_filenames))
            version_templates = list(version_templates)

        if len(version_filenames) != len(version_templates):
            raise RuntimeError(
                "devflow.conf contains '%s' version files and '%s' version "
                "templates. The number of version files and templates must "
                "match." % (len(version_filenames), len(version_templates)))

        v_files_templates = zip(version_filenames, version_templates)
        for (vfilename, vtemplate) in v_files_templates:
            if vtemplate:
                vtemplate_file = os.path.join(toplevel, vtemplate)
                try:
                    with file(vtemplate_file) as f:
                        content = f.read(-1) % env
                except IOError as e:
                    if e.errno == 2:
                        raise RuntimeError("devflow.conf contains '%s' as a"
                                           " version template file, but file"
                                           " does not exists!"
                                           % vtemplate_file)
                    else:
                        raise
            else:
                content = DEFAULT_VERSION_FILE % env
            with file(os.path.join(toplevel, vfilename), 'w+') as f:
                log.info("Updating version file '%s'" % vfilename)
                f.write(content)
Example #10
0
def get_debian_version():
    v = utils.get_vcs_info()
    b = get_base_version(v)
    mode = utils.get_build_mode()
    return debian_version(b, v, mode)
Example #11
0
def main():
    from devflow.version import __version__  # pylint: disable=E0611,F0401
    parser = OptionParser(usage="usage: %prog [options] mode",
                          version="devflow %s" % __version__,
                          add_help_option=False)
    parser.add_option("-h", "--help",
                      action="store_true",
                      default=False,
                      help="show this help message")
    parser.add_option("-k", "--keep-repo",
                      action="store_true",
                      dest="keep_repo",
                      default=False,
                      help="Do not delete the cloned repository")
    parser.add_option("-b", "--build-dir",
                      dest="build_dir",
                      default=None,
                      help="Directory to store created pacakges")
    parser.add_option("-r", "--repo-dir",
                      dest="repo_dir",
                      default=None,
                      help="Directory to clone repository")
    parser.add_option("-d", "--dirty",
                      dest="force_dirty",
                      default=False,
                      action="store_true",
                      help="Do not check if working directory is dirty")
    parser.add_option("-c", "--config-file",
                      dest="config_file",
                      help="Override default configuration file")
    parser.add_option("--no-sign",
                      dest="sign",
                      action="store_false",
                      default=True,
                      help="Do not sign the packages")
    parser.add_option("--key-id",
                      dest="keyid",
                      help="Use this keyid for gpg signing")
    parser.add_option("--dist",
                      dest="dist",
                      default=None,
                      help="Force distribution in Debian changelog")
    parser.add_option("-S", "--source-only",
                      dest="source_only",
                      default=False,
                      action="store_true",
                      help="Specifies a source-only build, no binary packages"
                           " need to be made.")
    parser.add_option("--debian-branch",
                      dest="debian_branch",
                      default=None,
                      help="Use this debian branch, instead of"
                           "auto-discovering the debian branch to use")
    parser.add_option("--push-back",
                      dest="push_back",
                      default=False,
                      action="store_true",
                      help="Automatically push branches and tags to repo.")
    parser.add_option("--color",
                      dest="color_output",
                      default="auto",
                      help="Enable/disable colored output. Default mode is" +
                           " auto, available options are yes/no")

    (options, args) = parser.parse_args()

    if options.color_output == "yes":
        use_colors = True
    elif options.color_output == "no":
        use_colors = False
    else:
        if sys.stdout.isatty():
            use_colors = True
        else:
            use_colors = False

    red = lambda x: x
    green = lambda x: x

    if use_colors:
        try:
            import colors
            red = colors.red
            green = colors.green
        except AttributeError:
            pass

    print_red = lambda x: sys.stdout.write(red(x) + "\n")
    print_green = lambda x: sys.stdout.write(green(x) + "\n")

    if options.help:
        print_help(parser.get_prog_name())
        parser.print_help()
        return

    # Get build mode
    try:
        mode = args[0]
    except IndexError:
        mode = utils.get_build_mode()
    if mode not in AVAILABLE_MODES:
        raise ValueError(red("Invalid argument! Mode must be one: %s"
                         % ", ".join(AVAILABLE_MODES)))

    # Load the repository
    original_repo = utils.get_repository()

    # Check that repository is clean
    toplevel = original_repo.working_dir
    if original_repo.is_dirty() and not options.force_dirty:
        raise RuntimeError(red("Repository %s is dirty." % toplevel))

    # Get packages from configuration file
    config = utils.get_config(options.config_file)
    packages = config['packages'].keys()
    print_green("Will build the following packages:\n" + "\n".join(packages))

    # Get current branch name and type and check if it is a valid one
    branch = original_repo.head.reference.name
    branch = utils.undebianize(branch)
    branch_type_str = utils.get_branch_type(branch)

    if branch_type_str not in BRANCH_TYPES.keys():
        allowed_branches = ", ".join(BRANCH_TYPES.keys())
        raise ValueError("Malformed branch name '%s', cannot classify as"
                         " one of %s" % (branch, allowed_branches))

    # Fix needed environment variables
    v = utils.get_vcs_info()
    os.environ["DEVFLOW_BUILD_MODE"] = mode
    os.environ["DEBFULLNAME"] = v.name
    os.environ["DEBEMAIL"] = v.email

    # Check that base version file and branch are correct
    versioning.get_python_version()

    # Get the debian branch
    if options.debian_branch:
        debian_branch = options.debian_branch
    else:
        debian_branch = utils.get_debian_branch(branch)
    origin_debian = "origin/" + debian_branch

    # Clone the repo
    repo_dir = options.repo_dir or create_temp_directory("df-repo")
    repo_dir = os.path.abspath(repo_dir)
    repo = original_repo.clone(repo_dir, branch=branch)
    print_green("Cloned repository to '%s'." % repo_dir)

    build_dir = options.build_dir or create_temp_directory("df-build")
    build_dir = os.path.abspath(build_dir)
    print_green("Build directory: '%s'" % build_dir)

    # Create the debian branch
    repo.git.branch(debian_branch, origin_debian)
    print_green("Created branch '%s' to track '%s'" % (debian_branch,
                origin_debian))

    # Go to debian branch
    repo.git.checkout(debian_branch)
    print_green("Changed to branch '%s'" % debian_branch)

    # Merge with starting branch
    repo.git.merge(branch)
    print_green("Merged branch '%s' into '%s'" % (branch, debian_branch))

    # Compute python and debian version
    cd(repo_dir)
    python_version = versioning.get_python_version()
    debian_version = versioning.\
        debian_version_from_python_version(python_version)
    print_green("The new debian version will be: '%s'" % debian_version)

    # Update the version files
    versioning.update_version()

    if not options.sign:
        sign_tag_opt = None
    elif options.keyid:
        sign_tag_opt = "-u=%s" % options.keyid
    elif mode == "release":
        sign_tag_opt = "-s"
    else:
        sign_tag_opt = None

    # Tag branch with python version
    branch_tag = python_version
    tag_message = "%s version %s" % (mode.capitalize(), python_version)
    try:
        repo.git.tag(branch_tag, branch, sign_tag_opt, "-m %s" % tag_message)
    except GitCommandError:
        # Tag may already exist, if only the debian branch has changed
        pass
    upstream_tag = "upstream/" + branch_tag
    repo.git.tag(upstream_tag, branch)

    # Update changelog
    dch = git_dch("--debian-branch=%s" % debian_branch,
                  "--git-author",
                  "--ignore-regex=\".*\"",
                  "--multimaint-merge",
                  "--since=HEAD",
                  "--new-version=%s" % debian_version)
    print_green("Successfully ran '%s'" % " ".join(dch.cmd))

    if options.dist is not None:
        distribution = options.dist
    elif mode == "release":
        distribution = utils.get_distribution_codename()
    else:
        distribution = "unstable"

    f = open("debian/changelog", 'r+')
    lines = f.readlines()
    lines[0] = lines[0].replace("UNRELEASED", distribution)
    lines[2] = lines[2].replace("UNRELEASED", "%s build" % mode)
    f.seek(0)
    f.writelines(lines)
    f.close()

    if mode == "release":
        call("vim debian/changelog")

    # Add changelog to INDEX
    repo.git.add("debian/changelog")
    # Commit Changes
    repo.git.commit("-s", "debian/changelog",
                    m="Bump version to %s" % debian_version)
    # Tag debian branch
    debian_branch_tag = "debian/" + utils.version_to_tag(debian_version)
    tag_message = "%s version %s" % (mode.capitalize(), debian_version)
    if mode == "release":
        repo.git.tag(debian_branch_tag, sign_tag_opt, "-m %s" % tag_message)

    # Create debian packages
    cd(repo_dir)
    version_files = []
    for _, pkg_info in config['packages'].items():
        if pkg_info.get("version_file"):
            version_files.extend(pkg_info.as_list('version_file'))

    # Add version.py files to repo
    repo.git.add("-f", *version_files)

    # Export version info to debuilg environment
    os.environ["DEB_DEVFLOW_DEBIAN_VERSION"] = debian_version
    os.environ["DEB_DEVFLOW_VERSION"] = python_version
    build_cmd = "git-buildpackage --git-export-dir=%s"\
                " --git-upstream-branch=%s --git-debian-branch=%s"\
                " --git-export=INDEX --git-ignore-new -sa"\
                " --source-option=--auto-commit"\
                " --git-upstream-tag=%s"\
                % (build_dir, branch, debian_branch, upstream_tag)
    if options.source_only:
        build_cmd += " -S"
    if not options.sign:
        build_cmd += " -uc -us"
    elif options.keyid:
        build_cmd += " -k\"'%s'\"" % options.keyid
    call(build_cmd)

    # Remove cloned repo
    if mode != 'release' and not options.keep_repo:
        print_green("Removing cloned repo '%s'." % repo_dir)
        rm("-r", repo_dir)

    # Print final info
    info = (("Version", debian_version),
            ("Upstream branch", branch),
            ("Upstream tag", branch_tag),
            ("Debian branch", debian_branch),
            ("Debian tag", debian_branch_tag),
            ("Repository directory", repo_dir),
            ("Packages directory", build_dir))
    print_green("\n".join(["%s: %s" % (name, val) for name, val in info]))

    # Print help message
    if mode == "release":
        origin = original_repo.remote().url
        repo.create_remote("original_origin", origin)
        print_green("Created remote 'original_origin' for the repository '%s'"
                    % origin)

        print_green("To update repositories '%s' and '%s' go to '%s' and run:"
                    % (toplevel, origin, repo_dir))
        for remote in ['origin', 'original_origin']:
            objects = [debian_branch, branch_tag, debian_branch_tag]
            print_green("git push %s %s" % (remote, " ".join(objects)))
        if options.push_back:
            objects = [debian_branch, branch_tag, debian_branch_tag]
            repo.git.push("origin", *objects)
            print_green("Automatically updated origin repo.")