require 'spec_helper' require 'r10k/git' require 'r10k/git/stateful_repository' describe R10K::Git::StatefulRepository do include_context 'Git integration' let(:dirname) { 'working-repo' } let(:cacherepo) { R10K::Git.cache.generate(remote) } let(:thinrepo) { R10K::Git.thin_repository.new(basedir, dirname, cacherepo) } let(:ref) { '0.9.x' } subject { described_class.new(remote, basedir, dirname) } describe 'status' do describe "when the directory does not exist" do it "is absent" do expect(subject.status(ref)).to eq :absent end end describe "when the directory is not a git repository" do it "is mismatched" do thinrepo.path.mkdir expect(subject.status(ref)).to eq :mismatched end end describe "when the directory has a .git file" do it "is mismatched" do thinrepo.path.mkdir File.open("#{thinrepo.path}/.git", "w") {} expect(subject.status(ref)).to eq :mismatched end end describe "when the repository doesn't match the desired remote" do it "is mismatched" do thinrepo.clone(remote, {:ref => '1.0.0'}) allow(subject.repo).to receive(:origin).and_return('http://some.site/repo.git') expect(subject.status(ref)).to eq :mismatched end end describe "when the wrong ref is checked out" do it "is outdated" do thinrepo.clone(remote, {:ref => '1.0.0'}) expect(subject.status(ref)).to eq :outdated end end describe "when the ref is a branch and the cache is not synced" do it "is outdated" do thinrepo.clone(remote, {:ref => ref}) cacherepo.reset! expect(subject.status(ref)).to eq :outdated end end describe "when the ref can't be resolved" do let(:ref) { '1.1.x' } it "is outdated" do thinrepo.clone(remote, {:ref => '0.9.x'}) expect(subject.status(ref)).to eq :outdated end end describe "when the workdir has local modifications" do it "is dirty when workdir is up to date" do thinrepo.clone(remote, {:ref => ref}) File.open(File.join(thinrepo.path, 'README.markdown'), 'a') { |f| f.write('local modifications!') } expect(subject.status(ref)).to eq :dirty end it "is dirty when workdir is not up to date" do thinrepo.clone(remote, {:ref => '1.0.0'}) File.open(File.join(thinrepo.path, 'README.markdown'), 'a') { |f| f.write('local modifications!') } expect(subject.status(ref)).to eq :dirty end end describe "if the right ref is checked out" do it "is insync" do thinrepo.clone(remote, {:ref => ref}) expect(subject.status(ref)).to eq :insync end end end describe "syncing" do describe "when the ref is unresolvable" do let(:ref) { '1.1.x' } it "raises an error" do expect { subject.sync(ref) }.to raise_error(R10K::Git::UnresolvableRefError) end end describe "when the repo is absent" do it "creates the repo" do subject.sync(ref) expect(subject.status(ref)).to eq :insync end end describe "when the repo is mismatched" do it "removes and recreates the repo" do thinrepo.path.mkdir subject.sync(ref) expect(subject.status(ref)).to eq :insync end end describe "when the repo is out of date" do it "updates the repository" do thinrepo.clone(remote, {:ref => '1.0.0'}) subject.sync(ref) expect(subject.status(ref)).to eq :insync end end describe "when the workdir is dirty" do before(:each) do thinrepo.clone(remote, {:ref => ref}) File.open(File.join(thinrepo.path, 'README.markdown'), 'a') { |f| f.write('local modifications!') } end context "when force == true" do let(:force) { true } it "warns and overwrites local modifications" do expect(subject.logger).to receive(:warn).with(/overwriting local modifications/i) subject.sync(ref, force) expect(subject.status(ref)).to eq :insync end end context "when force != true" do let(:force) { false } it "warns and does not overwrite local modifications" do expect(subject.logger).to receive(:warn).with(/skipping.*due to local modifications/i) subject.sync(ref, force) expect(subject.status(ref)).to eq :dirty end end end end end