Module: Gempilot

Defined in:
lib/gempilot.rb,
lib/gempilot/cli.rb,
lib/gempilot/origin.rb,
lib/gempilot/project.rb,
lib/gempilot/version.rb,
lib/gempilot/cli/command.rb,
lib/gempilot/version_tag.rb,
lib/gempilot/gem_constant.rb,
lib/gempilot/strict_shell.rb,
lib/gempilot/version_task.rb,
lib/gempilot/cli/generator.rb,
lib/gempilot/release_tasks.rb,
lib/gempilot/zeitwerk_task.rb,
lib/gempilot/github_release.rb,
lib/gempilot/cli/gem_builder.rb,
lib/gempilot/cli/gem_context.rb,
lib/gempilot/project/version.rb,
lib/gempilot/cli/commands/new.rb,
lib/gempilot/cli/commands/bump.rb,
lib/gempilot/segmented_version.rb,
lib/gempilot/cli/commands/create.rb,
lib/gempilot/cli/commands/console.rb,
lib/gempilot/cli/commands/destroy.rb,
lib/gempilot/cli/commands/release.rb

Overview

CLI toolkit for creating and managing Ruby gems.

Defined Under Namespace

Modules: ReleaseTasks, StrictShell Classes: CLI, CommandError, Error, GemConstant, GithubRelease, Origin, Project, VersionTag, VersionTask, ZeitwerkTask

Constant Summary collapse

ROOT =
Pathname(__dir__).parent.expand_path.freeze
LOADER =
Zeitwerk::Loader.for_gem.tap do |l|
  l.inflector.inflect("cli" => "CLI")
  l.push_dir ROOT.join("lib/core_ext")
  l.collapse ROOT.join("lib/core_ext/*/refinements")
  l.setup
end
VERSION =
"0.3.1".freeze
SegmentedVersion =

Arithmetic over the three version shapes gempilot accepts: release (+1.2.3+), tiny release (+1.2.3.1+), and dev prerelease (+1.2.3.dev1+).

Every bump returns the smallest version of the requested shape that is strictly greater than the current version under RubyGems ordering, so bumping always moves a project forward: a dev bump previews the next patch (+1.2.3+ to 1.2.4.dev1) and numeric bumps finalize a dev cycle (+1.2.4.dev2+ to 1.2.4 for :patch).

Data.define(:major, :minor, :patch, :tiny, :dev) do
  def self.parse(string)
    format = /\A(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:\.(?<tiny>\d+)|\.dev(?<dev>\d+))?\z/
    match = format.match(string)
    raise ArgumentError, "cannot parse version: #{string.inspect}" unless match

    new(**match.named_captures.to_h { |name, digits| [name.to_sym, digits&.to_i] })
  end

  def bump(segment)
    case segment.to_sym
    when :major then bump_major
    when :minor then bump_minor
    when :patch then bump_patch
    when :tiny  then bump_tiny
    when :dev   then bump_dev
    else raise ArgumentError, "Unknown segment #{segment.inspect}. Use :major, :minor, :patch, :tiny, or :dev"
    end
  end

  def to_s
    [major, minor, patch, tiny, ("dev#{dev}" if dev)].compact.join(".")
  end

  private

  def bump_major
    return finalize if dev && minor.zero? && patch.zero?

    with(major: major + 1, minor: 0, patch: 0, tiny: nil, dev: nil)
  end

  def bump_minor
    return finalize if dev && patch.zero?

    with(minor: minor + 1, patch: 0, tiny: nil, dev: nil)
  end

  def bump_patch
    dev ? finalize : with(patch: patch + 1, tiny: nil)
  end

  def bump_tiny
    with(tiny: (tiny || 0) + 1, dev: nil)
  end

  def bump_dev
    dev ? with(dev: dev + 1) : with(patch: patch + 1, tiny: nil, dev: 1)
  end

  def finalize
    with(tiny: nil, dev: nil)
  end
end.freeze