Class: GemHadar

Inherits:
Object
  • Object
show all
Extended by:
DSLKit::DSLAccessor
Includes:
Config, PromptTemplate, Utils, Rake::DSL, RbConfig, Term::ANSIColor, Tins::SecureWrite
Defined in:
lib/gem_hadar.rb,
lib/gem_hadar.rb,
lib/gem_hadar/version.rb,
lib/gem_hadar/simplecov.rb

Defined Under Namespace

Modules: GitHub, PromptTemplate, SimpleCov, Utils Classes: RvmConfig, Setup, TemplateCompiler

Constant Summary collapse

VERSION =

GemHadar version

'2.0.3'
VERSION_ARRAY =

:nodoc:

VERSION.split('.').map(&:to_i)
VERSION_MAJOR =

:nodoc:

VERSION_ARRAY[0]
VERSION_MINOR =

:nodoc:

VERSION_ARRAY[1]
VERSION_BUILD =

:nodoc:

VERSION_ARRAY[2]

Instance Method Summary collapse

Methods included from PromptTemplate

#default_git_release_prompt, #default_git_release_system_prompt, #default_version_bump_prompt, #default_version_bump_system_prompt

Methods included from Utils

#xdg_config_filename, #xdg_config_home

Constructor Details

#initialize(&block) ⇒ GemHadar

Returns a new instance of GemHadar.



48
49
50
51
52
# File 'lib/gem_hadar.rb', line 48

def initialize(&block)
  @dependencies = []
  @development_dependencies = []
  block and instance_eval(&block)
end

Instance Method Details

#ask?(prompt, pattern, default: nil) ⇒ MatchData?

The ask? method prompts the user with a message and reads their input It returns a MatchData object if the input matches the provided pattern.

Parameters:

  • prompt (String)

    the message to display to the user

  • pattern (Regexp)

    the regular expression to match against the input

Returns:

  • (MatchData, nil)

    the result of the pattern match or nil if no match



1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
# File 'lib/gem_hadar.rb', line 1471

def ask?(prompt, pattern, default: nil)
  if prompt.include?('%{default}')
    if default.present?
      prompt = prompt % { default: ", default is #{default.inspect}" }
    else
      prompt = prompt % { default: '' }
    end
  end
  STDOUT.print prompt
  answer = STDIN.gets.chomp
  default.present? && answer.blank? and answer = default
  if answer =~ pattern
    $~
  end
end

