Module: Copernicium::Repos

Includes:
RevLog
Included in:
Workspace
Defined in:
lib/repos.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from RevLog

add_file, delete_file, diff_files, get_file, #hash_array, hash_file, merge, updatelog

Class Method Details

.delete_branch(branch) ⇒ Object

todo - also delete snapshots unique to this branch



271
272
273
274
# File 'lib/repos.rb', line 271

def Repos.delete_branch(branch)
  @@history.delete(branch)
  update_history
end

.delete_snapshot(id) ⇒ Object

Find snapshot, delete from snaps/memory



173
174
175
176
177
# File 'lib/repos.rb', line 173

def Repos.delete_snapshot(id)
  @@history[@@branch].delete_if { |x| x == id }
  File.delete File.join(@@snap, id)
  update_history
end

.diff_snapshots(id1, id2) ⇒ Object

diff_snapshots needs to catch both files in snap1 that aren’t and snap2 and find individual differences in between the files by calling RevLogs diffy. Return same thing as merge # note: id1 gets priority for history



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/repos.rb', line 182

def Repos.diff_snapshots(id1, id2)
  new_files = []
  conflicts = []
  diffed = {}
  files1 = get_snapshot(id1).files
  files2 = get_snapshot(id2).files
  new_files = diffset(files2, files1)

  # adding each new file from the merged snapshot
  new_files.each { |x| diffed[x.path] = get_file(x.last) }

  # handle files that exist in both snapshots
  files1.each do |file|
    # find corresponding file object
    f2_index = files2.index { |y| y == file }

    # If found, check if same content
    unless f2_index.nil?
      id1 = file.last
      id2 = files2[f2_index].last

      # get file contents
      content1 = RevLog.get_file(id1)
      content2 = RevLog.get_file(id2)

      # check if the file content for each path is the same
      if content1 == content2
        diffed[file.path] = content1
      else # If not same, diff and add to conflicts
        diffed[file.path] = diff_files(id1, id2)
        conflicts << file.path
      end
    else # not found, use our version
      diffed[file.path] = content1
    end
  end

  # returns [{path => content}, [conflicting paths]]
  [diffed, conflicts]
end

.diffset(array1, array2) ⇒ Object

Select all elements of array1 that are not in array2



224
225
226
# File 'lib/repos.rb', line 224

def Repos.diffset(array1, array2)
  array1.select { |x| !array2.any? { |y| x == y } }
end

.get_branch(branch) ⇒ Object

From the branch names, get the history, ant build the array of snapshots This is different than the history branch which just contains ids



264
265
266
267
268
# File 'lib/repos.rb', line 264

def Repos.get_branch(branch)
  Repos.history(branch).inject([]) do |hist, snapid|
    hist << Repos.get_snapshot(snapid)
  end
end

.get_snapshot(id) ⇒ Object

Find snapshot and return snapshot from id



162
163
164
165
166
167
168
169
170
# File 'lib/repos.rb', line 162

def Repos.get_snapshot(id)
  @@history.each do |_branch, snapids|
    snapids.each do |snapid|
      return YAML.load_file(File.join(@@snap, id)) if snapid == id
    end
  end

  raise "Repos: snapshot #{id} not found in this repo.".red
end

.has_branch?(branch) ⇒ Boolean

check whether a specific branch exists

Returns:

  • (Boolean)


88
89
90
# File 'lib/repos.rb', line 88

def Repos.has_branch?(branch)
  Repos.branches.include? branch
end

.has_snapshots?Boolean

check if any snapshots exist for the current branch

Returns:

  • (Boolean)


93
94
95
# File 'lib/repos.rb', line 93

def Repos.has_snapshots?
  not Repos.history(@@branch).empty?
end

.hasher(obj) ⇒ Object

Return hash of an object



98
99
100
# File 'lib/repos.rb', line 98

def Repos.hasher(obj)
  Digest::SHA256.hexdigest Marshal.dump(obj)
end

.history(branch = nil) ⇒ Object

Return array of snapshot IDs



118
119
120
121
122
123
124
125
126
# File 'lib/repos.rb', line 118

def Repos.history(branch = nil)
  if branch.nil? # return a list of unique all commits
    (@@history.inject([]) { |o, x| o + x.last }).uniq
  elsif Repos.has_branch? branch # just return the stored history
    @@history[branch]
  else # no commits yet
    []
  end
end

.make_branch(branch) ⇒ Object

BRANCHING FUNCTIONALITY

Create and return hash ID of new branch



250
251
252
253
254
255
# File 'lib/repos.rb', line 250

def Repos.make_branch(branch)
  @@history[branch] = @@history[@@branch].inject([]) { |n, o| n << o }
  @@branch = branch
  update_history
  hasher @@history[branch]
end

.make_snapshot(files = [], msg = 'nil') ⇒ Object

Create and return snapshot id



129
130
131
132
133
134
135
136
137
# File 'lib/repos.rb', line 129

def Repos.make_snapshot(files = [], msg = 'nil')
  snap = Snapshot.new(files, msg)
  @@history[@@branch] << snap.id

  # Update snaps file
  update_snap snap
  update_history
  snap.id
end

.merge_history(branch, hist) ⇒ Object



107
108
109
# File 'lib/repos.rb', line 107

