-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
version-control-system #45
Changes from 8 commits
8545230
31bc7b1
30df542
4c05fbf
d7d87d0
5332694
d1f1658
338179b
4bfc151
d95ac6b
0bfea34
d4bb34e
4c00cc7
c42013e
f062559
4a923c2
64d6b09
1fe0d6f
4fd8216
b9b2cf3
fe852d3
147ee00
c7ab2ad
7829c50
73c03a2
bc025fe
4dc4f10
293ebfa
d53985d
256db12
31bdf8e
a71f996
d0325b2
b4aca5f
312f476
a89399d
398bed5
cce4e35
4f2a6f3
5710482
34900b6
0c4c349
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
require_relative 'vcs_internals' | ||
|
||
|
||
def create_blob(content) | ||
header = "blob #{File.size(content)}#{NULL}" | ||
sha_hash = get_sha_hash(header, content) | ||
hash_object(header, content, sha_hash) | ||
return sha_hash | ||
end | ||
|
||
|
||
def restore_blob(sha_hash, output_file_path) | ||
input_file_path = File.join(Dir.getwd, ".vcs", "objects", sha_hash) | ||
open(input_file_path, "r") do |input_file| | ||
open(output_file_path, "w") do |output_file| | ||
data = "" | ||
while not data.include? NULL | ||
current_data = input_file.read(BLOCK_SIZE) | ||
if current_data.nil? | ||
break | ||
end | ||
data += current_data | ||
end | ||
_header, _separator, data = data.partition(NULL) | ||
output_file.write(data.gsub(WINDOWS_LINE_END, UNIX_LINE_END)) | ||
while true | ||
data = input_file.read(BLOCK_SIZE) | ||
if data.nil? | ||
break | ||
end | ||
output_file.write(data.gsub(WINDOWS_LINE_END, UNIX_LINE_END)) | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
require_relative 'tree' | ||
require_relative 'vcs_internals' | ||
|
||
|
||
def create_commit(commit_message, parent) | ||
config_file_path = File.join(Dir.getwd, ".vcs", "config") | ||
config_parameters = {} | ||
open(config_file_path, "r") do |config_file| | ||
while true | ||
data = config_file.gets | ||
if data.nil? | ||
break | ||
end | ||
key, _separator, value = data.partition(':') | ||
config_parameters[key] = value | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd just use JSON or something standard, but upto you :P |
||
header = "" | ||
content = "" | ||
content = "sha:#{build_tree(Dir.getwd)}#{NULL}" | ||
content += "parent:#{parent}#{NULL}" | ||
content += "author:#{config_parameters.fetch("author")}#{NULL}" | ||
content += "email:#{config_parameters.fetch("author-email")}#{NULL}" | ||
content += "time:#{Time.now}#{NULL}" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use EOL here? |
||
content += "message:#{commit_message}" | ||
header = "commit #{content.length}#{NULL}" | ||
commit_hash = get_sha_hash(header, content) | ||
hash_object(header, content, commit_hash) | ||
return commit_hash | ||
end | ||
|
||
|
||
def parse_commit_object(commit_hash) | ||
content = {} | ||
input_file_path = File.join(Dir.getwd, ".vcs", "objects", commit_hash) | ||
open(input_file_path, "r") do |input_file| | ||
data = "" | ||
while not data.include? NULL | ||
current_data = input_file.read(BLOCK_SIZE) | ||
if current_data.nil? | ||
break | ||
end | ||
data += current_data | ||
end | ||
_header, _separator, data = data.partition(NULL) | ||
while true | ||
current_data = input_file.read(BLOCK_SIZE) | ||
if current_data.nil? | ||
break | ||
end | ||
data += current_data | ||
end | ||
data = data.split(NULL) | ||
for parameter in data | ||
key, _separator, value = parameter.partition(':') | ||
content[key] = value | ||
end | ||
end | ||
return content | ||
end | ||
|
||
|
||
def get_files_from_commit(sha_hash, directory_path) | ||
files_in_commit = {} | ||
files_in_current_node = {} | ||
files_in_current_node = get_directory_content(sha_hash) | ||
files_in_current_node.each do |file_name, sha_hash| | ||
if type(sha_hash).to_s.eql?("blob") | ||
files_in_commit[File.join(directory_path, file_name)] = \ | ||
sha_hash | ||
else | ||
files_in_commit.merge( | ||
get_files_from_commit( | ||
sha_hash, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This hash isn't a commit. Do you mean "get_files_from_tree"? |
||
File.join(directory_path, file_name) | ||
) | ||
) | ||
end | ||
end | ||
return files_in_commit | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
require_relative 'vcs_internals' | ||
|
||
|
||
NodeValue = Struct.new(:key, :parent_x, :parent_y) | ||
|
||
|
||
def get_lcs(old_lines, new_lines) | ||
lcs = Array.new(old_lines.length + 1) \ | ||
{Array.new(new_lines.length + 1, NodeValue.new(0, 0, 0))} | ||
for ii in (1..old_lines.length) | ||
for jj in (1..new_lines.length) | ||
if old_lines[ii - 1] == new_lines[jj - 1] | ||
lcs[ii][jj] = NodeValue.new( | ||
lcs[ii - 1][jj - 1].key + 1, | ||
ii - 1, | ||
jj - 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Trailing commas? |
||
) | ||
else | ||
lcs[ii][jj] = NodeValue.new(lcs[ii][jj - 1].key, ii, jj - 1) | ||
if lcs[ii - 1][jj].key > lcs[ii][jj].key | ||
lcs[ii][jj].key = lcs[ii - 1][jj].key | ||
lcs[ii][jj].parent_x = ii - 1 | ||
lcs[ii][jj].parent_y = jj | ||
end | ||
end | ||
end | ||
end | ||
lcs_old = Array.new(old_lines.length + 1, 0) | ||
lcs_new = Array.new(new_lines.length + 1, 0) | ||
current_x = old_lines.length | ||
current_y = new_lines.length | ||
while current_x != 0 || current_y != 0 | ||
parent_x = lcs[current_x][current_y].parent_x | ||
parent_y = lcs[current_x][current_y].parent_y | ||
if current_x - 1 == parent_x && current_y - 1 == parent_y | ||
lcs_old[current_x] = current_y | ||
lcs_new[current_y] = current_x | ||
end | ||
current_x = parent_x | ||
current_y = parent_y | ||
end | ||
return lcs_old, lcs_new | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont really understand these names. |
||
end | ||
|
||
|
||
def display_diff_delete(lines, lcs, index, line_new) | ||
start_index = index | ||
end_index = index | ||
index += 1 | ||
while index <= lines.length && lcs[index] == 0 | ||
end_index += 1 | ||
index += 1 | ||
end | ||
if start_index == end_index | ||
puts "#{start_index}d#{line_new}" | ||
puts "< #{lines[start_index - 1]}" | ||
else | ||
puts "#{start_index},#{end_index}d#{line_new}" | ||
while start_index <= end_index | ||
puts "< #{lines[start_index - 1]}" | ||
start_index += 1 | ||
end | ||
end | ||
return index | ||
end | ||
|
||
|
||
def display_diff_append(lines, lcs, index, line_old, line_new) | ||
line_new += 1 | ||
start_index = index | ||
end_index = index | ||
index += 1 | ||
while index <= lines.length && lcs[index] == 0 | ||
index += 1 | ||
end_index += 1 | ||
end | ||
if start_index == end_index | ||
puts "#{line_old}a#{line_new}" | ||
puts "> #{lines[start_index - 1]}" | ||
else | ||
puts "#{line_old}a#{line_new},#{line_new + (end_index - start_index)}" | ||
line_new += (end_index - start_index) | ||
while start_index <= end_index | ||
puts "> #{lines[start_index - 1]}" | ||
start_index += 1 | ||
end | ||
end | ||
return index, line_new | ||
end | ||
|
||
|
||
def display_diff_change( | ||
old_lines, | ||
new_lines, | ||
lcs_old, | ||
lcs_new, | ||
start_old_index, | ||
start_new_index, | ||
line_new | ||
) | ||
line_new += 1 | ||
start_old = start_old_index | ||
start_new = start_new_index | ||
end_old = start_old_index | ||
end_new = start_new_index | ||
|
||
start_old_index += 1 | ||
start_new_index += 1 | ||
while ( | ||
start_old_index <= old_lines.length && | ||
start_new_index <= new_lines.length && | ||
lcs_old[start_old_index] == 0 && | ||
lcs_new[start_new_index] == 0 | ||
) | ||
start_old_index += 1 | ||
end_old += 1 | ||
start_new_index += 1 | ||
end_new += 1 | ||
end | ||
if start_old == end_old | ||
puts "#{start_old}c#{line_new}" | ||
puts "< #{old_lines[start_old - 1]}" | ||
puts "---" | ||
puts "> #{new_lines[start_new - 1]}" | ||
else | ||
print "#{start_old},#{end_old}c#{line_new}," | ||
print "#{line_new + (end_old - start_old)}\n" | ||
line_new += (end_old - start_old) | ||
while start_old <= end_old | ||
puts "< #{old_lines[start_old - 1]}" | ||
start_old += 1 | ||
end | ||
puts "---" | ||
while start_new <= end_new | ||
puts "> #{new_lines[start_new - 1]}" | ||
start_new += 1 | ||
end | ||
end | ||
return start_old_index, start_new_index, line_new | ||
end | ||
|
||
|
||
def find_diff(file1, file2) | ||
old_lines = [] | ||
new_lines = [] | ||
if File.file?(file1) | ||
open(file1, "r") do |old_file| | ||
while true | ||
data = old_file.gets | ||
if data.nil? | ||
break | ||
end | ||
old_lines.push(data) | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make a get_lines method :P |
||
else | ||
old_lines.push(file1) | ||
end | ||
if File.file?(file2) | ||
open(file2, "r") do |new_file| | ||
while true | ||
data = new_file.gets | ||
if data.nil? | ||
break | ||
end | ||
new_lines.push(data) | ||
end | ||
end | ||
else | ||
new_lines.push(file2) | ||
end | ||
lcs_old, lcs_new = get_lcs(old_lines, new_lines) | ||
line_number_new = 0 | ||
old_index = 1 | ||
new_index = 1 | ||
while old_index <= old_lines.length || new_index <= new_lines.length | ||
if ( | ||
lcs_old[old_index] == 0 && | ||
(new_index > new_lines.length || lcs_new[new_index] != 0) | ||
) | ||
old_index = display_diff_delete( | ||
old_lines, | ||
lcs_old, | ||
old_index, | ||
line_number_new | ||
) | ||
elsif ( | ||
lcs_new[new_index] == 0 && | ||
(old_index > old_lines.length || lcs_old[old_index] != 0) | ||
) | ||
new_index, line_number_new = display_diff_append( | ||
new_lines, | ||
lcs_new, | ||
new_index, | ||
old_index - 1, | ||
line_number_new | ||
) | ||
elsif lcs_old[old_index] == 0 && lcs_new[new_index] == 0 | ||
old_index, new_index, line_number_new = display_diff_change( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO display_diff_change can handle the display_diff_append/display_diff_delete cases too, so you shouldn't need them. |
||
old_lines, | ||
new_lines, | ||
lcs_old, | ||
lcs_new, | ||
old_index, | ||
new_index, | ||
line_number_new | ||
) | ||
else lcs_new[new_index] == old_index | ||
line_number_new += 1 | ||
old_index += 1 | ||
new_index += 1 | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen this pattern in a bunch of places. You should probably extract it into a utility method.