root/lang/ruby/mdmaildir/mdd.rb @ 9074

Revision 9074, 3.2 kB (checked in by ihag, 5 years ago)

lang/ruby/mdmaildir/mdmerge.rb:

  • add -f COMMAND_FILE option for make cmdfile mode.
  • add -c -f COMMAND_FILE option for commit from cmdfile mode.
  • Introduced CMDProcessor class for abstracting the behavior of command.

lang/ruby/mdmaildir/mdd.rb: add comments.
lang/ruby/mdmaildir/README: fix typo.

  • Property svn:keywords set to Id
Line 
1#!/usr/local/bin/ruby
2# $Id$
3
4#
5# = Manipulates message-digest file for whole of messages in the Maildir.
6#
7# Authors::  $Author: genta $
8# Revision:: $Revision: 77 $
9#
10class MDDigest
11  require 'gdbm'
12  require 'digest/sha1'
13  require 'pp'
14
15  attr_reader :path, :basedir, :db
16
17  # Create MDDigest instance.  MDDigest opens a message-digest file in
18  # the specified Maildir.  The message-digest file is stored into the
19  # top-level directory as filename like "_maildir_/mddigest".
20  #
21  # _maildir_:: Path of Maildir.
22  # returns::   An instance of MDDigest class
23  def initialize(maildir)
24    @basedir = maildir.dup
25    @path = File.join(@basedir, 'mddigest')
26    open()
27  end
28
29  def open;  @db = GDBM.open(@path); end
30  private :open
31
32  # Close the backend DBM. Call this method at the end of your program.
33  def close;
34    @db.reorganize.close
35  end
36
37  # Truncate message-digest file.
38  def clear
39    @db.clear
40  end
41
42  # Caliculates a message-digest for specified message, and records it
43  # into message-digest file.
44  #
45  # _path_::  Relative path of a message from Maildir directory.
46  # returns:: void
47  def add(path)
48    apath = abspath(path)
49
50    md = hash(apath).hexdigest
51    size = File.size(apath)
52    key = md + '|' + size.to_s
53
54    if @db.key?(key) then
55      merge(key, path)
56      return
57    end
58    @db[key] = path
59  end
60
61  # Check specified key and file are already records in message-digest
62  # file, or not.
63  #
64  # _key_::   Key of file-hash. It typically message-digest + size of
65  #           message.
66  # _file_::  Relative path of a message from Maildir directory.
67  # returns:: *true* if it already exists.
68  #           *false* for not exists.
69  def has_file?(key, file)
70    return false if @db[key].nil?
71    @db[key].split('\0').each do |src|
72      return true if src == file
73    end
74    return false
75  end
76
77  # Wrapper of GDBM#each. It is for traversal all of messages in Maildir
78  # by using a message-digest file.
79  def each(&block)
80    @db.each(&block)
81  end
82
83
84  private
85
86  # Caliculates a Message digest for specified message.
87  #
88  # _file_::  Path for a message.
89  # returns:: Instance of Digest::SHA1.
90  def hash(file)
91    md = Digest::SHA1.new
92    File.open(file, 'r') do |fd|
93      buf = ''
94      while fd.read(256, buf)
95        md << buf
96      end
97    end
98    return md
99  end
100
101  # _key_::
102  # _dest_::
103  def merge(key, dest)
104    dfolder = folder(abspath(dest))
105    list = @db[key].split('\0')
106    list.map! do |src|
107      return if src == dest
108      if folder(src) == dfolder then
109        return if File.mtime(abspath(dest)) < File.mtime(abspath(src))
110        next
111      end
112      src
113    end.compact!
114    list += [dest]
115    raise "Idential" if list.join('\0') == @db[key]
116    @db[key] = list.join('\0')
117  end
118
119  # Determines a folder name for a specified message.
120  #
121  # _path_::  Relative path of a message from Maildir directory
122  # returns:: A folder name in Maildir for a message that directed by path.
123  def folder(path)
124    f, = path.split('/')
125    return '' unless f =~ /^\./
126    return f
127  end
128
129  # Convert relative path to the absolute path. The root of absolute path is
130  # Maildir directory.
131  #
132  # _file_::  Relative path from Maildir directory.
133  # returns:: Absolute path that converted from _file_.
134  def abspath(file)
135    File.expand_path(file, @basedir)
136  end
137end
Note: See TracBrowser for help on using the browser.