further file system abstractions

This commit is contained in:
Tom Preston-Werner 2009-07-23 15:21:59 -07:00
Родитель 82cac1a88e
Коммит 4e694b9a37
4 изменённых файлов: 177 добавлений и 10 удалений

Просмотреть файл

@ -1,3 +1,4 @@
require 'tempfile'
module Grit
class Git
@ -13,7 +14,11 @@ module Grit
undef_method :clone
include GitRuby
def exist?
File.exist?(self.git_dir)
end
def put_raw_object(content, type)
ruby_git.put_raw_object(content, type)
end
@ -49,6 +54,14 @@ module Grit
end
alias_method :e, :shell_escape
# Check if a normal file exists on the filesystem
# +file+ is the relative path from the Git dir
#
# Returns Boolean
def fs_exist?(file)
File.exist?(File.join(self.git_dir, file))
end
# Read a normal file from the filesystem.
# +file+ is the relative path from the Git dir
#
@ -75,9 +88,113 @@ module Grit
#
# Returns nothing
def fs_delete(file)
FileUtils.rm_f(File.join(self.git_dir,file))
FileUtils.rm_rf(File.join(self.git_dir, file))
end
# Move a normal file
# +from+ is the relative path to the current file
# +to+ is the relative path to the destination file
#
# Returns nothing
def fs_move(from, to)
FileUtils.mv(File.join(self.git_dir, from), File.join(self.git_dir, to))
end
# Make a directory
# +dir+ is the relative path to the directory to create
#
# Returns nothing
def fs_mkdir(dir)
FileUtils.mkdir_p(File.join(self.git_dir, dir))
end
# Chmod the the file or dir and everything beneath
# +file+ is the relative path from the Git dir
#
# Returns nothing
def fs_chmod(mode, file = '/')
FileUtils.chmod_R(mode, File.join(self.git_dir, file))
end
# Create a new directory
# +path+ is an absolute path
#
# Returns nothing
def fs_mkdir(path)
FileUtils.mkdir_p(path)
end
def fs_exist(path)
File.exist?(path)
end
def list_remotes
remotes = []
Dir.chdir(File.join(self.git_dir, 'refs/remotes')) do
remotes = Dir.glob('*')
end
remotes
rescue
[]
end
def create_tempfile(seed, unlink = false)
path = Tempfile.new(seed).path
File.unlink(path) if unlink
return path
end
def check_applies(head_sha, applies_sha)
git_index = create_tempfile('index', true)
(o1, exit1) = raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
(o2, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha} | git apply --check --cached >/dev/null 2>/dev/null", git_index)
return (exit1 + exit2)
end
def get_patch(applies_sha)
git_index = create_tempfile('index', true)
(patch, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha}", git_index)
patch
end
def apply_patch(head_sha, patch)
git_index = create_tempfile('index', true)
git_patch = create_tempfile('patch')
File.open(git_patch, 'w+') { |f| f.print patch }
raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
(op, exit) = raw_git("git apply --cached < #{git_patch}", git_index)
if exit == 0
return raw_git("git write-tree", git_index).first.chomp
end
false
end
# RAW CALLS WITH ENV SETTINGS
def raw_git_call(command, index)
tmp = ENV['GIT_INDEX_FILE']
ENV['GIT_INDEX_FILE'] = index
out = `#{command}`
after = ENV['GIT_INDEX_FILE'] # someone fucking with us ??
ENV['GIT_INDEX_FILE'] = tmp
if after != index
raise 'environment was changed for the git call'
end
[out, $?.exitstatus]
end
def raw_git(command, index)
output = nil
Dir.chdir(self.git_dir) do
output = raw_git_call(command, index)
end
output
end
# RAW CALLS WITH ENV SETTINGS END
# Run the given git command with the specified arguments and return
# the result as a String
# +cmd+ is the command

Просмотреть файл

