class Manifestly::CLI
Public Class Methods
exit_on_failure?()
click to toggle source
github.com/erikhuda/thor/issues/244 stackoverflow.com/a/18490048/1664216
# File lib/manifestly/cli.rb, line 17 def self.exit_on_failure? true end
file_option(description_action=nil)
click to toggle source
# File lib/manifestly/cli.rb, line 51 def self.file_option(description_action=nil) description = "The local manifest file" description += " to #{description_action}" if description_action method_option :file, desc: description, type: :string, banner: '', required: true end
repo_file_option(description=nil)
click to toggle source
# File lib/manifestly/cli.rb, line 42 def self.repo_file_option(description=nil) description ||= "The name of the repository file, with path if applicable" method_option :repo_file, desc: description, type: :string, banner: '', required: true end
repo_option()
click to toggle source
# File lib/manifestly/cli.rb, line 34 def self.repo_option method_option :repo, desc: "The github manifest repository to use, given as 'organization/reponame'", type: :string, banner: '', required: true end
search_paths_option()
click to toggle source
Common command line options
# File lib/manifestly/cli.rb, line 25 def self.search_paths_option method_option :search_paths, desc: "A list of paths where git repositories can be found", type: :array, required: false, banner: '', default: '.' end
Public Instance Methods
apply()
click to toggle source
# File lib/manifestly/cli.rb, line 224 def apply begin manifest = load_manifest(file: options[:file]) || error! manifest.items.each{ |item| item.checkout_commit!(options[:update]) } rescue Manifestly::ManifestItem::MultipleSameNameRepositories => e say "Multiple repositories have the same name (#{e.message}) so we " + "can't apply the manifest. Try limiting the search_paths or " + "separate the duplicates." error! rescue Manifestly::Repository::CommitNotPresent => e say "Could not find commit #{e.sha} in repository #{e.repository.github_name_or_path}. " + "Try running again with the `--update` option." error! end end
create()
click to toggle source
# File lib/manifestly/cli.rb, line 187 def create manifest = if options[:based_on] load_manifest(file: options[:based_on]) || error! else Manifest.new end if options[:interactive] present_create_menu(manifest) else repos_to_remove = get_repos_from_options(options[:remove]) repos_to_remove.each do |repo_to_remove| manifest.remove_repository(repo_to_remove) end repos_to_add = get_repos_from_options(options[:add]) repos_to_add.each do |repo_to_add| manifest.add_repository(repo_to_add) end write_manifest(manifest, false) end end
diff()
click to toggle source
# File lib/manifestly/cli.rb, line 449 def diff repository = Repository.load_cached(options[:repo], update: true) from_manifest = load_manifest(repository: repository, sha: options[:from_sha]) to_manifest = load_manifest(repository: repository, sha: options[:to_sha]) if !from_manifest || !to_manifest say("Could not load the 'from' manifest so cannot continue with the diff.") if !from_manifest say("Could not load the 'to' manifest so cannot continue with the diff.") if !to_manifest error! end manifest_diff = ManifestDiff.new(from_manifest, to_manifest) manifest_diff.to_markdown end
download()
click to toggle source
# File lib/manifestly/cli.rb, line 284 def download repository = Repository.load_cached(options[:repo], update: true) commit_content = begin repository.get_commit_content(options[:sha]) rescue Manifestly::Repository::CommitNotPresent say('That SHA is invalid') error! end save_as = options[:save_as] if save_as.nil? # Get the whole SHA so filenames are consistent sha = repository.find_commit(options[:sha]).sha save_as = "#{sha[0..9]}.manifest" end File.open(save_as, 'w') { |file| file.write(commit_content) } say "Downloaded #{save_as}. #{commit_content.split("\n").count} line(s)." end
find()
click to toggle source
# File lib/manifestly/cli.rb, line 415 def find repository = Repository.load_cached(options[:repo], update: true) shas = repository.get_shas_with_tag(tag: options[:tag], file: options[:repo_file]) shas = shas.take(options[:limit].to_i) if options[:limit] say shas.uniq.join("\n") end
list()
click to toggle source
# File lib/manifestly/cli.rb, line 315 def list repository = Repository.load_cached(options[:repo], update: true) commits = repository.file_commits(options[:repo_file]) present_list_menu(commits, show_author: true) end
tag()
click to toggle source
# File lib/manifestly/cli.rb, line 365 def tag repository = Repository.load_cached(options[:repo], update: true) begin repository.tag_scoped_to_file( tag: options[:tag], sha: options[:sha], message: options[:message], push: true ) rescue Manifestly::Repository::ShaAlreadyTagged end end
upload()
click to toggle source
# File lib/manifestly/cli.rb, line 256 def upload repository = Repository.load_cached(options[:repo], update: true) begin repository.push_file!(options[:file], options[:repo_file], options[:message]) rescue Manifestly::Repository::ManifestUnchanged ensure say repository.current_commit end end
version()
click to toggle source
# File lib/manifestly/cli.rb, line 465 def version say "Manifestly #{Manifestly::VERSION} - https://github.com/openstax/manifestly" end
Protected Instance Methods
add_repositories(manifest)
click to toggle source
# File lib/manifestly/cli.rb, line 627 def add_repositories(manifest) puts "\n" selected_repositories = select( repository_choices(manifest), hide_shortcuts: true, choice_name: "repository", question: "\nChoose which repositories you want in the manifest (e.g. '0 2 5') or (r)eturn:", no_selection: 'r' ) return if selected_repositories.nil? selected_repositories.each do |repository| begin manifest.add_repository(repository) rescue Manifestly::Repository::NoCommitsError => e say "Cannot add #{repository.display_name} because it doesn't have any commits." end end end
ask_and_split(message)
click to toggle source
# File lib/manifestly/cli.rb, line 579 def ask_and_split(message) answer = ask(message).downcase.split if answer.empty? say('No response provided, please try again.') return false end [answer.shift, answer] end
available_repositories()
click to toggle source
# File lib/manifestly/cli.rb, line 744 def available_repositories @available_repositories ||= (repository_search_paths.flat_map do |path| directories_under(path).collect{|dir| Manifestly::Repository.load(dir)} end).compact end
convert_args_to_indices(args, select_one=false)
click to toggle source
# File lib/manifestly/cli.rb, line 590 def convert_args_to_indices(args, select_one=false) if args.empty? say('You must specify index(es) of manifest items after the action, e.g. "r 2 7".') false elsif select_one && args.size > 1 say('You can only specify one manifest index for this action.') false elsif args.any? {|si| !si.is_i?} say('All specified indices must be integers.') false else args.collect{|index| index.to_i} end end
directories_under(path)
click to toggle source
# File lib/manifestly/cli.rb, line 750 def directories_under(path) entries = Dir.entries(path) entries.reject!{ |dir| dir =='.' || dir == '..' } full_entry_paths = entries.collect{|entry| File.join(path, entry)} full_entry_paths.reject{ |path| !File.directory?(path) } end
dynamic_height()
click to toggle source
# File lib/manifestly/cli.rb, line 775 def dynamic_height %x{stty size 2>/dev/null}.split[0].to_i end
error!()
click to toggle source
# File lib/manifestly/cli.rb, line 801 def error! exit 1 end
find_dir(path)
click to toggle source
Finds the provided directory looking first to see if it is an absolute directory, and then looking for it on the search paths
# File lib/manifestly/cli.rb, line 790 def find_dir(path) return path if path.starts_with?('/') && Dir.exist?(path) repository_search_paths.each do |search_path| combined_path = File.join(search_path, path) return combined_path if Dir.exist?(combined_path) end nil end
get_repos_from_options(options)
click to toggle source
# File lib/manifestly/cli.rb, line 779 def get_repos_from_options(options) if options.include?("all") available_repositories else dirs = options.collect{|option| find_dir(option)}.compact dirs.collect{|dir| Repository.load(dir)} end end
load_manifest(options={})
click to toggle source
# File lib/manifestly/cli.rb, line 605 def load_manifest(options={}) begin if options[:file] Manifest.read_file(options[:file], available_repositories) elsif options[:repository] && options[:sha] content = options[:repository].get_commit_content(options[:sha]) Manifest.read_string(content, available_repositories).tap do |manifest| manifest.manifest_repository = options[:repository] manifest.manifest_sha = options[:sha] manifest.manifest_file = options[:repository].get_commit_filename(options[:sha]) end else say "Missing arguments when trying to load manifest" nil end rescue Manifestly::ManifestItem::RepositoryNotFound => e say "Couldn't find the #{e.message} repository listed in the manifest. " + "Might need to specify --search-paths." nil end end
print_commits(commits, options={})
click to toggle source
# File lib/manifestly/cli.rb, line 680 def print_commits(commits, options={}) column_widths = { number: 4, sha: 10, message: 54, author: options[:show_author] ? 14 : 0, date: 25 } num_columns = column_widths.values.count{|v| v != 0} total_column_widths = column_widths.values.inject{|sum,x| sum + x } total_table_width = total_column_widths + num_columns + 1 + # column separators num_columns * 2 # padding width_overage = total_table_width - terminal_width if width_overage > 0 column_widths[:message] -= width_overage end page = options[:page] || 0 per_page = options[:per_page] || 15 last_page = commits.size / per_page last_page -= 1 if commits.size % per_page == 0 # account for full pages page = 0 if page < 0 page = last_page if page > last_page first_commit = page*per_page last_commit = [page*per_page+per_page-1, commits.size-1].min page_commits = commits[first_commit..last_commit] table border: true do row header: true do column "#", width: column_widths[:number] column "SHA", width: column_widths[:sha] column "Message", width: column_widths[:message] column "Author", width: column_widths[:author] if options[:show_author] column "Date", width: column_widths[:date] end page_commits.each_with_index do |commit, index| row do column "#{index}", align: 'right' column "#{commit.sha[0..9]}" column "#{Commit.new(commit).summarized_message}" column "#{commit.author.name[0..13]}" if options[:show_author] column "#{commit.date}" end end end end
print_manifest(manifest)
click to toggle source
# File lib/manifestly/cli.rb, line 649 def print_manifest(manifest) puts "\n" puts "Current Manifest:\n" puts "\n" table border: false do row header: true do column "#", width: 4 column "Repository", width: 36 column "Branch", width: 30 column "SHA", width: 10 end if manifest.empty? row do column "" column "----- EMPTY -----" end else manifest.items.each_with_index do |item, index| row do column "(#{index})", align: 'right', width: 4 column "#{item.repository_name}", width: 40 column "#{item.repository.current_branch_name}" column "#{item.commit.sha[0..9]}", width: 10 end end end end puts "\n" end
repository_choices(except_in_manifest=nil)
click to toggle source
# File lib/manifestly/cli.rb, line 737 def repository_choices(except_in_manifest=nil) choices = available_repositories.collect{|repo| {display: repo.display_name, value: repo}} except_in_manifest.nil? ? choices : choices.reject{|choice| except_in_manifest.includes?(choice[:value])} end
repository_search_paths()
click to toggle source
# File lib/manifestly/cli.rb, line 758 def repository_search_paths [options[:search_paths]].flatten end
terminal_height()
click to toggle source
# File lib/manifestly/cli.rb, line 762 def terminal_height # This code was derived from Thor and from Rake, the latter of which is # available under MIT-LICENSE Copyright 2003, 2004 Jim Weirich if ENV["THOR_ROWS"] result = ENV["THOR_ROWS"].to_i else result = unix? ? dynamic_width : 40 end result < 10 ? 40 : result rescue 40 end
write_manifest(manifest, prompt_for_filename=false, filename="")
click to toggle source
# File lib/manifestly/cli.rb, line 505 def write_manifest(manifest, prompt_for_filename=false, filename="") default_filename = options[:save_as].blank? ? Time.now.strftime("%Y%m%d-%H%M%S") + "-#{::SecureRandom.hex(2)}.manifest" : options[:save_as] if prompt_for_filename filename = ask("Enter desired manifest filename (ENTER for '#{default_filename}'):") end filename = default_filename if filename.blank? manifest.write(filename, options.slice("full_shas")) end