Example #1
0
    def setup_initial_release(self):
        """
    """
        if not choice("""
  do you want keybump to setup the initial release?"""):
            fail('aborting, initial release not created.')

        info("""
  ok, you asked for it..
    """)
        release = self.create_initial_release()
        self.changelog.write(release.format_changelog_summary())
        self.releases.append(release)
Example #2
0
    def new_release(self):
        """
      :returns: instance of a `Release` object.
    """
        rv = Release(self,
                     self.last_release.version_num,
                     datestr=self.today_str())
        rv.bump()

        if rv.version_num in self.tags:
            fail("version `{}` is already tagged", rv.version_num)

        rv.set_summaries(self.get_changelog_summaries_since(self.current_tag))
        return rv
Example #3
0
    def parse_releases(self):
        """
    sets the releases property, parsed from the changelog summaries.
    """
        self.releases = self.parse_changelog_to_releases()
        if len(self.releases) < 1:
            msg = "could not parse release from changelog history in {}.".format(
                self.changelog.path)

            # fail and exit..
            if self.config.skip_interactive:
                fail(msg)
            else:
                # don't fail, set to initial version..
                info(msg)

            self.setup_initial_release()
Example #4
0
 def _bump_num(self, version_num, bump_type=PATCH_BUMP):
   """
     :param version_num: string version name.
     :param bump_type: version bump type. one of:
         major  [x].0.0    minor  x.[x].0    patch  x.x.[x]
     :returns: concatenated string of the incremented version name.
   """
   # split the version number into a list of ints..
   try:
     version = [int(v) for v in version_num.split(".")]
     switch = {
       "major": lambda: [version[0] + 1, 0, 0],
       "minor": lambda: [version[0], version[1] + 1, 0],
       "patch": lambda: [version[0], version[1], version[2] + 1]}
     return ".".join(map(str, switch.get(bump_type)()))
   except ValueError:
     fail("version string: {} is an invalid format..", version_num)
Example #5
0
 def _bump_num(self, version_num, bump_type=PATCH_BUMP):
     """
   :param version_num: string version name.
   :param bump_type: version bump type. one of:
       major  [x].0.0    minor  x.[x].0    patch  x.x.[x]
   :returns: concatenated string of the incremented version name.
 """
     # split the version number into a list of ints..
     try:
         version = [int(v) for v in version_num.split(".")]
         switch = {
             "major": lambda: [version[0] + 1, 0, 0],
             "minor": lambda: [version[0], version[1] + 1, 0],
             "patch": lambda: [version[0], version[1], version[2] + 1]
         }
         return ".".join(map(str, switch.get(bump_type)()))
     except ValueError:
         fail("version string: {} is an invalid format..", version_num)
Example #6
0
    def parse_git_tags(self):
        """
    loads the repo's git tags, sets the `current_tag` + `latest_tag` attrs.
    """
        # what to do on first time run? no tags yet..
        if not self.has_initial_tag:
            fail("""
  looks as though the project has not been initialized yet for releases.

  create a tag for version: 0.0.0 and try again.

  sorry, we're still ghetto-riggin this script along.. workin on it..""")
            # todo: implement condition for new project without tags / version.
            # https://github.com/gregorynicholas/keybump/issues/2

        self.latest_tag = get_latest_git_tag()
        # logger.info 'get_latest_git_tag:', get_latest_git_tag()
        self.current_tag = self._current_or_last_git_tag()
Example #7
0
def set_version_in_file(filename, version_number, pattern):
    """
    :param filename:
    :param version_number:
    :param pattern:
  """
    changed = []

    def inject_version(match):
        before, old, after = match.groups()
        changed.append(True)
        return before + version_number + after

    with open(filename, "r") as f:
        data_str = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern,
                          inject_version, f.read())
    if len(changed) < 1:
        fail("could not set init file version. pattern {} not found in {}",
             pattern, filename)
    write(filename, data_str)
Example #8
0
def set_version_in_file(filename, version_number, pattern):
  """
    :param filename:
    :param version_number:
    :param pattern:
  """
  changed = []

  def inject_version(match):
    before, old, after = match.groups()
    changed.append(True)
    return before + version_number + after

  with open(filename, "r") as f:
    data_str = re.sub(
      r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern, inject_version, f.read())
  if len(changed) < 1:
    fail(
      "could not set init file version. pattern {} not found in {}",
      pattern, filename)
  write(filename, data_str)