The assert_valid_link method verifies that the provided URL is valid by checking if it returns an HTTP OK status after following redirects, unless project is still ‘developing`.

following redirects

Parameters:

  • name (String)

    the name associated with the link being validated

  • orig_url (String)

    the URL to validate

Returns:

  • (String)

    the original URL if validation succeeds

Raises:

  • (ArgumentError)

    if the final response is not an HTTP OK status after



1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
# File 'lib/gem_hadar.rb', line 1365

def assert_valid_link(name, orig_url)
  developing and return orig_url
  url = orig_url
  begin
    response = Net::HTTP.get_response(URI.parse(url))
    url = response['location']
  end while response.is_a?(Net::HTTPRedirection)
  response.is_a?(Net::HTTPOK) or
    fail "#{orig_url.inspect} for #{name} has to be a valid link"
  orig_url
end

#build_taskObject

The build_task method defines a Rake task that orchestrates the complete build process for packaging the gem.

This method sets up a :build task that depends on the tasks specified in the build_task_dependencies accessor. It provides a convenient way to execute all necessary steps for building packages for a release with a single command.



234
235
236
237
# File 'lib/gem_hadar.rb', line 234

def build_task
  desc 'Build task (builds all packages for a release)'
  task :build => build_task_dependencies
end

#clean(*args) ⇒ FileList?

The clean method manages the CLEAN file list for Rake tasks.

When called without arguments, it returns the current CLEAN file list. When called with arguments, it adds the specified files to the CLEAN list.

Parameters:

  • args (Array<String>)

    optional list of files to add to the CLEAN list

Returns:

  • (FileList, nil)

    the CLEAN file list when no arguments provided, nil otherwise



263
264
265
266
267
268
269
# File 'lib/gem_hadar.rb', line 263

def clean(*args)
  if args.empty?
    CLEAN
  else
    CLEAN.include(*args)
  end
end

#clobber(*args) ⇒ FileList?

The clobber method manages the CLOBBER file list for Rake tasks.

When called without arguments, it returns the current CLOBBER file list. When called with arguments, it adds the specified files to the CLOBBER list.

Parameters:

  • args (Array<String>)

    optional list of files to add to the CLOBBER list

Returns:

  • (FileList, nil)

    the CLOBBER file list when no arguments provided, nil otherwise



280
281
282
283
284
285
286
# File 'lib/gem_hadar.rb', line 280

def clobber(*args)
  if args.empty?
    CLOBBER
  else
    CLOBBER.include(*args)
  end
end

#compile_taskObject

The compile_task method sets up a Rake task to compile project extensions.

This method creates a :compile task that iterates through the configured extensions and compiles them using the system’s make command.



973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
# File 'lib/gem_hadar.rb', line 973

def compile_task
  for file in extensions
    dir = File.dirname(file)
    clean File.join(dir, 'Makefile'), File.join(dir, '*.{bundle,o,so}')
  end
  desc "Compile extensions: #{extensions * ', '}"
  task :compile do
    for file in extensions
      dir, file = File.split(file)
      cd dir do
        ruby file
        sh make
      end
    end
  end
end

#config_taskObject



1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
# File 'lib/gem_hadar.rb', line 1085

def config_task
  namespace :gem_hadar do
    desc "Display current gem_hadar configuration"
    task :config do
      puts "=== GemHadar Configuration ==="

      # RubyGems
      if ENV['GEM_HOST_API_KEY'].present?
        puts "RubyGems API Key: *** (set)"
      else
        puts "RubyGems API Key: Not set"
      end

      # GitHub
      if ENV['GITHUB_API_TOKEN'].present?
        puts "GitHub API Token: *** (set)"
      else
        puts "GitHub API Token: Not set"
      end

      # Ollama
      puts "Ollama Model: #{ollama_model} (default is #{ollama_model_default})"

      if url = ollama_client&.full?(:base_url)&.to_s
        puts "Ollama Base URL: #{url.inspect}"
      else
        puts "Ollama Base URL: Not set"
      end

      if ENV['OLLAMA_MODEL_OPTIONS']
        puts "Ollama Model Options: #{ENV['OLLAMA_MODEL_OPTIONS']}"
      else
        puts "Ollama Model Options: Not set (using defaults)"
      end

      # XDG config home
      puts "XDG config home: #{xdg_config_home.to_s.inspect}"

      # General
      puts "Gem Name: #{name}"
      puts "Version: #{version}"

      # Build/Development
      puts "MAKE: #{ENV['MAKE'] || 'Not set (will use gmake or make)'}"
      puts "EDITOR: #{ENV['EDITOR'] || 'Not set (will use vi)'}"

      # Git
      puts "Git Remote(s): #{ENV['GIT_REMOTE'] || 'origin'}"

      # Other
      puts "Force Operations: #{ENV['FORCE'] || '0'}"
      puts "Version Override: #{ENV['VERSION'] || 'Not set'}"
      puts "GitHub Release Enabled: #{ENV['GITHUB_RELEASE_ENABLED'] || 'Not set'}"

      puts "\n=== AI Prompt Configuration (Default Values) ==="
      arrow = ?⤵
      puts bold{"version_bump_system_prompt.txt"} + "#{arrow}\n" + italic{default_version_bump_system_prompt}
      puts bold{"version_bump_prompt.txt"} + "#{arrow}\n#{default_version_bump_prompt}"
      puts bold{"release_system_prompt.txt"} + "#{arrow}\n" + italic{default_git_release_system_prompt}
      puts bold{"release_prompt.txt"} + "#{arrow}\n" + italic{default_git_release_prompt}

      puts "=== End Configuration ==="
    end
  end
end

#create_all_tasksGemHadar

The create_all_tasks method sets up and registers all the Rake tasks for the gem project.

Returns:

  • (GemHadar)

    the instance of GemHadar



1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
# File 'lib/gem_hadar.rb', line 1155

def create_all_tasks
  default_task
  config_task
  build_task
  rvm_task
  version_task
  version_show_task
  version_diff_task
  gem_hadar_update_task
  gemspec_task
  gems_install_task
  if test_dir
    test_task
    rcov_task
  end
  spec_task
  package_task
  yard_task
  install_library_task
  version_bump_task
  version_tag_task
  push_task
  release_task
  write_ignore_file
  write_gemfile
  if extensions.full?
    compile_task
    task :prepare_install => :compile
  else
    task :prepare_install
  end
  self
end

#create_git_release_bodyString

The create_git_release_body method generates a changelog for a GitHub release by analyzing the git diff between the previous version and the current HEAD.

It retrieves the log differences, fetches or uses default system and prompt templates, and utilizes an AI model to produce a formatted changelog entry.

Returns:

  • (String)

    the generated changelog content for the release body



875
876
877
878
879
880
# File 'lib/gem_hadar.rb', line 875

def create_git_release_body
  log_diff = version_log_diff(to_version: version)
  system   = xdg_config('release_system_prompt.txt', default_git_release_system_prompt)
  prompt   = xdg_config('release_prompt.txt', default_git_release_prompt) % { name:, version:, log_diff: }
  ollama_generate(system:, prompt:)
end

#default_taskObject

The default_task method defines the default Rake task for the gem project.

This method sets up a Rake task named :default that depends on the tasks specified in the default_task_dependencies accessor. It provides a convenient way to run the most common or essential tasks for the project with a single command.



220
221
222
223
# File 'lib/gem_hadar.rb', line 220

def default_task
  desc 'Default task'
  task :default => default_task_dependencies
end

#dependency(*args) ⇒ Object

The dependency method adds a new runtime dependency to the gem.

Parameters:

  • args (Array)

    the arguments defining the dependency



327
328
329
# File 'lib/gem_hadar.rb', line 327

def dependency(*args)
  @dependencies << args
end

#determine_version_rangeArray(String, String)

Determine the start and end versions for diff comparison.

If the VERSION env var is set, it will be used as the starting version tag. Otherwise, it defaults to the current commit’s version or the latest tag.

Returns:

  • (Array(String, String))

    A fixed-size array containing:

    • The start version (e.g., ‘1.2.3’) from which changes are compared.

    • The end version (e.g., ‘1.2.4’ or ‘HEAD’) up to which changes are compared.



1315
1316
1317
1318
1319
1320
1321
# File 'lib/gem_hadar.rb', line 1315

def determine_version_range
  version_tags = versions.map { version_tag(_1) } + %w[ HEAD ]
  found_version_tag = version_tags.index(version_tag(version))
  found_version_tag.nil? and fail "cannot find version tag #{version_tag(version)}"
  start_version, end_version = version_tags[found_version_tag, 2]
  return start_version, end_version
end

#development_dependency(*args) ⇒ Object

The development_dependency method adds a new development-time dependency to the gem.

Parameters:

  • args (Array)

    the arguments defining the development dependency



335
336
337
# File 'lib/gem_hadar.rb', line 335

def development_dependency(*args)
  @development_dependencies << args
end

#edit_temp_file(content) ⇒ String?

The edit_temp_file method creates a temporary file with the provided content, opens it in an editor for user modification, and returns the updated content.

This method first determines the editor to use from the EDITOR environment variable or defaults to vi. If the editor cannot be found, it issues a warning and returns nil. It then creates a temporary file, writes the initial content to it, and opens the file in the editor. After the user saves and closes the editor, it reads the modified content from the temporary file. The temporary file is automatically cleaned up after use.

file

nil if the editor could not be found or failed

Parameters:

  • content (String)

    the initial content to write to the temporary

Returns:

  • (String, nil)

    the content of the temporary file after editing, or



1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
# File 'lib/gem_hadar.rb', line 1205

def edit_temp_file(content)
  editor = ENV.fetch('EDITOR', `which vi`.chomp)
  unless File.exist?(editor)
    warn "Can't find EDITOR. => Returning."
    return
  end
  temp_file = Tempfile.new(%w[ changelog .md ])
  temp_file.write(content)
  temp_file.close

  unless system("#{editor} #{temp_file.path}")
    warn "#{editor} returned #{$?.exitstatus} => Returning."
    return
  end

  File.read(temp_file.path)
ensure
  temp_file&.close&.unlink
end

#fail(*args) ⇒ Object

The fail method formats and displays failure messages using red colored output.

Parameters:

  • args (Array)

    the array of arguments to be formatted and passed to super



1443
1444
1445
1446
1447
1448
# File 'lib/gem_hadar.rb', line 1443

def fail(*args)
  args.map! do |a|
    a.respond_to?(:to_str) ? color(196) { a.to_str } : a
  end
  super(*args)
end

#gem_filesArray<String>

The gem_files method returns an array of files that are included in the gem package.

It calculates this by subtracting the files listed in package_ignore_files from the list of all files.

Returns:

  • (Array<String>)

    the list of files to include in the gem package



1494
1495
1496
# File 'lib/gem_hadar.rb', line 1494

def gem_files
  (files.to_a - package_ignore_files.to_a)
end

#gem_hadar_update_taskObject

The gem_hadar_update_task method defines a Rake task that updates the gem_hadar dependency version in the gemspec file.

This method creates a :gem_hadar:update task under the Rake namespace that prompts the user to specify a new gem_hadar version. It then reads the existing gemspec file, modifies the version constraint for the gem_hadar dependency, and writes the updated content back to the file. If the specified version is already present in the gemspec, it skips the update and notifies the user.



491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
# File 'lib/gem_hadar.rb', line 491

def gem_hadar_update_task
  namespace :gem_hadar do
    desc 'Update gem_hadar to a different version'
    task :update do
      answer = ask?("Which gem_hadar version? ", /^((?:\d+.){2}(?:\d+))$/)
      unless answer
        warn "Invalid version specification!"
        exit 1
      end
      gem_hadar_version = answer[0]
      filename = "#{name}.gemspec"
      old_data = File.read(filename)
      new_data = old_data.gsub(
        /(add_(?:development_)?dependency\(%q<gem_hadar>, \["~> )([\d.]+)("\])/
      ) { "#$1#{gem_hadar_version}#$3" }
      if old_data == new_data
        warn "#{filename.inspect} already depends on gem_hadar "\
          "#{gem_hadar_version} => Do nothing."
      else
        warn "Upgrading #{filename.inspect} to #{gem_hadar_version}."
        secure_write(filename) do |spec|
          spec.write new_data
        end
      end
    end
  end
end

#gem_push_taskObject

The gem_push_task method defines a Rake task for pushing the generated gem file to RubyGems.

This method sets up a :gem:push task under the Rake namespace that handles the process of uploading the gem package to RubyGems. It checks if the project is in developing mode and skips the push operation if so. Otherwise, it verifies the existence of the gem file, prompts the user for confirmation before pushing, and uses the gem push command with an optional API key from the environment. If the gem file does not exist or the user declines to push, appropriate messages are displayed and the task exits accordingly.



821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
# File 'lib/gem_hadar.rb', line 821

def gem_push_task
  namespace :gem do
    path = "pkg/#{name_version}.gem"
    desc "Push gem file #{File.basename(path)} to rubygems"
    if developing
      task :push => :build do
        puts "Skipping push to rubygems while developing mode is enabled."
      end
    else
      task :push => :build do
        if File.exist?(path)
          if ask?("Do you really want to push #{path.inspect} to rubygems? "\
              "(yes/NO) ", /\Ayes\z/i)
            then
            key = ENV['GEM_HOST_API_KEY'].full? { |k| "--key #{k} " }
            sh "gem push #{key}#{path}"
          else
            exit 1
          end
        else
          warn "Cannot push gem to rubygems: #{path.inspect} doesn't exist."
          exit 1
        end
      end
    end
  end
end

#gems_install_task(&block) ⇒ Object

The gems_install_task method defines a Rake task for installing all gem dependencies specified in the Gemfile.

This method sets up a :gems:install task that executes a block to install gems. If no block is provided, it defaults to running ‘bundle install’.

Parameters:

  • block (Proc)

    optional block containing the installation command



346
347
348
349
350
351
352
# File 'lib/gem_hadar.rb', line 346

def gems_install_task(&block)
  block ||= proc {  sh 'bundle install' }
  desc 'Install all gems from the Gemfile'
  namespace :gems do
    task :install => :gemspec , &block
  end
end

#gemspecGem::Specification

The gemspec method creates and returns a new Gem::Specification object that defines the metadata and dependencies for the gem package.

Returns:

  • (Gem::Specification)

    a fully configured Gem specification object



1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
# File 'lib/gem_hadar.rb', line 1381

def gemspec
  Gem::Specification.new do |s|
    s.name        = name
    s.version     = ::Gem::Version.new(version)
    s.author      = author
    s.email       = email
    s.homepage    = assert_valid_link(:homepage, homepage)
    s.summary     = summary
    s.description = description

    gem_files.full? { |f| s.files = Array(f) }
    test_files.full? { |t| s.test_files = Array(t) }
    extensions.full? { |e| s.extensions = Array(e) }
    bindir.full? { |b| s.bindir = b }
    executables.full? { |e| s.executables = Array(e) }
    licenses.full? { |l| s.licenses = Array(licenses) }
    post_install_message.full? { |m| s.post_install_message = m }

    required_ruby_version.full? { |v| s.required_ruby_version = v }
    s.add_development_dependency('gem_hadar', "~> #{VERSION[/\A\d+\.\d+/, 0]}")
    for d in @development_dependencies
      s.add_development_dependency(*d)
    end
    for d in @dependencies
      if s.respond_to?(:add_runtime_dependency)
        s.add_runtime_dependency(*d)
      else
        s.add_dependency(*d)
      end
    end

    require_paths.full? { |r| s.require_paths = Array(r) }

    if title
      s.rdoc_options << '--title' << title
    else
      s.rdoc_options << '--title' << "#{name.camelize} - #{summary}"
    end
    if readme
      if File.exist?(readme)
        s.rdoc_options << '--main' << readme
        s.extra_rdoc_files << readme
      else
        warn "Add a #{readme} file to document your gem!"
      end
    end
    doc_files.full? { |df| s.extra_rdoc_files.concat Array(df) }
  end
end

#gemspec_taskObject

The gemspec_task method defines a Rake task that generates and writes a gemspec file for the project.

This method creates a :gemspec task that depends on the :version task, ensuring the version is set before generating the gemspec. It constructs the filename based on the project name, displays a warning message indicating the file being written, and uses secure_write to create the gemspec file with content generated by the gemspec method.



527
528
529
530
531
532
533
534
# File 'lib/gem_hadar.rb', line 527

def gemspec_task
  desc 'Create a gemspec file'
  task :gemspec => :version do
    filename = "#{name}.gemspec"
    warn "Writing to #{filename.inspect} for #{version}"
    secure_write(filename, gemspec.to_ruby)
  end
end

#git_remoteObject

The git_remote method retrieves the primary Git remote name configured for the project.

It first checks the GIT_REMOTE environment variable for a custom remote specification. If not set, it defaults to ‘origin’. When multiple remotes are specified in the environment variable, only the first one is returned.



722
723
724
# File 'lib/gem_hadar.rb', line 722

def git_remote
  ENV.fetch('GIT_REMOTE', 'origin').split(/\s+/).first
end

#git_remotesArray<String>

The git_remotes method retrieves the list of remote repositories configured for the current Git project.

It first attempts to read the remotes from the ENV environment variable, splitting it by whitespace. If this is not available, it falls back to querying the local Git repository using ‘git remote`.

