diff --git a/lib/git/base.rb b/lib/git/base.rb index 068d7931..c033a845 100644 --- a/lib/git/base.rb +++ b/lib/git/base.rb @@ -58,7 +58,7 @@ def self.init(working_dir, opts = {}) # Submodules have a .git *file* not a .git folder. # This file's contents point to the location of # where the git refs are held (In the parent repo) - if File.file?('.git') + if opts[:working_directory] && File.file?(File.join(opts[:working_directory], '.git')) git_file = File.open('.git').read[8..-1].strip opts[:repository] = git_file opts[:index] = git_file + '/index' @@ -72,13 +72,24 @@ def self.init(working_dir, opts = {}) # opens a new Git Project from a working directory # you can specify non-standard git_dir and index file in the options def self.open(working_dir, opts={}) - self.new({:working_directory => working_dir}.merge(opts)) + opts[:working_directory] ||= working_dir + opts[:repository] ||= File.join(opts[:working_directory], '.git') + + # Submodules have a .git *file* not a .git folder. + # This file's contents point to the location of + # where the git refs are held (In the parent repo) + if opts[:working_directory] && File.file?(File.join(opts[:working_directory], '.git')) + git_file = File.open('.git').read[8..-1].strip + opts[:repository] = git_file + opts[:index] = git_file + '/index' + end + self.new(opts) end def initialize(options = {}) if working_dir = options[:working_directory] options[:repository] ||= File.join(working_dir, '.git') - options[:index] ||= File.join(working_dir, '.git', 'index') + options[:index] ||= File.join(options[:repository], 'index') end if options[:log] @logger = options[:log] diff --git a/tests/test_helper.rb b/tests/test_helper.rb index 617d8c83..e3729b0e 100644 --- a/tests/test_helper.rb +++ b/tests/test_helper.rb @@ -26,7 +26,7 @@ def set_file_paths teardown def git_teardown - if @tmp_path + if instance_variable_defined?(:@tmp_path) FileUtils.rm_r(@tmp_path) end end diff --git a/tests/units/test_git_dir.rb b/tests/units/test_git_dir.rb new file mode 100644 index 00000000..78d7c053 --- /dev/null +++ b/tests/units/test_git_dir.rb @@ -0,0 +1,73 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../test_helper' + +class TestGitDir < Test::Unit::TestCase + def test_index_calculated_from_git_dir + Dir.mktmpdir do |work_tree| + Dir.mktmpdir do |git_dir| + git = Git.open(work_tree, repository: git_dir) + + assert_equal(work_tree, git.dir.path) + assert_equal(git_dir, git.repo.path) + + # Since :index was not given in the options to Git#open, index should + # be defined automatically based on the git_dir. + # + index = File.join(git_dir, 'index') + assert_equal(index, git.index.path) + end + end + end + + # Test the case where the git-dir is not a subdirectory of work-tree + # + def test_git_dir_outside_work_tree + Dir.mktmpdir do |work_tree| + Dir.mktmpdir do |git_dir| + # Setup a bare repository + # + source_git_dir = File.expand_path(File.join('tests', 'files', 'working.git')) + FileUtils.cp_r(Dir["#{source_git_dir}/*"], git_dir, preserve: true) + git = Git.open(work_tree, repository: git_dir) + + assert_equal(work_tree, git.dir.path) + assert_equal(git_dir, git.repo.path) + + # Reconstitute the work tree from the bare repository + # + branch = 'master' + git.checkout(branch, force: true) + + # Make sure the work tree contains the expected files + # + expected_files = %w[ex_dir example.txt] + actual_files = Dir[File.join(work_tree, '*')].map { |f| File.basename(f) } + assert_equal(expected_files, actual_files) + + # None of the expected files should have a status that says it has been changed + # + expected_files.each do |file| + assert_equal(false, git.status.changed?(file)) + end + + # Change a file and make sure it's status says it has been changed + # + file = 'example.txt' + File.open(File.join(work_tree, file), "a") { |f| f.write("A new line") } + assert_equal(true, git.status.changed?(file)) + + # Add and commit the file and then check that: + # * the file is not flagged as changed anymore + # * the commit was added to the log + # + max_log_size = 100 + assert_equal(64, git.log(max_log_size).size) + git.add(file) + git.commit('This is a new commit') + assert_equal(false, git.status.changed?(file)) + assert_equal(65, git.log(max_log_size).size) + end + end + end +end