Example #9
0
def ensure_clean_index(skip_interactive=False, callback=None):
    """
  ensures the current git staging index has no uncommitted or stashed changes.

    :param skip_interactive: boolean flag to skip getting input from a cli.
    :param callback: recursive callback function.
  """
    if not has_unstaged_changes() and not has_uncommitted_changes():
        if callback:
            return callback(skip_interactive, callback)
        return True

    if callback is None:
        callback = ensure_clean_index

    files = git_diff_files()
    msg = """
  aborting.. un[stashed/committed] changes. fix uncommitted files by
  stashing, committing, or resetting the following files:

  {}
  """.format("\n  ".join(files))
    if skip_interactive:
        fail(msg)

    # clean the index..
    info(msg)
    if not choice("want keybump to snort ..achem stash.. your changes?"):
        fail("aborting.. un[stashed/committed] changes..")

    info("""
  ok, you asked for it..
  """)

    git_stash()

    if callback:
        return callback(skip_interactive, callback)
Example #10
0
def ensure_clean_index(skip_interactive=False, callback=None):
  """
  ensures the current git staging index has no uncommitted or stashed changes.

    :param skip_interactive: boolean flag to skip getting input from a cli.
    :param callback: recursive callback function.
  """
  if not has_unstaged_changes() and not has_uncommitted_changes():
    if callback:
      return callback(skip_interactive, callback)
    return True

  if callback is None:
    callback = ensure_clean_index

  files = git_diff_files()
  msg = """
  aborting.. un[stashed/committed] changes. fix uncommitted files by
  stashing, committing, or resetting the following files:

  {}
  """.format("\n  ".join(files))
  if skip_interactive:
    fail(msg)

  # clean the index..
  info(msg)
  if not choice("want keybump to snort ..achem stash.. your changes?"):
    fail("aborting.. un[stashed/committed] changes..")

  info("""
  ok, you asked for it..
  """)

  git_stash()

  if callback:
    return callback(skip_interactive, callback)
Example #11
0
    def parse_changelog_to_releases(self):
        """
    parses the contents of the changelog file, and returns a list of `Release`
    objects from the changelog summary.

      :returns: list of instance of a `Release` objects.
    """
        result = []

        # todo: need to handle encoding..
        with self.changelog.open() as f:
            lineiter = iter(f)
            hasdata = False
            version_num = None

            for line in lineiter:
                logger.debug('line: {}'.format(line))
                hasdata = True

                # parse the last version..
                ver_match = version.VERSION_RE.search(line.strip())
                if ver_match is None:
                    logger.warn('continuing..!')
                    continue

                version_num = ver_match.group(1).strip()
                # logger.debug('version_num: {}'.format(version_num))

                value = lineiter.next()
                # logger.debug('value: {}'.format(value))

                if not value.count(self.config.summary_separator):
                    # TODO: this is currently breaking things..
                    # logger.warn('continuing..!')
                    # continue
                    pass

                # parse the release data and codename..
                while 1:
                    release_header = lineiter.next().strip()
                    if release_header:
                        logger.debug(
                            'release_header: {}'.format(release_header))
                        break

                rel_match = self.release_header_re.search(release_header)
                if rel_match is None:
                    # TODO: raise exception here?
                    logger.warn('no release header found!')
                    # continue

                datestr, codename = rel_match.groups()
                logger.debug('datestr: {}'.format(datestr))

                # parse the change summary messages..
                summaries = []
                while 1:
                    try:
                        summary = lineiter.next()
                    except StopIteration, e:
                        break
                    if summary:
                        if len(summary.strip()) > 0:
                            # strip summary_item_fmt front beginning of item..
                            total = len(self.config.summaryitem_fmt)
                            if summary[0:total] == self.config.summaryitem_fmt:
                                summary = summary[total:]
                            # remove newline char at end..
                            summaries.append(summary[:-1])
                    else:
                        break

                release = Release(self,
                                  version_num,
                                  datestr=datestr,
                                  summaries=summaries)
                logger.debug('release: {}'.format(release))
                logger.debug('summaries: {}'.format(summaries))

                result.append(release)

            if len(result) == 0 and hasdata:
                fail("""unable to parse the changelog contents.

        format not recognized by parser:

        {}""".format(self.changelog.contents()))
            return result