<commit_before>#!/usr/bin/env ruby -Ku
# encoding: utf-8

require 'set'
require 'fileutils'
require 'pathname'

require 'thor'
require 'addressable/uri'
require 'ruby-github'

class ::Project

  def self.command_names
    %w[ sync bundle:install bundle:update spec release implode]
  end

  def self.command_name(name)
    command_fragments(name).join('_')
  end

  def self.command_class_name(name)
    command_fragments(name).map { |fragment| fragment.capitalize }.join('::')
  end

  def self.command_fragments(name)
    name.split(':').map { |fragment| fragment }
  end

  command_names.each do |name|
    class_eval <<-RUBY, __FILE__, __LINE__ + 1
      def self.#{command_name(name)}(options = {})
        new(options).send(:#{command_name(name)})
      end

      def #{command_name(name)}
        self.class.invoke :before, '#{command_name(name)}', env, repos
        @repos.each do |repo|
          @logger.progress!
          command_class('#{name}').new(repo, env, @logger).run
        end
        self.class.invoke :after, '#{command_name(name)}', env, repos
      end
    RUBY
  end

  attr_reader   :env
  attr_reader   :root
  attr_reader   :repos
  attr_reader   :options

  attr_accessor :commands

  def initialize(options = {})
    @options  = options
    @env      = environment_class.new(name, @options)
    @root     = @env.root
    @repos    = Repositories.new(@root, name, @env.included, @env.excluded + excluded_repos)
    @logger   = Logger.new(@env, @repos.count)
    @commands = {}
  end

  def environment_class
    Environment
  end

  def command_class(name)
    return commands[name] if commands[name]
    Utils.full_const_get(self.class.command_class_name(name), Command)
  end

  def self.before(command_name, &block)
    ((@before ||= {})[command_name] ||= []) << block
  end

  def self.after(command_name, &block)
    ((@after ||= {})[command_name] ||= []) << block
  end

  def self.invoke(kind, name, *args)
    hooks = instance_variable_get("@#{kind}")
    return unless hooks && hooks[name]
    hooks[name].each { |hook| hook.call(*args) }
  end

  module Utils

    def self.full_const_get(name, root = Object)
      obj = root
      namespaces(name).each do |x|
        # This is required because const_get tries to look for constants in the
        # ancestor chain, but we only want constants that are HERE
        obj = obj.const_defined?(x) ? obj.const_get(x) : obj.const_missing(x)
      end
      obj
    end

    def self.namespaced?(const_name)
      namespaces(const_name).size > 1
    end

    def self.namespaces(const_name)
      path = const_name.to_s.split('::')
      path.shift if path.first.empty?
      path
    end

  end

  class Repositories

    include Enumerable

    def initialize(root, user, repos, excluded_repos)
      @root, @user    = root, user
      @excluded_repos = excluded_repos
      @repositories   = fetch(repos).map do |repo|
        Repository.new(@root, repo)
      end
    end

    def each
      @repositories.each { |repo| yield(repo) }
    end

  private

    def fetch(repos)
      GitHub::API.user(@user).repositories.select do |repo|
        include?(repo, repos)
      end
    end

    def include?(repo, repos)
      if repos
        repos.include?(repo.name)
      else
        !@excluded_repos.include?(repo.name)
      end
    end

  end

  class Repository

    attr_reader :path
    attr_reader :name
    attr_reader :uri

    def initialize(root, repo)
      @name = repo.name
      @path = root.join(@name)
      @uri  = Addressable::URI.parse(repo.url)
    end

    def installable?
      path.join('Gemfile').file?
    end

  end

  class Environment
<commit_msg>Allow to skip -i option when inside a repo directory<commit_after>#!/usr/bin/env ruby -Ku
# encoding: utf-8

require 'set'
require 'fileutils'
require 'pathname'

require 'thor'
require 'addressable/uri'
require 'ruby-github'

class ::Project

  def self.command_names
    %w[ sync bundle:install bundle:update spec release implode]
  end

  def self.command_name(name)
    command_fragments(name).join('_')
  end

  def self.command_class_name(name)
    command_fragments(name).map { |fragment| fragment.capitalize }.join('::')
  end

  def self.command_fragments(name)
    name.split(':').map { |fragment| fragment }
  end

  command_names.each do |name|
    class_eval <<-RUBY, __FILE__, __LINE__ + 1
      def self.#{command_name(name)}(options = {})
        new(options).send(:#{command_name(name)})
      end

      def #{command_name(name)}
        self.class.invoke :before, '#{command_name(name)}', env, repos
        @repos.each do |repo|
          @logger.progress!
          command_class('#{name}').new(repo, env, @logger).run
        end
        self.class.invoke :after, '#{command_name(name)}', env, repos
      end
    RUBY
  end

  attr_reader   :env
  attr_reader   :root
  attr_reader   :repos
  attr_reader   :options

  attr_accessor :commands

  def initialize(options = {})
    @options  = options
    @env      = environment_class.new(name, @options)
    @root     = @env.root
    @repos    = Repositories.new(@root, name, @env.included, @env.excluded + excluded_repos)
    @logger   = Logger.new(@env, @repos.count)
    @commands = {}
  end

  def environment_class
    Environment
  end

  def command_class(name)
    return commands[name] if commands[name]
    Utils.full_const_get(self.class.command_class_name(name), Command)
  end

  def self.before(command_name, &block)
    ((@before ||= {})[command_name] ||= []) << block
  end

  def self.after(command_name, &block)
    ((@after ||= {})[command_name] ||= []) << block
  end

  def self.invoke(kind, name, *args)
    hooks = instance_variable_get("@#{kind}")
    return unless hooks && hooks[name]
    hooks[name].each { |hook| hook.call(*args) }
  end

  module Utils

    def self.full_const_get(name, root = Object)
      obj = root
      namespaces(name).each do |x|
        # This is required because const_get tries to look for constants in the
        # ancestor chain, but we only want constants that are HERE
        obj = obj.const_defined?(x) ? obj.const_get(x) : obj.const_missing(x)
      end
      obj
    end

    def self.namespaced?(const_name)
      namespaces(const_name).size > 1
    end

    def self.namespaces(const_name)
      path = const_name.to_s.split('::')
      path.shift if path.first.empty?
      path
    end

  end

  class Repositories

    include Enumerable

    def initialize(root, user, repos, excluded_repos)
      @root, @user    = root, user
      @repos          = repos
      @excluded_repos = excluded_repos
      @metadata       = GitHub::API.user(@user).repositories
      @repositories   = selected_repositories.map do |repo|
        Repository.new(@root, repo)
      end
    end

    def each
      @repositories.each { |repo| yield(repo) }
    end

  private

    def selected_repositories
      if use_current_directory?
        @metadata.select { |repo| managed_repo?(repo) }
      else
        @metadata.select { |repo| include_repo?(repo) }
      end
    end

    def managed_repo?(repo)
      repo.name == relative_path_name
    end

    def include_repo?(repo)
      if @repos
        !excluded_repo?(repo) && (include_all? || @repos.include?(repo.name))
      else
        !excluded_repo?(repo)
      end
    end

    def excluded_repo?(repo)
      @excluded_repos.include?(repo.name)
    end

    def use_current_directory?
      @repos.nil? && inside_available_repo? && !include_all?
    end

    def inside_available_repo?
      @metadata.map(&:name).include?(relative_path_name)
    end

    def include_all?
      explicitly_specified = @repos.respond_to?(:each) && @repos.count == 1 && @repos.first == 'all'
      if inside_available_repo?
        explicitly_specified
      else
        @repos.nil? || explicitly_specified
      end
    end

    def relative_path_name
      Pathname(Dir.pwd).relative_path_from(@root).to_s
    end

  end

  class Repository

    attr_reader :path
    attr_reader :name
    attr_reader :uri

    def initialize(root, repo)
      @name = repo.name
      @path = root.join(@name)
      @uri  = Addressable::URI.parse(repo.url)
    end

    def installable?
      path.join('Gemfile').file?
    end

  end

  class Environment

{'fraction_non_alphanumeric': 0.11950217496375061, 'fraction_numerical': 0.0008458192363460609, 'mean_word_length': 2.7537414965986393, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 5, 'https://': 0, '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': '579563', 'n_tokens_mistral': 2792, 'n_tokens_neox': 2675, 'n_words': 621}