version50 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/{version50 → v50} +3 -4
- data/lib/version50/git.rb +36 -25
- data/lib/version50/scm.rb +105 -11
- data/lib/version50.rb +75 -9
- metadata +5 -5
data/bin/{version50 → v50}
RENAMED
@@ -5,7 +5,7 @@ require 'version50'
|
|
5
5
|
|
6
6
|
# display help if no options are given
|
7
7
|
if ARGV.length == 0
|
8
|
-
Version50.new
|
8
|
+
Version50.new 'help'
|
9
9
|
exit
|
10
10
|
end
|
11
11
|
|
@@ -15,6 +15,5 @@ trap('INT') {
|
|
15
15
|
exit
|
16
16
|
}
|
17
17
|
|
18
|
-
#
|
19
|
-
|
20
|
-
version50 = Version50.new :action => action
|
18
|
+
# forward actions to version50
|
19
|
+
version50 = Version50.new(ARGV[0], ARGV[1..-1])
|
data/lib/version50/git.rb
CHANGED
@@ -1,11 +1,24 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
require 'tmpdir'
|
3
|
-
|
4
1
|
require 'version50/scm'
|
5
2
|
|
6
3
|
class Git < SCM
|
4
|
+
# create a branch
|
5
|
+
def branch b
|
6
|
+
`git branch #{b}`
|
7
|
+
end
|
8
|
+
|
9
|
+
# checkout a branch
|
10
|
+
def checkout b
|
11
|
+
super
|
12
|
+
`git checkout #{b}`
|
13
|
+
end
|
14
|
+
|
15
|
+
# clone a repository
|
16
|
+
def download(url, path = '')
|
17
|
+
`git clone #{url} #{path} > /dev/null 2> /dev/null`
|
18
|
+
end
|
19
|
+
|
7
20
|
# commit a new version without pushing
|
8
|
-
def commit
|
21
|
+
def commit(options = {})
|
9
22
|
# prompt for commit message
|
10
23
|
message = super
|
11
24
|
|
@@ -30,7 +43,7 @@ class Git < SCM
|
|
30
43
|
# create a new repo
|
31
44
|
def init
|
32
45
|
`git init`
|
33
|
-
`echo ".version50" > .gitignore`
|
46
|
+
`echo ".version50\n.version50-warps" > .gitignore`
|
34
47
|
end
|
35
48
|
|
36
49
|
# view the project history
|
@@ -56,7 +69,16 @@ class Git < SCM
|
|
56
69
|
return commits
|
57
70
|
end
|
58
71
|
|
72
|
+
# return to the present
|
73
|
+
def present
|
74
|
+
`git reset --hard`
|
75
|
+
`git checkout master > /dev/null 2> /dev/null`
|
76
|
+
end
|
77
|
+
|
59
78
|
def pull
|
79
|
+
# save before doing anything
|
80
|
+
self.save({ :quiet => true })
|
81
|
+
`git pull --rebase`
|
60
82
|
end
|
61
83
|
|
62
84
|
# push existing commits
|
@@ -64,6 +86,11 @@ class Git < SCM
|
|
64
86
|
`git push -u origin master > /dev/null 2>&1`
|
65
87
|
end
|
66
88
|
|
89
|
+
# reset all changes since last commit
|
90
|
+
def reset
|
91
|
+
`git reset --hard`
|
92
|
+
end
|
93
|
+
|
67
94
|
# view changed files
|
68
95
|
def status
|
69
96
|
# get status from SCM
|
@@ -118,27 +145,11 @@ class Git < SCM
|
|
118
145
|
end
|
119
146
|
|
120
147
|
# warp to a specific version
|
121
|
-
def warp
|
122
|
-
# save current state
|
123
|
-
revision = super
|
124
|
-
|
125
|
-
# determine project root and warp destination
|
126
|
-
path = @version50.root
|
127
|
-
dest = "version50-#{revision[:revision]}"
|
128
|
-
|
129
|
-
# create temporary directory to clone project into
|
130
|
-
Dir.mktmpdir do |d|
|
131
|
-
# clone project into temporary directory and revert to given revision
|
132
|
-
Dir.chdir(File.expand_path d)
|
133
|
-
`git clone #{path} . > /dev/null 2> /dev/null`
|
148
|
+
def warp r = nil
|
149
|
+
# save current state and determine revision to warp to
|
150
|
+
revision = super r
|
151
|
+
if revision
|
134
152
|
`git checkout #{revision[:id]} -f > /dev/null 2> /dev/null`
|
135
|
-
|
136
|
-
# switch back to project root and create folder for warp
|
137
|
-
Dir.chdir(File.expand_path path)
|
138
|
-
FileUtils.mkdir dest
|
139
|
-
|
140
|
-
# move all files in temporary directory into warp directory
|
141
|
-
FileUtils.mv(Dir.glob(File.expand_path(d) + '/*'), dest)
|
142
153
|
end
|
143
154
|
end
|
144
155
|
end
|
data/lib/version50/scm.rb
CHANGED
@@ -1,16 +1,35 @@
|
|
1
1
|
require 'pathname'
|
2
|
+
require 'yaml'
|
2
3
|
|
3
4
|
class SCM
|
4
5
|
def initialize(version50)
|
5
6
|
@version50 = version50
|
6
7
|
end
|
7
8
|
|
9
|
+
# create a branch
|
10
|
+
def branch b
|
11
|
+
end
|
12
|
+
|
13
|
+
# checkout a branch
|
14
|
+
def checkout b
|
15
|
+
self.save({ :quiet => true })
|
16
|
+
end
|
17
|
+
|
8
18
|
# commit changes without pushing
|
9
|
-
def commit
|
19
|
+
def commit(options = {})
|
20
|
+
# make sure we're not in a warp
|
21
|
+
config = @version50.parse_config
|
22
|
+
if config['warp']
|
23
|
+
puts "\033[31mYou cannot commit any changes until you warp back to the present!\033[0m"
|
24
|
+
return
|
25
|
+
end
|
26
|
+
|
10
27
|
# check if we have anything to commit
|
11
28
|
files = self.status
|
12
29
|
if files[:added].length == 0 && files[:modified].length == 0 && files[:deleted].length == 0
|
13
|
-
|
30
|
+
if !options[:quiet]
|
31
|
+
puts "Nothing has changed since your last save!"
|
32
|
+
end
|
14
33
|
|
15
34
|
# prompt for commit message
|
16
35
|
else
|
@@ -25,6 +44,9 @@ class SCM
|
|
25
44
|
def config info
|
26
45
|
end
|
27
46
|
|
47
|
+
def download(url, path = '')
|
48
|
+
end
|
49
|
+
|
28
50
|
# initialize a new repo
|
29
51
|
def init
|
30
52
|
end
|
@@ -33,6 +55,10 @@ class SCM
|
|
33
55
|
def log
|
34
56
|
end
|
35
57
|
|
58
|
+
# return to the present
|
59
|
+
def present
|
60
|
+
end
|
61
|
+
|
36
62
|
def pull
|
37
63
|
end
|
38
64
|
|
@@ -40,9 +66,48 @@ class SCM
|
|
40
66
|
def push
|
41
67
|
end
|
42
68
|
|
69
|
+
# recover a path from a warp
|
70
|
+
def recover path
|
71
|
+
# determine what warp we're in
|
72
|
+
config = @version50.parse_config
|
73
|
+
if !config['warp']
|
74
|
+
puts "\033[31mYou have to warp to another revision before you can recover anything!\033[0m"
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
78
|
+
# make sure file exists
|
79
|
+
if Dir.glob(path).empty?
|
80
|
+
puts "\033[31mSpecify a valid path to recover!\033[0m"
|
81
|
+
return
|
82
|
+
end
|
83
|
+
|
84
|
+
# copy all files in path into warps folder
|
85
|
+
warp = config['warp']
|
86
|
+
files = Dir.glob path
|
87
|
+
root = @version50.root
|
88
|
+
files.each do |f|
|
89
|
+
FileUtils.mkdir_p(root + '/.version50-warps/' + File.dirname(f))
|
90
|
+
FileUtils.cp(f, root + '/.version50-warps/' + File.dirname(f))
|
91
|
+
end
|
92
|
+
|
93
|
+
# display which files were recovered
|
94
|
+
if files.length == 1
|
95
|
+
puts "\033[032mRecovered #{files[0]}!\033[0m"
|
96
|
+
else
|
97
|
+
puts "\033[032mRecovered:\n"
|
98
|
+
files.each do |f|
|
99
|
+
puts "* #{f}"
|
100
|
+
end
|
101
|
+
puts "\033[0m"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def reset
|
106
|
+
end
|
107
|
+
|
43
108
|
# shortcut for commit and push
|
44
|
-
def save
|
45
|
-
self.commit
|
109
|
+
def save(commit_options = {})
|
110
|
+
self.commit commit_options
|
46
111
|
self.push
|
47
112
|
end
|
48
113
|
|
@@ -51,20 +116,49 @@ class SCM
|
|
51
116
|
end
|
52
117
|
|
53
118
|
# warp to a specific revision
|
54
|
-
def warp
|
55
|
-
#
|
56
|
-
|
119
|
+
def warp revision = nil
|
120
|
+
# warp back to the present
|
121
|
+
if revision == 'present'
|
122
|
+
puts "\033[032mWarped back to the present!\033[0m"
|
123
|
+
self.present
|
124
|
+
|
125
|
+
# remove warp number from .version50
|
126
|
+
config = @version50.parse_config
|
127
|
+
config.delete 'warp'
|
128
|
+
File.open(@version50.root + '/.version50', 'w') do |f|
|
129
|
+
f.write config.to_yaml
|
130
|
+
end
|
131
|
+
|
132
|
+
# move files from warps folder
|
133
|
+
root = @version50.root
|
134
|
+
FileUtils.mv(Dir.glob(root + '/.version50-warps/*'), root)
|
135
|
+
return false
|
136
|
+
end
|
57
137
|
|
58
|
-
#
|
59
|
-
|
60
|
-
revision = $stdin.gets.chomp.to_i(10)
|
138
|
+
# save before doing anything
|
139
|
+
self.save({ :quiet => true })
|
61
140
|
|
62
|
-
|
141
|
+
# prompt for revision if not given
|
142
|
+
if !revision
|
143
|
+
print "\033[34mWhat version would you like to warp to?\033[0m "
|
144
|
+
revision = $stdin.gets.chomp.to_i(10)
|
145
|
+
else
|
146
|
+
revision = revision.to_i(10)
|
147
|
+
end
|
63
148
|
|
64
149
|
# get revision from numerical index
|
65
150
|
revisions = self.log
|
66
151
|
r = revisions[revisions.length - revision]
|
67
152
|
|
153
|
+
# record where we warped
|
154
|
+
config = @version50.parse_config
|
155
|
+
config['warp'] = revision
|
156
|
+
File.open(@version50.root + '/.version50', 'w') do |f|
|
157
|
+
f.write config.to_yaml
|
158
|
+
end
|
159
|
+
|
160
|
+
puts "\033[032mWarped to revision ##{revision}!\033[0m"
|
161
|
+
|
68
162
|
# add numerical index to return value
|
69
163
|
r[:revision] = revision
|
70
164
|
return r
|
data/lib/version50.rb
CHANGED
@@ -5,15 +5,39 @@ require 'optparse'
|
|
5
5
|
require 'yaml'
|
6
6
|
require 'net/http'
|
7
7
|
require 'net/https'
|
8
|
+
require 'fileutils'
|
8
9
|
require 'highline/import'
|
9
10
|
HighLine.track_eof = false
|
10
11
|
|
11
12
|
class Version50
|
12
|
-
def initialize(args)
|
13
|
+
def initialize(action, args = [])
|
14
|
+
# help text
|
15
|
+
if action == 'help'
|
16
|
+
return self.help
|
17
|
+
end
|
18
|
+
|
19
|
+
# version number
|
20
|
+
if action == 'version'
|
21
|
+
return self.version
|
22
|
+
end
|
23
|
+
|
13
24
|
# parse configuration
|
14
25
|
config = self.parse_config
|
15
26
|
@scm = self.scm config
|
16
27
|
|
28
|
+
# download a repository
|
29
|
+
if action == 'download'
|
30
|
+
if args[0] =~ /git/
|
31
|
+
@scm = self.scm({ 'scm' => 'git' })
|
32
|
+
end
|
33
|
+
|
34
|
+
# download repository
|
35
|
+
puts "\033[033mDownloading project...\033[0m"
|
36
|
+
@scm.download args[0], args[1]
|
37
|
+
puts "\033[032mDownload complete!\033[0m"
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
17
41
|
# no configuration file, so prompt to create a new project
|
18
42
|
if !config
|
19
43
|
config = self.create
|
@@ -24,37 +48,62 @@ class Version50
|
|
24
48
|
# set user info
|
25
49
|
@scm.config config
|
26
50
|
|
51
|
+
# create a new branch
|
52
|
+
if action == 'branch'
|
53
|
+
@scm.branch args[0]
|
54
|
+
end
|
55
|
+
|
27
56
|
# commit a new version without pushing
|
28
|
-
if
|
57
|
+
if action == 'commit'
|
29
58
|
@scm.commit
|
30
59
|
end
|
31
60
|
|
32
61
|
# view the commit history
|
33
|
-
if
|
62
|
+
if action == 'history' || action == 'log'
|
34
63
|
commits = @scm.log
|
35
64
|
self.output_history commits
|
36
65
|
end
|
37
66
|
|
67
|
+
# pull from the main remote
|
68
|
+
if action == 'pull'
|
69
|
+
@scm.pull
|
70
|
+
end
|
71
|
+
|
38
72
|
# push the current project
|
39
|
-
if
|
73
|
+
if action == 'push'
|
40
74
|
@scm.push
|
41
75
|
end
|
42
76
|
|
77
|
+
# undo all changes since last save
|
78
|
+
if action == 'reset'
|
79
|
+
@scm.reset
|
80
|
+
end
|
81
|
+
|
43
82
|
# save a new version, which means commit and push
|
44
|
-
if
|
83
|
+
if action == 'save'
|
45
84
|
@scm.save
|
46
85
|
puts "\n\033[032mSaved a new version!\033[0m"
|
47
86
|
end
|
48
87
|
|
88
|
+
# switch to a branch
|
89
|
+
if action == 'switch'
|
90
|
+
@scm.checkout args[0]
|
91
|
+
end
|
92
|
+
|
49
93
|
# get the current status of files
|
50
|
-
if
|
94
|
+
if action == 'status'
|
51
95
|
files = @scm.status
|
52
96
|
self.output_status files
|
53
97
|
end
|
54
98
|
|
99
|
+
# recover a file from a warp
|
100
|
+
if action == 'recover'
|
101
|
+
@scm.recover args[0]
|
102
|
+
end
|
103
|
+
|
55
104
|
# warp to a past version
|
56
|
-
if
|
57
|
-
@scm.warp
|
105
|
+
if action == 'warp'
|
106
|
+
@scm.warp args[0]
|
58
107
|
end
|
59
108
|
end
|
60
109
|
|
@@ -124,16 +173,28 @@ class Version50
|
|
124
173
|
end
|
125
174
|
|
126
175
|
# save config
|
176
|
+
FileUtils.mkdir(Dir.pwd + '/.version50-warps')
|
127
177
|
File.open(Dir.pwd + '/.version50', 'w') do |f|
|
128
178
|
f.write config.to_yaml
|
129
179
|
end
|
130
180
|
|
131
|
-
puts "\n\033[032mYour project was created successfully
|
181
|
+
puts "\n\033[032mYour project was created successfully!"
|
132
182
|
puts "<3 version50\033[0m"
|
133
183
|
|
134
184
|
return config
|
135
185
|
end
|
136
186
|
|
187
|
+
# help text
|
188
|
+
def help
|
189
|
+
puts "\033[34mThis is Version50.\033[0m"
|
190
|
+
puts "Here are some things you can do!"
|
191
|
+
puts "* history: View the history of your project's versions"
|
192
|
+
puts "* recover: Recover an earlier version of a file"
|
193
|
+
puts "* save: Save a version of your project"
|
194
|
+
puts "* status: Get the current status of your project"
|
195
|
+
puts "* warp: Warp back to an earlier point in time"
|
196
|
+
end
|
197
|
+
|
137
198
|
# given a parsed SCM history output, show log
|
138
199
|
def output_history commits
|
139
200
|
# output each commit
|
@@ -234,4 +295,9 @@ class Version50
|
|
234
295
|
return Git.new(self)
|
235
296
|
end
|
236
297
|
end
|
298
|
+
|
299
|
+
# version number
|
300
|
+
def version
|
301
|
+
puts "This is Version50 v0.0.1"
|
302
|
+
end
|
237
303
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: version50
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tommy MacWilliam
|
@@ -48,7 +48,7 @@ dependencies:
|
|
48
48
|
description: A student-friendly SCM abstraction layer.
|
49
49
|
email: tmacwilliam@cs.harvard.edu
|
50
50
|
executables:
|
51
|
-
-
|
51
|
+
- v50
|
52
52
|
extensions: []
|
53
53
|
|
54
54
|
extra_rdoc_files: []
|
@@ -57,7 +57,7 @@ files:
|
|
57
57
|
- lib/version50.rb
|
58
58
|
- lib/version50/git.rb
|
59
59
|
- lib/version50/scm.rb
|
60
|
-
- bin/
|
60
|
+
- bin/v50
|
61
61
|
homepage: https://github.com/tmacwill/version50
|
62
62
|
licenses: []
|
63
63
|
|