@ -139,6 +139,34 @@ module Grit
def remotes
Remote.find_all(self)
end
def remote_list
self.git.list_remotes
end
def remote_add(name, url)
self.git.remote({}, 'add', name, url)
end
def remote_fetch(name)
self.git.fetch({}, name)
end
# takes an array of remote names and last pushed dates
# fetches from all of the remotes where the local fetch
# date is earlier than the passed date, then records the
# last fetched date
#
# { 'origin' => date,
# 'peter => date,
# }
def remotes_fetch_needed(remotes)
remotes.each do |remote, date|
# TODO: check against date
self.remote_fetch(remote)
end
end
# An array of Ref objects representing the refs in
# this repo
@ -280,9 +308,19 @@ module Grit
# Returns Grit::Repo (the newly created repo)
def self.init_bare(path, git_options = {}, repo_options = {})
git = Git.new(path)
git.fs_mkdir('..')
git.init(git_options)
self.new(path, repo_options)
end
def self.init_bare_or_open(path, git_options = {}, repo_options = {})
git = Git.new(path)
if !git.exist?
git.fs_mkdir(path)
git.init(git_options)
end
self.new(path, repo_options)
end
# Fork a bare git repository from this repo
# +path+ is the full path of the new repo (traditionally ends with /<name>.git)
@ -292,6 +330,7 @@ module Grit
def fork_bare(path, options = {})
default_options = {:bare => true, :shared => true}
real_options = default_options.merge(options)
Git.new(path).fs_mkdir('..')
self.git.clone(real_options, self.path, path)
Repo.new(path)
end
@ -335,7 +374,7 @@ module Grit
def archive_tar_gz(treeish = 'master', prefix = nil)
options = {}
options[:prefix] = prefix if prefix
self.git.archive(options, treeish, "| gzip")
self.git.archive(options, treeish, "| gzip -n")
end
# Write an archive directly to a file
@ -377,10 +416,9 @@ module Grit
#
# Returns Array[String] (pathnames of alternates)
def alternates
alternates_path = File.join(self.path, *%w{objects info alternates})
if File.exist?(alternates_path)
File.read(alternates_path).strip.split("\n")
alternates_path = "objects/info/alternates"
if self.git.fs_exist?(alternates_path)
self.git.fs_read(alternates_path).strip.split("\n")
else
[]
end
@ -418,6 +456,18 @@ module Grit
commit_sha
end
# Rename the current repository directory.
# +name+ is the new name
#
# Returns nothing
def rename(name)
if @bare
self.git.fs_move('/', "../#{name}")
else
self.git.fs_move('/', "../../#{name}")
end
end
# Pretty object inspection
def inspect
%Q{#<Grit::Repo "#{@path}">}

Просмотреть файл

@ -99,7 +99,7 @@ class TestGit < Test::Unit::TestCase
end
def test_fs_delete
FileUtils.expects(:rm_f).with(File.join(@git.git_dir, 'foo'))
FileUtils.expects(:rm_rf).with(File.join(@git.git_dir, 'foo'))
@git.fs_delete('foo')
end
end

Просмотреть файл

@ -242,7 +242,7 @@ class TestRepo < Test::Unit::TestCase
# disable_daemon_serve
def test_disable_daemon_serve
FileUtils.expects(:rm_f).with(File.join(@r.path, 'git-daemon-export-ok'))
FileUtils.expects(:rm_rf).with(File.join(@r.path, 'git-daemon-export-ok'))
@r.disable_daemon_serve
end
@ -255,7 +255,7 @@ class TestRepo < Test::Unit::TestCase
def test_alternates_with_two_alternates
File.expects(:exist?).with("#{absolute_project_path}/.git/objects/info/alternates").returns(true)
File.expects(:read).returns("/path/to/repo1/.git/objects\n/path/to/repo2.git/objects\n")
File.any_instance.expects(:read).returns("/path/to/repo1/.git/objects\n/path/to/repo2.git/objects\n")
assert_equal ["/path/to/repo1/.git/objects", "/path/to/repo2.git/objects"], @r.alternates
end