class ReaPack::Index::CLI
Constants
- CONFIG_SEARCH
- DEFAULTS
- PROGRAM_NAME
Attributes
index[R]
Public Class Methods
new(argv = [])
click to toggle source
# File lib/reapack/index/cli.rb, line 4 def initialize(argv = []) @opts = parse_options argv @git = ReaPack::Index::Git.new argv.first || Dir.pwd log "found git repository in #{@git.path}" read_config unless @opts[:noconfig] unless @opts[:output] @opts[:output] = expand_path DEFAULTS[:output], relative: true end @opts = DEFAULTS.merge @opts log Hash[@opts.sort].inspect @index = ReaPack::Index.new File.expand_path(@opts[:output]) @index.amend = @opts[:amend] @index.strict = @opts[:strict] set_url_template rescue Rugged::OSError, Rugged::RepositoryError, ReaPack::Index::Error => e $stderr.puts e.message throw :stop, false end
Public Instance Methods
parse_options(args, basepath = nil)
click to toggle source
# File lib/reapack/index/cli/options.rb, line 44 def parse_options(args, basepath = nil) opts = Hash.new OptionParser.new do |op| op.program_name = PROGRAM_NAME op.version = ReaPack::Index::VERSION op.banner = "Package indexer for git-based ReaPack repositories\n" + "Usage: #{PROGRAM_NAME} [options] [directory]" op.separator 'Modes:' op.on '-c', '--check', 'Test every package including uncommited changes and exit' do opts[:check] = true end op.on '-s', '--scan [PATH|COMMIT]', 'Scan new commits (default), a path or a specific commit' do |commit| opts[:check] = opts[:rebuild] = false opts[:scan] ||= [] if commit opts[:scan] << expand_path(commit.strip, base: basepath, relative: true) else opts[:scan].clear end end op.on '--no-scan', 'Do not scan for new commits' do opts[:scan] = false end op.on '--rebuild', 'Clear the index and rescan the whole git history' do opts[:check] = false opts[:rebuild] = true end op.separator 'Indexer options:' op.on '-a', '--[no-]amend', 'Update existing versions' do |bool| opts[:amend] = bool end op.on '-i', '--ignore PATH', "Don't check or index any file starting with PATH" do |path| opts[:ignore] ||= [] opts[:ignore] << expand_path(path, base: basepath) end op.on '-o', "--output FILE=#{DEFAULTS[:output]}", 'Set the output filename and path for the index' do |file| opts[:output] = expand_path(file.strip, base: basepath, relative: true) end op.on '--[no-]strict', 'Enable strict validation mode' do |bool| opts[:strict] = bool end op.on '-U', "--url-template TEMPLATE=#{DEFAULTS[:url_template]}", 'Set the template for implicit download links' do |tpl| opts[:url_template] = tpl.strip end op.separator 'Repository metadata:' op.on '-n', '--name NAME', 'Set the name shown in ReaPack for this repository' do |name| opts[:name] = name.strip end op.on '-l', '--link LINK', 'Add or remove a website link' do |link| opts[:links] ||= Array.new opts[:links] << [:website, link.strip] end op.on '--screenshot-link LINK', 'Add or remove a screenshot link' do |link| opts[:links] ||= Array.new opts[:links] << [:screenshot, link.strip] end op.on '--donation-link LINK', 'Add or remove a donation link' do |link| opts[:links] ||= Array.new opts[:links] << [:donation, link.strip] end op.on '--ls-links', 'Display the link list then exit' do opts[:lslinks] = true end op.on '-A', '--about=FILE', 'Set the about content from a file' do |file| opts[:about] = expand_path file.strip, base: basepath, relative: true end op.on '--remove-about', 'Remove the about content from the index' do opts[:rmabout] = true end op.on '--dump-about', 'Dump the raw about content in RTF and exit' do opts[:dump_about] = true end op.separator 'Misc options:' op.on '--[no-]progress', 'Enable or disable progress information' do |bool| opts[:progress] = bool end op.on '-V', '--[no-]verbose', 'Activate diagnosis messages' do |bool| opts[:verbose] = bool end op.on '-C', '--[no-]commit', 'Select whether to commit the modified index' do |bool| opts[:commit] = bool end op.on '--prompt-commit', 'Ask at runtime whether to commit the index' do opts[:commit] = nil end op.on '-m', "--commit-template MESSAGE", 'Customize the commit message. Supported placeholder: $changelog' do |msg| opts[:message] = msg end op.on '-W', '--warnings', 'Enable warnings' do opts[:warnings] = true end op.on '-w', '--no-warnings', 'Turn off warnings' do opts[:warnings] = false end op.on '-q', '--[no-]quiet', 'Disable almost all output' do opts[:warnings] = false opts[:progress] = false opts[:verbose] = false opts[:quiet] = true end op.on '--no-config', 'Bypass the configuration files' do opts[:noconfig] = true end op.on_tail '-v', '--version', 'Display version information' do puts op.ver throw :stop, true end op.on_tail '-h', '--help', 'Prints this help' do puts op throw :stop, true end end.parse! args if basepath && !args.empty? raise OptionParser::InvalidOption, "#{args.first}" end opts rescue OptionParser::ParseError => e $stderr.puts "#{PROGRAM_NAME}: #{e.message}" $stderr.puts "Try '#{PROGRAM_NAME} --help' for more information." throw :stop, false end
read_config()
click to toggle source
# File lib/reapack/index/cli/options.rb, line 25 def read_config CONFIG_SEARCH.each {|dir| dir = expand_path dir path = File.expand_path '.reapack-index.conf', dir log 'reading configuration from %s' % path unless File.readable? path log 'configuration file is unreadable, skipping' next end opts = Shellwords.split File.read(path) @opts = parse_options(opts, dir).merge @opts } rescue ArgumentError => e raise ReaPack::Index::Error, e.message end
run()
click to toggle source
# File lib/reapack/index/cli.rb, line 29 def run if @opts[:check] return do_check end if @opts[:lslinks] print_links return true end if @opts[:dump_about] print @index.about return true end do_name; do_about; eval_links; do_scan unless @index.modified? $stderr.puts 'Nothing to do!' unless @opts[:quiet] return true end # changelog will be cleared by Index#write! changelog = @index.changelog puts changelog unless @opts[:quiet] @index.write! commit changelog true end
Private Instance Methods
bump_progress()
click to toggle source
# File lib/reapack/index/cli.rb, line 306 def bump_progress @done += 1 print_progress end
check_name()
click to toggle source
# File lib/reapack/index/cli.rb, line 180 def check_name if @index.name.empty? warn 'This index is unnamed. ' \ 'Run the following command to set a name of your choice:' \ "\n #{File.basename $0} --name 'FooBar Scripts'" end end
commit(changelog)
click to toggle source
# File lib/reapack/index/cli.rb, line 260 def commit(changelog) return unless case @opts[:commit] when false, true @opts[:commit] else prompt 'Commit the new index?' end message = @opts[:message].gsub '$changelog', changelog @git.create_commit message, [@index.path] $stderr.puts 'commit created' end
do_about()
click to toggle source
# File lib/reapack/index/cli.rb, line 188 def do_about path = @opts[:about] unless path @index.about = String.new if @opts[:rmabout] return end log "converting #{path} into RTF..." # look for the file in the working directory, not on the repository root @index.about = File.read(path) rescue Errno::ENOENT => e warn '--about: ' + e.message.sub(' @ rb_sysopen', '') rescue ReaPack::Index::Error => e warn e.message end
do_check()
click to toggle source
# File lib/reapack/index/cli.rb, line 206 def do_check check_name @index.clear failures = [] pkgs = Hash[Find.find(@git.path).sort.map {|abs| rel = @git.relative_path abs @index.files << rel next if !File.file?(abs) || ignored?(abs) || !ReaPack::Index.is_package?(rel) [abs, rel] }.compact] # reiterate over the pkg list after registering every file pkgs.each_pair {|abs, rel| begin @index.scan rel, MetaHeader.from_file(abs) if @opts[:verbose] $stderr.puts '%s: passed' % rel elsif !@opts[:quiet] $stderr.print '.' end rescue ReaPack::Index::Error => e if @opts[:verbose] $stderr.puts '%s: failed' % rel elsif !@opts[:quiet] $stderr.print 'F' end failures << "%s failed:\n%s" % [rel, indent(e.message).yellow] end } $stderr.puts "\n" unless @opts[:quiet] || @opts[:verbose] failures.each_with_index {|msg, index| $stderr.puts unless @opts[:quiet] && index == 0 $stderr.puts '%d) %s' % [index + 1, msg] } unless @opts[:quiet] $stderr.puts "\n" $stderr.puts 'Finished checks for %d package%s with %d failure%s' % [ pkgs.size, pkgs.size == 1 ? '' : 's', failures.size, failures.size == 1 ? '' : 's', ] end failures.empty? end
do_name()
click to toggle source
# File lib/reapack/index/cli.rb, line 173 def do_name @index.name = @opts[:name] if @opts[:name] check_name rescue ReaPack::Index::Error => e warn '--name: ' + e.message end
do_scan()
click to toggle source
# File lib/reapack/index/cli.rb, line 70 def do_scan commits = if @opts[:rebuild] @index.clear @git.commits elsif @opts[:scan] == false [] elsif @opts[:scan].empty? @git.commits_since @index.last_commit else @index.auto_bump_commit = false # call process_commit only once per commit instead of once per --scan argument commits = Hash.new @opts[:scan].map {|hash| files = @git.last_commits_for @git.relative_path(hash) if !files.empty? files.each {|commit, files| commits[commit] = Array.new unless commits.has_key? commit # keep nil commits[commit].concat files unless commits[commit].nil? } elsif c = @git.get_commit(hash) commits[c] = nil else $stderr.puts "--scan: bad file or revision: '%s'" % hash throw :stop, false end } commits.to_a end unless commits.empty? progress_wrapper commits.size do commits.each {|args| process_commit *args } end end end
eval_links()
click to toggle source
# File lib/reapack/index/cli.rb, line 144 def eval_links Array(@opts[:links]).each {|link| begin @index.eval_link *link rescue ReaPack::Index::Error => e opt = case link.first when :website '--link' when :donation '--donation-link' when :screenshot '--screenshot-link' end warn "#{opt}: " + e.message end } end
expand_path(path, **options)
click to toggle source
# File lib/reapack/index/cli.rb, line 331 def expand_path(path, **options) # expand from the repository root or from the current directory if # the repository is not yet initialized path = File.expand_path path, options[:base] || (@git ? @git.path : Dir.pwd) if options[:relative] root = Pathname.new Dir.pwd file = Pathname.new path file.relative_path_from(root).to_s else path end end
ignored?(path)
click to toggle source
# File lib/reapack/index/cli.rb, line 321 def ignored?(path) path = path + '/' @opts[:ignore].each {|pattern| return true if path.start_with? pattern + '/' } false end
indent(input)
click to toggle source
# File lib/reapack/index/cli.rb, line 346 def indent(input) output = String.new input.each_line {|l| output += "\x20\x20#{l}" } output end
log(line)
click to toggle source
# File lib/reapack/index/cli.rb, line 284 def log(line) $stderr.puts line if @opts[:verbose] end
print_links()
click to toggle source
# File lib/reapack/index/cli.rb, line 163 def print_links ReaPack::Index::Link::VALID_TYPES.each {|type| prefix = "[#{type}]".bold.light_black @index.links(type).each {|link| display = link.name == link.url ? link.url : '%s (%s)' % [link.name, link.url] puts '%s %s' % [prefix, display] } } end
print_progress()
click to toggle source
# File lib/reapack/index/cli.rb, line 311 def print_progress return if @opts[:verbose] || !@opts[:progress] percent = (@done.to_f / @total) * 100 $stderr.print "\rIndexing commit %d of %d (%d%%)..." % [[@done + 1, @total].min, @total, percent] @add_nl = true end
process_commit(commit, files = nil)
click to toggle source
# File lib/reapack/index/cli.rb, line 107 def process_commit(commit, files = nil) if @opts[:verbose] log 'processing %s: %s' % [commit.short_id, commit.summary] end @index.commit = commit.id @index.time = commit.time @index.files = commit.filelist commit.each_diff .select {|diff| (files.nil? || files.include?(diff.file)) && (not ignored? expand_path(diff.file)) && ReaPack::Index.is_package?(diff.file) } .sort_by {|diff| diff.status == :deleted || diff.new_header[:noindex] ? 0 : 1 } .each {|diff| process_diff diff } ensure bump_progress end
process_diff(diff)
click to toggle source
# File lib/reapack/index/cli.rb, line 130 def process_diff(diff) log "-> indexing #{diff.status} file #{diff.file}" if diff.status == :deleted @index.remove diff.file else begin @index.scan diff.file, diff.new_header rescue ReaPack::Index::Error => e warn "#{diff.file}:\n#{indent e.message}" end end end
progress_wrapper(total, &block)
click to toggle source
# File lib/reapack/index/cli.rb, line 299 def progress_wrapper(total, &block) @done, @total = 0, total print_progress block[] $stderr.print "\n" if @add_nl end
prompt(question, &block)
click to toggle source
# File lib/reapack/index/cli.rb, line 273 def prompt(question, &block) $stderr.print "#{question} [y/N] " answer = $stdin.getch $stderr.puts answer yes = answer.downcase == 'y' block[] if block_given? && yes yes end
set_url_template()
click to toggle source
# File lib/reapack/index/cli.rb, line 61 def set_url_template tpl = @opts[:url_template] is_custom = tpl != DEFAULTS[:url_template] @index.url_template = is_custom ? tpl : @git.guess_url_template rescue ReaPack::Index::Error => e warn '--url-template: ' + e.message if is_custom end
warn(line)
click to toggle source
# File lib/reapack/index/cli.rb, line 288 def warn(line) return unless @opts[:warnings] if @add_nl $stderr.puts @add_nl = false end $stderr.puts "warning: #{line}".yellow end