def Repos.merge_history(branch, hist)
  @@history[branch] = sort_history(@@history[branch] + hist).uniq
end

.merge_snapshot(id) ⇒ Object

Merge the target snapshot into HEAD snapshot of the current branch todo - Check to make sure id is from a different branch



147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/repos.rb', line 147

def Repos.merge_snapshot(id)
  # run diff to get conflicts
  current = @@history[@@branch].last
  difference = diff_snapshots(current.id, id)
  conflicts = difference[1]

  if conflicts.empty? # make snapshot
    make_snap current.files + diffset(get_snapshot(id).files, current.files)
  end

  # returns [{path => content}, [conflicting paths]]
  difference
end

.setup(root = Dir.pwd) ⇒ Object

read in file of snapshot ids (.cn/history) check the current branch (.cn/branch)



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/repos.rb', line 56

def Repos.setup(root = Dir.pwd)
  @@copn = File.join(root, '.cn')
  @@snap = File.join(@@copn, 'snap')
  @@head = File.join(@@copn, 'branch')
  @@hist = File.join(@@copn, 'history')

  # read history from disk
  @@branch = File.read(@@head)
  @@history = YAML.load File.read(@@hist)
  @@brsnaps = Repos.get_branch @@branch
end

.setup_tester(root = Dir.pwd, branch = 'master') ⇒ Object

unit testing version - create folders for this code



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/repos.rb', line 69

def Repos.setup_tester(root = Dir.pwd, branch = 'master')
  @@copn = File.join(root, '.cn')
  @@snap = File.join(@@copn, 'snap')
  @@revs = File.join(@@copn, 'revs')
  @@head = File.join(@@copn, 'branch')
  @@hist = File.join(@@copn, 'history')

  # create folders for testing this module
  Dir.mkdir(@@copn) unless Dir.exist?(@@copn)
  Dir.mkdir(@@snap) unless Dir.exist?(@@snap)
  Dir.mkdir(@@revs) unless Dir.exist?(@@revs)

  # default new
  @@branch = branch
  @@history = {branch => []}
  RevLog.setup
end

.sort_history(hist) ⇒ Object



111
112
113
114
115
# File 'lib/repos.rb', line 111

def Repos.sort_history(hist)
  #fails if there is no snapshot with the target id (a | b)
  #hist.sort { |a, b| get_snapshot(a).date <=> get_snapshot(b).date }
  hist
end

.update(comm = UIComm.new) ⇒ Object

FOR PUSHPULL UPDATE

  • give a comm with user’s history to merge



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/repos.rb', line 284

def Repos.update(comm = UIComm.new)
  merge_name = File.join(@@copn, 'merging_' + comm.opts)

  if File.exist?(merge_name) # merge history
    branches = YAML.load File.read(merge_name)
    statuses = {}

    # merge @@history with remote hash
    branches.each do |branch, hist|
      statuses[branch] = 'is up-to-date with remote'
      if Repos.has_branch? branch # update
        hist.each_with_index do |snap, i|

          #byebug
          # merger hist length is longer than ours
          if @@history[branch][i].nil?
            statuses[branch] = 'updated successfully'
            Repos.merge_history branch, hist
            break

            # merger hist diverged from our system
          elsif @@history[branch][i] != snap
            statuses[branch] = 'merged history with local'
            Repos.merge_history branch, hist
            break

          end # else synchronized - no differences
        end # will exit cleanly if we are more up-to-date
      else # branch does not exist locally yet, copy
        statuses[branch] = 'created ok'
        @@history[branch] = hist
      end
      puts "Success: ".grn + "#{branch} ".yel + statuses[branch]
    end # end branch iterations

    # cleaning up...persist
    File.delete merge_name
    update_history
  else
    puts 'Error updating: '.red + merge_name + ' does not exist.'
  end
  statuses
end

.update_branch(branch) ⇒ Object



257
258
259
260
# File 'lib/repos.rb', line 257

def Repos.update_branch(branch)
  File.write(@@head, branch)
  @@branch = branch
end

.update_historyObject

helper to add snap to history



103
104
105
# File 'lib/repos.rb', line 103

def Repos.update_history
  File.write @@hist, YAML.dump(@@history) # write history
end

.update_snap(snap) ⇒ Object

helper to write a snapshot, saving a new commit marshal serializes the class instance to a string



141
142
143
# File 'lib/repos.rb', line 141

def Repos.update_snap(snap)
  File.write File.join(@@snap, snap.id), YAML.dump(snap)
end

Instance Method Details

#branchesObject

Return string array of what branches we have



244
# File 'lib/repos.rb', line 244

def branches() @@history.keys end

#currentObject

ADDITIONAL MODULE ACCESS INTERFACES

return the current branch we are on now (string name)



232
# File 'lib/repos.rb', line 232

def current() @@branch end

#current_filesObject

return the files in the latest snapshot



241
# File 'lib/repos.rb', line 241

def current_files() Repos.has_snapshots?? @@brsnaps.last.files : [] end

#current_headObject

return the snap id of branch head



235
# File 'lib/repos.rb', line 235

def current_head() @@history[@@branch].last end

#current_snapsObject

return the array of our branches snapshots



238
# File 'lib/repos.rb', line 238

def current_snaps() @@brsnaps end