module Copernicium::Repos
Public Class Methods
todo - also delete snapshots unique to this branch
# File lib/repos.rb, line 271 def Repos.delete_branch(branch) @@history.delete(branch) update_history end
Find snapshot, delete from snaps/memory
# 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 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
# 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
Select all elements of array1 that are not in array2
# File lib/repos.rb, line 224 def Repos.diffset(array1, array2) array1.select { |x| !array2.any? { |y| x == y } } end
From the branch names, get the history, ant build the array of snapshots This is different than the history branch which just contains ids
# 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
Find snapshot and return snapshot from id
# 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
check whether a specific branch exists
# File lib/repos.rb, line 88 def Repos.has_branch?(branch) Repos.branches.include? branch end
check if any snapshots exist for the current branch
# File lib/repos.rb, line 93 def Repos.has_snapshots? not Repos.history(@@branch).empty? end
Return hash of an object
# File lib/repos.rb, line 98 def Repos.hasher(obj) Digest::SHA256.hexdigest Marshal.dump(obj) end
Return array of snapshot IDs
# 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
BRANCHING FUNCTIONALITY
Create and return hash ID of new branch
# 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
Create and return snapshot id
# 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
# File lib/repos.rb, line 107 def Repos.merge_history(branch, hist) @@history[branch] = sort_history(@@history[branch] + hist).uniq end
Merge the target snapshot into HEAD snapshot of the current branch todo - Check to make sure id is from a different branch
# 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
read in file of snapshot ids (.cn/history) check the current branch (.cn/branch)
# 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
unit testing version - create folders for this code
# 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
# 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
FOR PUSHPULL UPDATE
-
give a comm with user's history to merge
# 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
# File lib/repos.rb, line 257 def Repos.update_branch(branch) File.write(@@head, branch) @@branch = branch end
helper to add snap to history
# File lib/repos.rb, line 103 def Repos.update_history File.write @@hist, YAML.dump(@@history) # write history end
helper to write a snapshot, saving a new commit marshal serializes the class instance to a string
# File lib/repos.rb, line 141 def Repos.update_snap(snap) File.write File.join(@@snap, snap.id), YAML.dump(snap) end
Public Instance Methods
Return string array of what branches we have
# File lib/repos.rb, line 244 def branches() @@history.keys end
ADDITIONAL MODULE ACCESS INTERFACES
return the current branch we are on now (string name)
# File lib/repos.rb, line 232 def current() @@branch end
return the files in the latest snapshot
# File lib/repos.rb, line 241 def current_files() Repos.has_snapshots?? @@brsnaps.last.files : [] end
return the snap id of branch head
# File lib/repos.rb, line 235 def current_head() @@history[@@branch].last end
return the array of our branches snapshots
# File lib/repos.rb, line 238 def current_snaps() @@brsnaps end