Skip to content

Commit fde3263

Browse files
author
scott Chacon
committed
few hours work - diff is done
1 parent 9d59d29 commit fde3263

File tree

13 files changed

+395
-68
lines changed

13 files changed

+395
-68
lines changed

EXAMPLES

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,43 +38,57 @@ g.grep('hello') # implies HEAD
3838
g.blob('v2.5:Makefile').grep('hello')
3939
g.tag('v2.5').grep('hello', 'docs/')
4040

41+
g.diff(commit1, commit2).size
42+
g.diff(commit1, commit2).stats
43+
g.tree('v2.5').diff('v2.6').insertions
44+
g.diff('gitsearch1', 'v2.5').path('lib/')
45+
g.diff('gitsearch1', @git.tree('v2.5'))
46+
g.diff('gitsearch1', 'v2.5').path('docs/').patch
47+
g.tree('v2.5').diff('v2.6').patch
48+
49+
g.tree('v2.5').diff('v2.6').each do |file_diff|
50+
puts file_diff.path
51+
puts file_diff.patch
52+
puts file_diff.blob(:src).contents
53+
end
54+
55+
g.config('user.name') # returns 'Scott Chacon'
56+
g.config # returns whole config hash
4157

4258
***** IMPLEMENTED *****
4359

44-
g.diff
45-
g.diff.shortstat
46-
g.diff.summary
47-
g.diff(commit1, commit2)
48-
g.diff("commit1..commit2")
60+
g.ls_files
61+
g.ls_files(:stage => true)
62+
63+
g.tag # returns array of Git::Tag objects
64+
4965

50-
g.diff_tree(Git::Tree, Git::Tree)
5166

5267

53-
g.status
5468

55-
g.ls_files
56-
g.ls_files(:stage => true)
5769

58-
g.tag # returns array of Git::Tag objects
5970

6071

6172
# needs write permission
6273

63-
g = Git.clone(URI, 'name', working_dir = GIT_DIR, {options})
64-
(username, password, ssl_key, git_dir, index_file)
6574

6675
g = Git.init
6776
Git.init('project')
6877
Git.init('/home/schacon/proj',
6978
{ :git_dir => '/opt/git/proj.git',
7079
:index_file => '/tmp/index'} )
80+
81+
82+
***** IMPLEMENTED *****
7183

