module Copernicium::Repos

Public Class Methods

delete_branch(branch) click to toggle source

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
delete_snapshot(id) click to toggle source

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(id1, id2) click to toggle source

::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
diffset(array1, array2) click to toggle source

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
get_branch(branch) click to toggle source

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
get_snapshot(id) click to toggle source

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
has_branch?(branch) click to toggle source

check whether a specific branch exists

# File lib/repos.rb, line 88
def Repos.has_branch?(branch)
  Repos.branches.include? branch
end
has_snapshots?() click to toggle source

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
hasher(obj) click to toggle source

Return hash of an object

# File lib/repos.rb, line 98
def Repos.hasher(obj)
  Digest::SHA256.hexdigest Marshal.dump(obj)
end
history(branch = nil) click to toggle source

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
make_branch(branch) click to toggle source

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
make_snapshot(files = [], msg = 'nil') click to toggle source

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
merge_history(branch, hist) click to toggle source
# File lib/repos.rb, line 107
def Repos.merge_history(branch, hist)
  @@history[branch] = sort_history(@@history[branch] + hist).uniq
end
merge_snapshot(id) click to toggle source

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
setup(root = Dir.pwd) click to toggle source

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
setup_tester(root = Dir.pwd, branch = 'master') click to toggle source

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
sort_history(hist) click to toggle source
# 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) click to toggle source

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
update_branch(branch) click to toggle source
# File lib/repos.rb, line 257
def Repos.update_branch(branch)
  File.write(@@head, branch)
  @@branch = branch
end
update_history() click to toggle source

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
update_snap(snap) click to toggle source

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

branches() click to toggle source

Return string array of what branches we have

# File lib/repos.rb, line 244
def branches() @@history.keys end
current() click to toggle source

ADDITIONAL MODULE ACCESS INTERFACES

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

# File lib/repos.rb, line 232
def current() @@branch end
current_files() click to toggle source

return the files in the latest snapshot

# File lib/repos.rb, line 241
def current_files() Repos.has_snapshots?? @@brsnaps.last.files : [] end
current_head() click to toggle source

return the snap id of branch head

# File lib/repos.rb, line 235
def current_head() @@history[@@branch].last end
current_snaps() click to toggle source

return the array of our branches snapshots

# File lib/repos.rb, line 238
def current_snaps() @@brsnaps end