Returns:

  • (Array<String>)

    an array of remote names



1458
1459
1460
1461
1462
# File 'lib/gem_hadar.rb', line 1458

def git_remotes
  remotes = ENV['GIT_REMOTE'].full?(:split, /\s+/)
  remotes or remotes = `git remote`.lines.map(&:chomp)
  remotes
end

#git_remotes_taskObject

The git_remotes_task method defines a Rake task that displays all Git remote repositories configured for the project.

This method sets up a :git_remotes task under the Rake namespace that retrieves and prints the list of Git remotes along with their URLs. It uses the git_remotes method to obtain the remote names and then fetches each remote’s URL using the ‘git remote get-url` command. The output is formatted to show each remote name followed by its corresponding URL on separate lines.



858
859
860
861
862
863
864
865
# File 'lib/gem_hadar.rb', line 858

def git_remotes_task
  task :git_remotes do
    puts git_remotes.map { |r|
      url = `git remote get-url #{r.inspect}`.chomp
      "#{r} #{url}"
    }
  end
end

#github_release_taskObject

The github_release_task method defines a Rake task that creates a GitHub release for the current version.

This method sets up a :github:release task that prompts the user to confirm publishing a release message on GitHub. It retrieves the GitHub API token from the environment, derives the repository owner and name from the git remote URL, generates a changelog using AI, and creates the release via the GitHub API.



