boof-grit 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/API.txt +101 -0
  2. data/History.txt +53 -0
  3. data/LICENSE +22 -0
  4. data/README.md +210 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/ex_add_commit.rb +13 -0
  7. data/examples/ex_index.rb +14 -0
  8. data/lib/grit.rb +68 -0
  9. data/lib/grit/actor.rb +36 -0
  10. data/lib/grit/blame.rb +61 -0
  11. data/lib/grit/blob.rb +126 -0
  12. data/lib/grit/commit.rb +246 -0
  13. data/lib/grit/commit_stats.rb +128 -0
  14. data/lib/grit/config.rb +44 -0
  15. data/lib/grit/diff.rb +70 -0
  16. data/lib/grit/errors.rb +7 -0
  17. data/lib/grit/git-ruby.rb +186 -0
  18. data/lib/grit/git-ruby/commit_db.rb +52 -0
  19. data/lib/grit/git-ruby/file_index.rb +193 -0
  20. data/lib/grit/git-ruby/git_object.rb +350 -0
  21. data/lib/grit/git-ruby/internal/file_window.rb +58 -0
  22. data/lib/grit/git-ruby/internal/loose.rb +137 -0
  23. data/lib/grit/git-ruby/internal/pack.rb +382 -0
  24. data/lib/grit/git-ruby/internal/raw_object.rb +37 -0
  25. data/lib/grit/git-ruby/object.rb +325 -0
  26. data/lib/grit/git-ruby/repository.rb +740 -0
  27. data/lib/grit/git.rb +141 -0
  28. data/lib/grit/index.rb +122 -0
  29. data/lib/grit/lazy.rb +33 -0
  30. data/lib/grit/merge.rb +45 -0
  31. data/lib/grit/ref.rb +177 -0
  32. data/lib/grit/repo.rb +452 -0
  33. data/lib/grit/ruby1.9.rb +7 -0
  34. data/lib/grit/status.rb +151 -0
  35. data/lib/grit/submodule.rb +88 -0
  36. data/lib/grit/tag.rb +66 -0
  37. data/lib/grit/tree.rb +123 -0
  38. data/lib/open3_detach.rb +46 -0
  39. data/test/bench/benchmarks.rb +126 -0
  40. data/test/helper.rb +18 -0
  41. data/test/profile.rb +21 -0
  42. data/test/suite.rb +6 -0
  43. data/test/test_actor.rb +35 -0
  44. data/test/test_blame.rb +32 -0
  45. data/test/test_blame_tree.rb +33 -0
  46. data/test/test_blob.rb +83 -0
  47. data/test/test_commit.rb +207 -0
  48. data/test/test_commit_stats.rb +33 -0
  49. data/test/test_commit_write.rb +20 -0
  50. data/test/test_config.rb +58 -0
  51. data/test/test_diff.rb +18 -0
  52. data/test/test_file_index.rb +56 -0
  53. data/test/test_git.rb +94 -0
  54. data/test/test_grit.rb +32 -0
  55. data/test/test_head.rb +72 -0
  56. data/test/test_index_status.rb +40 -0
  57. data/test/test_merge.rb +17 -0
  58. data/test/test_raw.rb +16 -0
  59. data/test/test_real.rb +19 -0
  60. data/test/test_reality.rb +17 -0
  61. data/test/test_remote.rb +14 -0
  62. data/test/test_repo.rb +381 -0
  63. data/test/test_rubygit.rb +192 -0
  64. data/test/test_rubygit_alt.rb +40 -0
  65. data/test/test_rubygit_index.rb +76 -0
  66. data/test/test_rubygit_iv2.rb +28 -0
  67. data/test/test_submodule.rb +69 -0
  68. data/test/test_tag.rb +103 -0
  69. data/test/test_tree.rb +101 -0
  70. metadata +143 -0
