public
Fork of Caged/gitnub
Description: A Gitk-like application written in RubyCocoa that looks like it belongs on a Mac. See the wiki for downloads and screenshots.
Homepage: http://alternateidea.com
Clone URL: git://github.com/benstiglitz/gitnub.git
gitnub / grit / lib / grit / diff.rb
100644 71 lines (56 sloc) 2.169 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module Grit
  
  class Diff
    attr_reader :a_path, :b_path
    attr_reader :a_commit, :b_commit
    attr_reader :a_mode, :b_mode
    attr_reader :new_file, :deleted_file
    attr_reader :diff
    
    def initialize(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
      @repo = repo
      @a_path = a_path
      @b_path = b_path
      @a_commit = a_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => a_commit)
      @b_commit = b_commit =~ /^0{40}$/ ? nil : Commit.create(repo, :id => b_commit)
      @a_mode = a_mode
      @b_mode = b_mode
      @new_file = new_file
      @deleted_file = deleted_file
      @diff = diff
    end
    
    def self.list_from_string(repo, text)
      lines = text.split("\n")
      
      diffs = []
      
      while !lines.empty?
        m, a_path, b_path = *lines.shift.match(%r{^diff --git a/(\S+) b/(\S+)$})
        
        if lines.first =~ /^old mode/
          m, a_mode = *lines.shift.match(/^old mode (\d+)/)
          m, b_mode = *lines.shift.match(/^new mode (\d+)/)
        end
        
        if lines.empty? || lines.first =~ /^diff --git/
          diffs << Diff.new(repo, a_path, b_path, nil, nil, a_mode, b_mode, false, false, nil)
          next
        end
        
        new_file = false
        deleted_file = false
        
        if lines.first =~ /^new file/
          m, b_mode = lines.shift.match(/^new file mode (.+)$/)
          a_mode = nil
          new_file = true
        elsif lines.first =~ /^deleted file/
          m, a_mode = lines.shift.match(/^deleted file mode (.+)$/)
          b_mode = nil
          deleted_file = true
        end
        
        m, a_commit, b_commit, b_mode = *lines.shift.match(%r{^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$})
        b_mode.strip! if b_mode
        
        diff_lines = []
        while lines.first && lines.first !~ /^diff/
          diff_lines << lines.shift
        end
        diff = diff_lines.join("\n")
        
        diffs << Diff.new(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)
      end
      
      diffs
    end
  end # Diff
  
end # Grit