Class: KSync::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/ksync.rb

Overview

this is the only class in the KSync module, needs to be instantiated

Constant Summary collapse

SSIZE_I =

index for size of file

0
MTIME_I =

index for modification date of file

1
KSYNC_FILES_HASH =

the name of the file containing the hash for the destination folder

'.ksync_files_hash'
VERSION =

the version of the ksync gem

'0.5.1'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(init_opt) ⇒ Base

initializes the class



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/ksync.rb', line 24

def initialize(init_opt)
  @all_h={}
  @changes = false
  init_opt[:real_copy] = init_opt[:real_copy] == nil ? true : init_opt[:real_copy]
  init_opt[:use_hash] = init_opt[:use_hash] == nil ? false : init_opt[:use_hash]
  init_opt[:verbose] = init_opt[:verbose] == nil ? 0 : init_opt[:verbose]
  init_opt[:force_dest_hash] = init_opt[:force_dest_hash] == nil ? false : init_opt[:force_dest_hash]

  return nil if !init_opt[:src] | !init_opt[:dst]
  @options = init_opt
  @ll = [init_opt[:src], init_opt[:dst]]
  create_hash
end

Instance Attribute Details

#all_hObject

Returns the value of attribute all_h.



22
23
24
# File 'lib/ksync.rb', line 22

def all_h
  @all_h
end

#llObject

Returns the value of attribute ll.



22
23
24
# File 'lib/ksync.rb', line 22

def ll
  @ll
end

Instance Method Details

#create_hashObject

creates the initial file list hash for the source and potentially the destination



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/ksync.rb', line 162

def create_hash
  if !File.exists?(ll.first)
    puts "source folder #{ll.first} does not exist ! "
    return
  end
  ll.each do |prefix|
    all_h[prefix] = {}
    if prefix == ll.last
      next if @options[:real_copy] == false
      dest_hash_file_name = File.join(ll.last,KSYNC_FILES_HASH)
      if File.exists?(dest_hash_file_name) && @options[:force_dest_hash] == false
        all_h[prefix] = load_files_hash(dest_hash_file_name)
        next unless @options[:force_dest_hash]
      end
    end

    cnt = 0
    if !File.exists?(prefix)
      puts "creating folder #{prefix}" if @options[:verbose] > 1
      FileUtils.mkdir_p prefix
    end

    Find.find(prefix).each do |f|
      next if prefix == f
      ff = f.unpack('U*').pack('U*')  # to get rid of funny encoding related errors
      all_h[prefix][ff.split(prefix)[1]] = [File.size(ff), File.mtime(ff)]
      puts "(#{ff})" if @options[:verbose] > 2
      puts cnt if cnt % 100 == 0 && @options[:verbose] > 1
      cnt += 1
    end

    save_files_hash(File.join(ll.last, KSYNC_FILES_HASH)) if prefix == ll.last

  end
end

#do_copy(src_fp, dst_fp) ⇒ Object

does the actual copy between source and destination



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/ksync.rb', line 102

def do_copy(src_fp, dst_fp)
  begin
    if File.directory?(src_fp)
      file_op = "mkdir"
      FileUtils.mkdir_p dst_fp
    else
      file_op = "cp"
      FileUtils.copy_file src_fp, dst_fp
    end
  rescue
    puts "ERR: while copying (#{file_op}) [#{src_fp} to #{dst_fp}] : (#{$!})"
  end
end

#do_delete(dst_fp) ⇒ Object

deletes file from destination



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ksync.rb', line 117

def do_delete (dst_fp)
  begin
    if File.exists?(dst_fp)
      if File.directory?(dst_fp)
        file_op = 'remove_dir'
        FileUtils.remove_dir(dst_fp)
      else
        file_op = 'rm'
        FileUtils.rm dst_fp
      end
    else
      puts "ERR: inexistent file/folder : #{dst_fp}"
    end
  rescue
    puts "ERR: (#{file_op}) for #{dst_fp} : (#{$!})"
  end
end

#do_syncObject

this method does the actual syncing : frontend



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
# File 'lib/ksync.rb', line 39

def do_sync
  # browse source hash to detect new and changed files
  return false unless File.exists?(ll.first)
  all_h[ll.first].each do |k,v|
    src_fp = File.join(ll.first,k)
    dst_fp = File.join(ll.last,k)
    if !all_h[ll.last][k]
      copy_del_actions('New', k, src_fp, dst_fp)
    else
      if !File.directory?(File.join(ll.first,k))
        copy_del_actions('Changed',k, src_fp, dst_fp) if !same?(src_fp, dst_fp, v, all_h[ll.last][k])
      end
    end
  end
  # browse destination hash to detect obsolete files
  all_h[ll.last].each do |k,v|
    #next if File.join(ll.last,KSYNC_FILES_HASH) == f  # ignore files list hash

    if !all_h[ll.first][k]
      dst_fp = File.join(ll.last,k)
      copy_del_actions('Deleted', k, nil, dst_fp )
    end
  end
  #puts "there were changes" if @changes
  #puts "nothing changed" if !@changes
  save_files_hash(File.join(ll.last, KSYNC_FILES_HASH)) if @changes and @options[:real_copy] == true
  return @changes
end

#get_hash(in_file) ⇒ Object

calculate a hash of a file



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ksync.rb', line 79

def get_hash(in_file)
  if !File.exists?(in_file)
    puts "ERR: inexistent file : #{in_file}"
    return nil
  end
  sha1 = Digest::SHA1.new
  begin
    File.open(in_file) do |file|
      buffer = ''
      # Read the file 512 bytes at a time
      while not file.eof
        file.read(512, buffer)
        sha1.update(buffer)
      end
    end
  rescue
    puts "ERR: while calculating hash for : #{in_file}: (#{$!})"
    return nil
  end
  return sha1.to_s
end

#load_files_hash(file) ⇒ Object

loads the files hash from disk



74
75
76
# File 'lib/ksync.rb', line 74

def load_files_hash(file)
  return YAML::load_file(file)
end

#same?(src_fp, dst_fp, src, dst) ⇒ Boolean

if hash => also check hash if sizes are same

Returns:

  • (Boolean)


136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/ksync.rb', line 136

def same?(src_fp, dst_fp, src, dst)
  size_ok = false
  date_ok = false
  if src[SSIZE_I] == dst[SSIZE_I] # sizes are the same
    size_ok = true
    if dst[MTIME_I] - dst[MTIME_I]  >=  0
      date_ok = true
    else
      puts "DATE diff for #{src_fp} vs #{dst_fp}" if @options[:verbose] > 1
    end
  else
    puts "SIZE diff for #{src_fp} vs #{dst_fp}" if @options[:verbose] > 1
  end
  return false if !size_ok
  return false if !date_ok
  return true if !@options[:use_hash]
  h1 = get_hash(src_fp)
  h2 = get_hash(dst_fp)
  if h1 != h2
    puts "SHA1 diff for #{src_fp} vs #{dst_fp}" if @options[:verbose] > 1
    return false
  end
  return true
end

#save_files_hash(file) ⇒ Object

saves the files hash to disk



69
70
71
# File 'lib/ksync.rb', line 69

def save_files_hash(file)
  File.open(file, 'w'){|f| f.write all_h[ll.last].to_yaml }
end