@@ -0,0 +1,151 @@
1
+ module Grit
2
+
3
+ class Status
4
+ include Enumerable
5
+
6
+ @base = nil
7
+ @files = nil
8
+
9
+ def initialize(base)
10
+ @base = base
11
+ construct_status
12
+ end
13
+
14
+ def changed
15
+ @files.select { |k, f| f.type == 'M' }
16
+ end
17
+
18
+ def added
19
+ @files.select { |k, f| f.type == 'A' }
20
+ end
21
+
22
+ def deleted
23
+ @files.select { |k, f| f.type == 'D' }
24
+ end
25
+
26
+ def untracked
27
+ @files.select { |k, f| f.untracked }
28
+ end
29
+
30
+ def pretty
31
+ out = ''
32
+ self.each do |file|
33
+ out << file.path
34
+ out << "\n\tsha(r) " + file.sha_repo.to_s + ' ' + file.mode_repo.to_s
35
+ out << "\n\tsha(i) " + file.sha_index.to_s + ' ' + file.mode_index.to_s
36
+ out << "\n\ttype " + file.type.to_s
37
+ out << "\n\tstage " + file.stage.to_s
38
+ out << "\n\tuntrac " + file.untracked.to_s
39
+ out << "\n"
40
+ end
41
+ out << "\n"
42
+ out
43
+ end
44
+
45
+ # enumerable method
46
+
47
+ def [](file)
48
+ @files[file]
49
+ end
50
+
51
+ def each
52
+ @files.each do |k, file|
53
+ yield file
54
+ end
55
+ end
56
+
57
+ class StatusFile
58
+ attr_accessor :path, :type, :stage, :untracked
59
+ attr_accessor :mode_index, :mode_repo
60
+ attr_accessor :sha_index, :sha_repo
61
+
62
+ @base = nil
63
+
64
+ def initialize(base, hash)
65
+ @base = base
66
+ @path = hash[:path]
67
+ @type = hash[:type]
68
+ @stage = hash[:stage]
69
+ @mode_index = hash[:mode_index]
70
+ @mode_repo = hash[:mode_repo]
71
+ @sha_index = hash[:sha_index]
72
+ @sha_repo = hash[:sha_repo]
73
+ @untracked = hash[:untracked]
74
+ end
75
+
76
+ def blob(type = :index)
77
+ if type == :repo
78
+ @base.object(@sha_repo)
79
+ else
80
+ @base.object(@sha_index) rescue @base.object(@sha_repo)
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ private
87
+
88
+ def construct_status
89
+ @files = ls_files
90
+
91
+ Dir.chdir(@base.working_dir) do
92
+ # find untracked in working dir
93
+ Dir.glob('**/*') do |file|
94
+ if !@files[file]
95
+ @files[file] = {:path => file, :untracked => true} if !File.directory?(file)
96
+ end
97
+ end
98
+
99
+ # find modified in tree
100
+ diff_files.each do |path, data|
101
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
102
+ end
103
+
104
+ # find added but not committed - new files
105
+ diff_index('HEAD').each do |path, data|
106
+ @files[path] ? @files[path].merge!(data) : @files[path] = data
107
+ end
108
+
109
+ @files.each do |k, file_hash|
110
+ @files[k] = StatusFile.new(@base, file_hash)
111
+ end
112
+ end
113
+ end
114
+
115
+ # compares the index and the working directory
116
+ def diff_files
117
+ hsh = {}
118
+ @base.git.diff_files.split("\n").each do |line|
119
+ (info, file) = line.split("\t")
120
+ (mode_src, mode_dest, sha_src, sha_dest, type) = info.split
121
+ hsh[file] = {:path => file, :mode_file => mode_src.to_s[1, 7], :mode_index => mode_dest,
122
+ :sha_file => sha_src, :sha_index => sha_dest, :type => type}
123
+ end
124
+ hsh
125
+ end
126
+
127
+ # compares the index and the repository
128
+ def diff_index(treeish)
129
+ hsh = {}
130
+ @base.git.diff_index({}, treeish).split("\n").each do |line|
131
+ (info, file) = line.split("\t")
132
+ (mode_src, mode_dest, sha_src, sha_dest, type) = info.split
133
+ hsh[file] = {:path => file, :mode_repo => mode_src.to_s[1, 7], :mode_index => mode_dest,
134
+ :sha_repo => sha_src, :sha_index => sha_dest, :type => type}
135
+ end
136
+ hsh
137
+ end
138
+
139
+ def ls_files
140
+ hsh = {}
141
+ lines = @base.git.ls_files({:stage => true})
142
+ lines.split("\n").each do |line|
143
+ (info, file) = line.split("\t")
144
+ (mode, sha, stage) = info.split
145
+ hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
146
+ end
147
+ hsh
148
+ end
149
+ end
150
+
151
+ end
@@ -0,0 +1,88 @@
1
+ module Grit
2
+
3
+ class Submodule
4
+ attr_reader :id
5
+ attr_reader :mode
6
+ attr_reader :name
7
+
8
+ # Create a Submodule containing just the specified attributes
9
+ # +repo+ is the Repo
10
+ # +atts+ is a Hash of instance variable data
11
+ #
12
+ # Returns Grit::Submodule (unbaked)
13
+ def self.create(repo, atts)
14
+ self.allocate.create_initialize(repo, atts)
15
+ end
16
+
17
+ # Initializer for Submodule.create
18
+ # +repo+ is the Repo
19
+ # +atts+ is a Hash of instance variable data
20
+ #
21
+ # Returns Grit::Submodule
22
+ def create_initialize(repo, atts)
23
+ @repo = repo
24
+ atts.each do |k, v|
25
+ instance_variable_set("@#{k}".to_sym, v)
26
+ end
27
+ self
28
+ end
29
+
30
+ # The url of this submodule
31
+ # +ref+ is the committish that should be used to look up the url
32
+ #
33
+ # Returns String
34
+ def url(ref)
35
+ config = self.class.config(@repo, ref)
36
+
37
+ lookup = config.keys.inject({}) do |acc, key|
38
+ id = config[key]['id']
39
+ acc[id] = config[key]['url']
40
+ acc
41
+ end
42
+
43
+ lookup[@id]
44
+ end
45
+
46
+ # The configuration information for the given +repo+
47
+ # +repo+ is the Repo
48
+ # +ref+ is the committish (defaults to 'master')
49
+ #
50
+ # Returns a Hash of { <path:String> => { 'url' => <url:String>, 'id' => <id:String> } }
51
+ # Returns {} if no .gitmodules file was found
52
+ def self.config(repo, ref = "master")
53
+ commit = repo.commit(ref)
54
+ blob = commit.tree/'.gitmodules'
55
+ return {} unless blob
56
+
57
+ lines = blob.data.gsub(/\r\n?/, "\n" ).split("\n")
58
+
59
+ config = {}
60
+ current = nil
61
+
62
+ lines.each do |line|
63
+ if line =~ /^\[submodule "(.+)"\]$/
64
+ current = $1
65
+ config[current] = {}
66
+ config[current]['id'] = (commit.tree/current).id
67
+ elsif line =~ /^\t(\w+) = (.+)$/
68
+ config[current][$1] = $2
69
+ config[current]['id'] = (commit.tree/$2).id if $1 == 'path'
70
+ else
71
+ # ignore
72
+ end
73
+ end
74
+
75
+ config
76
+ end
77
+
78
+ def basename
79
+ File.basename(name)
80
+ end
81
+
82
+ # Pretty object inspection
83
+ def inspect
84
+ %Q{#<Grit::Submodule "#{@id}">}
85
+ end
86
+ end # Submodule
87
+
88
+ end # Grit
data/lib/grit/tag.rb ADDED
@@ -0,0 +1,66 @@
1
+ module Grit
2
+
3
+ class Tag < Ref
4
+ def self.find_all(repo, options = {})
5
+ refs = []
6
+ already = {}
7
+
8
+ Dir.chdir(repo.path) do
9
+ files = Dir.glob(prefix + '/**/*')
10
+
11
+ files.each do |ref|
12
+ next if !File.file?(ref)
13
+
14
+ id = File.read(ref).chomp
15
+ name = ref.sub("#{prefix}/", '')
16
+ commit = commit_from_sha(repo, id)
17
+
18
+ if !already[name]
19
+ refs << self.new(name, commit)
20
+ already[name] = true
21
+ end
22
+ end
23
+
24
+ if File.file?('packed-refs')
25
+ lines = File.readlines('packed-refs')
26
+ lines.each_with_index do |line, i|
27
+ if m = /^(\w{40}) (.*?)$/.match(line)
28
+ next if !Regexp.new('^' + prefix).match(m[2])
29
+ name = m[2].sub("#{prefix}/", '')
30
+
31
+ # Annotated tags in packed-refs include a reference
32
+ # to the commit object on the following line.
33
+ next_line = lines[i+1]
34
+ if next_line && next_line[0] == ?^
35
+ commit = Commit.create(repo, :id => next_line[1..-1].chomp)
36
+ else
37
+ commit = commit_from_sha(repo, m[1])
38
+ end
39
+
40
+ if !already[name]
41
+ refs << self.new(name, commit)
42
+ already[name] = true
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ refs
50
+ end
51
+
52
+ def self.commit_from_sha(repo, id)
53
+ git_ruby_repo = GitRuby::Repository.new(repo.path)
54
+ object = git_ruby_repo.get_object_by_sha1(id)
55
+
56
+ if object.type == :commit
57
+ Commit.create(repo, :id => id)
58
+ elsif object.type == :tag
59
+ Commit.create(repo, :id => object.object)
60
+ else
61
+ raise "Unknown object type."
62
+ end
63
+ end
64
+ end
65
+
66
+ end
data/lib/grit/tree.rb ADDED
@@ -0,0 +1,123 @@
1
+ module Grit
2
+
3
+ class Tree
4
+ lazy_reader :contents
5
+ attr_reader :id
6
+ attr_reader :mode
7
+ attr_reader :name
8
+
9
+ # Construct the contents of the tree
10
+ # +repo+ is the Repo
11
+ # +treeish+ is the reference
12
+ # +paths+ is an optional Array of directory paths to restrict the tree
13
+ #
14
+ # Returns Grit::Tree (baked)
15
+ def self.construct(repo, treeish, paths = [])
16
+ output = repo.git.ls_tree({}, treeish, *paths)
17
+ self.allocate.construct_initialize(repo, treeish, output)
18
+ end
19
+
20
+ def construct_initialize(repo, id, text)
21
+ @repo = repo
22
+ @id = id
23
+ @contents = []
24
+
25
+ text.split("\n").each do |line|
26
+ @contents << content_from_string(repo, line)
27
+ end
28
+ @contents.compact!
29
+
30
+ self
31
+ end
32
+
33
+ def lazy_source
34
+ Tree.construct(@repo, @id, [])
35
+ end
36
+
37
+ # Create an unbaked Tree containing just the specified attributes
38
+ # +repo+ is the Repo
39
+ # +atts+ is a Hash of instance variable data
40
+ #
41
+ # Returns Grit::Tree (unbaked)
42
+ def self.create(repo, atts)
43
+ self.allocate.create_initialize(repo, atts)
44
+ end
45
+
46
+ # Initializer for Tree.create
47
+ # +repo+ is the Repo
48
+ # +atts+ is a Hash of instance variable data
49
+ #
50
+ # Returns Grit::Tree (unbaked)
51
+ def create_initialize(repo, atts)
52
+ @repo = repo
53
+
54
+ atts.each do |k, v|
55
+ instance_variable_set("@#{k}", v)
56
+ end
57
+ self
58
+ end
59
+
60
+ # Parse a content item and create the appropriate object
61
+ # +repo+ is the Repo
62
+ # +text+ is the single line containing the items data in `git ls-tree` format
63
+ #
64
+ # Returns Grit::Blob or Grit::Tree
65
+ def content_from_string(repo, text)
66
+ mode, type, id, name = text.split(" ", 4)
67
+ case type
68
+ when "tree"
69
+ Tree.create(repo, :id => id, :mode => mode, :name => name)
70
+ when "blob"
71
+ Blob.create(repo, :id => id, :mode => mode, :name => name)
72
+ when "link"
73
+ Blob.create(repo, :id => id, :mode => mode, :name => name)
74
+ when "commit"
75
+ Submodule.create(repo, :id => id, :mode => mode, :name => name)
76
+ else
77
+ raise "Invalid type: #{type}"
78
+ end
79
+ end
80
+
81
+ # Find the named object in this tree's contents
82
+ #
83
+ # Examples
84
+ # Repo.new('/path/to/grit').tree/'lib'
85
+ # # => #<Grit::Tree "6cc23ee138be09ff8c28b07162720018b244e95e">
86
+ # Repo.new('/path/to/grit').tree/'README.txt'
87
+ # # => #<Grit::Blob "8b1e02c0fb554eed2ce2ef737a68bb369d7527df">
88
+ #
89
+ # Returns Grit::Blob or Grit::Tree or nil if not found
90
+ def /(file)
91
+ if file =~ /\//
92
+ file.split("/").inject(self) { |acc, x| acc/x } rescue nil
93
+ else
94
+ self.contents.find { |c| c.name == file }
95
+ end
96
+ end
97
+
98
+ def basename
99
+ File.basename(name)
100
+ end
101
+
102
+ # Pretty object inspection
103
+ def inspect
104
+ %Q{#<Grit::Tree "#{@id}">}
105
+ end
106
+
107
+ # Find only Tree objects from contents
108
+ def trees
109
+ contents.select {|v| v.kind_of? Tree}
110
+ end
111
+
112
+ # Find only Blob objects from contents
113
+ def blobs
114
+ contents.select {|v| v.kind_of? Blob}
115
+ end
116
+
117
+ # Compares trees by name
118
+ def <=>(other)
119
+ name <=> other.name
120
+ end
121
+ end # Tree
122
+
123
+ end # Grit
@@ -0,0 +1,46 @@
1
+ module Open3
2
+ extend self
3
+
4
+ def popen3(*cmd)
5
+ pw = IO::pipe # pipe[0] for read, pipe[1] for write
6
+ pr = IO::pipe
7
+ pe = IO::pipe
8
+
9
+ pid = fork{
10
+ # child
11
+ fork{
12
+ # grandchild
13
+ pw[1].close
14
+ STDIN.reopen(pw[0])
15
+ pw[0].close
16
+
17
+ pr[0].close
18
+ STDOUT.reopen(pr[1])
19
+ pr[1].close
20
+
21
+ pe[0].close
22
+ STDERR.reopen(pe[1])
23
+ pe[1].close
24
+
25
+ exec(*cmd)
26
+ }
27
+ exit!(0)
28
+ }
29
+
30
+ pw[0].close
31
+ pr[1].close
32
+ pe[1].close
33
+ Process.waitpid(pid)
34
+ pi = [pw[1], pr[0], pe[0]]
35
+ pw[1].sync = true
36
+ if defined? yield
37
+ begin
38
+ return yield(*pi)
39
+ ensure
40
+ Process.detach(pid) if pid
41
+ pi.each { |p| p.close unless p.closed? }
42
+ end
43
+ end
44
+ pi
45
+ end
46
+ end