lib/gitrb/repository.rb in gitrb-0.2.3 vs lib/gitrb/repository.rb in gitrb-0.2.4
- old
+ new
@@ -40,12 +40,10 @@
def initialize(options = {})
@bare = options[:bare] || false
@branch = options[:branch] || 'master'
@logger = options[:logger] || Logger.new(nil)
@encoding = options[:encoding] || DEFAULT_ENCODING
- @lock = {}
- @transaction = Mutex.new
@path = options[:path]
@path.chomp!('/')
@path += '/.git' if !@bare
@@ -54,21 +52,27 @@
load_packs
load
end
+ def dup
+ super.instance_eval do
+ @objects = Trie.new
+ load
+ self
+ end
+ end
+
# Bare repository?
def bare?
@bare
end
# Switch branch
def branch=(branch)
- @transaction.synchronize do
- @branch = branch
- load
- end
+ @branch = branch
+ load
end
# Has our repository been changed on disk?
def changed?
!head || head.id != read_head_id
@@ -79,26 +83,19 @@
load if changed?
end
# Clear cached objects
def clear
- @transaction.synchronize do
- @objects.clear
- load
- end
+ @objects.clear
+ load
end
- # Is there any transaction going on?
- def in_transaction?
- !!@lock[Thread.current.object_id]
- end
-
# Difference between versions
# Options:
# :to - Required target commit
# :from - Optional source commit (otherwise comparision with empty tree)
- # :path - Restrict to path
+ # :path - Restrict to path/or paths
# :detect_renames - Detect renames O(n^2)
# :detect_copies - Detect copies O(n^2), very slow
def diff(opts)
from, to = opts[:from], opts[:to]
if from && !(Commit === from)
@@ -110,33 +107,34 @@
to = Reference.new(:repository => self, :id => to)
end
Diff.new(from, to, git_diff_tree('--root', '--full-index', '-u',
opts[:detect_renames] ? '-M' : nil,
opts[:detect_copies] ? '-C' : nil,
- from ? from.id : nil, to.id, '--', opts[:path]))
+ from ? from.id : nil, to.id, '--', *opts[:path]))
end
# All changes made inside a transaction are atomic. If some
# exception occurs the transaction will be rolled back.
#
# Example:
# repository.transaction { repository['a'] = 'b' }
#
def transaction(message = '', author = nil, committer = nil)
- @transaction.synchronize do
- begin
- start_transaction
- result = yield
- commit(message, author, committer)
- result
- rescue
- rollback_transaction
- raise
- ensure
- finish_transaction
- end
- end
+ lock = File.open("#{head_path}.lock", 'w')
+ lock.flock(File::LOCK_EX)
+ refresh
+
+ result = yield
+ commit(message, author, committer)
+ result
+ rescue
+ @objects.clear
+ load
+ raise
+ ensure
+ lock.close rescue nil
+ File.unlink("#{head_path}.lock") rescue nil
end
# Write a commit object to disk and set the head of the current branch.
#
# Returns the commit object
@@ -160,19 +158,23 @@
commit
end
# Returns a list of commits starting from head commit.
+ # Options:
+ # :path - Restrict to path/or paths
+ # :max_count - Maximum count of commits
+ # :skip - Skip n commits
+ # :start - Commit to start from
def log(opts = {})
max_count = opts[:max_count]
skip = opts[:skip]
start = opts[:start]
- path = opts[:path]
raise ArgumentError, "Invalid commit: #{start}" if start.to_s =~ /^\-/
log = git_log('--pretty=tformat:%H%n%P%n%T%n%an%n%ae%n%at%n%cn%n%ce%n%ct%n%x00%s%n%b%x00',
skip ? "--skip=#{skip.to_i}" : nil,
- max_count ? "--max-count=#{max_count.to_i}" : nil, start, '--', path).split(/\n*\x00\n*/)
+ max_count ? "--max-count=#{max_count.to_i}" : nil, start, '--', *opts[:path]).split(/\n*\x00\n*/)
commits = []
log.each_slice(2) do |data, message|
data = data.split("\n")
parents = data[1].empty? ? nil : data[1].split(' ').map {|id| Reference.new(:repository => self, :id => id) }
commits << Commit.new(:repository => self,
@@ -259,11 +261,11 @@
def put(object)
raise ArgumentError unless object && GitObject === object
content = object.dump
data = "#{object.type} #{content.bytesize rescue content.length}\0#{content}"
- id = sha(data)
+ id = Digest::SHA1.hexdigest(data)
path = object_path(id)
@logger.debug "gitrb: Storing #{id}"
if !File.exists?(path)
@@ -346,47 +348,19 @@
else
raise ArgumentError, "Not a valid Git repository: '#{@path}'" if !File.directory?("#{@path}/objects")
end
end
- # Start a transaction.
- #
- # Tries to get lock on lock file, load the this repository if
- # has changed in the repository.
- def start_transaction
- file = File.open("#{head_path}.lock", 'w')
- file.flock(File::LOCK_EX)
- @lock[Thread.current.object_id] = file
- refresh
- end
-
- # Rerepository the state of the repository.
- #
- # Any changes made to the repository are discarded.
- def rollback_transaction
- @objects.clear
- load
- end
-
- # Finish the transaction.
- #
- # Release the lock file.
- def finish_transaction
- @lock[Thread.current.object_id].close rescue nil
- @lock.delete(Thread.current.object_id)
- File.unlink("#{head_path}.lock") rescue nil
- end
-
def get_type(id, expected)
object = get(id)
raise NotFound, "Wrong type #{object.type}, expected #{expected}" if object && object.type != expected
object
end
def load_packs
@packs = Trie.new
- @objects = Util::Synchronized.new(Trie.new)
+ @objects = Trie.new
packs_path = "#{@path}/objects/pack"
if File.directory?(packs_path)
Dir.open(packs_path) do |dir|
entries = dir.select { |entry| entry =~ /\.pack$/i }
@@ -406,14 +380,9 @@
else
@head = nil
@root = Tree.new(:repository => self)
end
@logger.debug "gitrb: Reloaded, head is #{head ? head.id : 'nil'}"
- end
-
- # Returns the hash value of an object string.
- def sha(str)
- Digest::SHA1.hexdigest(str)[0, 40]
end
# Returns the path to the current head file.
def head_path
"#{path}/refs/heads/#{branch}"