<commit_before># encoding: utf-8

require 'net/https'
require 'uri'
require 'octokit'
require 'json'

module Pod
  class Command
    class Spec < Command
      def self.banner
        %{Managing PodSpec files:

  $ pod spec create [ NAME | https://github.com/USER/REPO ]

    Creates a PodSpec, in the current working dir, called `NAME.podspec'.
    If a GitHub url is passed the spec is prepopulated.

  $ pod spec lint [ NAME.podspec | REPO ]

    Validates `NAME.podspec'. In case `NAME.podspec' is omitted, it defaults
    to `*.podspec' in the current working dir. If the name of a repo is
    provided it validates all its specs.}
      end

      def initialize(argv)
        args = argv.arguments
        unless (args[0] == 'create' && 2..3 === args.size) ||
          (args[0] == 'lint' && args.size <= 2)
          super
        end
        @action, @name_or_url = args.first(2)
        if @action == 'create' && args.size == 3
          @url = args[2]
        end
      end

      def run
        send @action
      end

      def create
        if repo_id_match = (@url || @name_or_url).match(/github.com\/([^\/\.]*\/[^\/\.]*)\.*/)
          repo_id = repo_id_match[1]
          data = github_data_for_template(repo_id)
          data[:name] = @name_or_url if @url
          puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
        else
          data = default_data_for_template(@name_or_url)
        end
        spec = spec_template(data)
        (Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
        puts "\nSpecification created at #{data[:name]}.podspec".green
      end

      def lint
        is_repo = repo_with_name_exist(@name_or_url)
        if is_repo
          files = (config.repos_dir + @name_or_url).glob('**/*.podspec')
        else
          name = @name_or_url
          files = name ? [Pathname.new(name)] : Pathname.pwd.glob('*.podspec')
        end
        puts
        lint_specs_files(files, is_repo)
      end

      private

      def repo_with_name_exist(name)
        name && (config.repos_dir + name).exist?
      end

      # Takes an array of podspec files and lints them all
      #
      # It returns true if **all** the files passed validation
      #
      def lint_specs_files(files, is_repo)
        tmpdir = Pathname.new('/tmp/CocoaPods').mkpath
        all_valid = true
        files.each do |file|
          file = file.realpath
          spec = Specification.from_file(file)
          print " -> #{spec}\r" unless config.silent? || is_repo

          spec.validate!
          warnings     = warnings_for_spec(spec, file, is_repo)
          deprecations = deprecation_notices_for_spec(spec, file, is_repo)
          # TODO: check that the dependencies of the spec exist
          if is_repo
            build_errors, file_errors = [], []
          else
            build_errors = Dir.chdir('/tmp/CocoaPods') { build_errors_for_spec(spec, file, is_repo) }
            file_errors  = Dir.chdir('/tmp/CocoaPods') { file_errors_for_spec(spec, file, is_repo) }
          end

          # This overwrites the previous printed text
          is_valid = deprecations.empty? && warnings.empty? && file_errors.empty?
          unless config.silent?
            if is_valid
              puts " -> ".green + "#{spec} passed validation" unless is_repo
            else
              puts " -> ".red + spec.to_s
              all_valid = false
            end
          end
          types    = ["WARN", "DPRC", "XCDB", "ERFL"]
          messages = [warnings, deprecations, build_errors, file_errors]
          types.each_with_index do |type, i|
            unless messages[i].empty?
              messages[i].each {|msg| puts "  - #{type} | #{msg}"} unless config.silent?
            end
          end
          puts unless config.silent? || ( is_repo && messages.flatten.empty? )
        end
        all_valid
      end

      # It checks a spec for minor non fatal defects
      #
      # It returns a array of messages
      #
      def warnings_for_spec(spec, file, is_repo)
        license  = spec.license
        source   = spec.source
        warnings = []
        warnings << "The name of the spec should match the name of the file" unless path_matches_name?(file, spec)
        warnings << "Missing license[:type]" unless license && license[:type]
        warnings << "Github repositories should end in `.git'" if source && source[:git] =~ /github.com/ && source[:git] !~ /.*\.git/
        warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./
        warnings << "The summary should end with a dot" if spec.summary !~ /.*\./
        warnings << "Missing license[:file] or [:text]" unless is_repo || license && (license[:file] || license[:text])
        #TODO: the previous ´is_repo' check is there only because at the time of 0.6.0rc1 it would be triggered in all specs
        warnings
      end

      def path_matches_name?(file, spec)
        file.basename.to_s == spec.name + '.podspec'
      end

      # It reads a podspec file and checks for strings corresponding
      # to a feature that are or will be deprecated
      #
      # It returns a array of messages
      #
      def deprecation_notices_for_spec(spec, file, is_repo)
        text = file.read
        deprecations = []
        deprecations << "`config.ios?' and `config.osx' will be removed in version 0.7" if text. =~ /config\..os?/
        deprecations << "Currently there is no known reason to use the `post_install' hook" if text. =~ /post_install/
        deprecations
      end

      # It creates a podfile in memory and builds a library containing
      # the pod for all available platfroms with xcodebuild.
      #
      # It returns a array of messages
      #
      def build_errors_for_spec(spec, file, is_repo)
        messages = []
        platform_names(spec).each do |platform_name|
          config.silent = true
          config.integrate_targets = false
          config.project_root = Pathname.pwd
          podfile = podfile_from_spec(spec, file, platform_name)
          Installer.new(podfile).install!

          config.silent = false
          output        = Dir.chdir('Pods') { `xcodebuild 2>&1` }
          clean_output  = proces_xcode_build_output(output).map {|l| "#{platform_name}: #{l}"}
          messages     += clean_output
        end
        messages
      end

      def podfile_from_spec(spec, file, platform_name)
        podfile = Pod::Podfile.new do
          platform platform_name
          dependency spec.name, :podspec => file.realpath.to_s
        end
      end

      def proces_xcode_build_output(output)
        output_by_line = output.split("\n")
        selected_lines = output_by_line.select do |l|
          l.include?('error') || l.include?('warning') && !l.include?('warning generated.')
        end
      end

      # It checks that every file pattern specified in a spec yields
      # at least one file. It requires the pods to be alredy present
      # in the current working directory under Pods/spec.name
      #
      # It returns a array of messages<commit_msg>Fix spelling error and print build output from `spec lint` when in verbose mode.<commit_after># encoding: utf-8

require 'net/https'
require 'uri'
require 'octokit'
require 'json'

module Pod
  class Command
    class Spec < Command
      def self.banner
        %{Managing PodSpec files:

  $ pod spec create [ NAME | https://github.com/USER/REPO ]

    Creates a PodSpec, in the current working dir, called `NAME.podspec'.
    If a GitHub url is passed the spec is prepopulated.

  $ pod spec lint [ NAME.podspec | REPO ]

    Validates `NAME.podspec'. In case `NAME.podspec' is omitted, it defaults
    to `*.podspec' in the current working dir. If the name of a repo is
    provided it validates all its specs.}
      end

      def initialize(argv)
        args = argv.arguments
        unless (args[0] == 'create' && 2..3 === args.size) ||
          (args[0] == 'lint' && args.size <= 2)
          super
        end
        @action, @name_or_url = args.first(2)
        if @action == 'create' && args.size == 3
          @url = args[2]
        end
      end

      def run
        send @action
      end

      def create
        if repo_id_match = (@url || @name_or_url).match(/github.com\/([^\/\.]*\/[^\/\.]*)\.*/)
          repo_id = repo_id_match[1]
          data = github_data_for_template(repo_id)
          data[:name] = @name_or_url if @url
          puts semantic_versioning_notice(repo_id, data[:name]) if data[:version] == '0.0.1'
        else
          data = default_data_for_template(@name_or_url)
        end
        spec = spec_template(data)
        (Pathname.pwd + "#{data[:name]}.podspec").open('w') { |f| f << spec }
        puts "\nSpecification created at #{data[:name]}.podspec".green
      end

      def lint
        is_repo = repo_with_name_exist(@name_or_url)
        if is_repo
          files = (config.repos_dir + @name_or_url).glob('**/*.podspec')
        else
          name = @name_or_url
          files = name ? [Pathname.new(name)] : Pathname.pwd.glob('*.podspec')
        end
        puts
        lint_specs_files(files, is_repo)
      end

      private

      def repo_with_name_exist(name)
        name && (config.repos_dir + name).exist?
      end

      # Takes an array of podspec files and lints them all
      #
      # It returns true if **all** the files passed validation
      #
      def lint_specs_files(files, is_repo)
        tmpdir = Pathname.new('/tmp/CocoaPods').mkpath
        all_valid = true
        files.each do |file|
          file = file.realpath
          spec = Specification.from_file(file)
          print " -> #{spec}\r" unless config.silent? || is_repo

          spec.validate!
          warnings     = warnings_for_spec(spec, file, is_repo)
          deprecations = deprecation_notices_for_spec(spec, file, is_repo)
          # TODO: check that the dependencies of the spec exist
          if is_repo
            build_errors, file_errors = [], []
          else
            build_errors = Dir.chdir('/tmp/CocoaPods') { build_errors_for_spec(spec, file, is_repo) }
            file_errors  = Dir.chdir('/tmp/CocoaPods') { file_errors_for_spec(spec, file, is_repo) }
          end

          # This overwrites the previous printed text
          is_valid = deprecations.empty? && warnings.empty? && file_errors.empty?
          unless config.silent?
            if is_valid
              puts " -> ".green + "#{spec} passed validation" unless is_repo
            else
              puts " -> ".red + spec.to_s
              all_valid = false
            end
          end
          types    = ["WARN", "DPRC", "XCDB", "ERFL"]
          messages = [warnings, deprecations, build_errors, file_errors]
          types.each_with_index do |type, i|
            unless messages[i].empty?
              messages[i].each {|msg| puts "  - #{type} | #{msg}"} unless config.silent?
            end
          end
          puts unless config.silent? || ( is_repo && messages.flatten.empty? )
        end
        all_valid
      end

      # It checks a spec for minor non fatal defects
      #
      # It returns a array of messages
      #
      def warnings_for_spec(spec, file, is_repo)
        license  = spec.license
        source   = spec.source
        warnings = []
        warnings << "The name of the spec should match the name of the file" unless path_matches_name?(file, spec)
        warnings << "Missing license[:type]" unless license && license[:type]
        warnings << "Github repositories should end in `.git'" if source && source[:git] =~ /github.com/ && source[:git] !~ /.*\.git/
        warnings << "The description should end with a dot" if spec.description && spec.description !~ /.*\./
        warnings << "The summary should end with a dot" if spec.summary !~ /.*\./
        warnings << "Missing license[:file] or [:text]" unless is_repo || license && (license[:file] || license[:text])
        #TODO: the previous ´is_repo' check is there only because at the time of 0.6.0rc1 it would be triggered in all specs
        warnings
      end

      def path_matches_name?(file, spec)
        file.basename.to_s == spec.name + '.podspec'
      end

      # It reads a podspec file and checks for strings corresponding
      # to a feature that are or will be deprecated
      #
      # It returns a array of messages
      #
      def deprecation_notices_for_spec(spec, file, is_repo)
        text = file.read
        deprecations = []
        deprecations << "`config.ios?' and `config.osx' will be removed in version 0.7" if text. =~ /config\..os?/
        deprecations << "Currently there is no known reason to use the `post_install' hook" if text. =~ /post_install/
        deprecations
      end

      # It creates a podfile in memory and builds a library containing
      # the pod for all available platfroms with xcodebuild.
      #
      # It returns a array of messages
      #
      def build_errors_for_spec(spec, file, is_repo)
        messages = []
        platform_names(spec).each do |platform_name|
          config.silent = true
          config.integrate_targets = false
          config.project_root = Pathname.pwd
          podfile = podfile_from_spec(spec, file, platform_name)
          Installer.new(podfile).install!

          config.silent = false
          output        = Dir.chdir('Pods') { `xcodebuild 2>&1` }
          clean_output  = process_xcode_build_output(output).map {|l| "#{platform_name}: #{l}"}
          messages     += clean_output

          puts(output) if config.verbose?
        end
        messages
      end

      def podfile_from_spec(spec, file, platform_name)
        podfile = Pod::Podfile.new do
          platform platform_name
          dependency spec.name, :podspec => file.realpath.to_s
        end
      end

      def process_xcode_build_output(output)
        output_by_line = output.split("\n")
        selected_lines = output_by_line.select do |l|
          l.include?('error') || l.include?('warning') && !l.include?('warning generated.')
        end
      end

      # It checks that every file pattern specified in a spec yields
      # at least one file. It requires the pods to be alredy present
      # in the current working directory under Pods/spec.name
      #
      # It returns a array of messages
{'fraction_non_alphanumeric': 0.10660285753918712, 'fraction_numerical': 0.002913025384935497, 'mean_word_length': 2.1102243313201035, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 13, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '493598', 'n_tokens_mistral': 4335, 'n_tokens_neox': 4260, 'n_words': 1257}