890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
# File 'lib/gem_hadar.rb', line 890

def github_release_task
  namespace :github do
    unless github_api_token = ENV['GITHUB_API_TOKEN'].full?
      warn "GITHUB_API_TOKEN not set. => Skipping github release task."
      task :release
      return
    end
    desc "Create a new GitHub release for the current version with a AI-generated changelog"
    task :release do
      yes = ask?(
        "Do you want to publish a release message on github? (y/n%{default}) ",
        /\Ay/i, default: ENV['GITHUB_RELEASE_ENABLED']
      )
      unless yes
          warn "Skipping publication of a github release message."
          next
      end
      if %r(\A/*(?<owner>[^/]+)/(?<repo>[^/.]+)) =~ github_remote_url&.path
        rc = GitHub::ReleaseCreator.new(owner:, repo:, token: github_api_token)
        tag_name         = version_tag(version)
        target_commitish = `git show -s --format=%H #{tag_name.inspect}^{commit}`.chomp
        body             = edit_temp_file(create_git_release_body)
        if body.present?
          begin
            response = rc.perform(tag_name:, target_commitish:, body:)
            puts "Release created successfully! See #{response.html_url}"
          rescue => e
            warn e.message
          end
        else
          warn "Skipping creation of github release message."
        end
      else
        warn "Could not derive github remote url from git remotes. => Skipping github release task."
      end
    end
  end
end

#github_remote_urlURI?

The github_remote_url method retrieves and parses the GitHub remote URL from the local Git configuration.

It executes ‘git remote -v` to get all remote configurations, extracts the push URLs, processes them to construct valid URIs, and returns the first URI pointing to GitHub.com.

Returns:

  • (URI, nil)

    The parsed GitHub remote URI or nil if not found.



1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
# File 'lib/gem_hadar.rb', line 1545

def github_remote_url
  if remotes = `git remote -v`
    remotes_urls = remotes.scan(/^(\S+)\s+(\S+)\s+\(push\)/)
    remotes_uris = remotes_urls.map do |name, url|
      if %r(\A(?<scheme>[^@]+)@(?<hostname>[A-Za-z0-9.]+):(?:\d*)(?<path>.*)) =~ url
        path = ?/ + path unless path.start_with? ?/
        url = 'ssh://%s@%s%s' % [ scheme, hostname, path ] # approximate correct URIs
      end
      URI.parse(url)
    end
    remotes_uris.find { |uri| uri.hostname == 'github.com' }
  end
end

#has_to_be_set(name) ⇒ Object

The has_to_be_set method raises an error if a required gem configuration attribute is not set.

Parameters:

  • name (String)

    the name of the required attribute

Raises:

  • (ArgumentError)

    if the specified attribute has not been set



60
61
62
# File 'lib/gem_hadar.rb', line 60

def has_to_be_set(name)
  fail "#{self.class}: #{name} has to be set for gem"
end

#ignore(*args) ⇒ Set<String>?

The ignore method manages the list of files to be ignored by the gem.

When called without arguments, it returns the current set of ignored files. When called with arguments, it adds the specified files to the ignore list.

Parameters:

  • args (Array<String>)

    optional list of file patterns to add to the ignore list

Returns:

  • (Set<String>, nil)

    the set of ignored files when no arguments provided, nil otherwise



297
298
299
300
301
302
303
# File 'lib/gem_hadar.rb', line 297

def ignore(*args)
  if args.empty?
    ignore_files
  else
    args.each { |a| ignore_files << a }
  end
end

#install_library(&block) ⇒ Object

The install_library method sets up a Rake task for installing the library or executable into site_ruby directories.

This method configures an :install task that depends on the :prepare_install task and executes the provided block. It stores the block in an instance variable to be called later when the task is executed.

Parameters:

  • block (Proc)

    the block containing the installation logic



247
248
249
250
251
252
# File 'lib/gem_hadar.rb', line 247

def install_library(&block)
  @install_library_block = -> do
    desc 'Install executable/library into site_ruby directories'
    task :install => :prepare_install, &block
  end
end

#install_library_taskObject

The install_library_task method executes the installed library task block if it has been defined.



552
553
554
# File 'lib/gem_hadar.rb', line 552

def install_library_task
  @install_library_block.full?(:call)
end

#master_prepare_taskObject

The master_prepare_task method defines a Rake task that sets up a remote Git repository for the project.

This method creates a :master:prepare task under the Rake namespace that guides the user through creating a new bare Git repository on a remote server via SSH. It prompts for the remote name, directory path, and SSH account details to configure the repository and establish a connection back to the local project.



734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
# File 'lib/gem_hadar.rb', line 734

def master_prepare_task
  namespace :master do
    desc "Prepare a remote git repository for this project"
    task :prepare do
      puts "Create a new remote git repository for #{name.inspect}"
      remote_name = ask?('Name (default: origin) ? ', /^.+$/).
        full?(:[], 0) || 'origin'
      dir         = ask?("Directory (default: /git/#{name}.git)? ", /^.+$/).
        full?(:[], 0) || "/git/#{name}.git"
       = ask?('SSH account (format: login@host)? ', /^[^@]+@[^@]+/).
        full?(:[], 0) || exit(1)
      sh "ssh #{} 'git init --bare #{dir}'"
      sh "git remote add -m master #{remote_name} #{}:#{dir}"
    end
  end
end

#master_push_taskObject

The master_push_task method defines Rake tasks for pushing the master branch to configured Git remotes.

This method sets up a hierarchical task structure under the :master namespace:

  • It creates subtasks in the :master:push namespace for each configured Git remote, allowing individual pushes to specific remotes.

  • It also defines a top-level :master:push task that depends on all the individual remote push tasks, enabling a single command to push the master branch to all remotes.

The tasks utilize the git_remotes method to determine which remotes are configured and generate appropriate push commands for each one.



794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
# File 'lib/gem_hadar.rb', line 794

def master_push_task
  namespace :master do
    git_remotes.each do |gr|
      namespace gr.to_sym do
        desc "Push master to git remote #{gr}"
        task :push do
          sh "git push #{gr} master"
        end
      end
    end

    desc "Push master #{version} to all git remotes: #{git_remotes * ' '}"
    task :push => git_remotes.map { |gr| :"master:#{gr}:push" }
  end
end

#ollama_clientOllama::Client?

The ollama_client method creates and returns an Ollama::Client instance configured with a base URL derived from environment variables.

It first checks for the OLLAMA_URL environment variable to determine the base URL. If that is not set, it falls back to using the OLLAMA_HOST environment variable, defaulting to ‘localhost:11434’ if that is also not set. The method then constructs the full base URL and initializes an Ollama::Client with appropriate timeouts for read and connect operations.

Returns:

  • (Ollama::Client, nil)

    An initialized Ollama::Client instance if a valid base URL is present, otherwise nil.



1269
1270
1271
1272
1273
1274
1275
1276
1277
# File 'lib/gem_hadar.rb', line 1269

def ollama_client
  base_url = ENV['OLLAMA_URL']
  if base_url.blank?
    host = ENV.fetch('OLLAMA_HOST', 'localhost:11434')
    base_url = 'http://%s' % host
  end
  base_url.present? or return
  ollama = Ollama::Client.new(base_url:, read_timeout: 600, connect_timeout: 60)
end

#ollama_generate(system:, prompt:) ⇒ String?

Generates a response from an AI model using the Ollama::Client.

Parameters:

  • system (String)

    The system prompt for the AI model.

  • prompt (String)

    The user prompt to generate a response to.

Returns:

  • (String, nil)

    The generated response or nil if generation fails.



1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
# File 'lib/gem_hadar.rb', line 1284

def ollama_generate(system:, prompt:)
  unless ollama = ollama_client
    warn "Ollama is not configured. => Returning."
    return
  end
  model    = ollama_model
  options  = ENV['OLLAMA_MODEL_OPTIONS'].full? { |o| JSON.parse(o) } || {}
  options |= { "temperature" => 0, "top_p" => 1, "min_p" => 0.1 }
  ollama.generate(model:, system:, prompt:, options:, stream: false, think: false).response
end

#ollama_modelString

The ollama_model method retrieves the name of the Ollama AI model to be used for generating responses.

It first checks the OLLAMA_MODEL environment variable for a custom model specification. If the environment variable is not set, it falls back to using the default model name, which is determined by the ollama_model_default dsl method.

Returns:

  • (String)

    the name of the Ollama AI model to be used



1255
1256
1257
# File 'lib/gem_hadar.rb', line 1255

def ollama_model
  ENV.fetch('OLLAMA_MODEL', ollama_model_default)
end

#package_ignore(*args) ⇒ Set<String>?

The package_ignore method manages the list of files to be ignored during gem packaging.

When called without arguments, it returns the current set of package ignore files. When called with arguments, it adds the specified file patterns to the package ignore list.

Parameters:

  • args (Array<String>)

    optional list of file patterns to add to the package ignore list

Returns:

  • (Set<String>, nil)

    the set of package ignore files when no arguments provided, nil otherwise



316
317
318
319
320
321
322
# File 'lib/gem_hadar.rb', line 316

def package_ignore(*args)
  if args.empty?
    package_ignore_files
  else
    args.each { |a| package_ignore_files << a }
  end
end

#package_taskObject

The package_task method sets up a Rake task for packaging the gem.

This method configures a task that creates a package directory, initializes a Gem::PackageTask with the current gem specification, and specifies that tar files should be created. It also includes the files to be packaged by adding gem_files to the package_files attribute of the Gem::PackageTask.



542
543
544
545
546
547
548
# File 'lib/gem_hadar.rb', line 542

def package_task
  clean 'pkg'
  Gem::PackageTask.new(gemspec) do |pkg|
    pkg.need_tar      = true
    pkg.package_files += gem_files
  end
end

#push_taskObject

The push_task method defines a Rake task that orchestrates the complete process of pushing changes and artifacts to remote repositories and package managers.

This method sets up multiple subtasks including preparing the master branch, pushing version tags, pushing to gem repositories, and creating GitHub releases. It also includes a check for uncommitted changes before proceeding with the push operations.



939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
# File 'lib/gem_hadar.rb', line 939

def push_task
  master_prepare_task
  version_push_task
  master_push_task
  gem_push_task
  git_remotes_task
  github_release_task
  task :modified do
    changed_files = `git status --porcelain`.gsub(/^\s*\S\s+/, '').lines
    unless changed_files.empty?
      warn "There are still modified files:\n#{changed_files * ''}"
      exit 1
    end
  end
  desc "Push all changes for version #{version} into the internets."
  task :push => push_task_dependencies
end

#rcov_taskObject

The rcov_task method sets up a Rake task for executing code coverage tests using RCov.

This method configures a :rcov task that runs the project’s test suite with RCov to generate code coverage reports. It includes the test directory and required paths in the load path, specifies the test files to run, and enables verbose output. The task also conditionally depends on the :compile task if project extensions are present. If RCov is not available, it displays a warning message suggesting to install RCov.



601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
# File 'lib/gem_hadar.rb', line 601

def rcov_task
  if defined?(::Rcov)
    rt = ::Rcov::RcovTask.new(:run_rcov) do |t|
      t.libs << test_dir
      t.libs.concat require_paths.to_a
      t.libs.uniq!
      t.test_files = test_files
      t.verbose    = true
      t.rcov_opts  = %W[-x '\\b#{test_dir}\/' -x '\\bgems\/']
    end
    desc 'Run the rcov code coverage tests'
    task :rcov => [ (:compile if extensions.full?), rt.name ].compact
    clobber 'coverage'
  else
    desc 'Run the rcov code coverage tests'
    task :rcov do
      warn "rcov doesn't work for some reason, have you tried 'gem install rcov'?"
    end
  end
end

#release_taskObject

The release_task method defines a Rake task that orchestrates the complete release process for the gem.

This method sets up a :release task that depends on the :push task, ensuring all necessary steps for publishing the gem are executed in sequence. It provides a convenient way to perform a full release workflow with a single command.



964
965
966
967
# File 'lib/gem_hadar.rb', line 964

def release_task
  desc "Release the new version #{version} for the gem #{name}."
  task :release => :push
end

#require_path(path = nil) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/gem_hadar.rb', line 98

def require_path(path = nil)
  if path
    self.require_paths = Set[path]
  else
    require_paths.first
  end
end

#rvm(&block) ⇒ GemHadar::RvmConfig

The rvm method configures RVM (Ruby Version Manager) settings for the gem project.

This method initializes and returns an RvmConfig object that holds RVM-specific configuration such as the Ruby version to use and the gemset name. If a block is provided, it configures the RvmConfig object with the given settings. If no block is provided and no existing RvmConfig object exists, it creates a new one with default settings.

Parameters:

  • block (Proc)

    optional block to configure RVM settings

Returns:



203
204
205
206
207
208
209
210
# File 'lib/gem_hadar.rb', line 203

def rvm(&block)
  if block
    @rvm = RvmConfig.new(&block)
  elsif !@rvm
    @rvm = RvmConfig.new { }
  end
  @rvm
end

#rvm_taskObject

The rvm_task method creates a .rvmrc file that configures RVM to use the specified Ruby version and gemset for the project.

This task generates a .rvmrc file in the project root directory with commands to:

  • Use the Ruby version specified by the rvm.use accessor

  • Create the gemset specified by the rvm.gemset accessor

  • Switch to using that gemset

The generated file is written using the secure_write method to ensure proper file permissions.



1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
# File 'lib/gem_hadar.rb', line 1000

def rvm_task
  desc 'Create .rvmrc file'
  task :rvm do
    secure_write('.rvmrc') do |output|
      output.write <<~EOT
        rvm use #{rvm.use}
        rvm gemset create #{rvm.gemset}
        rvm gemset use #{rvm.gemset}
      EOT
    end
  end
end

#spec_taskObject

The spec_task method sets up a Rake task for executing RSpec tests.

This method configures a :spec task that runs the project’s RSpec test suite. It initializes an RSpec::Core::RakeTask with appropriate Ruby options, test pattern, and verbose output. The task also conditionally depends on the :compile task if project extensions are present.



581
582
583
584
585
586
587
588
589
590
# File 'lib/gem_hadar.rb', line 581

def spec_task
  defined? ::RSpec::Core::RakeTask or return
  st =  RSpec::Core::RakeTask.new(:run_specs) do |t|
    t.ruby_opts ||= ''
    t.ruby_opts << ' -I' << ([ spec_dir ] + require_paths.to_a).uniq * ':'
    t.pattern = spec_pattern
    t.verbose = true
  end
  task :spec => [ (:compile if extensions.full?), st.name ].compact
end

#test_taskObject

The test_task method sets up a Rake task for executing the project’s test suite.

This method configures a Rake task named :test that runs the test suite using Rake::TestTask. It includes the test directory and required paths in the load path, specifies the test files to run, and enables verbose output. The task also conditionally depends on the :compile task if project extensions are present.



564
565
566
567
568
569
570
571
572
573
# File 'lib/gem_hadar.rb', line 564

def test_task
  tt =  Rake::TestTask.new(:run_tests) do |t|
    t.libs << test_dir
    t.libs.concat require_paths.to_a
    t.test_files = test_files
    t.verbose    = true
  end
  desc 'Run the tests'
  task :test => [ (:compile if extensions.full?), tt.name ].compact
end

#version_bump_taskObject

The version_bump_task method defines Rake tasks for incrementing the gem’s version number.

This method sets up a hierarchical task structure under the :version namespace:

  • It creates subtasks in the :version:bump namespace for explicitly bumping

major, minor, or build versions.

  • It also defines a :version:bump task that automatically suggests the

appropriate version bump type by analyzing recent changes using AI. The suggestion is based on the git log diff between the previous version and the current HEAD, and it prompts the user for confirmation before applying the bump.

The tasks utilize the version_log_diff method to gather change information, the ollama_generate method to get AI-powered suggestions, and the version_bump_to method to perform the actual version update.



639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
# File 'lib/gem_hadar.rb', line 639

def version_bump_task
  namespace :version do
    namespace :bump do
      desc 'Bump major version'
      task :major do
        version_bump_to(:major)
      end

      desc 'Bump minor version'
      task :minor do
        version_bump_to(:minor)
      end

      desc 'Bump build version'
      task :build do
        version_bump_to(:build)
      end
    end

    desc 'Bump version with AI suggestion'
    task :bump do
      log_diff = version_log_diff(from_version: nil, to_version: 'HEAD')
      system   = xdg_config('version_bump_system_prompt.txt', default_version_bump_system_prompt)
      prompt   = xdg_config('version_bump_prompt.txt', default_version_bump_prompt) % { version:, log_diff: }
      response = ollama_generate(system:, prompt:)
      puts response
      default = nil
      if response =~ /(major|minor|build)\s*$/
        default = $1
      end
      response = ask?(
        'Bump a major, minor, or build version%{default}? ',
        /\A(major|minor|build)\z/,
        default:
      )
      if version_type = response&.[](1)
        version_bump_to(version_type)
      else
        exit 1
      end
    end
  end
end

#version_bump_to(type) ⇒ Object

Increases the specified part of the version number and writes it back to the VERSION file.

Parameters:

  • type (Symbol, String)

    The part of the version to bump (:major, :minor, or :build)



1299
1300
1301
1302
1303
1304
1305
# File 'lib/gem_hadar.rb', line 1299

def version_bump_to(type)
  type    = type.to_sym
  version = File.read('VERSION').chomp.version
  version.bump(type)
  secure_write('VERSION') { |v| v.puts version }
  exit 0
end

#version_diff_taskObject

The version_diff_task method defines Rake tasks for listing and displaying git version differences.

This method sets up two subtasks under the :version namespace:

  • A :list task that fetches all git tags, ensures the operation succeeds,

and outputs the sorted list of versions.

  • A :diff task that calculates the version range, displays a colored diff

between the versions, and shows the changes.



464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
# File 'lib/gem_hadar.rb', line 464

def version_diff_task
  namespace :version do
    desc "List all versions in order"
    task :list do
      system 'git fetch --tags'
      $?.success? or exit $?.exitstatus
      puts versions
    end

    desc "Displaying the diff from env var VERSION to the next version or HEAD"
    task :diff do
      start_version, end_version = determine_version_range
      puts color(172) { "Showing diff from version %s to %s:" % [ start_version, end_version ] }
      puts `git diff --color=always #{start_version}..#{end_version}`
    end
  end
end

#version_log_diff(to_version: 'HEAD', from_version: nil) ⇒ String

The version_log_diff method generates a git log output containing patch differences between two specified versions.

This method retrieves the commit history between a starting version and an ending version, including detailed changes (patch format) for each commit. It supports comparing against the current HEAD or specific version tags, and automatically determines the appropriate previous version when only a target version is provided.

Parameters:

  • to_version (String) (defaults to: 'HEAD')

    the ending version tag or ‘HEAD’ to compare up to the latest commit

  • from_version (String, nil) (defaults to: nil)

    the starting version tag; if nil, it defaults based on to_version

Returns:

  • (String)

    the git log output in patch format showing changes between the two versions

Raises:

  • (RuntimeError)

    if the specified version tags are not found in the repository



423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/gem_hadar.rb', line 423

def version_log_diff(to_version: 'HEAD', from_version: nil)
  if to_version == 'HEAD'
    if from_version.blank?
      from_version = versions.last
    else
      unless versions.find { |v| v == from_version }
        fail "Could not find #{from_version.inspect}."
      end
    end
    `git log -p #{version_tag(from_version)}..HEAD`
  else
    unless versions.find { |v| v == to_version }
      fail "Could not find #{to_version.inspect}."
    end
    if from_version.blank?
      from_version = versions.each_cons(2).find do |previous_version, v|
        if v == to_version
          break previous_version
        end
      end
      unless from_version
        return `git log -p #{version_tag(to_version)}`
      end
    else
      unless versions.find { |v| v == from_version }
        fail "Could not find #{from_version.inspect}."
      end
    end
    `git log -p #{version_tag(from_version)}..#{version_tag(to_version)}`
  end
end

#version_push_taskObject

The version_push_task method defines Rake tasks for pushing version tags to Git remotes.

This method sets up a hierarchical task structure under the :version namespace:

  • It creates subtasks in the :version:push namespace for each configured

Git remote, allowing individual pushes to specific remotes.

  • It also defines a top-level :version:push task that depends on all the

individual remote push tasks, enabling a single command to push the version tag to all remotes.

The tasks utilize the git_remotes method to determine which remotes are configured and generate appropriate push commands for each one.



765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
# File 'lib/gem_hadar.rb', line 765

def version_push_task
  namespace :version do
    git_remotes.each do |gr|
      namespace gr.to_sym do
        desc "Push version #{version} to git remote #{gr}"
        task :push do
          sh "git push #{gr} v#{version}"
        end
      end
    end

    desc "Push version #{version} to all git remotes: #{git_remotes * ' '}"
    task :push => git_remotes.map { |gr| :"version:#{gr}:push" }
  end
end

#version_show_taskObject

The version_show_task method defines a Rake task that displays the current version of the gem.

This method creates a :version:show task under the Rake namespace that reads the version from the generated version file in the lib directory and compares it with the version specified in the GemHadar configuration. It then outputs a message indicating whether the versions match or not.



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/gem_hadar.rb', line 390

def version_show_task
  namespace :version do
    desc "Displaying the current version"
    task :show do
      require path_name
      dir = File.join('lib', path_name)
      version_file = File.join(dir, 'version.rb')
      m = Module.new
      m.instance_eval File.read(version_file)
      version_rb   = m.const_get(
        [ path_module, 'VERSION' ] * '::'
      )
      equal        = version == version_rb ? '==' : '!='
      puts "version.rb=#{version_rb} #{equal} VERSION=#{version}"
    end
  end
end

#version_tag(version) ⇒ String

The version_tag method prepends a ‘v’ prefix to the given version string, unless it’s HEAD.

Parameters:

  • version (String)

    the version string to modify

Returns:

  • (String)

    the modified version string with a ‘v’ prefix



1520
1521
1522
1523
1524
1525
1526
# File 'lib/gem_hadar.rb', line 1520

def version_tag(version)
  if version != 'HEAD'
    version.dup.prepend ?v
  else
    version.dup
  end
end

#version_tag_taskObject

The version_tag_task method defines a Rake task that creates a Git tag for the current version.

This method sets up a :version:tag task under the Rake namespace that creates an annotated Git tag for the project’s current version. It checks if a tag with the same name already exists and handles the case where the tag exists but is different from the current commit. If the tag already exists and is different, it prompts the user to confirm whether to overwrite it forcefully.



692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
# File 'lib/gem_hadar.rb', line 692

def version_tag_task
  namespace :version do
    desc "Tag this commit as version #{version}"
    task :tag do
      force = ENV['FORCE'].to_i == 1
      begin
        sh "git tag -a -m 'Version #{version}' #{'-f' if force} #{version_tag(version)}"
      rescue RuntimeError
        if `git diff v#{version}..HEAD`.empty?
          puts "Version #{version} is already tagged, but it's no different"
        else
          if ask?("Different version tag #{version} already exists. Overwrite with "\
              "force? (yes/NO) ", /\Ayes\z/i)
            force = true
            retry
          else
            exit 1
          end
        end
      end
    end
  end
end

#version_taskObject

The version_task method defines a Rake task that generates a version file for the gem.

This method creates a task named :version that writes version information to a Ruby file in the lib directory. The generated file contains constants for the version and its components, as well as an optional epilogue section. The task ensures the target directory exists and uses secure file writing to prevent permission issues.



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/gem_hadar.rb', line 362

def version_task
  desc m = "Writing version information for #{name}-#{version}"
  task :version do
    puts m
    mkdir_p dir = File.join('lib', path_name)
    secure_write(File.join(dir, 'version.rb')) do |v|
      v.puts <<~EOT
        #{module_type} #{path_module}
          # #{path_module} version
          VERSION         = '#{version}'
          VERSION_ARRAY   = VERSION.split('.').map(&:to_i) # :nodoc:
          VERSION_MAJOR   = VERSION_ARRAY[0] # :nodoc:
          VERSION_MINOR   = VERSION_ARRAY[1] # :nodoc:
          VERSION_BUILD   = VERSION_ARRAY[2] # :nodoc:
        end
      EOT
      version_epilogue.full? { |ve| v.puts ve }
    end
  end
end

#version_untag(version_tag) ⇒ String

The version_untag method removes the ‘v’ prefix from a version tag string.

Parameters:

  • version_tag (String)

    the version tag string that may start with ‘v’

Returns:

  • (String)

    the version string with the ‘v’ prefix removed



1533
1534
1535
# File 'lib/gem_hadar.rb', line 1533

def version_untag(version_tag)
  version.sub(/\Av/, '')
end

#versionsArray<String>

The versions method retrieves and processes the list of git tags that match semantic versioning patterns.

It executes ‘git tag` to get all available tags, filters them using a regular expression to identify valid version strings, removes any ’v’ prefix from each version string, trims whitespace, and sorts the resulting array based on semantic versioning order.

order according to semantic versioning rules.

Returns:

  • (Array<String>)

    an array of version strings sorted in ascending



1508
1509
1510
1511
1512
1513
# File 'lib/gem_hadar.rb', line 1508

memoize method:
def versions
  `git tag`.lines.grep(/^v?\d+\.\d+\.\d+$/).map(&:chomp).map {
    _1.sub(/\Av/, '')
  }.sort_by(&:version)
end

#warn(*msgs) ⇒ Object

The warn method displays warning messages using orange colored output.

Parameters:

  • msgs (Array<String>)

    the array of message strings to display



1434
1435
1436
1437
# File 'lib/gem_hadar.rb', line 1434

def warn(*msgs)
  msgs.map! { |m| color(208) { m } }
  super(*msgs, uplevel: 1)
end

#write_gemfileObject

The write_gemfile method creates and writes the default Gemfile content if it doesn’t exist. If a custom Gemfile exists, it only displays a warning.



1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
# File 'lib/gem_hadar.rb', line 1333

def write_gemfile
  default_gemfile =<<~EOT
    # vim: set filetype=ruby et sw=2 ts=2:

    source 'https://rubygems.org'

    gemspec
  EOT
  current_gemfile = File.exist?('Gemfile') && File.read('Gemfile')
  case current_gemfile
  when false
    secure_write('Gemfile') do |output|
      output.write default_gemfile
    end
  when default_gemfile
    ;;
  else
    warn "INFO: Current Gemfile differs from default Gemfile."
  end
end

#write_ignore_fileObject

The write_ignore_file method writes the current ignore_files configuration to a .gitignore file in the project root directory.



1325
1326
1327
1328
1329
# File 'lib/gem_hadar.rb', line 1325

def write_ignore_file
  secure_write('.gitignore') do |output|
    output.puts(ignore.sort)
  end
end

#yard_doc_taskObject



1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
# File 'lib/gem_hadar.rb', line 1013

def yard_doc_task
  YARD::Rake::YardocTask.new(:yard_doc) do |t|
    t.files = files.select { _1 =~ /\.rb\z/ }

    output_dir = yard_dir
    t.options = [ "--output-dir=#{output_dir}" ]

    # Include private & protected methods in documentation
    t.options << '--private' << '--protected'

    # Handle readme if present
    if readme && File.exist?(readme)
      t.options << "--readme=#{readme}"
    end

    # Add additional documentation files
    if doc_files&.any?
      t.files.concat(doc_files.flatten)
    end

    # Add before hook for cleaning
    t.before = proc {
      clean output_dir
      puts "Generating full documentation in #{output_dir}..."
    }
  end
end

#yard_taskObject

The yard_task method sets up and registers Rake tasks for generating and managing YARD documentation.

It creates multiple subtasks under the :yard namespace, including tasks for creating private documentation, viewing the generated documentation, cleaning up documentation files, and listing undocumented elements. If YARD is not available, the method returns early without defining any tasks.



1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
# File 'lib/gem_hadar.rb', line 1048

def yard_task
  defined? YARD or return
  yard_doc_task
  desc 'Create yard documentation (including private)'
  task :doc => :yard_doc
  namespace :yard do
    my_yard_dir = Pathname.new(yard_dir)

    task :private => :yard_doc

    task :public => :yard_doc

    desc 'Create yard documentation'
    task :doc => :yard_doc

    desc 'View the yard documentation'
    task :view do
      index_file = my_yard_dir + 'index.html'
      File.exist?(index_file)
      sh "open #{index_file}"
    end

    desc 'Clean the yard documentation'
    task :clean do
      rm_rf my_yard_dir
    end

    desc 'List all undocumented classes/modules/methods'
    task :'list-undoc' do
      sh "yard stats --list-undoc"
    end
  end

  desc 'Create the yard documentation and view it'
  task :yard => %i[ yard:private yard:view ]
end