GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Fork of al3x/git-wiki
Description: A wiki engine that uses a Git repository as its data store.
Homepage: http://atonie.org/2008/02/git-wiki
Clone URL: git://github.com/zmalltalker/git-wiki.git
git-wiki / page.rb
100644 182 lines (152 sloc) 4.008 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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
class Page
  attr_reader :name, :attach_dir
 
  def initialize(name, rev=nil)
    @name = name
    @rev = rev
    @filename = File.join(GIT_REPO, @name)
    @attach_dir = File.join(GIT_REPO, '_attachments', unwiki(@name))
  end
  
  def unwiki(string)
    string.downcase
  end
 
  def body
    @body ||= RubyPants.new(RedCloth.new(raw_body).to_html).to_html.wiki_linked
  end
  
  def body=(something)
    update(something)
  end
  
  def branch_name
    $repo.current_branch
  end
  
  def updated_at
    commit.committer_date rescue Time.now
  end
 
  def raw_body
    if @rev
       @raw_body ||= blob.contents
    else
      @raw_body ||= File.exists?(@filename) ? File.read(@filename) : ''
    end
  end
 
  def update(content, message=nil)
    File.open(@filename, 'w') { |f| f << content }
    commit_message = tracked? ? "edited #{@name}" : "created #{@name}"
    commit_message += ' : ' + message if message && message.length > 0
    begin
      $repo.add(@name)
      $repo.commit(commit_message)
    rescue
      nil
    end
    @body = nil; @raw_body = nil
    @body
  end
 
  def tracked?
    $repo.ls_files.keys.include?(@name)
  end
 
  def history
    return nil unless tracked?
    @history ||= $repo.log.path(@name)
  end
 
  def delta(rev)
    $repo.diff(previous_commit, rev).path(@name).patch
  end
  
  def commit
    @commit ||= $repo.log.object(@rev || 'master').path(@name).first
  end
 
  def previous_commit
    @previous_commit ||= $repo.log(2).object(@rev || 'master').path(@name).to_a[1]
  end
 
  def next_commit
    begin
      if (self.history.first.sha == self.commit.sha)
        @next_commit ||= nil
      else
        matching_index = nil
        history.each_with_index { |c, i| matching_index = i if c.sha == self.commit.sha }
        @next_commit ||= history.to_a[matching_index - 1]
      end
    rescue
      @next_commit ||= nil
    end
  end
 
  def version(rev)
    data = blob.contents
    RubyPants.new(RedCloth.new(data).to_html).to_html.wiki_linked
  end
 
  def blob
    @blob ||= ($repo.gblob(@rev + ':' + @name))
  end
  
  # save a file into the _attachments directory
  def save_file(file, name = '')
    if name.size > 0
      filename = name + File.extname(file[:filename])
    else
      filename = file[:filename]
    end
    FileUtils.mkdir_p(@attach_dir) if !File.exists?(@attach_dir)
    new_file = File.join(@attach_dir, filename)
 
    f = File.new(new_file, 'w')
    f.write(file[:tempfile].read)
    f.close
        
    commit_message = "uploaded #{filename} for #{@name}"
    begin
      $repo.add(new_file)
      $repo.commit(commit_message)
    rescue
      nil
    end
  end
  
  def delete_file(file)
    file_path = File.join(@attach_dir, file)
    if File.exists?(file_path)
      File.unlink(file_path)
 
      commit_message = "removed #{file} for #{@name}"
      begin
        $repo.remove(file_path)
        $repo.commit(commit_message)
      rescue
        nil
      end
      
    end
  end
  
  def attachments
    if File.exists?(@attach_dir)
      return Dir.glob(File.join(@attach_dir, '*')).map { |f| Attachment.new(f, unwiki(@name)) }
    else
      false
    end
  end
  
  class Attachment
    attr_accessor :path, :page_name
    def initialize(file_path, name)
      @path = file_path
      @page_name = name
    end
    
    def name
      File.basename(@path)
    end
 
    def link_path
      File.join('/_attachment', @page_name, name)
    end
 
    def delete_path
      File.join('/a/file/delete', @page_name, name)
    end
 
    def image?
      ext = File.extname(@path)
      case ext
      when '.png', '.jpg', '.jpeg', '.gif'; return true
      else; return false
      end
    end
 
    def size
      size = File.size(@path).to_i
      case
      when size.to_i == 1; "1 Byte"
      when size < 1024; "%d Bytes" % size
      when size < (1024*1024); "%.2f KB" % (size / 1024.0)
      else "%.2f MB" % (size / (1024 * 1024.0))
      end.sub(/([0-9])\.?0+ /, '\1 ' )
    end
  end
  
end