<commit_before>require 'spec_helper'

describe Palimpsest::Environment do

  let(:site_1) { Palimpsest::Site.new name: 'site_1' }
  let(:site_2) { Palimpsest::Site.new name: 'site_2' }

  subject(:environment) { Palimpsest::Environment.new }

  before :each do
    allow(Kernel).to receive(:system)
  end

  describe ".new" do

    it "sets default options" do
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS
    end

    it "merges default options" do
      environment = Palimpsest::Environment.new options: { tmp_dir: '/tmp/path' }
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS.merge(tmp_dir: '/tmp/path')
    end
  end

  describe "#options" do

    it "merges with default options" do
      environment.options[:tmp_dir] = '/tmp/path'
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS.merge(tmp_dir: '/tmp/path')
    end

    it "can be called twice and merge options" do
      environment.options[:tmp_dir] = '/tmp/path'
      environment.options[:dir_prefix] = '/tmp/path'
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS.merge(tmp_dir: '/tmp/path', dir_prefix: '/tmp/path')
    end
  end

  describe "#site" do

    it "cannot be redefinfed while populated" do
      environment.site = site_1
      allow(environment).to receive(:populated).and_return(true)
      expect { environment.site = site_2 }.to raise_error RuntimeError, /populated/
    end
  end

  describe "#treeish" do

    it "must be a string" do
      expect { environment.treeish = 1 }.to raise_error TypeError
    end

    it "cannot be redefinfed while populated" do
      environment.treeish = 'treeish_1'
      allow(environment).to receive(:populated).and_return(true)
      expect { environment.treeish = 'treeish_2' }.to raise_error RuntimeError, /populated/
    end
  end

  describe "#directory" do

    before :each do
      allow(Dir).to receive(:mktmpdir).and_return('/tmp/rand_dir')
    end

    context "when directory is unset" do

      it "makes and returns a temporary directory" do
        environment.site = site_1
        rest = environment.options[:tmp_dir]
        prefix = "#{environment.options[:dir_prefix]}site_1_"
        expect(Dir).to receive(:mktmpdir).with(prefix, rest).and_return('/tmp/rand_dir')
        expect(environment.directory).to eq '/tmp/rand_dir'
      end
    end

    context "when directory is set" do

      it "returns the current directory" do
        expect(Dir).to receive(:mktmpdir).once
        environment.directory
        expect(environment.directory).to eq '/tmp/rand_dir'
      end
    end
  end

  describe "#copy" do

    it "copies the environment to the destination" do
      dir = environment.directory
      allow(Dir).to receive(:[]).with("#{dir}/*").and_return( %W(#{dir}/path/1 #{dir}/path/2) )
      expect(FileUtils).to receive(:mkdir_p).with('/dest/path')
      expect(FileUtils).to receive(:cp_r).with( %W(#{dir}/path/1 #{dir}/path/2), '/dest/path', preserve: true)
      environment.copy destination: '/dest/path'
    end

    context "when destination is nil" do

      it "fails" do
        expect { environment.copy destination: nil }.to raise_error RuntimeError, /destination/
      end
    end
  end

  describe "#cleanup" do

    subject(:environment) { Palimpsest::Environment.new site: site_1 }

    it "removes the directory and resets @directory" do
      expect(FileUtils).to receive(:remove_entry_secure).with(environment.directory)
      environment.directory
      environment.cleanup
      expect(environment.instance_variable_get :@directory).to eq nil
    end

    it "returns itself" do
      expect(environment.cleanup).to be environment
    end
  end

  describe "#populate" do

    it "fails when missing site" do
      environment.treeish = 'master'
      expect { environment.populate }.to raise_error RuntimeError, /populate without/
    end

    context "populate from repo" do

      subject(:environment) { Palimpsest::Environment.new site: site_1, treeish: 'master' }

      before :each do
        site_1.repo = double Grit::Repo
        allow(Palimpsest::Utility).to receive :extract_repo
      end

      it "extracts the repo to the directory and sets populated true" do
        expect(Palimpsest::Utility).to receive(:extract_repo).with(site_1.repo, 'master', environment.directory)
        environment.populate from: :repo
        expect(environment.populated).to eq true
      end

      it "fails when missing treeish" do
        environment.site = site_1
        environment.treeish = ''
        expect { environment.populate from: :repo }.to raise_error RuntimeError, /populate without/
      end

      it "returns itself" do
        expect(environment.populate from: :repo).to be environment
      end

      it "will cleanup if populated" do
        environment.populate
        expect(environment).to receive :cleanup
        environment.populate from: :repo
      end
    end

    context "populate from source" do

      it "copies the source files to the directory preserving mtime" do
        environment.site = site_1
        site_1.source = '/path/to/source'
        expect(Kernel).to receive(:system).with('rsync', '-rt', %q{--exclude='.git/'}, '/path/to/source/', environment.directory)
        environment.populate from: :source
      end

      context "site source not given" do

        it "copies from the working directory" do
          environment.site = site_1
          expect(Kernel).to receive(:system).with('rsync', '-rt', %q{--exclude='.git/'}, './', environment.directory)
          environment.populate from: :source
        end
      end
    end
  end

  describe "#config" do

    subject(:environment) { Palimpsest::Environment.new site: site_1, treeish: 'master' }

    before :each do
      allow(YAML).to receive(:load_file).and_return({})
    end

    it "populate if not populated" do
      expect(environment).to receive :populate
      environment.config
    end

    it "populate only if not populated" do
      allow(environment).to receive(:populated).and_return(true)
      expect(environment).not_to receive :populate
      environment.config
    end

    it "loads the config if populated" do
      allow(environment).to receive(:populated).and_return(true)
      expect(YAML).to receive(:load_file).with("#{environment.directory}/palimpsest.yml")<commit_msg>Need to stub File.exists? for Environment#config.<commit_after>require 'spec_helper'

describe Palimpsest::Environment do

  let(:site_1) { Palimpsest::Site.new name: 'site_1' }
  let(:site_2) { Palimpsest::Site.new name: 'site_2' }

  subject(:environment) { Palimpsest::Environment.new }

  before :each do
    allow(Kernel).to receive(:system)
  end

  describe ".new" do

    it "sets default options" do
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS
    end

    it "merges default options" do
      environment = Palimpsest::Environment.new options: { tmp_dir: '/tmp/path' }
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS.merge(tmp_dir: '/tmp/path')
    end
  end

  describe "#options" do

    it "merges with default options" do
      environment.options[:tmp_dir] = '/tmp/path'
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS.merge(tmp_dir: '/tmp/path')
    end

    it "can be called twice and merge options" do
      environment.options[:tmp_dir] = '/tmp/path'
      environment.options[:dir_prefix] = '/tmp/path'
      expect(environment.options).to eq Palimpsest::Environment::DEFAULT_OPTIONS.merge(tmp_dir: '/tmp/path', dir_prefix: '/tmp/path')
    end
  end

  describe "#site" do

    it "cannot be redefinfed while populated" do
      environment.site = site_1
      allow(environment).to receive(:populated).and_return(true)
      expect { environment.site = site_2 }.to raise_error RuntimeError, /populated/
    end
  end

  describe "#treeish" do

    it "must be a string" do
      expect { environment.treeish = 1 }.to raise_error TypeError
    end

    it "cannot be redefinfed while populated" do
      environment.treeish = 'treeish_1'
      allow(environment).to receive(:populated).and_return(true)
      expect { environment.treeish = 'treeish_2' }.to raise_error RuntimeError, /populated/
    end
  end

  describe "#directory" do

    before :each do
      allow(Dir).to receive(:mktmpdir).and_return('/tmp/rand_dir')
    end

    context "when directory is unset" do

      it "makes and returns a temporary directory" do
        environment.site = site_1
        rest = environment.options[:tmp_dir]
        prefix = "#{environment.options[:dir_prefix]}site_1_"
        expect(Dir).to receive(:mktmpdir).with(prefix, rest).and_return('/tmp/rand_dir')
        expect(environment.directory).to eq '/tmp/rand_dir'
      end
    end

    context "when directory is set" do

      it "returns the current directory" do
        expect(Dir).to receive(:mktmpdir).once
        environment.directory
        expect(environment.directory).to eq '/tmp/rand_dir'
      end
    end
  end

  describe "#copy" do

    it "copies the environment to the destination" do
      dir = environment.directory
      allow(Dir).to receive(:[]).with("#{dir}/*").and_return( %W(#{dir}/path/1 #{dir}/path/2) )
      expect(FileUtils).to receive(:mkdir_p).with('/dest/path')
      expect(FileUtils).to receive(:cp_r).with( %W(#{dir}/path/1 #{dir}/path/2), '/dest/path', preserve: true)
      environment.copy destination: '/dest/path'
    end

    context "when destination is nil" do

      it "fails" do
        expect { environment.copy destination: nil }.to raise_error RuntimeError, /destination/
      end
    end
  end

  describe "#cleanup" do

    subject(:environment) { Palimpsest::Environment.new site: site_1 }

    it "removes the directory and resets @directory" do
      expect(FileUtils).to receive(:remove_entry_secure).with(environment.directory)
      environment.directory
      environment.cleanup
      expect(environment.instance_variable_get :@directory).to eq nil
    end

    it "returns itself" do
      expect(environment.cleanup).to be environment
    end
  end

  describe "#populate" do

    it "fails when missing site" do
      environment.treeish = 'master'
      expect { environment.populate }.to raise_error RuntimeError, /populate without/
    end

    context "populate from repo" do

      subject(:environment) { Palimpsest::Environment.new site: site_1, treeish: 'master' }

      before :each do
        site_1.repo = double Grit::Repo
        allow(Palimpsest::Utility).to receive :extract_repo
      end

      it "extracts the repo to the directory and sets populated true" do
        expect(Palimpsest::Utility).to receive(:extract_repo).with(site_1.repo, 'master', environment.directory)
        environment.populate from: :repo
        expect(environment.populated).to eq true
      end

      it "fails when missing treeish" do
        environment.site = site_1
        environment.treeish = ''
        expect { environment.populate from: :repo }.to raise_error RuntimeError, /populate without/
      end

      it "returns itself" do
        expect(environment.populate from: :repo).to be environment
      end

      it "will cleanup if populated" do
        environment.populate
        expect(environment).to receive :cleanup
        environment.populate from: :repo
      end
    end

    context "populate from source" do

      it "copies the source files to the directory preserving mtime" do
        environment.site = site_1
        site_1.source = '/path/to/source'
        expect(Kernel).to receive(:system).with('rsync', '-rt', %q{--exclude='.git/'}, '/path/to/source/', environment.directory)
        environment.populate from: :source
      end

      context "site source not given" do

        it "copies from the working directory" do
          environment.site = site_1
          expect(Kernel).to receive(:system).with('rsync', '-rt', %q{--exclude='.git/'}, './', environment.directory)
          environment.populate from: :source
        end
      end
    end
  end

  describe "#config" do

    subject(:environment) { Palimpsest::Environment.new site: site_1, treeish: 'master' }

    before :each do
      allow(File).to receive(:exists?).and_return(true)
      allow(YAML).to receive(:load_file).and_return({})
    end

    it "populate if not populated" do
      expect(environment).to receive :populate
      environment.config
    end

    it "populate only if not populated" do
      allow(environment).to receive(:populated).and_return(true)
      expect(environment).not_to receive :populate
      environment.config
    end

    it "loads the config if populated" do
      allow(environment).to receive(:populated).and_return(true)
      expect(YAML).to receive(:load_file).with("#{environment.directory}/palimpsest.yml")
{'fraction_non_alphanumeric': 0.11183294663573086, 'fraction_numerical': 0.0037122969837587007, 'mean_word_length': 3.058694287507847, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4299352', 'n_tokens_mistral': 3847, 'n_tokens_neox': 3691, 'n_words': 1012}