84+
85+
g = Git.clone(URI, :name => 'name', :path => '/tmp/checkout'
86+
(username, password, ssl_key, git_dir, index_file)
7287

7388

89+
7490
g.config('user.name', 'Scott Chacon')
75-
g.config('user.email', 'email@email.com')
76-
g.config('user.name') # returns 'Scott Chacon'
77-
g.config # returns whole config hash
91+
g.config('user.email', 'email@email.com')
7892

7993
g.add('.')
8094
g.add([file1, file2])

lib/git.rb

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,11 @@
1919
require 'git/branch'
2020
require 'git/remote'
2121

22+
require 'git/diff'
2223
=begin
2324
require 'git/author'
2425
require 'git/file'
2526
26-
require 'git/diff'
27-
require 'git/remote'
28-
2927
require 'git/sha'
3028
require 'git/ref'
3129
=end
@@ -40,12 +38,12 @@ def self.open(working_dir, options = {})
4038
Base.open(working_dir, options)
4139
end
4240

43-
def clone
44-
Base.clone()
41+
def self.init(working_dir = '.', options = {})
42+
Base.init(working_dir, options)
4543
end
4644

47-
def init(working_dir = '.')
48-
Base.clone()
45+
def self.clone(uri, options = {})
46+
Base.clone(working_dir, options)
4947
end
50-
48+
5149
end

lib/git/base.rb

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,33 @@ def self.open(working_dir, opts={})
2222
self.new(git_options)
2323
end
2424

25-
def initialize(options = {})
26-
@working_directory = Git::Repository.new(options[:working_directory]) if options[:working_directory]
27-
@repository = Git::Repository.new(options[:repository]) if options[:repository]
28-
@index = Git::Index.new(options[:index]) if options[:index]
25+
def self.init(working_dir, opts = {})
26+
default = {:working_directory => working_dir,
27+
:repository => File.join(working_dir, '.git')}
28+
git_options = default.merge(opts)
29+
30+
if git_options[:working_directory]
31+
# if !working_dir, make it
32+
FileUtils.mkdir_p(git_options[:working_directory]) if !File.directory?(git_options[:working_directory])
33+
end
34+
35+
# run git_init there
36+
Git::Lib.new(git_options).init
37+
38+
self.new(git_options)
2939
end
30-
40+
3141
def self.clone
3242
raise NotImplementedError
3343
end
34-
35-
def self.init
36-
raise NotImplementedError
44+
45+
def initialize(options = {})
46+
@working_directory = Git::WorkingDirectory.new(options[:working_directory]) if options[:working_directory]
47+
@repository = Git::Repository.new(options[:repository]) if options[:repository]
48+
@index = Git::Index.new(options[:index]) if options[:index]
3749
end
50+
51+
3852

3953

4054
def dir
@@ -49,6 +63,23 @@ def index
4963
@index
5064
end
5165

66+
67+
#g.config('user.name', 'Scott Chacon') # sets value
68+
#g.config('user.email', 'email@email.com') # sets value
69+
#g.config('user.name') # returns 'Scott Chacon'
70+
#g.config # returns whole config hash
71+
def config(name = nil, value = nil)
72+
if(name && value)
73+
# set value
74+
elsif (name)
75+
# return value
76+
lib.config_get(name)
77+
else
78+
# return hash
79+
lib.config_list
80+
end
81+
end
82+
5283
# factory methods
5384

5485
def object(objectish)
@@ -75,6 +106,10 @@ def grep(string)
75106
self.object('HEAD').grep(string)
76107
end
77108

109+
def diff(objectish = 'HEAD', obj2 = nil)
110+
Git::Diff.new(self, objectish, obj2)
111+
end
112+
78113
# convenience methods
79114

80115
def revparse(objectish)

lib/git/branches.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ def initialize(base)
1111
@branches = {}
1212

1313
@base = base
14+
1415
@base.lib.branches_all.each do |b|
15-
@branches[b.full] = b
16+
@branches[b[0]] = Git::Branch.new(@base, b[0], b[1])
1617
end
1718
end
1819

lib/git/diff.rb

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,137 @@ class Diff
77
@base = nil
88
@from = nil
99
@to = nil
10+
@path = nil
1011

1112
@full_diff = nil
13+
@full_diff_files = nil
14+
@stats = nil
1215

1316
def initialize(base, from = nil, to = nil)
14-
dirty_log
1517
@base = base
16-
@from = from
17-
@to = to
18+
@from = from.to_s
19+
@to = to.to_s
1820
end
1921

20-
def
22+
def path(path)
23+
@path = path
24+
return self
25+
end
26+
27+
def size
28+
cache_stats
29+
@stats[:total][:files]
30+
end
31+
32+
def lines
33+
cache_stats
34+
@stats[:total][:lines]
35+
end
36+
37+
def deletions
38+
cache_stats
39+
@stats[:total][:deletions]
40+
end
41+
42+
def insertions
43+
cache_stats
44+
@stats[:total][:insertions]
45+
end
46+
47+
def stats
48+
cache_stats
49+
@stats
50+
end
51+
52+
# if file is provided and is writable, it will write the patch into the file
53+
def patch(file = nil)
54+
cache_full
55+
@full_diff
56+
end
57+
alias_method :to_s, :patch
58+
2159
# enumerable methods
2260

61+
def [](key)
62+
process_full
63+
@full_diff_files.assoc(key)[1]
64+
end
65+
2366
def each
24-
cache_diff
25-
@full_diff.each do |file|
26-
yield file
67+
process_full
68+
@full_diff_files.each do |file|
69+
yield file[1]
70+
end
71+
end
72+
73+
class DiffFile
74+
attr_accessor :patch, :path, :mode, :src, :dst, :type
75+
@base = nil
76+
77+
def initialize(base, hash)
78+
@base = base
79+
@patch = hash[:patch]
80+
@path = hash[:path]
81+
@mode = hash[:mode]
82+
@src = hash[:src]
83+
@dst = hash[:dst]
84+
@type = hash[:type]
85+
end
86+
87+
def blob(type = :dst)
88+
if type == :src
89+
@base.object(@src) if @src != '0000000'
90+
else
91+
@base.object(@dst) if @dst != '0000000'
92+
end
2793
end
2894
end
2995

3096
private
3197

32-
def cache_diff
98+
def cache_full
3399
if !@full_diff
34-
@full_diff = @base.lib.diff_files(@from, @to)
100+
@full_diff = @base.lib.diff_full(@from, @to, {:path_limiter => @path})
101+
end
102+
end
103+
104+
def process_full
105+
if !@full_diff_files
106+
cache_full
107+
@full_diff_files = process_full_diff
108+
end
109+
end
110+
111+
def cache_stats
112+
if !@stats
113+
@stats = @base.lib.diff_stats(@from, @to, {:path_limiter => @path})
114+
end
115+
end
116+
117+
# break up @diff_full
118+
def process_full_diff
119+
final = {}
120+
current_file = nil
121+
@full_diff.split("\n").each do |line|
122+
if m = /diff --git a\/(.*?) b\/(.*?)/.match(line)
123+
current_file = m[1]
124+
final[current_file] = {:patch => line, :path => current_file,
125+
:mode => '', :src => '', :dst => '', :type => 'modified'}
126+
else
127+
if m = /index (.......)\.\.(.......)( ......)*/.match(line)
128+
final[current_file][:src] = m[1]
129+
final[current_file][:dst] = m[2]
130+
final[current_file][:mode] = m[3].strip if m[3]
131+
end
132+
if m = /(.*?) file mode (......)/.match(line)
133+
final[current_file][:type] = m[1]
134+
final[current_file][:mode] = m[2]
135+
end
136+
final[current_file][:patch] << "\n" + line
137+
end
35138
end
139+
final.map { |e| [e[0], DiffFile.new(@base, e[1])] }
36140
end
141+
142+
end
37143
end

0 commit comments

Comments
 (0)