# frozen_string_literal: true require 'travis/cli' require 'yaml' module Travis module CLI class RepoCommand < ApiCommand GIT_REGEX = %r{/?(.*/.+?)(\.git)?$} TRAVIS = %r{^https://(staging-)?api\.travis-ci\.com} on('-g', '--github-token TOKEN', 'identify by GitHub token') on('-r', '--repo SLUG', 'repository to use (will try to detect from current git clone)') do |c, slug| c.slug = slug c.error 'SLUG should be of the form OWNER/REPO' unless slug.split('/').compact.size == 2 end on('-R', '--store-repo SLUG', 'like --repo, but remembers value for current directory') do |c, slug| c.slug = slug c.send(:store_slug, slug) end attr_accessor :slug abstract def setup setup_enterprise unless self.slug ||= find_slug error "Can't figure out GitHub repo name. Ensure you're in the repo directory, or specify the repo name via the -r option (e.g. travis -r /)" end error "GitHub repo name is invalid, it should be of the form 'owner/repo'" unless self.slug.include?('/') self.api_endpoint = detect_api_endpoint super repository.load # makes sure we actually have access to the repo end def repository repo(slug) rescue Travis::Client::NotFound error "repository not known to #{api_endpoint}: #{color(slug, :important)}" end private def build(number_or_id) return super if number_or_id.is_a? Integer repository.build(number_or_id) end def job(number_or_id) return super if number_or_id.is_a? Integer repository.job(number_or_id) end def branch(name) repository.branch(name) end def last_build repository.last_build or error("no build yet for #{slug}") end def detected_endpoint? !explicit_api_endpoint? end def find_slug load_slug || begin slug = detect_slug if slug interactive? ? store_slug(slug) : slug end end end def detect_slug git_head = `git name-rev --name-only HEAD 2>#{IO::NULL}`.chomp git_remote = `git config --get branch.#{git_head}.remote 2>#{IO::NULL}`.chomp git_remote = 'origin' if git_remote.empty? git_info = `git ls-remote --get-url #{git_remote} 2>#{IO::NULL}`.chomp return unless parse_remote(git_info) =~ GIT_REGEX detected_slug = ::Regexp.last_match(1) if interactive? if agree("Detected repository as #{color(detected_slug, :info)}, is this correct? ") do |q| q.default = 'yes' end detected_slug else ask('Repository slug (owner/name): ') { |q| q.default = detected_slug } end else info "detected repository as #{color(detected_slug, :bold)}" detected_slug end end def parse_remote(url) if url =~ /^git@[^:]+:/ path = url.split(':').last path = "/#{path}" unless path.start_with?('/') path else URI.parse(url).path end end def load_slug stored = `git config --get travis.slug`.chomp stored unless stored.empty? end def store_slug(value) `git config travis.slug #{value}` if value value end def repo_config config['repos'] ||= {} config['repos'][slug] ||= {} end def detect_api_endpoint if explicit_api_endpoint? || enterprise? repo_config['endpoint'] = api_endpoint elsif ENV['TRAVIS_ENDPOINT'] ENV['TRAVIS_ENDPOINT'] elsif config['default_endpoint'] && config['default_endpoint'] !~ (TRAVIS) repo_config['endpoint'] ||= config['default_endpoint'] else repo_config['endpoint'] ||= begin load_gh GH.head("/repos/#{slug}") Travis::Client::COM_URI rescue GH::Error Travis::Client::COM_URI end end end def travis_config @travis_config ||= begin payload = YAML.load_file(travis_yaml) payload.respond_to?(:to_hash) ? payload.to_hash : {} end end def travis_yaml(dir = Dir.pwd) path = File.expand_path('.travis.yml', dir) if File.exist? path path else parent = File.expand_path('..', dir) error 'no .travis.yml found' if parent == dir travis_yaml(parent) end end def confirm_and_save_travis_config(confirm = true, _file = travis_yaml) if confirm ans = ask [ nil, color("Overwrite the config file #{travis_yaml} with the content below?", %i[info yellow]), color('This reformats the existing file.', %i[info red]), travis_config.to_yaml, color('(y/N)', %i[info yellow]) ].join("\n\n") proceed = ans =~ /^y/i else proceed = true end save_travis_config if proceed end def save_travis_config(file = travis_yaml) yaml = travis_config.to_yaml yaml.gsub!(/^(\s+)('on'|true):/, '\\1on:') yaml.gsub!(/\A---\s*\n/, '') File.write(file, yaml) end end end end