copernicium 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cffaf1f93a4556043ac0a484ef0e10c24f7ea692
4
+ data.tar.gz: 41ece5cd459baf3690d2701e153b232293f3a433
5
+ SHA512:
6
+ metadata.gz: 215e18ebaa93fb182b3ea4407bbf266cee5004baef77e1ff195cbcd32061a7314e7c49b02b1f762482c950436c495b802f302d8d2bf976c0b17518bd17d5444c
7
+ data.tar.gz: ebf39e146f63bc17bc70de329ea98c2b5f0cbea79f6a4aa620f9f21719f96879ea7737864e34a2d747ee75861ba2c5f9daad1c9a6f55c81a509a6a95a324f265
data/bin/cn ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # copernicium - a distributed version control system
4
+
5
+ require_relative "../lib/required.rb"
6
+
7
+ include Copernicium
8
+
9
+ Copernicium::Driver.new.run(ARGV)
10
+
data/lib/RevLog.rb ADDED
@@ -0,0 +1,141 @@
1
+ # Revlog Top Level Function Definitions (Xiangru)
2
+ #
3
+ # add_file: add a file to the revision history
4
+ # in - file name, content
5
+ # out - hash id of file (file_id)
6
+ #
7
+ # delete_file: a delete a file from revision history
8
+ # in - file_id
9
+ # out - exit status code
10
+ #
11
+ # diff_files: generate the differences between 2 files
12
+ # in - two file_ids
13
+ # out - list of differences
14
+ #
15
+ # get_file: get the contents of a file based on hash id
16
+ # in - file_id
17
+ # out - content of specified file
18
+ #
19
+ # hash_file: generate hash id for a given file
20
+ # in - file name, content
21
+ # out - hashed id
22
+ #
23
+ # merge: given two files, try to merge them
24
+ # in - file_id_1, file_id_2
25
+ # out - success and merged file name/content, or failure and conflict
26
+
27
+ module Copernicium
28
+ class RevLog
29
+ def initialize(project_path)
30
+ @project_path = project_path
31
+ @cop_path = File.join(project_path, ".cop")
32
+ @log_path = File.join(@cop_path, "logmap.yaml")
33
+ @hash_path = File.join(@cop_path, "hashmap.yaml")
34
+ if File.exist?(@log_path) and File.exist?(@hash_path) then
35
+ @logmap = default_hash_factory.merge(YAML.load_file(@log_path))
36
+ @hashmap = default_hash_factory.merge(YAML.load_file(@hash_path))
37
+ else
38
+ @logmap = default_hash_factory()
39
+ @hashmap = default_hash_factory()
40
+ unless File.exist?(@cop_path)
41
+ Dir.mkdir(@cop_path)
42
+ end
43
+ end
44
+ end
45
+
46
+ def default_hash_factory()
47
+ Hash.new {[]}
48
+ end
49
+
50
+ def add_file(file_name, content)
51
+ hash = hash_file(file_name, content)
52
+ File.open(File.join(@cop_path, hash), "w") { |f|
53
+ f.write(content)
54
+ }
55
+ @logmap[file_name] = @logmap[file_name] << {:time => Time.now,
56
+ :hash => hash}
57
+ @hashmap[hash] = @hashmap[hash] << {:time => Time.now,
58
+ :filename => file_name}
59
+ update_log_file()
60
+ return hash
61
+ end
62
+
63
+ ## return 1 if succeed, otherwise 0
64
+ def delete_file(file_id)
65
+ begin
66
+ file_name = @hashmap[file_id][0][:filename]
67
+ @hashmap[file_id].delete_if { |e|
68
+ e[:filename] == file_name
69
+ }
70
+ @logmap[file_name].delete_if { |e|
71
+ e[:hash] == file_id
72
+ }
73
+ update_log_file()
74
+ File.delete(File.join(@cop_path, file_id))
75
+ return 1
76
+ rescue Exception
77
+ return 0
78
+ end
79
+ end
80
+
81
+
82
+ def get_file(file_id)
83
+ file_path = File.join(@cop_path, file_id)
84
+ if File.exist?(file_path)
85
+ File.open(file_path, "r") { |f|
86
+ return f.read
87
+ }
88
+ else
89
+ raise Exception, "Invalid file_id!"
90
+ end
91
+ end
92
+
93
+
94
+ def diff_files(file_id1, file_id2)
95
+ return Diffy::Diff.new(get_file(file_id1),
96
+ get_file(file_id2)).to_s()
97
+ end
98
+
99
+ def hash_file(file_name, content)
100
+ Digest::SHA256.hexdigest(file_name + content.to_s)
101
+ end
102
+
103
+ def merge(file_id1, file_id2)
104
+ diff_a = Diffy::Diff.new(get_file(file_id1),
105
+ get_file(file_id2)).each_chunk.to_a()
106
+ if diff_a.all? { |d| d[0]!="-"}
107
+ return get_file(file_id2)
108
+ end
109
+ # if diff_a.all? { |d| d[0]!="+"}
110
+ # return get_file(file_id1)
111
+ # end
112
+ return diff_a
113
+ end
114
+
115
+ def history(file_name)
116
+ hashs = []
117
+ for m in @logmap[file_name]
118
+ hashs << m[:hash]
119
+ end
120
+ return hashs
121
+ end
122
+
123
+ def update_log_file()
124
+ File.open(File.join(@cop_path, "logmap.yaml"), "w") { |f|
125
+ f.write(@logmap.to_yaml)
126
+ }
127
+ File.open(File.join(@cop_path, "hashmap.yaml"), "w") { |f|
128
+ f.write(@hashmap.to_yaml)
129
+ }
130
+ end
131
+
132
+ # def alterFile(fileObject, fileReferenceString, versionReferenceString)
133
+ # end
134
+
135
+ # def deleteFileVersion(fileReferenceString, versionReferenceString)
136
+ # end
137
+
138
+ # def viewFileHistory(fileReferenceString)
139
+ # end
140
+ end
141
+ end
data/lib/banners.rb ADDED
@@ -0,0 +1,23 @@
1
+ # file for large constant strings
2
+
3
+
4
+ HELP_BANNER = <<-EOS
5
+ Copernicium - simple DVCS
6
+
7
+ Starting:
8
+ init - create a new repository
9
+ status - check repo status
10
+
11
+ Commands:
12
+ commit <files> -m [message]
13
+ checkout [branch name]
14
+ merge [branch name]
15
+ clone [remote url]
16
+ push <remote name>
17
+ pull <remote name>
18
+
19
+ Options:
20
+ -v: print version
21
+ -h: show help
22
+ EOS
23
+
data/lib/pushpull.rb ADDED
@@ -0,0 +1,168 @@
1
+ # Frank Tamburrino
2
+ # CSC 253
3
+ # PushPull Module
4
+ # November 6, 2015
5
+
6
+
7
+ module Copernicium
8
+ class PushPull
9
+
10
+ def connect(remote, user = nil, passwd = nil, &block)
11
+ exit_code = false
12
+ if(block.nil?)
13
+ begin
14
+ if(user.nil?)
15
+ print "Username for remote repo?: "
16
+ user = (STDIN.readline).strip
17
+ end
18
+ if(passwd.nil?)
19
+ print "Password for #{user}: "
20
+ passwd = (STDIN.noecho(&:gets)).strip
21
+ puts
22
+ end
23
+ Net::SSH.start(remote, user, :password => passwd) do |ssh|
24
+ result = ssh.exec!("echo Successful Connection!")
25
+ puts result
26
+ exit_code = true;
27
+ end
28
+ rescue
29
+ puts "Connection Unsuccessful"
30
+ end
31
+ else
32
+ begin
33
+ if(user.nil?)
34
+ print "Username for remote repo: "
35
+ user = (STDIN.readline).strip
36
+ end
37
+ if(passwd.nil?)
38
+ print "Password for #{user}: "
39
+ passwd = (STDIN.noecho(&:gets)).strip
40
+ puts
41
+ end
42
+ Net::SSH.start(remote, user, :password => passwd) do |ssh|
43
+ yield ssh
44
+ end
45
+ exit_code = true;
46
+ rescue
47
+ puts "Unable to execute command!"
48
+ end
49
+ end
50
+ return exit_code
51
+ end
52
+
53
+ def transfer(remote, local, dest, user = nil, passwd = nil)
54
+ exit_code = false
55
+ if(user.nil?)
56
+ print "Username for remote repo: "
57
+ user = (STDIN.readline).strip
58
+ end
59
+ if(passwd.nil?)
60
+ print "Password for #{user}: "
61
+ passwd = (STDIN.noecho(&:gets)).strip
62
+ puts
63
+ end
64
+ begin
65
+ Net::SCP.start(remote, user, :password => passwd) do |scp|
66
+ scp.upload!(local, dest)
67
+ end
68
+ exit_code = true
69
+ rescue
70
+ puts "Unable to upload file!"
71
+ end
72
+ end
73
+
74
+ def fetch(remote, dest, local, user = nil, passwd = nil)
75
+ exit_code = false
76
+ if(user.nil?)
77
+ print "Username for remote repo: "
78
+ user = (STDIN.readline).strip
79
+ end
80
+ if(passwd.nil?)
81
+ print "Password for #{user}: "
82
+ passwd = (STDIN.noecho(&:gets)).strip
83
+ puts
84
+ end
85
+ begin
86
+ Net::SCP.start(remote, user, :password => passwd) do |scp|
87
+ scp.download!(dest, local, :recursive => true)
88
+ end
89
+ exit_code = true
90
+ rescue
91
+ puts "Unable to fetch file(s)!"
92
+ end
93
+
94
+ return exit_code
95
+ end
96
+
97
+ def push(remote, branch, remote_dir)
98
+ ################ One way we can handle it ###################
99
+ ################ Needs Repos and Revlog Functionality! ######
100
+ # snap_id = (Repos::Repo.history(branch)).last
101
+ # snap = RevLog::RevLog.get_file(snap_id)
102
+ # connect(remote) do |x|
103
+ # result = test.exec!("<call to Repos to diff the snapshots>")
104
+ # end
105
+ # print "Username for remote repo: "
106
+ # user = (STDIN.readline).strip
107
+ # print "Password for #{user}: "
108
+ # passwd = (STDIN.noecho(&:gets)).strip
109
+ # puts
110
+ # for result.each do |x|
111
+ # transfer(remote, "./#{x}", remote_dir, user, passwd)
112
+ # end
113
+ # connect(remote) do |x|
114
+ # test.exec!("<call to Repos to merge the files>")
115
+ # test.exec!("<clean up the files>")
116
+ # end
117
+ #############################################################
118
+ end
119
+
120
+ def pull(remote, branch, remote_dir)
121
+ ################ One way we can handle it ###################
122
+ ################ Needs Repos and Revlog Functionality! ######
123
+ # snap_id = (Repos::Repo.history(branch)).last
124
+ # snap = RevLog::RevLog.get_file(snap_id)
125
+ # connect(remote) do |x|
126
+ # result = test.exec!("<call to Repos to diff the snapshots>")
127
+ # end
128
+ # print "Username for remote repo: "
129
+ # user = (STDIN.readline).strip
130
+ # print "Password for #{user}: "
131
+ # passwd = (STDIN.noecho(&:gets)).strip
132
+ # puts
133
+ # for result.each do |x|
134
+ # fetch(remote, remote_dir, "./#{x}", user, passwd)
135
+ # RevLog::Revlog.merge(x, local_x)
136
+ # File.delete(x)
137
+ # end
138
+ #############################################################
139
+ end
140
+
141
+ def clone(remote, dir, user = nil, passwd = nil)
142
+ exit_code = false
143
+ if(user.nil?)
144
+ print "Username for remote repo: "
145
+ user = (STDIN.readline).strip
146
+ end
147
+ if(passwd.nil?)
148
+ print "Password for #{user}: "
149
+ passwd = (STDIN.noecho(&:gets)).strip
150
+ puts
151
+ end
152
+ begin
153
+ fetch(remote, dir, ".", user, passwd)
154
+ nd = File.basename(dir)
155
+ ################ Needs Repos Functionality! #################
156
+ # Initializes the folder as a Repo
157
+ # Repos::Repos.make_branch(nd)
158
+ #############################################################
159
+ exit_code = true;
160
+ rescue
161
+ puts "Failed to clone the remote branch!"
162
+ end
163
+
164
+ return exit_code
165
+ end
166
+
167
+ end
168
+ end
data/lib/repos.rb ADDED
@@ -0,0 +1,165 @@
1
+ # repos module
2
+
3
+ #require 'marshal'
4
+ # Details from this link:
5
+ # https://docs.google.com/document/d/1r3-NquhyRLbCncqTOQPwsznSZ-en6G6xzLbWIAmxhys/edit#heading=h.7pyingf1unu
6
+
7
+
8
+ # Repos Top Level Function Definitions (Logan)
9
+
10
+ # make_snapshot: Creates new snapshot from current files and versions
11
+ # in - array of file objects. file object = array of all versions: {id, content}
12
+ # out - hash id of snapshot
13
+
14
+ # restore_snapshot: Set current file versions to specified snapshot
15
+ # in - id of target snapshot
16
+ # out - Comm object with status
17
+
18
+ # history: Returns ids for all snapshots
19
+ # in - branch name
20
+ # out - Array of snapshot ids
21
+
22
+ # delete_snapshot: delete specified a snapshot
23
+ # in - target snapshot
24
+ # out - Comm object with status
25
+
26
+ # diff_snapshots: Returns diff between two different snapshots
27
+ # in - two ids of snapshots to perform diff on
28
+ # out - list of filenames and versions
29
+
30
+ # make_branch: make a new branch
31
+ # in - branch name
32
+ # out - hash id of new branch
33
+
34
+ # delete_branch: delete a branch
35
+ # in - branch name
36
+ # out - exit status code
37
+
38
+ # Also do a get_snapshot
39
+
40
+ module Copernicium
41
+ class Snapshot
42
+ def initialize(in_array)
43
+ @files = in_array
44
+ @id = ""
45
+ # id = hash of in array?
46
+ end
47
+
48
+ def set_id(in_id)
49
+ @id = in_id
50
+ end
51
+
52
+ # drop get prefix?
53
+ def get_id()
54
+ @id
55
+ end
56
+
57
+ def get_files()
58
+ @files
59
+ end
60
+ # Initialize hash at startup
61
+ # Possible? Or problem with self object?
62
+ end
63
+
64
+ class Repos
65
+ def initialize()
66
+ # Create manifest
67
+ # It's a list of snapshots in chronological order
68
+ @manifest = {"default" => []}
69
+ @curr_branch = "default"
70
+ # what to do about branch IDs?
71
+ # Read in project path and make manifest file?
72
+ # Create current
73
+ end
74
+
75
+ def manifest()
76
+ @manifest
77
+ end
78
+
79
+ def make_snapshot(file_array)
80
+ # Return hash ID of snapshot
81
+ new_snap = Snapshot.new(file_array)
82
+ # Set ID, consider breaking up that line
83
+ new_snap.set_id(Digest::SHA256.hexdigest(Marshal.dump(new_snap)))
84
+ @manifest[@curr_branch].push(new_snap)
85
+ # Update manifest file?
86
+ return new_snap.get_id()
87
+ end
88
+
89
+ def get_snapshot(target_id)
90
+ # Return snapshot (or just contents) given id
91
+ # Find snapshot
92
+ found_index = @manifest[@curr_branch].index{ |x| x.get_id() == target_id }
93
+ # Handle not found case
94
+ # Return it
95
+ if(found_index)
96
+ return @manifest[@curr_branch][found_index]
97
+ else
98
+ return found_index
99
+ end
100
+ #return ret_snap
101
+ end
102
+
103
+ # Not sure how I'm gonna do this one
104
+ def restore_snapshot(target_id)
105
+ # Return comm object with status
106
+ # Need a way to change files in workspace
107
+ return 1
108
+ end
109
+
110
+ #def history(branch_name)
111
+ def history()
112
+ # Return array of snapshot IDs
113
+ names_list = []
114
+ @manifest[@curr_branch].each {|x| names_list.push(x.get_id())}
115
+ return names_list
116
+ end
117
+
118
+ def delete_snapshot(target_id)
119
+ # Return comm object with status
120
+ # Find snapshot, delete from manifest/memory
121
+ @manifest[@curr_branch].delete_if { |x| x.get_id() == target_id }
122
+ # catch error
123
+ # update manifest file?
124
+ end
125
+
126
+ # Finds the files in snap1 that aren't in snap2, change this?
127
+ # Consider using diffy?
128
+ def diff_snapshots(id1, id2)
129
+ # Return list of filenames and versions
130
+ diff_files = []
131
+ # Put in error catching
132
+ files1 = get_snapshot(id1).get_files()
133
+ files2 = get_snapshot(id2).get_files()
134
+ # Find snapshot1 and snapshot2
135
+ files1.each do |x|
136
+ if(!files2.include?(x))
137
+ diff_files.push(x)
138
+ end
139
+ end
140
+ return diff_files
141
+ # Use revlog diff on each set of files? Look at Diffy
142
+ end
143
+
144
+ def make_branch(branch_name)
145
+ # Return hash ID of new branch
146
+ # Not sure where to store branches
147
+ # What goes in to the hash?
148
+ @manifest[branch_name] = @manifest[@curr_branch]
149
+ @curr_branch = branch_name
150
+ return 1
151
+ end
152
+
153
+ def delete_branch(branch_name)
154
+ # Exit status code
155
+ @manifest.delete("branch_name")
156
+ end
157
+
158
+ def clear()
159
+ # Just a placeholder for now
160
+ end
161
+
162
+ end
163
+ end
164
+
165
+
data/lib/required.rb ADDED
@@ -0,0 +1,21 @@
1
+ # gem requirements
2
+
3
+ require 'yaml'
4
+ require 'diffy'
5
+ require 'digest'
6
+ require 'pathname'
7
+ require 'singleton'
8
+ require 'socket' # Socket needed for communicating over the network
9
+ require 'io/console' # Needed to hide password at console
10
+ require 'net/ssh' # Needed to communicate with the remote
11
+ require 'net/scp' # Needed for file transfer between servers
12
+
13
+ # coperncicium files
14
+
15
+ require_relative "ui"
16
+ require_relative "repos"
17
+ require_relative "RevLog"
18
+ require_relative "banners"
19
+ require_relative "pushpull"
20
+ require_relative "workspace"
21
+
data/lib/ui.rb ADDED
@@ -0,0 +1,161 @@
1
+ # user interface module - parse and execute commands
2
+ # integrates all modules, central module
3
+
4
+
5
+ VERSION = "0.0.1"
6
+
7
+ module Copernicium
8
+ class Driver
9
+ # Get some info from the user when they dont specify it
10
+ def get(info)
11
+ puts "Hi, #{info} not specified. Enter #{info}:"
12
+ gets.chomp # read a line from user, and return it
13
+ end
14
+
15
+ # Print and exit with a specific code
16
+ def pexit(msg, sig)
17
+ puts msg
18
+ exit sig
19
+ end
20
+
21
+ # Executes the required action for a given user command.
22
+ #
23
+ # Parameters:
24
+ # * args - an array containing the tokenized argv from the user
25
+ # For instance: "cn hello world" -> ['hello', 'world']
26
+ #
27
+ # Return value:
28
+ # A UIComm object containing details of the command to be
29
+ # executed by the respective backend module.
30
+ #
31
+ def run(args)
32
+
33
+ # if no arguments given show help information
34
+ pexit HELP_BANNER, 0 if args.empty?
35
+
36
+ # get first command
37
+ cmd = args.shift
38
+
39
+ # if no arguments given show help information
40
+ pexit HELP_BANNER, 0 if cmd == '-h'
41
+
42
+ # if -v flag givem show version
43
+ pexit VERSION, 0 if cmd == '-v'
44
+
45
+ # Handle standard commands
46
+ case cmd
47
+ when 'init'
48
+ init args
49
+ when 'status'
50
+ status args
51
+ when 'clone'
52
+ clone args
53
+ when 'commit'
54
+ commit args
55
+ when 'checkout'
56
+ checkout args
57
+ when 'merge'
58
+ merge args
59
+ when 'push'
60
+ push args
61
+ when 'pull'
62
+ pull args
63
+ else # handle an unrecognized argument, show help and exit
64
+ pexit "Unrecognized command #{cmd}\n" + HELP_BANNER, 1
65
+ end
66
+ end # run
67
+
68
+ def init(args)
69
+ UIComm.new(command: 'init', opts: args)
70
+ # todo - make call to repos to create repo
71
+ end
72
+
73
+ def status(args)
74
+ UIComm.new(command: 'status', opts: args)
75
+ # todo - make call to workspace, get and show status
76
+ end
77
+
78
+ def push(args)
79
+ UIComm.new(command: 'push', opts: args)
80
+ # todo - make call to pushpull, push remote
81
+ end
82
+
83
+ def pull(args)
84
+ UIComm.new(command: 'pull', opts: args)
85
+ # todo - make call to pushpull, pull remote
86
+ end
87
+
88
+ def checkout(args)
89
+ if args.empty?
90
+ rev = get 'branch or revision'
91
+ else
92
+ rev = args.shift
93
+ files = args
94
+ end
95
+
96
+ # todo - call repos checkout the given / branch
97
+ # todo - also, figure out if is branch or rev id
98
+ # this can be done by checking if it is a branch, and if not, then just
99
+ # assume it is a rev id. if it isnt, then something will break :/
100
+
101
+ UIComm.new(command: 'checkout', rev: rev, files: files)
102
+ end
103
+
104
+ def clone(args)
105
+ # todo - optionally check for folder to clone into, instead of cwd
106
+ if args.empty?
107
+ repo = get 'repo url to clone'
108
+ else
109
+ repo = args.first
110
+ end
111
+
112
+ # todo - actually clone remote locally
113
+
114
+ UIComm.new(command: 'clone', repo: repo)
115
+ end
116
+
117
+ def commit(args)
118
+ messflag = args.find_index('-m')
119
+ if messflag.nil?
120
+ message = get 'commit message'
121
+ else # mash everything after -m into a single string
122
+ message = args[messflag + 1..-1].join ' '
123
+ end
124
+
125
+ # todo parse file list, in case just commiting some files
126
+ # todo call revlog, commit files
127
+ # todo call repos, update commit
128
+
129
+ UIComm.new(command: 'commit', commit_message: message)
130
+ end
131
+
132
+ def merge(args)
133
+ if args.empty?
134
+ puts 'I need a commit to merge.'
135
+ rev = get 'single commit to merge'
136
+ else # use given
137
+ rev = args.first
138
+ end
139
+
140
+ # todo - call repos merge command
141
+
142
+ UIComm.new(command: 'merge', rev: rev)
143
+ end
144
+ end
145
+
146
+ # Communication object that will pass commands to backend modules
147
+ # rev - A single revision indicator (commit #, branch name, HEAD, etc.)
148
+ # repo - URL/path to a remote repository
149
+ class UIComm
150
+ attr_reader :command, :arguments, :files, :rev, :commit_message, :repo
151
+ def initialize(command: nil, files: nil, rev: nil,
152
+ commit_message: nil, repo: nil, opts: nil)
153
+ @commit_message = commit_message
154
+ @command = command
155
+ @files = files
156
+ @opts = opts
157
+ @repo = repo
158
+ @rev = rev
159
+ end
160
+ end
161
+ end
data/lib/workspace.rb ADDED
@@ -0,0 +1,212 @@
1
+ # This is the workspace module
2
+ # The functions are clean, commit, checkout and status
3
+
4
+ module Copernicium
5
+ class FileObj
6
+ attr_reader :path, :history_hash_ids
7
+ def initialize(path, ids)
8
+ @path = path
9
+ @history_hash_ids = ids
10
+ end
11
+
12
+ def ==(rhs)
13
+ if rhs.is_a? String
14
+ @path == rhs
15
+ else
16
+ @path == rhs.path
17
+ end
18
+ end
19
+ end
20
+
21
+ class Workspace
22
+ def writeFile(path, content)
23
+ f = open(path, 'w')
24
+ f.write(content)
25
+ f.close
26
+ end
27
+
28
+ def readFile(path)
29
+ f = open(path, 'r')
30
+ txt = f.read
31
+ f.close
32
+ txt
33
+ end
34
+
35
+ #private_class_method :writeFile
36
+ #private_class_method :readFile
37
+
38
+ def initialize(bname = 'master', rootdir = './workspace')
39
+ @files = []
40
+ @branch_name = bname
41
+ @revlog = Copernicium::RevLog.new('.')
42
+ @repos = Copernicium::Repos.new
43
+ @root = rootdir
44
+ if !File.directory?(@root)
45
+ Dir.mkdir(@root)
46
+ end
47
+ end
48
+
49
+ def indexOf(x)
50
+ index = -1
51
+ @files.each_with_index do |e,i|
52
+ if e.path == x
53
+ index = i
54
+ break
55
+ end
56
+ end
57
+ index
58
+ end
59
+
60
+ # if include all the elements in list_files
61
+ def include?(list_files)
62
+ list_files.each do |x|
63
+ if indexOf(x) == -1
64
+ return false
65
+ end
66
+ end
67
+ true
68
+ end
69
+
70
+ # if list_files is nil, then rollback the list of files from the branch
71
+ # or rollback to the entire branch head pointed
72
+ def clean(comm)
73
+ list_files = comm.files
74
+ if list_files.nil? # reset first: delete them from disk and reset @files
75
+ @files.each{|x| File.delete(x.path)}
76
+ @files = []
77
+ # restore it with checkout() if we have had a branch name
78
+ if @branch_name != ''
79
+ # or it is the initial state, no commit and no checkout
80
+ return checkout(@branch_name)
81
+ else
82
+ return 0
83
+ end
84
+
85
+ else #list_files are not nil
86
+ # check that every file need to be reset should have been recognized by the workspace
87
+ #workspace_files_paths = @files.each{|x| x.path}
88
+ return -1 if (self.include? list_files) == false
89
+
90
+ # the actual action, delete all of them from the workspace first
91
+ list_files.each do |x|
92
+ File.delete(x)
93
+ idx = indexOf(x)
94
+ if !idx==-1
95
+ @files.delete_at(idx)
96
+ end
97
+ end
98
+
99
+ # if we have had a branch, first we get the latest snapshot of it
100
+ # and then checkout with the restored version of them
101
+ if @branch_name != ''
102
+ return checkout(list_files)
103
+ else
104
+ return 0
105
+ end
106
+ end
107
+ end
108
+
109
+ # commit a list of files or the entire workspace to make a new snapshot
110
+ def commit(comm)
111
+ # for this commented version, we first get all files in the workspace and then add files from comm obj
112
+ # it's not used at this time
113
+ # Linfeng Song
114
+ #list_files = @files.each{|x| x.path}
115
+ #if comm.files != nil
116
+ # comm.files.each do |x|
117
+ # if indexOf(x) == -1
118
+ # list_files.push(x)
119
+ # end
120
+ # end
121
+ #end
122
+ list_files = Dir[ File.join(@root, '**', '*') ].reject { |p| File.directory? p }
123
+ if list_files != nil
124
+ list_files.each do |x|
125
+ if indexOf(x) == -1
126
+ content = readFile(x)
127
+ hash = @revlog.add_file(x, content)
128
+ fobj = FileObj.new(x, [hash,])
129
+ @files.push(fobj)
130
+ else
131
+ content = readFile(x)
132
+ hash = @revlog.add_file(x, content)
133
+ if @files[indexOf(x)].history_hash_ids[-1] != hash
134
+ @files[indexOf(x)].history_hash_ids << hash
135
+ end
136
+ end
137
+ end
138
+ end
139
+ return @repos.make_snapshot(@files)
140
+ end
141
+
142
+ def checkout(comm)
143
+ argu = comm.files
144
+ # if argu is an Array Object, we assume it is a list of files to be added to the workspace
145
+ if argu != nil
146
+ # we add the list of files to @files regardless whether it has been in it.
147
+ # that means there may be multiple versions of a file.
148
+ list_files = argu
149
+ snapshot_id = @repos.history()[-1]
150
+ returned_snapshot = @repos.get_snapshot(snapshot_id)
151
+ list_files_last_commit = returned_snapshot.get_files()
152
+ list_files_last_commit.each do |x|
153
+ if list_files.include? x.path
154
+ path = x.path
155
+ content = @revlog.get_file(x.history_hash_ids[-1])
156
+ idx = indexOf(x.path)
157
+ if idx == -1
158
+ @files.push(x)
159
+ else
160
+ @files[idx] = x
161
+ end
162
+ writeFile(path,content)
163
+ end
164
+ end
165
+ # if argu is not an Array, we assume it is a String, representing the branch name
166
+ # we first get the last snapshot id of the branch, and then get the commit object
167
+ # and finally push all files of it to the workspace
168
+ else
169
+ argu = comm.rev #branch name
170
+ snapshot_id = @repos.history()[-1]
171
+ snapshot_obj = @repos.get_snapshot(snapshot_id).get_files()
172
+ snapshot_obj.each do |fff|
173
+ idx = indexOf(fff.path)
174
+ if idx == -1
175
+ @files.push(fff)
176
+ else
177
+ @files[idx] = fff
178
+ end
179
+ path = fff.path
180
+ content = @revlog.get_file(fff.history_hash_ids[-1])
181
+ writeFile(path,content)
182
+ end
183
+ end
184
+ end
185
+
186
+ def status(comm)
187
+ adds = []
188
+ deletes = []
189
+ edits = []
190
+ wsFiles = Dir[ File.join(@root, '**', '*') ].reject { |p| File.directory? p }
191
+ wsFiles.each do |f|
192
+ idx = indexOf(f)
193
+ if idx != -1
194
+ x1 = @revlog.get_file(@files[idx].history_hash_ids[-1])
195
+ x2 = readFile(f)
196
+ if x1 != x2
197
+ edits.push(f)
198
+ end
199
+ else
200
+ adds.push(f)
201
+ end
202
+ end
203
+ @files.each do |f|
204
+ if ! (wsFiles.include? f.path)
205
+ deletes.push(f.path)
206
+ end
207
+ end
208
+ return [adds, edits, deletes]
209
+ end
210
+ end
211
+ end
212
+
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: copernicium
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Team Copernicium
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: diffy
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.0.7
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.7
33
+ - !ruby/object:Gem::Dependency
34
+ name: net-scp
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.2'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 1.2.1
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.2'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 1.2.1
53
+ - !ruby/object:Gem::Dependency
54
+ name: net-ssh
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '3.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 3.0.1
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.0.1
73
+ - !ruby/object:Gem::Dependency
74
+ name: minitest
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '5.8'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 5.8.1
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.8'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 5.8.1
93
+ - !ruby/object:Gem::Dependency
94
+ name: minitest-reporters
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '1.1'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 1.1.4
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.1'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 1.1.4
113
+ description: A simple distributed version control system written in Ruby.
114
+ email: jeremywrnr@gmail.com
115
+ executables:
116
+ - cn
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - bin/cn
121
+ - lib/RevLog.rb
122
+ - lib/banners.rb
123
+ - lib/pushpull.rb
124
+ - lib/repos.rb
125
+ - lib/required.rb
126
+ - lib/ui.rb
127
+ - lib/workspace.rb
128
+ homepage: http://github.com/jeremywrnr/copernicium
129
+ licenses:
130
+ - MIT
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubyforge_project:
148
+ rubygems_version: 2.4.8
149
+ signing_key:
150
+ specification_version: 4
151
+ summary: Simple DVCS in Ruby.
152
+ test_files: []